Update stm scaladoc

This commit is contained in:
Peter Vlugter 2010-11-07 16:07:29 +13:00
parent 9f725b2742
commit 9a0b442704
7 changed files with 186 additions and 119 deletions

View file

@ -14,18 +14,20 @@ object Transactor {
}
/**
* Transactor - an actor with built-in support for coordinated transactions.
* <p/>
* 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.
* <p/>
* Simple transactors will just implement the 'atomically' method, similar to
* the actor 'receive' method, but which runs within a coordinated transaction.
* <p/>
* Transactors can also accept explicitly sent `Coordinated` messages.
* <br/><br/>
*
* 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:
* <p/>
* <pre>
*
* {{{
* class Counter extends Transactor {
* val count = Ref(0)
*
@ -33,18 +35,19 @@ object Transactor {
* case Increment => count alter (_ + 1)
* }
* }
* </pre>
* <p/>
* 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.
* <p/>
* Example of using coordinate:
* <p/>
* <pre>
* }}}
* <br/>
*
* 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)
* }
* }
* </pre>
* <p/>
* Using 'include' to include more than one transactor:
* <p/>
* <pre>
* }}}
* <br/>
*
* Using `include` to include more than one transactor:
*
* {{{
* override def coordinate = {
* case Message => include(actor1, actor2, actor3)
* }
* </pre>
* <p/>
* Using 'sendTo' to coordinate transactions but send on a different message
* }}}
* <br/>
*
* Using `sendTo` to coordinate transactions but send on a different message
* than the one that was received:
* <p/>
* <pre>
*
* {{{
* override def coordinate = {
* case Message => sendTo(someActor -> SomeOtherMessage)
* case SomeMessage => sendTo(actor1 -> Message1, actor2 -> Message2)
* }
* </pre>
* <p/>
* }}}
* <br/>
*
* 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.
* <p/>
* 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.
* <p/>
* @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

View file

@ -6,10 +6,10 @@ package akka.stm
/**
* Java-friendly atomic blocks.
* <p/>
* Example usage (in Java):
* <p/>
* <pre>
*
* Example usage ''(Java)''
*
* {{{
* import akka.stm.*;
*
* final Ref<Integer> ref = new Ref<Integer>(0);
@ -31,7 +31,7 @@ package akka.stm
* return ref.get();
* }
* }.execute();
* </pre>
* }}}
*/
abstract class Atomic[T](factory: TransactionFactory) {
def this() = this(DefaultTransactionFactory)

View file

@ -21,52 +21,62 @@ object Coordinated {
}
/**
* Coordinated transactions across actors.
* <p/>
* 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:
* <p/>
* <pre>
* `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.
* <br/><br/>
*
* To start a new coordinated transaction set that you will also participate in just create
* a `Coordinated` object:
*
* {{{
* val coordinated = Coordinated()
* </pre>
* <p/>
* 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.
* <p/>
* 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:
* <p/>
* <pre>
* }}}
* <br/>
*
* 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)
* </pre>
* <p/>
* To receive a coordinated message in an actor:
* <p/>
* <pre>
* }}}
* <br/>
*
* To receive a coordinated message in an actor simply match it in a case statement:
*
* {{{
* def receive = {
* case coordinated @ Coordinated(Message) => ...
* }
* </pre>
* <p/>
* }}}
* <br/>
*
* 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.
* <p/>
* <pre>
* involved by one and create a new `Coordinated` object to be sent.
*
* {{{
* actor ! coordinated(Message)
* </pre>
* <p/>
* To enter a coordinated transaction use the atomic method of the Coordinated object:
* <p/>
* <pre>
* }}}
* <br/>
*
* 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 ...
* }
* </pre>
* <p/>
* }}}
*
* 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) = {

View file

@ -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.
* <br/><br/>
*
* <p/>
* Creating a Ref (in Scala):
* <p/>
* <pre>
* 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]
* </pre>
* }}}
* <br/>
*
* <p/>
* Creating a Ref (in Java):
* <p/>
* <pre>
* 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<Integer> ref = new Ref<Integer>();
* </pre>
* }}}
*/
class Ref[T](initialValue: T) extends BasicRef[T](initialValue) with Transactional {
self =>

View file

@ -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.
* <p/>
* If you need to coordinate transactions across actors @see Coordinated.
* <p/>
* Example of atomic transaction management using the atomic block (in Scala).
* <p/>
* <pre>
* import akka.stm._
* Defines the atomic block for local transactions. Automatically imported with:
*
* {{{
* import akka.stm._
* }}}
* <br/>
*
* If you need to coordinate transactions across actors see [[akka.stm.Coordinated]].
* <br/><br/>
*
* Example of using the atomic block ''(Scala)''
*
* {{{
* atomic {
* // do something within a transaction
* }
* </pre>
* <p/>
* @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._
* }}}
* <br/>
*
* 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
* }
* }
* }}}
* <br/>
*
* 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
* }
* }
* }}}
* <br/>
*
* STM retry for blocking transactions (use within an atomic).
* Can be used to wait for a condition.
*
* {{{
* atomic {
* if (!someCondition) retry
* // ...
* }
* }}}
* <br/>
*
* Use either-orElse to combine two blocking transactions.
*
* {{{
* atomic {
* either {
* // ...
* } orElse {
* // ...
* }
* }
* }}}
* <br/>
*/
trait StmUtil {
/**
@ -67,14 +126,6 @@ trait StmUtil {
/**
* Use either-orElse to combine two blocking transactions.
* Usage:
* <pre>
* either {
* ...
* } orElse {
* ...
* }
* </pre>
*/
def either[T](firstBody: => T) = new {
def orElse(secondBody: => T) = new OrElseTemplate[T] {

View file

@ -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 {

View file

@ -149,23 +149,23 @@ object TransactionFactory {
/**
* Wrapper for transaction config, factory, and boilerplate. Used by atomic.
* Can be passed to atomic implicitly or explicitly.
* <p/>
* <pre>
*
* {{{
* implicit val txFactory = TransactionFactory(readonly = true)
* ...
* atomic {
* // do something within a readonly transaction
* }
* </pre>
* <p/>
* }}}
*
* 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.
* <p/>
*
* 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,