mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-12 12:26:29 +00:00
Estimated hours taken: 3 Branches: main Provide a mechanism for resetting the trail. This allows the reuse of memory that is occupied by any entries on the trail. This can only be done safely after it is certain that any calls that added the trail entries cannot be backtracked over. For some programs doing this can prevent trail exhaustation. This diff does not provide a way of doing this at the Mercury level, nor can the compiler currently automatically add calls to reclaim memory used by trail. Both these things are future work. XXX the interaction between this and the debugger is a bit unclear since trailing and debugging don't currently work together properly. runtime/mercury_trail.h: runtime/mercury_trail.c: Add a new function MR_reset_trail(). When called this function walks back along the trail calling function trail entries with the MR_gc untrail reason. It then zeros out the trail zone and resets the ticket counter and ticket high water mark to their initial values. Define two macros, MR_TRAIL_ZONE and MR_TRAIL_BASE that expand to the addresses of the trail zone and the base of the trail respectively in a grade independent manner. Redefine MR_num_trail_entries() using the MR_TRAIL_BASE macro. Document that MR_gc is now used for this. Fix a typo. tests/trailing/Mmakefile: tests/trailing/test_trail_reset.m: tests/trailing/test_trail_reset.exp: A test of the trail reset functionality.
80 lines
1.4 KiB
Mathematica
80 lines
1.4 KiB
Mathematica
% vim: ft=mercury ts=4 et
|
|
:- module test_trail_reset.
|
|
:- interface.
|
|
|
|
:- import_module io.
|
|
|
|
:- pred main(io::di, io::uo) is det.
|
|
|
|
:- implementation.
|
|
|
|
:- import_module int.
|
|
|
|
main(!IO) :-
|
|
( test(10, _) ->
|
|
io.write_string("Call to test/1 succeeded\n", !IO)
|
|
;
|
|
io.write_string("Call to test/1 failed\n", !IO)
|
|
),
|
|
reset_trail(!IO).
|
|
|
|
:- pred test(int::in, int::out) is semidet.
|
|
|
|
test(X, 3) :-
|
|
add_trail_entry(X),
|
|
add_trail_entry(X + 1).
|
|
|
|
:- pragma foreign_decl("C", "
|
|
|
|
#include \"mercury_trail.h\"
|
|
#include <stdio.h>
|
|
|
|
extern void
|
|
foo(void *, MR_untrail_reason);
|
|
|
|
").
|
|
|
|
:- pred add_trail_entry(int::in) is semidet.
|
|
|
|
:- pragma foreign_proc("C",
|
|
add_trail_entry(X::in),
|
|
[will_not_call_mercury, promise_pure, thread_safe],
|
|
"
|
|
MR_trail_function(foo, (void *) X);
|
|
SUCCESS_INDICATOR = MR_TRUE;
|
|
").
|
|
|
|
:- pred reset_trail(io::di, io::uo) is det.
|
|
|
|
:- pragma foreign_proc("C",
|
|
reset_trail(IO0::di, IO::uo),
|
|
[will_not_call_mercury, promise_pure, thread_safe],
|
|
"
|
|
MR_reset_trail();
|
|
IO = IO0;
|
|
").
|
|
|
|
:- pragma foreign_code("C", "
|
|
|
|
void
|
|
foo(void *value, MR_untrail_reason reason)
|
|
{
|
|
printf(\"calling function trail entry with %ld: \",
|
|
(long) value);
|
|
|
|
switch (reason) {
|
|
|
|
case MR_commit:
|
|
printf(\"commit\\n\");
|
|
break;
|
|
|
|
case MR_gc:
|
|
printf(\"gc\\n\");
|
|
break;
|
|
|
|
default:
|
|
printf(\"unexpected trail reason\");
|
|
}
|
|
}
|
|
").
|