package mediabrowser.apiinteraction.tasks;
/**
* <p>A cancellation token to signal and propagate cancellation
* requests when executing asynchronous operations.</p>
*
* <p>All the methods of this class are thread safe and may be used concurrently</p>
*
* <p>The interface of this class is inspired (and copied for some of its parts)
* from the Microsoft .NET 4 platform.</p>
*
* @author Mauro Luigi Drago
* https://code.google.com/p/bytenose-extra-utils/source/browse/src/main/java/com/bytenose/extrautils/concurrent/CancellationToken.java
*
*/
public final class CancellationToken {
/**
* The states regulating the behavior of this class.
* A newly created token starts in the NOT_FIXED state.
* Whenever the isCancellationRequested attribute is set
* (no matter the value), the state changes to FIXED.
* In the FIXED state, no more changes to the cancellation
* token are possible.
*/
private enum TokenState { FIXED, NOT_FIXED };
/** The current state of the token */
private TokenState tokenState;
/** A flag indicating whether cancellation has been requested */
private boolean isCancellationRequested;
/**
* Creates a new {@link CancellationToken} with the
* canceled state set to false and which
* may be subsequently canceled.
*/
public CancellationToken() {
tokenState = TokenState.NOT_FIXED;
isCancellationRequested = false;
}
/**
* <p>Creates a new {@link CancellationToken} with a fixed
* and immutable cancellation state.</p>
*
* <p>This constructor is useful when asynchronous operations
* cannot be canceled.</p>
* @param canceled
* the canceled state for this token.
*/
public CancellationToken(boolean canceled) {
tokenState = TokenState.FIXED;
isCancellationRequested = canceled;
}
/**
* Checks whether cancellation has been requested for this token.
* @return true if cancellation has been requested, false otherwise.
*/
public synchronized boolean isCancellationRequested() {
return isCancellationRequested;
}
/**
* Changes the cancellation state of this token to canceled.
* This method has no effect if the token is already in the canceled state.
*
* @throws IllegalStateException
* if the token is already in the FIXED state.
*/
public synchronized void cancel() throws IllegalStateException {
if (isCancellationRequested) return;
if (tokenState == TokenState.FIXED)
throw new IllegalStateException("Cannot change the state of a fixed cancellation token");
isCancellationRequested = true;
tokenState = TokenState.FIXED;
}
}