Next: , Previous: Value trailing, Up: Trailing   [Contents]


20.5.3 Function trailing

For more complicated uses of trailing, you can store the address of a C function on the trail and have the Mercury runtime call your function back whenever future execution backtracks to the current choice point or earlier, or whenever that choice point is pruned, because execution commits to never backtracking over that point, or whenever that choice point is garbage collected.

Note the garbage collector in the current Mercury implementation does not garbage-collect the trail; this case is mentioned only so that we can cater for possible future extensions.

MR_trail_function()

Prototype:

typedef enum {
        MR_undo,
        MR_exception,
        MR_retry,
        MR_commit,
        MR_solve,
        MR_gc
} MR_untrail_reason;

void MR_trail_function(
        void (*untrail_func)(void *, MR_untrail_reason),
        void *value
);

A call to ‘MR_trail_function(untrail_func, value)’ adds an entry to the function trail. The Mercury implementation ensures that if future execution ever backtracks to the current choicepoint, or backtracks past the current choicepoint to some earlier choicepoint, then (*untrail_func)(value, reason) will be called, where reason will be ‘MR_undo’ if the backtracking was due to a goal failing, ‘MR_exception’ if the backtracking was due to a goal throwing an exception, or ‘MR_retry’ if the backtracking was due to the use of the “retry” command in ‘mdb’, the Mercury debugger, or any similar user request in a debugger. The Mercury implementation also ensures that if the current choice point is pruned because execution commits to never backtracking to it, then (*untrail_func)(value, MR_commit) will be called. It also ensures that if execution requires that the current goal be solvable, then (*untrail_func)(value, MR_solve) will be called. This happens in calls to solutions/2, for example. (MR_commit is used for “hard” commits, i.e. when we commit to a solution and prune away the alternative solutions; MR_solve is used for “soft” commits, i.e. when we must commit to a solution but do not prune away all the alternatives.)

MR_gc is currently not used — it is reserved for future use.

Typically if the untrail_func is called with reason being ‘MR_undo’, ‘MR_exception’, or ‘MR_retry’, then it should undo the effects of the update(s) specified by value, and then free any resources associated with that trail entry. If it is called with reason being ‘MR_commit’ or ‘MR_solve’, then it should not undo the update(s); instead, it may check for floundering (see the next section). In the ‘MR_commit’ case it may, in some cases, be possible to also free resources associated with the trail entry. If it is called with anything else (such as ‘MR_gc’), then it should probably abort execution with an error message.

Note that the address of the C function passed as the first argument of MR_trail_function() must be word aligned.


Next: , Previous: Value trailing, Up: Trailing   [Contents]