Library
Module
Module type
Parameter
Class
Class type
Explicit transaction log passing on shared memory locations.
Type of an explicit transaction log on shared memory locations.
Note that a transaction log itself is not domain-safe and should generally only be used by a single domain. If a new domain is spawned inside a function recording shared memory accesses to a log and the new domain also records accesses to the log it may become inconsistent.
Accesses of shared memory locations using an explicit transaction log first ensure that the initial value of the shared memory location is recorded in the log and then act on the current value of the shared memory location as recorded in the log.
It is important to understand that it is possible for a transaction to observe the contents of two (or more) different shared memory locations from two (or more) different committed updates. This means that invariants that hold between two (or more) different shared memory locations may be seen as broken inside the transaction function. However, it is not possible to commit a transaction after it has seen such an inconsistent view of the shared memory locations.
To mitigate potential issues due to this read skew anomaly and due to very long running transactions, all of the access recording operations in this section periodically validate the entire transaction log. An important guideline for writing transactions is that loops inside a transaction should always include an access of some shared memory location through the transaction log or should otherwise be guaranteed to be bounded.
get ~xt r
returns the current value of the shared memory location r
in the explicit transaction log xt
.
set ~xt r v
records the current value of the shared memory location r
to be the given value v
in the explicit transaction log xt
.
update ~xt r f
is equivalent to let x = get ~xt r in set ~xt r (f x); x
with the limitation that f
must not and is not allowed to access the transaction log.
modify ~xt r f
is equivalent to let x = get ~xt r in set ~xt r (f x)
with the limitation that f
must not and is not allowed to access the transaction log.
exchange ~xt r v
is equivalent to update ~xt r (fun _ -> v)
.
swap ~xt l1 l2
is equivalent to set ~xt l1 @@ exchange ~xt l2 @@ get ~xt l1
.
compare_and_swap ~xt r before after
is equivalent to
update ~xt r @@ fun actual ->
if actual == before then after else actual
fetch_and_add ~xt r n
is equivalent to update ~xt r ((+) n)
.
decr ~xt r
is equivalent to fetch_and_add ~xt r (-1) |> ignore
.
to_blocking ~xt tx
converts the non-blocking transaction tx
to a blocking transaction by retrying on None
.
to_nonblocking ~xt tx
converts the blocking transaction tx
to a non-blocking transaction by returning None
on retry.
The transaction mechanism does not implicitly rollback changes recorded in the transaction log. Using snapshot
and rollback
it is possible to implement nested conditional transactions that may tentatively record changes in the transaction log and then later discard those changes.
Type of a snapshot
of a transaction log.
snapshot ~xt
returns a snapshot of the transaction log.
Taking a snapshot is a fast constant time O(1)
operation.
rollback ~xt snap
discards any changes of shared memory locations recorded in the transaction log after the snap
was taken by snapshot
.
Performing a rollback is potentially as expensive as linear time O(n)
in the number of locations accessed, but, depending on the exact access patterns, may also be performed more quickly. The implementation is optimized with the assumption that a rollback is performed at most once per snapshot.
NOTE: Only changes are discarded. Any location newly accessed after the snapshot was taken will remain recorded in the log as a read-only entry.
first ~xt txs
calls each transaction in the given list in turn and either returns the value returned by the first transaction in the list or raises Retry.Later
in case all of the transactions raised Retry.Later
.
NOTE: first
does not automatically rollback changes made by the transactions.
val post_commit : xt:'x t -> (unit -> unit) -> unit
post_commit ~xt action
adds the action
to be performed after the transaction has been performed successfully.
validate ~xt r
determines whether the shared memory location r
has been modified outside of the transaction and raises Retry.Invalid
in case it has.
Due to the possibility of read skew, in cases where some important invariant should hold between two or more different shared memory locations, one may explicitly validate the locations, after reading all of them, to ensure that no read skew is possible.
is_in_log ~xt r
determines whether the shared memory location r
has been accessed by the transaction.
Type of a transaction function that is polymorphic with respect to an explicit transaction log. The universal quantification helps to ensure that the transaction log cannot accidentally escape.
commit tx
repeatedly calls tx
to record a log of shared memory accesses and attempts to perform them atomically until it succeeds and then returns whatever tx
returned. tx
may raise Retry.Later
or Retry.Invalid
to explicitly request a retry or any other exception to abort the transaction.
The default for commit
is Mode.obstruction_free
. However, after enough attempts have failed during the verification step, commit
switches to Mode.lock_free
. Note that commit
never raises the Mode.Interference
exception.