package org.multiverse.api;

import org.multiverse.*;
import org.multiverse.api.callables.*;
import java.util.concurrent.Callable;

/**
 * An TxnExecutor is responsible for executing an atomic callable. It is created by the {@link TxnFactoryBuilder}
 * and this gives the {@link Stm} the opportunity to return different implementations based on the
 * {@link TxnFactory} 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.
 *
 * <p>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.
 *
 * <h3>Transactional Callables</h3>
 *
 * <p>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 {@link org.multiverse.api.callables.TxnVoidCallable} that prevents
 * returning a value if none is needed. And last but not least there also is the general purpose
 * {@link org.multiverse.api.callables.TxnCallable} that returns an Object reference.
 *
 * <h3>Automatic retries</h3>
 *
 * <p>If a transaction encounters a {@link org.multiverse.api.exceptions.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 a {@link BackoffPolicy} is used, to prevent transactions from causing more contention
 * if there already is contention. For configuring the maximum number of retries, see the {@link TxnFactoryBuilder#setMaxRetries}
 * and for configuring the BackoffPolicy, see {@link TxnFactoryBuilder#setBackoffPolicy}.
 *
 * <p>It is very important to realize that automatically retrying a transaction on a conflict is something else than the
 * {@link Txn#retry}. The latter is really a blocking operation that only retries when there is a reason to retry.
 *
 * <h3>Configuration</h3>
 *
 * <p>The {@link TxnExecutor} can be configured through the {@link TxnFactoryBuilder}. So see that for more details since
 * there are tons of settings to choose from.
 *
 * <h3>Thread-safety</h3>
 *
 * <p>TxnExecutors are threadsafe. The TxnExecutor is designed to be shared between threads.
 *
 * <h3>Reuse</h3>
 *
 * <p>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).
 *
 * <p>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.
 *
 * <p>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.
 *
 * <h3>execute vs executeChecked</h3>
 *
 * <p>The TxnExecutor provides two different types of execute methods:
 * <ol>
 * <li>execute: it will automatically wrap the checked exception that can be thrown from an TxnCallable in a
 * {@link org.multiverse.api.exceptions.InvisibleCheckedException}. Unchecked exceptions are let through as is.
 * </li>
 * <li>execute checked: it will not do anything with thrown checked of unchecked exceptions and lets them through
 * </li>
 * </ol>
 * If an exception happens inside an TxnCallable, the Txn will be always aborted (unless it is caught by the logic
 * inside the TxnCallable). Catching the exceptions inside the callable should be done with care since an exception could
 * indicate that the system has entered an invalid state.
 *
 * <p>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
 * <a href="http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html#transaction-declarative-rolling-back}">9.5.3: Rolling back</a>
 *
 * <h3>Atomic operation composition/nesting</h3>
 *
 * <p>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 {@link TxnFactoryBuilder#setPropagationLevel} where the {@link PropagationLevel#Requires} is the default.
 *
 * <p>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.
 *
 * <p>If the transaction is committed (or aborted) manually, operations on the transaction will fail with a
 * {@link org.multiverse.api.exceptions.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, the {@link Txn#setAbortOnly} can be called, to make sure that the
 * transaction is not going to commit (or prepare) successfully.
 *
 * <p>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.
 */
public interface TxnExecutor extends MultiverseConstants{

   /**
    * Returns the {@link TxnFactory} that is used by this TxnExecutor to create transactions used to execute
    * transactional closures.
    *
    * @return the TxnFactory used by this TxnExecutor.
    */
    TxnFactory getTxnFactory();

#foreach($callable in $callables)
   /**
    * 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.
    *
    * @param callable the callable to execute.
#if(${callable.type} ne 'void')
    * @return the result of the execution.
#end
    * @throws NullPointerException if callable is null.
    * @throws org.multiverse.api.exceptions.InvisibleCheckedException if a checked exception is thrown by the callable.
    */
    ${callable.typeParameter} ${callable.type} execute(${callable.name}${callable.typeParameter} callable);

   /**
    * Executes the callable.
    *
    * @param callable the callable to execute.
#if(${callable.type} ne 'void')
    * @return the result of the execution.
#end
    * @throws NullPointerException if callable is null.
    * @throws Exception if the execute call fails.
    */
    ${callable.typeParameter} ${callable.type} executeChecked(${callable.name}${callable.typeParameter} callable)throws Exception;

#end
}
