Search in sources :

Example 1 with ObjectBorower

use of org.spf4j.recyclable.ObjectBorower in project spf4j by zolyfarkas.

the class SimpleSmartObjectPool method tryDispose.

@Override
public boolean tryDispose(final long timeoutMillis) throws ObjectDisposeException, InterruptedException {
    factory.dispose(sample);
    long deadlineNanos = TimeSource.nanoTime() + TimeUnit.MILLISECONDS.toNanos(timeoutMillis);
    lock.lock();
    try {
        maxSize = 0;
        List<Pair<ObjectBorower<T>, T>> returnedObjects = new ArrayList<>();
        for (Entry<ObjectBorower<T>, Collection<T>> b : borrowedObjects.asMap().entrySet()) {
            ObjectBorower<T> borrower = b.getKey();
            final int nrObjects = b.getValue().size();
            for (int i = 0; i < nrObjects; i++) {
                Either<Action, T> object = borrower.tryRequestReturnObject();
                if (object.isRight()) {
                    returnedObjects.add(Pair.of(borrower, object.getRight()));
                }
            }
        }
        for (Pair<ObjectBorower<T>, T> objectAndBorrower : returnedObjects) {
            T object = objectAndBorrower.getSecond();
            if (!borrowedObjects.remove(objectAndBorrower.getFirst(), object)) {
                throw new IllegalStateException("Returned Object hasn't been borrowed " + object);
            }
            availableObjects.add(object);
        }
        ObjectDisposeException exception = disposeReturnedObjects(null);
        while (!borrowedObjects.isEmpty()) {
            long waitTimeNanos = deadlineNanos - TimeSource.nanoTime();
            if (waitTimeNanos <= 0) {
                return false;
            }
            if (!available.await(waitTimeNanos, TimeUnit.NANOSECONDS)) {
                return false;
            }
            exception = disposeReturnedObjects(exception);
        }
        if (exception != null) {
            throw exception;
        }
        return true;
    } catch (InterruptedException | RuntimeException e) {
        throw e;
    } finally {
        lock.unlock();
    }
}
Also used : ObjectBorower(org.spf4j.recyclable.ObjectBorower) Action(org.spf4j.recyclable.ObjectBorower.Action) ArrayList(java.util.ArrayList) ObjectDisposeException(org.spf4j.recyclable.ObjectDisposeException) Collection(java.util.Collection) Pair(org.spf4j.base.Pair)

Example 2 with ObjectBorower

use of org.spf4j.recyclable.ObjectBorower in project spf4j by zolyfarkas.

the class SimpleSmartObjectPool method get.

@Override
@SuppressFBWarnings({ "RV_RETURN_VALUE_IGNORED_BAD_PRACTICE", "PRMC_POSSIBLY_REDUNDANT_METHOD_CALLS" })
public T get(final ObjectBorower borower) throws InterruptedException, TimeoutException, ObjectCreationException {
    lock.lock();
    try {
        if (maxSize <= 0) {
            throw new IllegalStateException("Pool closed, noting available for " + borower);
        }
        int nrAvailable = availableObjects.size();
        // trying to be fair here, if others are already waiting, we will not get one.
        if (nrAvailable - waitingForReturn > 0) {
            Iterator<T> it = availableObjects.iterator();
            T object = it.next();
            it.remove();
            if (!borrowedObjects.put(borower, object)) {
                throw new IllegalStateException("Cannot borrow " + object + ", " + borrowedObjects);
            }
            return object;
        } else if (borrowedObjects.size() + nrAvailable < maxSize) {
            T object = factory.create();
            if (!borrowedObjects.put(borower, object)) {
                throw new IllegalStateException("Cannot borrow " + object + ", " + borrowedObjects);
            }
            return object;
        } else {
            // try to reclaim object from borrowers
            for (ObjectBorower<T> b : borrowedObjects.keySet()) {
                if (borower != b) {
                    T object = b.tryReturnObjectIfNotInUse();
                    if (object != null) {
                        if (!borrowedObjects.remove(b, object)) {
                            throw new IllegalStateException("Returned Object hasn't been borrowed " + object);
                        }
                        if (!borrowedObjects.put(borower, object)) {
                            throw new IllegalStateException("Cannot borrow " + object + ", " + borrowedObjects);
                        }
                        return object;
                    }
                }
            }
            // evrything in use, try to place a return request
            boolean requestMade = false;
            while (!requestMade) {
                boolean hasValidBorowers = false;
                for (ObjectBorower<T> b : borrowedObjects.keySet()) {
                    if (borower != b) {
                        hasValidBorowers = true;
                        Either<ObjectBorower.Action, T> objOrPromise = b.tryRequestReturnObject();
                        if (objOrPromise.isRight()) {
                            T obj = objOrPromise.getRight();
                            if (!borrowedObjects.remove(b, obj)) {
                                throw new IllegalStateException("Returned Object " + obj + " hasn't been borrowed: " + borrowedObjects);
                            }
                            if (!borrowedObjects.put(borower, obj)) {
                                throw new IllegalStateException("Cannot boroow " + obj + ", " + borrowedObjects);
                            }
                            return obj;
                        } else {
                            requestMade = objOrPromise.getLeft() == Action.REQUEST_MADE;
                            if (requestMade) {
                                break;
                            }
                        }
                    }
                }
                if (!hasValidBorowers) {
                    throw new IllegalStateException("Borrower asks for more than possible " + borower);
                }
                if (!requestMade) {
                    // probably was unable to acquire the locks
                    do {
                        available.await(1, TimeUnit.MILLISECONDS);
                        long millisToDeadline = ExecutionContexts.getTimeRelativeToDeadline(TimeUnit.MILLISECONDS);
                        if (millisToDeadline < 0) {
                            throw new TimeoutException("Object wait timeout expired by " + (-millisToDeadline));
                        }
                    } while (borrowedObjects.isEmpty());
                }
            }
            waitingForReturn++;
            while (availableObjects.isEmpty()) {
                long waitTime = ExecutionContexts.getTimeToDeadline(TimeUnit.MILLISECONDS);
                if (!available.await(waitTime, TimeUnit.MILLISECONDS)) {
                    throw new TimeoutException("Object wait timeout expired, waitTime = " + waitTime);
                }
            }
            waitingForReturn--;
            Iterator<T> it = availableObjects.iterator();
            T objectT = it.next();
            it.remove();
            if (!borrowedObjects.put(borower, objectT)) {
                throw new IllegalStateException("Cannot borrow " + objectT + ", " + borrowedObjects);
            }
            return objectT;
        }
    } finally {
        lock.unlock();
    }
}
Also used : ObjectBorower(org.spf4j.recyclable.ObjectBorower) Iterator(java.util.Iterator) Either(org.spf4j.base.Either) TimeoutException(java.util.concurrent.TimeoutException) SuppressFBWarnings(edu.umd.cs.findbugs.annotations.SuppressFBWarnings)

Aggregations

ObjectBorower (org.spf4j.recyclable.ObjectBorower)2 SuppressFBWarnings (edu.umd.cs.findbugs.annotations.SuppressFBWarnings)1 ArrayList (java.util.ArrayList)1 Collection (java.util.Collection)1 Iterator (java.util.Iterator)1 TimeoutException (java.util.concurrent.TimeoutException)1 Either (org.spf4j.base.Either)1 Pair (org.spf4j.base.Pair)1 Action (org.spf4j.recyclable.ObjectBorower.Action)1 ObjectDisposeException (org.spf4j.recyclable.ObjectDisposeException)1