diff --git a/akka-core/src/main/scala/stm/Transaction.scala b/akka-core/src/main/scala/stm/Transaction.scala index 06e2b78ac2..b4fb0cda4c 100644 --- a/akka-core/src/main/scala/stm/Transaction.scala +++ b/akka-core/src/main/scala/stm/Transaction.scala @@ -26,48 +26,12 @@ class StmConfigurationException(message: String) extends RuntimeException(messag object Transaction { val idFactory = new AtomicLong(-1L) - /** - * Module for "local" transaction management, local in the context of threads. - * You should only use these if you do not need to have one transaction span - * multiple threads (or Actors). - *

- * Example of atomic transaction management using the atomic block. - *

- *

-   * import se.scalablesolutions.akka.stm.Transaction.Local._
-   *
-   * atomic  {
-   *   .. // do something within a transaction
-   * }
-   * 
- * - * @author Jonas Bonér - */ - @deprecated("Use the akka.stm.local package object instead.") + @deprecated("Use the se.scalablesolutions.akka.stm.local package object instead.") object Local extends LocalStm - /** - * 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). - *

- * Example of atomic transaction management using the atomic block. - *

: - *

-   * import se.scalablesolutions.akka.stm.Transaction.Global._
-   *
-   * atomic  {
-   *   .. // do something within a transaction
-   * }
-   * 
- * - * @author Jonas Bonér - */ - @deprecated("Use the akka.stm.global package object instead.") + @deprecated("Use the se.scalablesolutions.akka.stm.global package object instead.") object Global extends GlobalStm - /** - * TODO: document - */ object Util extends StmUtil /** diff --git a/akka-core/src/main/scala/stm/TransactionFactory.scala b/akka-core/src/main/scala/stm/TransactionFactory.scala index 2269e0edf7..7c6cfce536 100644 --- a/akka-core/src/main/scala/stm/TransactionFactory.scala +++ b/akka-core/src/main/scala/stm/TransactionFactory.scala @@ -13,7 +13,7 @@ import org.multiverse.templates.TransactionBoilerplate import org.multiverse.api.TraceLevel /** - * For configuring multiverse transactions. + * For configuring multiverse transactions. See TransactionConfig class for options. */ object TransactionConfig { val FAMILY_NAME = "DefaultTransaction" @@ -57,6 +57,19 @@ object TransactionConfig { /** * 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, val readonly: Boolean = TransactionConfig.READONLY, @@ -75,6 +88,24 @@ object DefaultTransactionConfig extends TransactionConfig /** * 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. + *

+ * See TransactionConfig for configuration options. + *

+ * 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 { def apply(config: TransactionConfig) = new TransactionFactory(config) diff --git a/akka-core/src/main/scala/stm/TransactionManagement.scala b/akka-core/src/main/scala/stm/TransactionManagement.scala index c92ddc6b51..2b4b9f888c 100644 --- a/akka-core/src/main/scala/stm/TransactionManagement.scala +++ b/akka-core/src/main/scala/stm/TransactionManagement.scala @@ -8,7 +8,7 @@ import se.scalablesolutions.akka.util.Logging 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.{Transaction => MultiverseTransaction} 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 not need to have one transaction span + * multiple threads (or Actors). + *

+ * Example of atomic transaction management using the atomic block. + *

+ *

+ * import se.scalablesolutions.akka.stm.local._
+ *
+ * atomic  {
+ *   // do something within a transaction
+ * }
+ * 
+ */ class LocalStm extends TransactionManagement with Logging { 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). + *

+ * Example of atomic transaction management using the atomic block: + *

+ *

+ * import se.scalablesolutions.akka.stm.global._
+ *
+ * atomic  {
+ *   // do something within a transaction
+ * }
+ * 
+ */ class GlobalStm extends TransactionManagement with Logging { val DefaultGlobalTransactionConfig = TransactionConfig() @@ -133,13 +162,27 @@ class GlobalStm extends TransactionManagement with Logging { } 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 }) - - def retry = StmUtils.retry + /** + * STM retry. Use within an atomic. + * 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 orElse(secondBody: => T) = new OrElseTemplate[T] { 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 -} diff --git a/akka-core/src/main/scala/stm/packages.scala b/akka-core/src/main/scala/stm/packages.scala index 4cdbaf7999..cbb3ad4804 100644 --- a/akka-core/src/main/scala/stm/packages.scala +++ b/akka-core/src/main/scala/stm/packages.scala @@ -5,15 +5,26 @@ package se.scalablesolutions.akka.stm /** - * For importing 'local' stm. + * For importing 'local' STM. */ 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 +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 * and transactional data structures from Multiverse.