4.14.1 Managing (dynamic) predicates
AllApplicationManualNameSummaryHelp

  • Documentation
    • Reference manual
      • Built-in Predicates
        • Database
          • Managing (dynamic) predicates
            • abolish/1
            • abolish/2
            • copy_predicate_clauses/2
            • redefine_system_predicate/1
            • retract/1
            • retractall/1
            • asserta/1
            • assertz/1
            • assert/1
            • asserta/2
            • assertz/2
            • assert/2
            • Transactions
            • Impact of transactions
    • Packages

4.14.1.2 Impact of transactions

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.