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();
}
}
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();
}
}
Aggregations