Availability:built-in
transaction(:Goal,
:Constraint, +Mutex)
- Call
once(Goal) - Lock Mutex
- Change the visibility to the current global state combined with the changes made by Goal
- Call
once(Constraint) - Commit the changes
- Unlock Mutex.
This predicate is intended to execute multiple transactions with a time consuming Goal in part concurrently. For example, it can be used for a Compare And Swap (CAS) like design. We illustrate this using a simple counter in the code below. Note that the transaction fails if some other thread concurrently updated the counter. This is why we need the repeat/0 and a final !/0. The CAS-style update is in general useful if Goal is expensive and conflicts are rare.
:- dynamic counter/1.
increment_counter(Delta) :-
repeat,
transaction(( counter(Value),
Value2 is Value+Delta,
),
( retract(counter(Value)),
asserta(counter(Value2))
),
counter_lock),
!.