<chapter xml:id="chapter-deferred-and-compensating-tasks">

    <title>Transaction (in progress)</title>

    <sect1>
        <title>Introduction</title>
        <para>
              This chapter contains many of the txn config options.
        </para>
    </sect1>

    <sect1>
        <title>Customizing a txn</title>
        <para>
            Transactions can be configured by creating a custom AtomicBlock, e.g.
            <programlisting language="java">

    import org.multiverse.api.*;
    import org.multiverse.api.refs.*;
    import static org.multiverse.api.StmUtils.*;
    import static org.multiverse.api.GlobalStmInstance.*

    public class Account{
        private final static AtomicBlock transferBlock = getGlobalStmInstance()
            .newTransactionFactoryBuilder()
            .newAtomicBlock();

        private final IntRef amount = newTxnInteger(0);

        public void transfer(final int a){
            transferBlock.execute(new AtomicVoidClosure()){
                public void execute(Transaction tx){
                    amount.increment(tx, a);
                }
            });
        }

        ...
    }
    </programlisting>
            By configuring the TransactionFactoryBuilder, you can control the behavior of the Transaction.
            AtomicBlocks are designed to be threadsafe and not form a contention point. It is easiest to
            store them in a final static field so that they can be shared over multiple threads and objects.
        </para>

        <para>
            It is important to realize that a TransactionFactoryBuilder is immutable, so if a config
            method is called, a new instance is returned. This instance should be used to do the following
            config step or by used for creating the AtomicBlock.
        </para>
    </sect1>

    <sect1>
        <title>Familyname</title>
        <para>
            For debugging purposes, the txn family name can be set. It is best to choose a name that makes
            it easy to find the code that is executed by the AtomicBlock, e.g.:
            <programlisting language="java">

                import org.multiverse.api.*;
                import org.multiverse.api.refs.*;
                import static org.multiverse.api.StmUtils.*;
                import static org.multiverse.api.GlobalStmInstance.*

                public class Account{
                    private final static AtomicBlock transferBlock = getGlobalStmInstance()
                        .newTransactionFactoryBuilder()
                        .setFamilyName("Account.transfer")
                        .newAtomicBlock();

                    private final IntRef amount = newTxnInteger(0);

                    public void transfer(final int a){
                        transferBlock.execute(new AtomicVoidClosure()){
                            public void execute(Transaction tx){
                                amount.increment(tx, a);
                            }
                        });
                    }

                    ...
                }
                </programlisting>
            If no value is set, some generated value (which most likely is not very usable) is used.
        </para>
    </sect1>

    <sect1>
        <title>Readonly</title>
        <para>
            By default a txn is configured as an update txn; so it is allowed to make changes to transactional
            references. This behavior can be changed by setting the readonly property of the Transaction, e.g.:
            <programlisting language="java">

    import org.multiverse.api.*;
    import org.multiverse.api.refs.*;
    import static org.multiverse.api.StmUtils.*;
    import static org.multiverse.api.GlobalStmInstance.*

    public class Account{
        private final static AtomicBlock transferBlock = getGlobalStmInstance()
            .newTransactionFactoryBuilder()
            .setReadonly(true)
            .newAtomicBlock();

        private final IntRef amount = newTxnInteger(0);

        public void transfer(final int a){
            transferBlock.execute(new AtomicVoidClosure()){
                public void execute(Transaction tx){
                    amount.increment(tx, a);
                }
            });
        }

        ...
    }
    </programlisting>
            In this case a org.multiverse.api.exceptions.ReadonlyException is thrown when the amount.increment is called. In case of the GammaStm
            it doesn't make much of a performance impact if a txn is configured as readonly.
        </para>

    </sect1>

    <sect1>
        <title>Maximum retries</title>
        <para>
            An AtomicBlock automatically is going to be retried until one of the following things happens:
            <itemizedlist>
                <listitem>
                    It completes.
                </listitem>
                <listitem>
                    An exception (a Throwable) is thrown during the execution of the atomic block.
                </listitem>
                <listitem>
                    The txn has executed too many times and a org.multiverse.api.exceptions.TooManyRetriesException
                    is thrown.
                </listitem>
                <listitem>
                    The txn is going to block (see the retry functionality for more information how this works).
                </listitem>
            </itemizedlist>
            The default for the maximum retries is 1000 and can be configured through the TransactionFactoryBuilder:
              <programlisting language="java">

    import org.multiverse.api.*;
    import org.multiverse.api.refs.*;
    import static org.multiverse.api.StmUtils.*;
    import static org.multiverse.api.GlobalStmInstance.*

    public class Account{
        private final static AtomicBlock transferBlock = getGlobalStmInstance()
            .newTransactionFactoryBuilder()
            .setMaximumRetries(200)
            .newAtomicBlock();

        private final IntRef amount = newTxnInteger(0);

        public void transfer(final int a){
            transferBlock.execute(new AtomicVoidClosure()){
                public void execute(Transaction tx){
                    amount.increment(tx, a);
                }
            });
        }

        ...
    }
    </programlisting>
            In this example the maximum number of retries is configured to be 200. Setting the value very low, could lead to txns
            not being able to complete. If the speculative config mechanism is enabled for an AtomicBlock (defaults to true), it
            can happen that the first few times an AtomicBlock is used, some ControlFlowErrors (org.multiverse.api.exceptions.SpeculativeConfigurationError)
            are thrown even though there is no contention. If the value is set to a very high value, the system could suffer more from
            livelock problems. The consequence of a livelock is that the system is doing work (so consuming cpu and memory), but isn't making
            any progress.
        </para>
    </sect1>

    <sect1>
        <title>Don't rely on Transaction instance</title>
        <para>
            To prevent causing a lot of unwanted gc overhead, txn instances are reused. This means that the same txn instance
            could be used for different executions of the same AtomicBlock, but it also could be reused to execute a completely different
            AtomicBlock. That is why it is important to realize that Transaction instances should not be stored.
        </para>
    </sect1>
</chapter>