Interface TxnExecutor
-
- All Superinterfaces:
MultiverseConstants
- All Known Subinterfaces:
GammaTxnExecutor
- All Known Implementing Classes:
AbstractGammaTxnExecutor
,FatGammaTxnExecutor
,LeanGammaTxnExecutor
public interface TxnExecutor extends MultiverseConstants
An TxnExecutor is responsible for executing an atomic callable. It is created by theTxnFactoryBuilder
and this gives theStm
the opportunity to return different implementations based on theTxnFactory
configuration. And it also gives the opportunity to provide Stm specific transaction handling mechanism. In the Multiverse 0.6 design and before, a single TransactionTemplate implementation was used that should be used by all Stm's, but that design is limiting.Another useful features of this design is that for certain primitives it doesn't require any form of boxing. It also provides an execute for a transactional Callables which doesn't force a developer to return something when nothing needs to be returned.
Transactional Callables
The TxnCallable is the functionality that needs to be executed isolated, consistent and atomically. There are different tastes of TxnCallables but essentially the only difference is the return type. There are primitive closures that prevent unwanted autoboxing and there also is a
TxnVoidCallable
that prevents returning a value if none is needed. And last but not least there also is the general purposeTxnCallable
that returns an Object reference.Automatic retries
If a transaction encounters a
ReadWriteConflict
or a { @link org.multiverse.api.exceptions.SpeculativeConfigurationError} it will automatically retry the the TxnCallable until either the next execution completes or the maximum number of retries has been reached. To prevent contention, also aBackoffPolicy
is used, to prevent transactions from causing more contention if there already is contention. For configuring the maximum number of retries, see theTxnFactoryBuilder.setMaxRetries(int)
and for configuring the BackoffPolicy, seeTxnFactoryBuilder.setBackoffPolicy(org.multiverse.api.BackoffPolicy)
.It is very important to realize that automatically retrying a transaction on a conflict is something else than the
Txn.retry()
. The latter is really a blocking operation that only retries when there is a reason to retry.Configuration
The
TxnExecutor
can be configured through theTxnFactoryBuilder
. So see that for more details since there are tons of settings to choose from.Thread-safety
TxnExecutors are threadsafe. The TxnExecutor is designed to be shared between threads.
Reuse
TxnExecutor can be expensive to create and should be reused. Creating an TxnExecutor can lead to a lot of objects being created and not reusing them leads to a lot of object waste (so put a lot of pressure on the garbage collector).
It is best to create the TxnExecutor in the beginning and store it in a (static) field and reuse it. It is very unlikely that an TxnExecutor is going to be a contention point itself since in almost all cases only volatile reads are required and for the rest it will be mostly immutable.
This is even more important when speculative transactions are used because speculative transactions learn on the TxnExecutor level. So if the TxnExecutor is not reused, the speculative mechanism will not have full effect.
execute vs executeChecked
The TxnExecutor provides two different types of execute methods:
- execute: it will automatically wrap the checked exception that can be thrown from an TxnCallable in a
InvisibleCheckedException
. Unchecked exceptions are let through as is. - execute checked: it will not do anything with thrown checked of unchecked exceptions and lets them through
In the future also a rollback-for functionality will be added to let a transaction commit, even though certain types of exceptions have occurred. This is similar with the Spring framework where this can be configured through the 9.5.3: Rolling back
Atomic operation composition/nesting
Using traditional concurrency control, composing locking operations is extremely hard because it is very likely that it is impossible without knowing implementation details of the structure, or because of deadlocks. With Stm transactional operations can be composed and controlling how the system should react on existing or missing transactions can be controlled through the
TxnFactoryBuilder.setPropagationLevel(org.multiverse.api.PropagationLevel)
where thePropagationLevel.Requires
is the default.Normally the system uses a flat-nesting approach, so only the outermost commit is going to lead to a commit. But if a commit is done before the outer most TxnExecutor completes, that commit is leading.
If the transaction is committed (or aborted) manually, operations on the transaction will fail with a
IllegalTxnStateException
exception. So in most cases you want to let the TxnExecutor be in charge of committing/aborting. If also allows for a correct flattening of nested transactions. If a transaction should not commit, but you don't want to disrupt the code, theTxn.setAbortOnly()
can be called, to make sure that the transaction is not going to commit (or prepare) successfully.The configuration of the outer most TxnExecutor is leading. So if the outer TxnExecutor is not readonly and the inner is, the transaction will not be readonly. If this becomes an issue (e.g. for security) it can be implemented that some form of runtime verification is done to prevent this behavior.
- Author:
- Peter Veentjer.
-
-
Field Summary
-
Fields inherited from interface org.multiverse.MultiverseConstants
LOCKMODE_EXCLUSIVE, LOCKMODE_NONE, LOCKMODE_READ, LOCKMODE_WRITE, SHAKE_BUGS, SPIN_YIELD, TRACING_ENABLED
-
-
Method Summary
All Methods Instance Methods Abstract Methods Modifier and Type Method Description boolean
execute(TxnBooleanCallable callable)
Executes the transactional callable.<E> E
execute(TxnCallable<E> callable)
Executes the transactional callable.double
execute(TxnDoubleCallable callable)
Executes the transactional callable.int
execute(TxnIntCallable callable)
Executes the transactional callable.long
execute(TxnLongCallable callable)
Executes the transactional callable.void
execute(TxnVoidCallable callable)
Executes the transactional callable.boolean
executeChecked(TxnBooleanCallable callable)
Executes the callable.<E> E
executeChecked(TxnCallable<E> callable)
Executes the callable.double
executeChecked(TxnDoubleCallable callable)
Executes the callable.int
executeChecked(TxnIntCallable callable)
Executes the callable.long
executeChecked(TxnLongCallable callable)
Executes the callable.void
executeChecked(TxnVoidCallable callable)
Executes the callable.TxnFactory
getTxnFactory()
Returns theTxnFactory
that is used by this TxnExecutor to create transactions used to execute transactional closures.
-
-
-
Method Detail
-
getTxnFactory
TxnFactory getTxnFactory()
Returns theTxnFactory
that is used by this TxnExecutor to create transactions used to execute transactional closures.- Returns:
- the TxnFactory used by this TxnExecutor.
-
execute
<E> E execute(TxnCallable<E> callable)
Executes the transactional callable. If in the execution of the callable a checked exception is thrown, the exception is wrapped in a InvisibleCheckedException. The original exception can be retrieved by calling the getCause method.- Parameters:
callable
- the callable to execute.- Returns:
- the result of the execution.
- Throws:
NullPointerException
- if callable is null.InvisibleCheckedException
- if a checked exception is thrown by the callable.
-
executeChecked
<E> E executeChecked(TxnCallable<E> callable) throws Exception
Executes the callable.- Parameters:
callable
- the callable to execute.- Returns:
- the result of the execution.
- Throws:
NullPointerException
- if callable is null.Exception
- if the execute call fails.
-
execute
int execute(TxnIntCallable callable)
Executes the transactional callable. If in the execution of the callable a checked exception is thrown, the exception is wrapped in a InvisibleCheckedException. The original exception can be retrieved by calling the getCause method.- Parameters:
callable
- the callable to execute.- Returns:
- the result of the execution.
- Throws:
NullPointerException
- if callable is null.InvisibleCheckedException
- if a checked exception is thrown by the callable.
-
executeChecked
int executeChecked(TxnIntCallable callable) throws Exception
Executes the callable.- Parameters:
callable
- the callable to execute.- Returns:
- the result of the execution.
- Throws:
NullPointerException
- if callable is null.Exception
- if the execute call fails.
-
execute
long execute(TxnLongCallable callable)
Executes the transactional callable. If in the execution of the callable a checked exception is thrown, the exception is wrapped in a InvisibleCheckedException. The original exception can be retrieved by calling the getCause method.- Parameters:
callable
- the callable to execute.- Returns:
- the result of the execution.
- Throws:
NullPointerException
- if callable is null.InvisibleCheckedException
- if a checked exception is thrown by the callable.
-
executeChecked
long executeChecked(TxnLongCallable callable) throws Exception
Executes the callable.- Parameters:
callable
- the callable to execute.- Returns:
- the result of the execution.
- Throws:
NullPointerException
- if callable is null.Exception
- if the execute call fails.
-
execute
double execute(TxnDoubleCallable callable)
Executes the transactional callable. If in the execution of the callable a checked exception is thrown, the exception is wrapped in a InvisibleCheckedException. The original exception can be retrieved by calling the getCause method.- Parameters:
callable
- the callable to execute.- Returns:
- the result of the execution.
- Throws:
NullPointerException
- if callable is null.InvisibleCheckedException
- if a checked exception is thrown by the callable.
-
executeChecked
double executeChecked(TxnDoubleCallable callable) throws Exception
Executes the callable.- Parameters:
callable
- the callable to execute.- Returns:
- the result of the execution.
- Throws:
NullPointerException
- if callable is null.Exception
- if the execute call fails.
-
execute
boolean execute(TxnBooleanCallable callable)
Executes the transactional callable. If in the execution of the callable a checked exception is thrown, the exception is wrapped in a InvisibleCheckedException. The original exception can be retrieved by calling the getCause method.- Parameters:
callable
- the callable to execute.- Returns:
- the result of the execution.
- Throws:
NullPointerException
- if callable is null.InvisibleCheckedException
- if a checked exception is thrown by the callable.
-
executeChecked
boolean executeChecked(TxnBooleanCallable callable) throws Exception
Executes the callable.- Parameters:
callable
- the callable to execute.- Returns:
- the result of the execution.
- Throws:
NullPointerException
- if callable is null.Exception
- if the execute call fails.
-
execute
void execute(TxnVoidCallable callable)
Executes the transactional callable. If in the execution of the callable a checked exception is thrown, the exception is wrapped in a InvisibleCheckedException. The original exception can be retrieved by calling the getCause method.- Parameters:
callable
- the callable to execute.- Throws:
NullPointerException
- if callable is null.InvisibleCheckedException
- if a checked exception is thrown by the callable.
-
executeChecked
void executeChecked(TxnVoidCallable callable) throws Exception
Executes the callable.- Parameters:
callable
- the callable to execute.- Throws:
NullPointerException
- if callable is null.Exception
- if the execute call fails.
-
-