Wraps array of TRef and adds methods for convenience.
A TPriorityQueue
contains values of type A
that an Ordering
is defined
on.
A TPriorityQueue
contains values of type A
that an Ordering
is defined
on. Unlike a TQueue
, take
returns the highest priority value (the value
that is first in the specified ordering) as opposed to the first value
offered to the queue. The ordering that elements with the same priority will
be taken from the queue is not guaranteed.
A TReentrantLock
is a reentrant read/write lock.
A TReentrantLock
is a reentrant read/write lock. Multiple readers may all
concurrently acquire read locks. Only one writer is allowed to acquire a
write lock at any given time. Read locks may be upgraded into write locks. A
fiber that has a write lock may acquire other write locks or read locks.
The two primary methods of this structure are readLock
, which acquires a
read lock in a managed context, and writeLock
, which acquires a write lock
in a managed context.
Although located in the STM package, there is no need for locks within STM transactions. However, this lock can be quite useful in effectful code, to provide consistent read/write access to mutable state; and being in STM allows this structure to be composed into more complicated concurrent structures that are consumed from effectful code.
A TSemaphore
is a semaphore that can be composed transactionally.
A TSemaphore
is a semaphore that can be composed transactionally. Because
of the extremely high performance of ZIO's implementation of software
transactional memory TSemaphore
can support both controlling access to some
resource on a standalone basis as well as composing with other STM data
structures to solve more advanced concurrency problems.
For basic use cases, the most idiomatic way to work with a semaphore is to
use the withPermit
operator, which acquires a permit before executing some
ZIO
effect and release the permit immediately afterward. The permit is
guaranteed to be released immediately after the effect completes execution,
whether by success, failure, or interruption. Attempting to acquire a permit
when a sufficient number of permits are not available will semantically block
until permits become available without blocking any underlying operating
system threads. If you want to acquire more than one permit at a time you can
use withPermits
, which allows specifying a number of permits to acquire.
You can also use withPermitManaged
or withPermitsManaged
to acquire and
release permits within the context of a managed effect for composing with
other resources.
For more advanced concurrency problems you can use the acquire
and
release
operators directly, or their variants acquireN
and releaseN
,
all of which return STM transactions. Thus, they can be composed to form
larger STM transactions, for example acquiring permits from two different
semaphores transactionally and later releasing them transactionally to safely
synchronize on access to two different mutable variables.
Transactional set implemented on top of TMap.
STM[E, A]
represents an effect that can be performed transactionally,
resulting in a failure E
or a value A
.
STM[E, A]
represents an effect that can be performed transactionally,
resulting in a failure E
or a value A
.
def transfer(receiver: TRef[Int], sender: TRef[Int], much: Int): UIO[Int] = STM.atomically { for { balance <- sender.get _ <- STM.check(balance >= much) _ <- receiver.update(_ + much) _ <- sender.update(_ - much) newAmnt <- receiver.get } yield newAmnt } val action: UIO[Int] = for { t <- STM.atomically(TRef.make(0).zip(TRef.make(20000))) (receiver, sender) = t balance <- transfer(receiver, sender, 1000) } yield balance
Software Transactional Memory is a technique which allows composition of arbitrary atomic operations. It is the software analog of transactions in database systems.
The API is lifted directly from the Haskell package Control.Concurrent.STM although the implementation does not resemble the Haskell one at all. http://hackage.haskell.org/package/stm-2.5.0.0/docs/Control-Concurrent-STM.html
STM in Haskell was introduced in: Composable memory transactions, by Tim Harris, Simon Marlow, Simon Peyton Jones, and Maurice Herlihy, in ACM Conference on Principles and Practice of Parallel Programming 2005. https://www.microsoft.com/en-us/research/publication/composable-memory-transactions/
See also: Lock Free Data Structures using STMs in Haskell, by Anthony Discolo, Tim Harris, Simon Marlow, Simon Peyton Jones, Satnam Singh) FLOPS 2006: Eighth International Symposium on Functional and Logic Programming, Fuji Susono, JAPAN, April 2006 https://www.microsoft.com/en-us/research/publication/lock-free-data-structures-using-stms-in-haskell/
A transactional queue that can only be dequeued.
A transactional queue that can only be enqueued.
A ZTHub[RA, RB, EA, EB, A, B]
is a transactional message hub.
A ZTHub[RA, RB, EA, EB, A, B]
is a transactional message hub. Publishers
can publish messages of type A
to the hub and subscribers can subscribe to
take messages of type B
from the hub. Publishing messages can require an
environment of type RA
and fail with an error of type EA
. Taking messages
can require an environment of type RB
and fail with an error of type EB
.
A ZTQueue[RA, RB, EA, EB, A, B]
is a transactional queue.
A ZTQueue[RA, RB, EA, EB, A, B]
is a transactional queue. Offerors can
offer values of type A
to the queue and takers can take values of type B
from the queue. Offering values can require an environment of type RA
and
fail with an error of type EA
. Taking values can require an environment of
type RB
and fail with an error of type EB
.
A ZTRef[EA, EB, A, B]
is a polymorphic, purely functional description of a
mutable reference that can be modified as part of a transactional effect.
A ZTRef[EA, EB, A, B]
is a polymorphic, purely functional description of a
mutable reference that can be modified as part of a transactional effect. The
fundamental operations of a ZTRef
are set
and get
. set
takes a value
of type A
and transactionally sets the reference to a new value,
potentially failing with an error of type EA
. get
gets the current value
of the reference and returns a value of type B
, potentially failing with an
error of type EB
.
When the error and value types of the ZTRef
are unified, that is, it is a
ZTRef[E, E, A, A]
, the ZTRef
also supports atomic modify
and update
operations. All operations are guaranteed to be executed transactionally.
NOTE: While ZTRef
provides the transactional equivalent of a mutable
reference, the value inside the ZTRef
should be immutable. For performance
reasons ZTRef
is implemented in terms of compare and swap operations rather
than synchronization. These operations are not safe for mutable values that
do not support concurrent access.