package ch.unibe.scg.cells; import java.util.HashMap; import java.util.Map; import java.util.WeakHashMap; import com.google.inject.Key; import com.google.inject.Provider; import com.google.inject.Scope; /** The scope behind {@link PipelineScoped}. */ // The implementation follows Guice's Scopes.SINGLETON class. class PipelineStageScope implements Scope { // Weak because the life-cycle of providers is up to Guice, and not to us, // and we have no use for them once Guice has given them up. final private WeakHashMap<ScopedProvider<?>, Void> scopedProviders = new WeakHashMap<>(); /* Exits a scope. This method is reentrant, but should not be called concurrently. */ void exit() { for (ScopedProvider<?> e : scopedProviders.keySet()) { synchronized(e) { e.values.clear(); } } } /** The produced providers are threadsafe. */ @Override public <T> Provider<T> scope(Key<T> key, Provider<T> unscoped) { ScopedProvider<T> ret = new ScopedProvider<>(key, unscoped); scopedProviders.put(ret, null); return ret; } // TODO: should this be serializable? private static class ScopedProvider<T> implements Provider<T> { final Map<Key<?>, Object> values = new HashMap<>(); final Key<T> key; final Provider<T> unscoped; ScopedProvider(Key<T> key, Provider<T> unscoped) { this.key = key; this.unscoped = unscoped; } @Override public synchronized T get() { if (!values.containsKey(key)) { values.put(key, unscoped.get()); } return (T) values.get(key); } } }