org.multiverse.api.TxnThreadLocal Maven / Gradle / Ivy
package org.multiverse.api;
import org.multiverse.api.exceptions.TxnMandatoryException;
/**
* A {@link ThreadLocal} that contains the current {@link Txn}. The {@link Stm} and the {@link Txn}
* should not rely on threadlocals, they are only used for convenience to reduce the need to carry around a
* Txn.
*
* This TxnThreadLocal has an optimization that prevents accessing the threadlocal too many times.
* The Container wraps the Txn, so if a Thread gets a reference to that container and holds it, it
* can modify the current transaction with a direct field access instead of another threadlocal access. It should
* be used with extreme care, because the Container should not leak to another thread. It is very useful for the
* {@link TxnExecutor} for example because a get/getAndSet/clear needs to be called otherwise.
*
* @author Peter Veentjer.
*/
public final class TxnThreadLocal {
public final static ThreadLocal threadlocal = new ThreadLocal() {
protected Container initialValue() {
return new Container();
}
};
/**
* Gets the threadlocal {@link Txn}. If no transaction is set, null is returned.
*
* No checks are done on the state of the transaction (so it could be that an aborted or committed transaction is
* returned).
*
* @return the threadlocal transaction.
*/
public static Txn getThreadLocalTxn() {
return threadlocal.get().txn;
}
/** ThreadLocalTransaction
* Gets the ThreadLocal container that stores the Txn. Use this with extreme care because
* the Container should not leak to another thread. It is purely means as a performance optimization
* to prevent repeated (expensive) threadlocal access, and replace it by a cheap field access.
*
* @return the Container. The returned value will never be null.
*/
public static Container getThreadLocalTxnContainer() {
return threadlocal.get();
}
/**
* Gets the threadlocal {@link Txn} or throws a {@link org.multiverse.api.exceptions.TxnMandatoryException} if no transaction is found.
*
*
No checks are done on the state of the transaction (so it could be that an aborted or committed transaction is
* returned).
*
* @return the threadlocal transaction.
* @throws org.multiverse.api.exceptions.TxnMandatoryException
* if no thread local transaction is found.
*/
public static Txn getRequiredThreadLocalTxn() {
Txn txn = threadlocal.get().txn;
if (txn == null) {
throw new TxnMandatoryException("No transaction is found on the TxnThreadLocal");
}
return txn;
}
/**
* Clears the threadlocal transaction.
*
*
If a transaction is available, it isn't aborted or committed.
*/
public static void clearThreadLocalTxn() {
threadlocal.get().txn = null;
}
/**
* Sets the threadlocal transaction. The transaction is allowed to be null, effectively clearing the
* current thread local transaction.
*
*
If a transaction is available, it isn't aborted or committed.
*
* @param txn the new thread local transaction.
*/
public static void setThreadLocalTxn(Txn txn) {
threadlocal.get().txn = txn;
}
//we don't want any instances.
private TxnThreadLocal() {
}
public static class Container {
public Txn txn;
public Object txPool;
}
}