Using call_cleanup/2. Trying to understand when to use it or others predicates of the same intention

Use case related to asserta/2

From test_read.pl

	setup_call_cleanup(
	    asserta((user:thread_message_hook(Term, Kind, _) :-
		        \+ \+ (prolog_load_context(variable_names, VarNames),
			       bind_variable_names(VarNames),
			       assertz(message(Term)))), Ref),
	    once(Goal),
	    erase(Ref))

Use case related to set_prolog_flag/2

From thread_agc.pl

	current_prolog_flag(agc_margin, Old),
	set_prolog_flag(agc_margin, 1000),
	call_cleanup(test(Threads, Count),
		     set_prolog_flag(agc_margin, Old)).

Use case related to process_create/3

From git.pl

setup_call_cleanup(
    process_create(path(git), Argv1,
                   [ stdout(pipe(Out)),
                     stderr(pipe(Error)),
                     process(PID)
                   | Extra
                   ]),
    call_cleanup(
        ( read_stream_to_codes(Out, OutCodes, []),
          read_stream_to_codes(Error, ErrorCodes, [])
        ),
        process_wait(PID, Status)),
    close_streams([Out,Error]))

Use case related to setting value based on exception using catch/3

From statistics.pl

call_cleanup(catch(Goal, E, (report(State0,10), throw(E))),Det = true),
    time_true(State0),
    (   Det == true
    ->  !
    ;   true
    )

test.pl has a predicate with multiple clauses using call_cleanup/2. Some of the use cases are noted above, some are used for testing throw/1 and one I don’t understand

% check handling of CHP_TOP
% notrace/1 does a call-back via C
notrace(call_cleanup(true, true)).