diff --git a/akka-stm/src/main/scala/actor/Transactor.scala b/akka-stm/src/main/scala/actor/Transactor.scala index 3baf4d81c0..a23db1de7a 100644 --- a/akka-stm/src/main/scala/actor/Transactor.scala +++ b/akka-stm/src/main/scala/actor/Transactor.scala @@ -14,18 +14,20 @@ object Transactor { } /** - * Transactor - an actor with built-in support for coordinated transactions. - *

- * Transactors implement the general pattern for using Coordinated where first - * any coordination messages are sent to other transactors, then the coordinated + * An actor with built-in support for coordinated transactions. + * + * Transactors implement the general pattern for using [[akka.stm.Coordinated]] where + * first any coordination messages are sent to other transactors, then the coordinated * transaction is entered. - *

- * Simple transactors will just implement the 'atomically' method, similar to - * the actor 'receive' method, but which runs within a coordinated transaction. - *

+ * Transactors can also accept explicitly sent `Coordinated` messages. + *

+ * + * Simple transactors will just implement the `atomically` method which similar to + * the actor `receive` method but runs within a coordinated transaction. + * * Example of a simple transactor that will join a coordinated transaction: - *

- *

+ *
+ * {{{
  * class Counter extends Transactor {
  *   val count = Ref(0)
  *
@@ -33,18 +35,19 @@ object Transactor {
  *     case Increment => count alter (_ + 1)
  *   }
  * }
- * 
- *

- * To coordinate with other transactors override the 'coordinate' method. - * The 'coordinate' method matches messages to a set of 'SendTo' objects, - * a pair of ActorRef and Message. You can use the 'include' and 'sendTo' methods - * to easily coordinate with other transactors. The 'include' method will send - * on the same message that was received to other transactors. The 'sendTo' method - * allows you to specify both the actor to send to, and message to send. - *

- * Example of using coordinate: - *

- *

+ * }}}
+ * 
+ * + * To coordinate with other transactors override the `coordinate` method. + * The `coordinate` method maps a message to a set + * of [[akka.actor.Transactor.SendTo]] objects, pairs of `ActorRef` and a message. + * You can use the `include` and `sendTo` methods to easily coordinate with other transactors. + * The `include` method will send on the same message that was received to other transactors. + * The `sendTo` method allows you to specify both the actor to send to, and message to send. + * + * Example of using coordinating an increment: + * + * {{{ * class FriendlyCounter(friend: ActorRef) extends Transactor { * val count = Ref(0) * @@ -56,37 +59,40 @@ object Transactor { * case Increment => count alter (_ + 1) * } * } - *
- *

- * Using 'include' to include more than one transactor: - *

- *

+ * }}}
+ * 
+ * + * Using `include` to include more than one transactor: + * + * {{{ * override def coordinate = { * case Message => include(actor1, actor2, actor3) * } - *
- *

- * Using 'sendTo' to coordinate transactions but send on a different message + * }}} + *
+ * + * Using `sendTo` to coordinate transactions but send on a different message * than the one that was received: - *

- *

+ *
+ * {{{
  * override def coordinate = {
  *   case Message => sendTo(someActor -> SomeOtherMessage)
  *   case SomeMessage => sendTo(actor1 -> Message1, actor2 -> Message2)
  * }
- * 
- *

+ * }}} + *
+ * * To exeucte directly before or after the coordinated transaction, override - * the 'before' and 'after' methods. These methods also expect partial functions + * the `before` and `after` methods. These methods also expect partial functions * like the receive method. They do not execute within the transaction. - *

- * To completely bypass coordinated transactions override the normally method. - * Any message matched by 'normally' will not be matched by the other methods, + * + * To completely bypass coordinated transactions override the `normally` method. + * Any message matched by `normally` will not be matched by the other methods, * and will not be involved in coordinated transactions. In this method you * can implement normal actor behavior, or use the normal STM atomic for * local transactions. - *

- * @see Coordinated for more information about the underlying mechanism. + * + * @see [[akka.stm.Coordinated]] for more information about the underlying mechanism */ trait Transactor extends Actor { import Transactor.SendTo diff --git a/akka-stm/src/main/scala/stm/Atomic.scala b/akka-stm/src/main/scala/stm/Atomic.scala index 05531ed4af..00092019a8 100644 --- a/akka-stm/src/main/scala/stm/Atomic.scala +++ b/akka-stm/src/main/scala/stm/Atomic.scala @@ -6,10 +6,10 @@ package akka.stm /** * Java-friendly atomic blocks. - *

- * Example usage (in Java): - *

- *

+ *
+ * Example usage ''(Java)''
+ *
+ * {{{
  * import akka.stm.*;
  *
  * final Ref ref = new Ref(0);
@@ -31,7 +31,7 @@ package akka.stm
  *         return ref.get();
  *     }
  * }.execute();
- * 
+ * }}} */ abstract class Atomic[T](factory: TransactionFactory) { def this() = this(DefaultTransactionFactory) diff --git a/akka-stm/src/main/scala/stm/Coordinated.scala b/akka-stm/src/main/scala/stm/Coordinated.scala index f025be3053..a722dc3636 100644 --- a/akka-stm/src/main/scala/stm/Coordinated.scala +++ b/akka-stm/src/main/scala/stm/Coordinated.scala @@ -21,52 +21,62 @@ object Coordinated { } /** - * Coordinated transactions across actors. - *

- * Coordinated is a wrapper for any message that adds a CountDownCommitBarrier to - * coordinate transactions across actors or threads. To start a new coordinated transaction - * that you will also participate in, use: - *

- *

+ * `Coordinated` is a message wrapper that adds a `CountDownCommitBarrier` for explicitly
+ * coordinating transactions across actors or threads.
+ *
+ * Creating a `Coordinated` will create a count down barrier with initially one member.
+ * For each member in the coordination set a transaction is expected to be created using
+ * the coordinated atomic method. The number of included parties must match the number of
+ * transactions, otherwise a successful transaction cannot be coordinated.
+ * 

+ * + * To start a new coordinated transaction set that you will also participate in just create + * a `Coordinated` object: + * + * {{{ * val coordinated = Coordinated() - *
- *

- * Creating a Coordinated object will create a count down barrier with one member. For each - * member in the coordination set a coordinated transaction is expected to be created. - *

- * To start a coordinated transaction in another actor that you won't participate in yourself - * can send the Coordinated message directly and the recipient is the first member of the - * coordinating actors: - *

- *

+ * }}}
+ * 
+ * + * To start a coordinated transaction that you won't participate in yourself you can create a + * `Coordinated` object with a message and send it directly to an actor. The recipient of the message + * will be the first member of the coordination set: + * + * {{{ * actor ! Coordinated(Message) - *
- *

- * To receive a coordinated message in an actor: - *

- *

+ * }}}
+ * 
+ * + * To receive a coordinated message in an actor simply match it in a case statement: + * + * {{{ * def receive = { * case coordinated @ Coordinated(Message) => ... * } - *
- *

+ * }}} + *
+ * * To include another actor in the same coordinated transaction set that you've created or * received, use the apply method on that object. This will increment the number of parties - * involved by one. - *

- *

+ * involved by one and create a new `Coordinated` object to be sent.
+ *
+ * {{{
  * actor ! coordinated(Message)
- * 
- *

- * To enter a coordinated transaction use the atomic method of the Coordinated object: - *

- *

+ * }}}
+ * 
+ * + * To enter the coordinated transaction use the atomic method of the coordinated object: + * + * {{{ * coordinated atomic { - * // Do something in transaction that will wait for the other transactions before committing. - * // If any of the coordinated transactions fail then they all fail. + * // do something in transaction ... * } - *
- *

+ * }}} + * + * The coordinated transaction will wait for the other transactions before committing. + * If any of the coordinated transactions fail then they all fail. + * + * @see [[akka.actor.Transactor]] for an actor that implements coordinated transactions */ class Coordinated(val message: Any, barrier: CountDownCommitBarrier) { def apply(msg: Any) = { diff --git a/akka-stm/src/main/scala/stm/Ref.scala b/akka-stm/src/main/scala/stm/Ref.scala index 1bb8779b1b..3c5237388a 100644 --- a/akka-stm/src/main/scala/stm/Ref.scala +++ b/akka-stm/src/main/scala/stm/Ref.scala @@ -28,12 +28,12 @@ object Ref { * To ensure safety the value stored in a Ref should be immutable (they can also * contain refs themselves). The value referenced by a Ref can only be accessed * or swapped within a transaction. If a transaction is not available, the call will - * be executed in its own transaction (equivalent to using the Ref.atomic* methods). + * be executed in its own transaction. + *

* - *

- * Creating a Ref (in Scala): - *

- *

+ * Creating a Ref ''(Scala)''
+ *
+ * {{{
  * import akka.stm._
  *
  * // giving an initial value
@@ -41,12 +41,12 @@ object Ref {
  *
  * // specifying a type but no initial value
  * val ref = Ref[Int]
- * 
+ * }}} + *
* - *

- * Creating a Ref (in Java): - *

- *

+ * Creating a Ref ''(Java)''
+ *
+ * {{{
  * import akka.stm.*;
  *
  * // giving an initial value
@@ -54,7 +54,7 @@ object Ref {
  *
  * // specifying a type but no initial value
  * final Ref ref = new Ref();
- * 
+ * }}} */ class Ref[T](initialValue: T) extends BasicRef[T](initialValue) with Transactional { self => diff --git a/akka-stm/src/main/scala/stm/Stm.scala b/akka-stm/src/main/scala/stm/Stm.scala index f9bf1cec6a..44f639ae22 100644 --- a/akka-stm/src/main/scala/stm/Stm.scala +++ b/akka-stm/src/main/scala/stm/Stm.scala @@ -9,21 +9,26 @@ import org.multiverse.api.{Transaction => MultiverseTransaction} import org.multiverse.templates.{TransactionalCallable, OrElseTemplate} /** - * Stm trait that defines the atomic block for local transactions. - *

- * If you need to coordinate transactions across actors @see Coordinated. - *

- * Example of atomic transaction management using the atomic block (in Scala). - *

- *

- * import akka.stm._
+ * Defines the atomic block for local transactions. Automatically imported with:
  *
+ * {{{
+ * import akka.stm._
+ * }}}
+ * 
+ * + * If you need to coordinate transactions across actors see [[akka.stm.Coordinated]]. + *

+ * + * Example of using the atomic block ''(Scala)'' + * + * {{{ * atomic { * // do something within a transaction * } - *
- *

- * @see Atomic for creating atomic blocks in Java. + * }}} + * + * @see [[akka.stm.Atomic]] for creating atomic blocks in Java. + * @see [[akka.stm.StmUtil]] for useful methods to combine with `atomic` */ trait Stm { val DefaultTransactionFactory = TransactionFactory(DefaultTransactionConfig, "DefaultTransaction") @@ -42,7 +47,61 @@ trait Stm { } /** - * Stm utils for scheduling transaction lifecycle tasks and for blocking transactions. + * Stm utility methods for scheduling transaction lifecycle tasks and for blocking transactions. + * Automatically imported with: + * + * {{{ + * import akka.stm._ + * }}} + *
+ * + * Schedule a deferred task on the thread local transaction (use within an atomic). + * This is executed when the transaction commits. + * + * {{{ + * atomic { + * deferred { + * // executes when transaction successfully commits + * } + * } + * }}} + *
+ * + * Schedule a compensating task on the thread local transaction (use within an atomic). + * This is executed when the transaction aborts. + * + * {{{ + * atomic { + * compensating { + * // executes when transaction aborts + * } + * } + * }}} + *
+ * + * STM retry for blocking transactions (use within an atomic). + * Can be used to wait for a condition. + * + * {{{ + * atomic { + * if (!someCondition) retry + * // ... + * } + * }}} + *
+ * + * Use either-orElse to combine two blocking transactions. + * + * {{{ + * atomic { + * either { + * // ... + * } orElse { + * // ... + * } + * } + * }}} + *
*/ trait StmUtil { /** @@ -67,14 +126,6 @@ trait StmUtil { /** * Use either-orElse to combine two blocking transactions. - * Usage: - *

-   * either {
-   *   ...
-   * } orElse {
-   *   ...
-   * }
-   * 
*/ def either[T](firstBody: => T) = new { def orElse(secondBody: => T) = new OrElseTemplate[T] { diff --git a/akka-stm/src/main/scala/stm/Transaction.scala b/akka-stm/src/main/scala/stm/Transaction.scala index 1509bd29d8..0fa38a0ff9 100644 --- a/akka-stm/src/main/scala/stm/Transaction.scala +++ b/akka-stm/src/main/scala/stm/Transaction.scala @@ -202,7 +202,7 @@ trait Abortable { } /** - * For reflective access to the JTA module. + * Used internally for reflective access to the JTA module. * Allows JTA integration to work when akka-jta.jar is on the classpath. */ object ReflectiveJtaModule { diff --git a/akka-stm/src/main/scala/stm/TransactionFactory.scala b/akka-stm/src/main/scala/stm/TransactionFactory.scala index d348aee8a5..a6c847002b 100644 --- a/akka-stm/src/main/scala/stm/TransactionFactory.scala +++ b/akka-stm/src/main/scala/stm/TransactionFactory.scala @@ -149,23 +149,23 @@ object TransactionFactory { /** * Wrapper for transaction config, factory, and boilerplate. Used by atomic. * Can be passed to atomic implicitly or explicitly. - *

- *

+ *
+ * {{{
  * implicit val txFactory = TransactionFactory(readonly = true)
  * ...
  * atomic {
  *   // do something within a readonly transaction
  * }
- * 
- *

+ * }}} + * * Can be created at different levels as needed. For example: as an implicit object * used throughout a package, as a static implicit val within a singleton object and * imported where needed, or as an implicit val within each instance of a class. - *

+ * * If no explicit transaction factory is passed to atomic and there is no implicit * transaction factory in scope, then a default transaction factory is used. * - * @see TransactionConfig for configuration options. + * @see [[akka.stm.TransactionConfig]] for configuration options. */ class TransactionFactory( val config: TransactionConfig = DefaultTransactionConfig,