A CommitBarrier
allows multiple transactions on separate threads to
perform a single atomic commit.
A CommitBarrier
allows multiple transactions on separate threads to
perform a single atomic commit. All of the actions performed by all of
the atomic blocks executed by members of the barrier will appear to
occur as a single atomic action, even though they are spread across
multiple threads.
Commit barriers can be used to implement transactors, where actions taken by multiple actors should be atomic as a single unit.
Because there is no ordering possible between the atomic blocks that
make up a commit barrier, if those transactions conflict then the only
way to avoid deadlock is to roll back all of the barrier's members. If
you observe a cancel cause of CommitBarrier.MemberCycle
then this has
happened to you, and you need to run more of the logic on a single
thread inside a single transaction.
This abstraction is based on Multiverse's CountDownCommitBarrier
, by
Peter Veentjer.
The presence of an implicit InTxn
instance grants the caller permission
to perform transactional reads and writes on Ref
instances, as well as
permission to call object Txn
methods that require an InTxnEnd
.
The presence of an implicit InTxn
instance grants the caller permission
to perform transactional reads and writes on Ref
instances, as well as
permission to call object Txn
methods that require an InTxnEnd
.
InTxn
instances themselves might be reused by the STM, use
NestingLevel.current
or NestingLevel.root
to get a NestingLevel
if
you need to track an individual execution attempt.
The presence of an implicit InTxnEnd
instance inside a transaction
life-cycle handler grants permission to call methods in object Txn
that
locate nesting levels or register additional handlers.
The presence of an implicit InTxnEnd
instance inside a transaction
life-cycle handler grants permission to call methods in object Txn
that
locate nesting levels or register additional handlers. This functionality
is separated from that granted by InTxn
because Ref
operations are not
allowed from handlers after commit has begun.
MaybeTxn
allows lookup of the implicit InTxn
instance without failing
if the InTxn
is not known at compile time.
MaybeTxn
allows lookup of the implicit InTxn
instance without failing
if the InTxn
is not known at compile time. implicitly[MaybeTxn]
will
bind to an implicit InTxn
if one is available, otherwise it will bind to
the object TxnUnkown
. A MaybeTxn
of TxnUnknown
should trigger a
dynamically-scoped InTxn
search using Txn.findCurrent
.
A NestingLevel
instance describes a single attempt to execute an atomic
block inside a transaction.
A NestingLevel
instance describes a single attempt to execute an atomic
block inside a transaction. Reads and writes performed by a transaction
will only be made visible to other threads after (if) the root nesting
level commits.
Methods on this class may be called from any thread, and may be called after the corresponding execution attempt has been completed.
Instances of PendingAtomicBlock
defer the execution of an atomic block
until all of the alternatives can be gathered from the user.
Instances of PendingAtomicBlock
defer the execution of an atomic block
until all of the alternatives can be gathered from the user. There is an
implicit conversion in the stm
package object from any type A
to a
PendingAtomicBlock[A]
, which will kick in if there is an attempt to call
.orAtomic
on a value.
Provides access to a single element of type A.
Provides access to a single element of type A. Accesses are
performed as part of a memory transaction that comprises all of the
operations of an atomic block and any nested blocks. Single-operation
memory transactions may be performed without an explicit atomic block using
the Ref.View
returned from single
. The software transactional memory
performs concurrency control to make sure that all committed transactions
are linearizable. Reads and writes performed by a successful transaction
return the same values as if they were executed instantaneously at the
transaction's commit (linearization) point.
The static scope of an atomic block is defined by access to an implicit
InTxn
passed to the block by the STM. Atomic blocks nest, so to
participate in an atomic block for which a InTxn
is not conveniently
available, just create a new atomic block using
atomic { implicit t => // the body }
In the static scope of an atomic block reads and writes of a Ref
are performed by x.get
and x.set(v)
, or more concisely by x()
and
x() = v
. x.single
returns a Ref.View
that will dynamically resolve
the current scope during each method call, automatically creating a
single-operation atomic block if no transaction is active.
It is possible for separate Ref
instances to refer to the same element;
in this case they will compare equal. (As an example, a transactional
array class might store elements in an array and create Ref
s on demand.)
Ref
s may be provided for computed values, such as the emptiness of a
queue, to allow conditional retry and waiting on semantic properties.
To perform an access outside a transaction, use the view returned by
single
. Each access through the returned view will act as if it was
performed in its own single-operation transaction, dynamically nesting into
an active atomic block as appropriate.
Ref
's companion object contains factory methods that create Ref
instances paired with a single STM-managed memory location.
Provides all of the operations of a Ref[A]
, without the ability to get a
Ref.View
.
Sink[+A]
consists of the contra-variant write-only operations of
Ref[A]
.
Provides all of the operations of a Sink[A]
, without the ability to get
a Sink.View
.
Source[+A]
consists of the covariant read-only operations of Ref[A]
.
Provides all of the operations of a Source[A]
, without the ability to get
a Source.View
.
Bulk transactional storage, roughly equivalent to Array[Ref[T]]
but
potentially much more space efficient.
Bulk transactional storage, roughly equivalent to Array[Ref[T]]
but
potentially much more space efficient. Elements can be read and written
directly, or the refs
method can be used to obtain transient Ref
instances backed by the elements of the TArray
.
A transactional map implementation that requires that all of its map-like operations be called from inside an atomic block.
A transactional map implementation that requires that all of its map-like
operations be called from inside an atomic block. Rather than extending
Map
, an implicit conversion is provided from TMap
to Map
if the
current scope is part of an atomic block (see TMap.asMap
).
The keys (with type A
) must be immutable, or at least not modified while
they are in the map. The TMap
implementation assumes that it can safely
perform key equality and hash checks outside a transaction without
affecting atomicity.
A transactional set implementation that requires that all of its set-like operations be called from inside an atomic block.
A transactional set implementation that requires that all of its set-like
operations be called from inside an atomic block. Rather than extending
Set
, an implicit conversion is provided from TSet
to Set
if the
current scope is part of an atomic block (see TSet.asSet
).
The elements (with type A
) must be immutable, or at least not modified
while they are in the set. The TSet
implementation assumes that it can
safely perform equality and hash checks outside a transaction without
affecting atomicity.
This trait implements methods that can be used to examine the content of transactional data structures in a debugger with minimal modification to the behavior of the program.
This trait implements methods that can be used to examine the content of
transactional data structures in a debugger with minimal modification to
the behavior of the program. Normal transactional reads would add to an
atomic block's read set, which could reduce the number of valid program
execution orders. dbgStr
and dbgValue
perform transactional reads,
but then erase them from the enclosing transaction (if any).
You can use these methods from an IDE debugger manually, by watching
x.dbgStr
or x.dbgValue
rather than x
.
If you use Eclipse, you can make this method the default view by going to
Window->Preferences->Java[+]->Debug[+]->Detail Formatters and
entering the code snippet dbgStr()
(or dbgValue()
) for instances of
scala.concurrent.stm.TxnDebuggable
.
If you use IntelliJ IDEA, go to
File->Settings...->Debugger->Data Type Renderers and create a new
renderer for scala.concurrent.stm.TxnDebuggable
that uses
dbgStr()
for rendering and dbgValue()
for node expansion.
A TxnExecutor
is responsible for executing atomic blocks transactionally
using a set of configuration parameters.
A TxnExecutor
is responsible for executing atomic blocks transactionally
using a set of configuration parameters. Configuration changes are made by
constructing a new TxnExecutor
using withConfig
or withHint
. The
new executor may be used immediately, saved and used multiple times, or
registered as the new system-wide default using
TxnExecutor.transformDefault
.
TxnLocal[A]
holds an instance of A
that is local to an atomic block.
TxnLocal[A]
holds an instance of A
that is local to an atomic block.
See the factory method in the companion object for information about the
life-cycle.
object Ref
contains factory methods that allocate an STM-managed memory
location and return a Ref
instance that provides access to that location.
The Txn
object provides methods that operate on the current transaction
context.
The Txn
object provides methods that operate on the current transaction
context. These methods are only valid within an atomic block or a
transaction life-cycle handler, which is checked at compile time by
requiring that an implicit InTxn
or InTxnEnd
be available.
object TxnExecutor
manages the system-wide default TxnExecutor
.
An object that represents the absence of a statically-bound current transaction.
An object that represents the absence of a statically-bound current transaction.
scala.concurrent.stm.MaybeTxn
Atomically executes atomic blocks using the default TxnExecutor
.
Atomically executes atomic blocks using the default TxnExecutor
. See
TxnExecutor.apply
.
Equivalent to Txn.retry
.
Equivalent to Txn.retryFor(timeout, unit)
.
This is the first half of the machinery for implementing orAtomic
.