class Context {

	public <T> T get(final Supplier<T> factory) {

		if ( factory == null ) {
			throw new NullPointerException("null factory");
		}

		synchronized ( services ) {

			final T cached=(T)services.get(factory);

			if ( pending.equals(cached) ) {
				throw new IllegalStateException("circular dependency ["+factory+"]");
			}

			return cached != null ? cached : context(() -> {
				try {

					services.put(factory, pending); // mark factory as being acquired

					final T acquired=((Supplier<T>)factories.getOrDefault(factory, factory)).get();

					services.put(factory, acquired); // cache actual resource

					return acquired;

				} catch ( final Throwable e ) {

					services.remove(factory); // roll back acquisition marker

					throw e;

				}
			});

		}
	}

}