Added some documentation for stm

This commit is contained in:
Peter Vlugter 2010-06-18 17:13:10 +12:00
parent 91f3c83ba1
commit f3335ea11a
4 changed files with 95 additions and 56 deletions

View file

@ -26,48 +26,12 @@ class StmConfigurationException(message: String) extends RuntimeException(messag
object Transaction { object Transaction {
val idFactory = new AtomicLong(-1L) val idFactory = new AtomicLong(-1L)
/** @deprecated("Use the se.scalablesolutions.akka.stm.local package object instead.")
* Module for "local" transaction management, local in the context of threads.
* You should only use these if you do <b>not</b> need to have one transaction span
* multiple threads (or Actors).
* <p/>
* Example of atomic transaction management using the atomic block.
* <p/>
* <pre>
* import se.scalablesolutions.akka.stm.Transaction.Local._
*
* atomic {
* .. // do something within a transaction
* }
* </pre>
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
@deprecated("Use the akka.stm.local package object instead.")
object Local extends LocalStm object Local extends LocalStm
/** @deprecated("Use the se.scalablesolutions.akka.stm.global package object instead.")
* Module for "global" transaction management, global in the context of multiple threads.
* You have to use these if you do need to have one transaction span multiple threads (or Actors).
* <p/>
* Example of atomic transaction management using the atomic block.
* <p/>:
* <pre>
* import se.scalablesolutions.akka.stm.Transaction.Global._
*
* atomic {
* .. // do something within a transaction
* }
* </pre>
*
* @author <a href="http://jonasboner.com">Jonas Bon&#233;r</a>
*/
@deprecated("Use the akka.stm.global package object instead.")
object Global extends GlobalStm object Global extends GlobalStm
/**
* TODO: document
*/
object Util extends StmUtil object Util extends StmUtil
/** /**

View file

@ -13,7 +13,7 @@ import org.multiverse.templates.TransactionBoilerplate
import org.multiverse.api.TraceLevel import org.multiverse.api.TraceLevel
/** /**
* For configuring multiverse transactions. * For configuring multiverse transactions. See TransactionConfig class for options.
*/ */
object TransactionConfig { object TransactionConfig {
val FAMILY_NAME = "DefaultTransaction" val FAMILY_NAME = "DefaultTransaction"
@ -57,6 +57,19 @@ object TransactionConfig {
/** /**
* For configuring multiverse transactions. * For configuring multiverse transactions.
*
* @param familyName Family name for transactions. Useful for debugging.
* @param readonly Sets transaction as readonly. Readonly transactions are cheaper.
* @param maxRetries The maximum number of times a transaction will retry.
* @param timeout The maximum time a transaction will block for.
* @param trackReads Whether all reads should be tracked. Needed for blocking operations.
* @param writeSkew Whether writeskew is allowed. Disable with care.
* @param explicitRetries Whether explicit retries are allowed.
* @param interruptible Whether a blocking transaction can be interrupted.
* @param speculative Whether speculative configuration should be enabled.
* @param quickRelease Whether locks should be released as quickly as possible (before whole commit).
* @param traceLevel Transaction trace level.
* @param hooks Whether hooks for persistence modules and JTA should be added to the transaction.
*/ */
class TransactionConfig(val familyName: String = TransactionConfig.FAMILY_NAME, class TransactionConfig(val familyName: String = TransactionConfig.FAMILY_NAME,
val readonly: Boolean = TransactionConfig.READONLY, val readonly: Boolean = TransactionConfig.READONLY,
@ -75,6 +88,24 @@ object DefaultTransactionConfig extends TransactionConfig
/** /**
* Wrapper for transaction config, factory, and boilerplate. Used by atomic. * 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/>
* See TransactionConfig for configuration options.
* <p/>
* If no explicit transactin factory is passed to atomic and there is no implicit
* transaction factory in scope, then a default transaction factory is used.
*/ */
object TransactionFactory { object TransactionFactory {
def apply(config: TransactionConfig) = new TransactionFactory(config) def apply(config: TransactionConfig) = new TransactionFactory(config)

View file

@ -8,7 +8,7 @@ import se.scalablesolutions.akka.util.Logging
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
import org.multiverse.api.StmUtils import org.multiverse.api.{StmUtils => MultiverseStmUtils}
import org.multiverse.api.ThreadLocalTransaction._ import org.multiverse.api.ThreadLocalTransaction._
import org.multiverse.api.{Transaction => MultiverseTransaction} import org.multiverse.api.{Transaction => MultiverseTransaction}
import org.multiverse.commitbarriers.CountDownCommitBarrier import org.multiverse.commitbarriers.CountDownCommitBarrier
@ -91,6 +91,21 @@ trait TransactionManagement {
} }
} }
/**
* Local transaction management, local in the context of threads.
* Use this if you do <b>not</b> need to have one transaction span
* multiple threads (or Actors).
* <p/>
* Example of atomic transaction management using the atomic block.
* <p/>
* <pre>
* import se.scalablesolutions.akka.stm.local._
*
* atomic {
* // do something within a transaction
* }
* </pre>
*/
class LocalStm extends TransactionManagement with Logging { class LocalStm extends TransactionManagement with Logging {
val DefaultLocalTransactionConfig = TransactionConfig() val DefaultLocalTransactionConfig = TransactionConfig()
@ -108,6 +123,20 @@ class LocalStm extends TransactionManagement with Logging {
} }
} }
/**
* Global transaction management, global in the context of multiple threads.
* You this if you need to have one transaction span multiple threads (or Actors).
* <p/>
* Example of atomic transaction management using the atomic block:
* <p/>
* <pre>
* import se.scalablesolutions.akka.stm.global._
*
* atomic {
* // do something within a transaction
* }
* </pre>
*/
class GlobalStm extends TransactionManagement with Logging { class GlobalStm extends TransactionManagement with Logging {
val DefaultGlobalTransactionConfig = TransactionConfig() val DefaultGlobalTransactionConfig = TransactionConfig()
@ -133,13 +162,27 @@ class GlobalStm extends TransactionManagement with Logging {
} }
trait StmUtil { trait StmUtil {
/**
* Schedule a deferred task on the thread local transaction (use within an atomic).
* This is executed when the transaction commits.
*/
def deferred[T](body: => T): Unit = MultiverseStmUtils.scheduleDeferredTask(new Runnable { def run = body })
def deferred[T](body: => T): Unit = StmUtils.scheduleDeferredTask(new Runnable { def run = body }) /**
* Schedule a compensating task on the thread local transaction (use within an atomic).
* This is executed when the transaction aborts.
*/
def compensating[T](body: => T): Unit = MultiverseStmUtils.scheduleCompensatingTask(new Runnable { def run = body })
def compensating[T](body: => T): Unit = StmUtils.scheduleCompensatingTask(new Runnable { def run = body }) /**
* STM retry. Use within an atomic.
def retry = StmUtils.retry * Blocks the current transaction. Can be used to wait for a condition.
*/
def retry = MultiverseStmUtils.retry
/**
* Use either-orElse to combine two blocking transactions.
*/
def either[T](firstBody: => T) = new { def either[T](firstBody: => T) = new {
def orElse(secondBody: => T) = new OrElseTemplate[T] { def orElse(secondBody: => T) = new OrElseTemplate[T] {
def either(mtx: MultiverseTransaction) = firstBody def either(mtx: MultiverseTransaction) = firstBody
@ -148,14 +191,4 @@ trait StmUtil {
} }
} }
trait StmCommon {
type TransactionConfig = se.scalablesolutions.akka.stm.TransactionConfig
val TransactionConfig = se.scalablesolutions.akka.stm.TransactionConfig
type TransactionFactory = se.scalablesolutions.akka.stm.TransactionFactory
val TransactionFactory = se.scalablesolutions.akka.stm.TransactionFactory
type Ref[T] = se.scalablesolutions.akka.stm.Ref[T]
val Ref = se.scalablesolutions.akka.stm.Ref
}

View file

@ -5,15 +5,26 @@
package se.scalablesolutions.akka.stm package se.scalablesolutions.akka.stm
/** /**
* For importing 'local' stm. * For importing 'local' STM.
*/ */
package object local extends LocalStm with StmUtil with StmCommon package object local extends LocalStm with StmUtil with StmCommon
/** /**
* For importing 'global' stm. * For importing 'global' STM.
*/ */
package object global extends GlobalStm with StmUtil with StmCommon package object global extends GlobalStm with StmUtil with StmCommon
trait StmCommon {
type TransactionConfig = se.scalablesolutions.akka.stm.TransactionConfig
val TransactionConfig = se.scalablesolutions.akka.stm.TransactionConfig
type TransactionFactory = se.scalablesolutions.akka.stm.TransactionFactory
val TransactionFactory = se.scalablesolutions.akka.stm.TransactionFactory
type Ref[T] = se.scalablesolutions.akka.stm.Ref[T]
val Ref = se.scalablesolutions.akka.stm.Ref
}
/** /**
* For importing the transactional data structures, including the primitive refs * For importing the transactional data structures, including the primitive refs
* and transactional data structures from Multiverse. * and transactional data structures from Multiverse.