Transactions interact with other facilities that depend on changing
dynamic predicates. This section discusses these interactions.
- Last modified generation
- Using the predicate_property/2
property
last_modified_generation(Generation)
we can determine
whether a predicate was modified. When a predicate is changed inside a
transaction this generation is not updated. The generation for dynamic
predicates that are modified in the transaction is updated to the commit
generation when the transaction is committed. Asking for the last
modified generation inside the transaction examines the log of
modified clauses and reports the generation as one of
- The global modified generation if the predicate was not modified in
the transaction and not modified outside the transaction to beyond the
start generation of the transaction. If the modified generation is
higher than the transaction start generation, this generation is
reported.
bugNote that the above implies
that inside a transaction we observe a changing last modified generation
for predicates that have only been modified outside the transaction
while these changes are not visible.
- The transaction start generation plus the local generation of the
last change if the predicate is modified inside the transaction.
- Wait for database changes
- The predicate thread_wait/2
does not wakeup threads for changes inside a transaction. The wakeup is
delayed until the transaction is committed. Note that thread_wait/2
cannot be meaningfully called from inside a transaction because no
external entities can cause changes to the dynamic database inside the
transaction.
- Incremental tabling
- Consistency of tables must be restored if the transaction is rolled
back. For local tables this is realised as follows:
- Tables are either marked to be invalidated on rollback or,
for monotonic tabling individual answers are marked to be
removed on rollback.
- A table is marked to be invalidated if, while it is created
or reevaluated, at least one dependent dynamic predicate has been
modified inside the transaction.
- Answers are marked to be retracted when they result from monotonic
reevaluation based on changes inside the transaction.
In other words: tables being reevaluated inside a transaction that do
not depend on predicates modified inside the transaction remain valid.
Monotonic tables that get new answers due to asserts inside the
transaction have these answers removed during the rollback while the
table remains valid. Monotonic tables that are for some reason
invalidated inside the transaction are invalidated during the rollback.
Correct interaction between tabling and transaction currently
only deals with local tables. Shared tables should not
be combined with transactions. Future versions may improve on that. A
possible route is to make a local copy from a shared table when
(re)evaluation is performed inside a transaction.
Status SWI-Prolog transaction basics and API are stable.
Interaction with other parts of the system that depend on dynamic
predicates is still unsettled. Future versions may support
non-determinism through transactions and snapshots.