All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.atlassian.util.concurrent.Expiring Maven / Gradle / Ivy

Go to download

This project contains utility classes that are used by various products and projects inside Atlassian and may have some utility to the world at large.

The newest version!
package io.atlassian.util.concurrent;

import io.atlassian.util.concurrent.atomic.AtomicReference;

import java.util.function.Predicate;
import java.util.function.Supplier;

import static java.util.Objects.requireNonNull;

/**
 * A Reference that can expire based on some strategy.
 * 

* The strategy is a continuous supply of Predicates that will remain true until * the reference has expired, from which point they should always fail. A new * reference will then be * * @param the type of reference held. * * @since 2.1 */ final class Expiring implements Supplier { private final AtomicReference> r = new AtomicReference>(Dead. instance()); private final Supplier factory; private final Supplier> strategy; Expiring(final Supplier factory, final Supplier> strategy) { this.factory = requireNonNull(factory); this.strategy = requireNonNull(strategy); } /** {@inheritDoc} */ @Override public T get() { int i = 0; while (true) { final Alive e = r.get(); if (e.alive()) { return e.get(); } if (i++ > 100) { // infinite loop detection, must halt throw new AssertionError(100 + " attempts to CAS update the next value, aborting!"); } r.compareAndSet(e, new Value()); } } // // inner classes // /** * Get a value and let us know whether it should still be current/alive. */ interface Alive extends Supplier { boolean alive(); } /** * Holds a value and the liveness predicate. *

* Lazily computes the value so the construction is cheap and fast. */ final class Value extends LazyReference implements Alive { final Predicate alive = requireNonNull(strategy.get()); @Override public boolean alive() { return alive.test(null); } @Override public T create() { return factory.get(); } } /** * Initial state is dead. */ enum Dead implements Alive { DEAD; public boolean alive() { return false; } @Override public Object get() { throw new UnsupportedOperationException("dead"); } static Alive instance() { @SuppressWarnings("unchecked") final Alive result = (Alive) DEAD; return result; } } }