org.javabits.yar.guice.BlockingSupplierImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of yar-guice Show documentation
Show all versions of yar-guice Show documentation
Yar Guice: provide a implementation / integration base on guice
package org.javabits.yar.guice;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.util.concurrent.Futures.addCallback;
import static com.google.common.util.concurrent.Futures.getUnchecked;
import java.lang.InterruptedException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;
import javax.annotation.Nullable;
import org.javabits.yar.*;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
import org.javabits.yar.Supplier;
class BlockingSupplierImpl implements BlockingSupplier, SupplierListener, SupplierWrapper {
private final AtomicReference>> supplierRef;
private final Id id;
private final InternalRegistry registry;
// preserve a reference to the registration to avoid garbage collection.
@SuppressWarnings({"unused", "FieldCanBeLocal"})
private Registration selfRegistration;
BlockingSupplierImpl(Id id, InternalRegistry registry) {
this.id = checkNotNull(id, "id");
this.registry = registry;
this.supplierRef = new AtomicReference<>();
initSupplierRef();
}
@Override
public long defaultTimeout() {
return registry.defaultTimeout();
}
@Override
public TimeUnit defaultTimeUnit() {
return registry.defaultTimeUnit();
}
@Override
public Id id() {
return id;
}
@Nullable
@Override
public T get() {
Future> future = supplierRef.get();
// Do not block on Future.get() here. Just check if the future is done.
if (future.isDone())
return future.isCancelled() ? null : getUnchecked(future).get();
return null;
}
@Override
public T getSync() throws InterruptedException {
try {
return getAsync().get();
} catch (ExecutionException e) {
// getAsync() future can't fail (by design). If it did then there is something
// horribly wrong with this code.
throw new AssertionError(e);
}
}
@Nullable
@Override
public T getSync(long timeout, TimeUnit unit) throws InterruptedException, TimeoutException {
try {
return getAsync().get(timeout, unit);
} catch (ExecutionException e) {
// getAsync() future can't fail (by design). If it did then there is something
// horribly wrong with this code.
throw new AssertionError(e);
}
}
@Override
public ListenableFuture getAsync() {
final SettableFuture future = SettableFuture.create();
// The future callback will be executed either on the current thread (if the future is
// already completed) or on the registry's action handler thread.
addCallback(supplierRef.get(), new FutureCallback>() {
@Override
public void onSuccess(Supplier supplier) {
future.set(supplier.get());
}
@Override
public void onFailure(Throwable t) {
}
});
return future;
}
@SuppressWarnings("unchecked")
@Override
public void supplierChanged(SupplierEvent supplierEvent) {
SupplierEvent.Type type = supplierEvent.type();
Supplier supplier = (Supplier) supplierEvent.supplier();
switch (type) {
case ADD:
supplierRef.get().set(supplier);
break;
case REMOVE:
Future> future = supplierRef.get();
// Do not block on Future.get() here. Just check if the future is done.
if (future.isDone() && !future.isCancelled()) {
Supplier currentSupplier = getUnchecked(future);
if (supplier.equals(currentSupplier)) {
initSupplierRef();
}
} else if (future.isCancelled()) {
supplierRef.set(SettableFuture.>create());
}
// else nothing to do we preserve the previous one
break;
default:
throw new IllegalStateException("Unknown supplier event: " + supplierEvent);
}
}
@Nullable
@Override
public com.google.common.base.Supplier getNativeSupplier() {
Future> future = supplierRef.get();
// Do not block on Future.get() here. Just check if the future is done.
if (future.isDone())
return future.isCancelled() ? null : getUnchecked(future);
return null;
}
@Override
public com.google.common.base.Supplier getWrapped() {
return getNativeSupplier();
}
//preserve a strong reference on the registration listener registration
void setSelfRegistration(Registration selfRegistration) {
this.selfRegistration = selfRegistration;
}
@Override
public String toString() {
SettableFuture> delegateSupplier = supplierRef.get();
return "BlockingSupplierImpl{" +
"id=" + id +
", delegate=" + (delegateSupplier != null? delegateSupplier.getClass().getName():"null") +
'}';
}
private void initSupplierRef() {
SettableFuture> settableFuture = SettableFuture.create();
supplierRef.set(settableFuture);
Supplier supplier = registry.getDirectly(id);
if (supplier != null) {
settableFuture.set(supplier);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy