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

com.firefly.utils.concurrent.CompletableCallback Maven / Gradle / Ivy

There is a newer version: 5.0.2
Show newest version
package com.firefly.utils.concurrent;

import java.util.concurrent.atomic.AtomicReference;

/**
 * 

* A callback to be used by driver code that needs to know whether the callback * has been succeeded or failed (that is, completed) just after the asynchronous * operation or not, typically because further processing depends on the * callback being completed. The driver code competes with the asynchronous * operation to complete the callback. *

*

* If the callback is already completed, the driver code continues the * processing, otherwise it suspends it. If it is suspended, the callback will * be completed some time later, and {@link #resume()} or * {@link #abort(Throwable)} will be called to allow the application to resume * the processing. *

* Typical usage: * *
 * CompletableCallback callback = new CompletableCallback()
 * {
 *     @Override
 *     public void resume()
 *     {
 *         // continue processing
 *     }
 *
 *     @Override
 *     public void abort(Throwable failure)
 *     {
 *         // abort processing
 *     }
 * }
 * asyncOperation(callback);
 * boolean completed = callback.tryComplete();
 * if (completed)
 *     // suspend processing, async operation not done yet
 * else
 *     // continue processing, async operation already done
 * 
*/ public abstract class CompletableCallback implements Callback { private final AtomicReference state = new AtomicReference<>(State.IDLE); @Override public void succeeded() { while (true) { State current = state.get(); switch (current) { case IDLE: { if (state.compareAndSet(current, State.SUCCEEDED)) return; break; } case COMPLETED: { if (state.compareAndSet(current, State.SUCCEEDED)) { resume(); return; } break; } case FAILED: { return; } default: { throw new IllegalStateException(current.toString()); } } } } @Override public void failed(Throwable x) { while (true) { State current = state.get(); switch (current) { case IDLE: case COMPLETED: { if (state.compareAndSet(current, State.FAILED)) { abort(x); return; } break; } case FAILED: { return; } default: { throw new IllegalStateException(current.toString()); } } } } /** * Callback method invoked when this callback is succeeded after a * first call to {@link #tryComplete()}. */ public abstract void resume(); /** * Callback method invoked when this callback is failed. * * @param failure * the throwable reprsenting the callback failure */ public abstract void abort(Throwable failure); /** * Tries to complete this callback; driver code should call this method once * after the asynchronous operation to detect whether the * asynchronous operation has already completed or not. * * @return whether the attempt to complete was successful. */ public boolean tryComplete() { while (true) { State current = state.get(); switch (current) { case IDLE: { if (state.compareAndSet(current, State.COMPLETED)) return true; break; } case SUCCEEDED: case FAILED: { return false; } default: { throw new IllegalStateException(current.toString()); } } } } private enum State { IDLE, SUCCEEDED, FAILED, COMPLETED } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy