The following predicates are used to semantically invalidate tables and/or reclaim their space. The use of the word ``tables'' in this section is rather unspecific. For the purpose of deletion a table can either be information pertaining to a single subgoal of a tabled predicate (which is called here a tabled subgoal), or pertaining to all subgoals of a tabled predicate. Predicates are provided to invalidate tables not only for particular predicates and subgoals, but for all tabled predicates, all tabled predicates in a module, and in the multi-threaded engine all thread-private tabled predicates or all thread-shared tabled predicates. Overall, these predicates share similar characteristics.
First, an incomplete tabled subgoal
may not be abolished by the
user except under special circumstances described below. This
restriction is made since if
is incomplete there may be pointers
to
from various elements of the current execution environment, and
removing all of these pointers may be difficult to do. If one of the
deletion predicates is called when the current execution environment
contains a choice point into a completed table that is being
abolished, space for the abolished information is not immediately
reclaimed. More precisely, if the current execution envonment has a
choice point that points to an answer
we say that
is active in the current environment. If a tabled predicate
or
subgoal
to be abolished has an answer that is active in the
current environment, reclamation of space for
or
will be
delayed until no answers for
or
are active. New calls to
or
, however, will derive a new table, rather than using the
abolished information.
When conditional answers are present, abolishing a specific table or
call may lead to semantic or implementational complications. Consider
the conditional answer r(a,b):- undef| from
Figure 6.1. If the predicate r/2) (or subgoal
r(a,X)) is abolished and later rederived, the rederivation of
r(a,X) might have different semantics than the original
derivation (e.g. if undef depended on a dynamic predicate whose
definition has changed). From an implementation perspective, if space
for r(a,X)) is reclaimed, then the call get_residual(p(a,X),Y) may core dump, even if there are no choice
points for completed tables anywhere in the choice point stack. To
address this problem, by default abolishing a subgoal
(predicate
) will abolish all subgoals (predicates) that (transtively) depend
on
(
) 6.12. In this case the goal abolish_table_call(r(a,X)) would cause the deletion of p(a,X) while the goal abolish_table_pred(r/2) would cause
the deletion of p/2, since there are tabled subgoals of p/2 that depend on r/2. Only dependencies from subgoals or
answers to the answers that are conditional on them are taken into
account for table deletion: thus the deletion r(a,X) deletes
p(a,X), but not undef.
Users with programs that give rise to conditional answers in completed tables are encouraged to maintain this default behavior. However the default behavior may be changed either by setting an XSB flag:
?- set_xsb_flag(table_gc_action,abolish_tables_singly).or by calling a 2-ary abolish command with abolish_tables_singly in the options list.
|
In the multi-threaded engine abolishing tables private to a thread
behaves exactly as in the sequential engine, regardless of whether the
tables are complete or incomplete, or contain conditional answers. In
addition, when a thread
exits (by normal termination or via an
exception), tables private to
are abolished automatically and
their space reclaimed, as are any incomplete shared tables owned by
in local evaluation. Shared tables can be abolished by the user
at any time, but their space will not be reclaimed until there is a
single active thread.
As mentioned above, during normal execution, an incomplete tabled subgoal may not be abolished by the user, a restriction that is made to ensure correct evaluations. Accordingly, calling an abolish_xxx predicate when tables are incomplete raises an error. However, we note that any incomplete tables are abolished automatically by the system on exceptions (by the default system error handler) when the interpreter level is resumed.