This is a low-level primitive that, together with condition_wait/2 and with_mutex/2, can be used to implement synchronization between concurrent threads.
The predicate unblocks one (or all) currently waiting invocations of condition_wait/2 on the given Handle.
The typical usage pattern is this:
wait_for_something(Handle) :-
with_mutex(Handle, wait_for_something_locked(Handle)).
wait_for_something_locked(Handle) :-
( test_for_something ->
true
;
condition_wait(Handle, block),
wait_for_something_locked(Handle)
).
produce_something(Handle) :-
with_mutex(Handle, produce_something_locked(Handle)).
produce_something_locked(Handle) :-
make_something_true,
condition_signal(Handle, all).
The following object handles can be used for condition signaling (to obtain a handle from an object's alias name, use name_to_handle/3):
% Basic example
?- bag_create(Handle),
engine_create(E, []),
engine_resume_thread(E, (
with_mutex(Handle, condition_wait(Handle, block)),
writeln(condition_was_signaled)
)),
sleep(3),
condition_signal(Handle, one).
condition_was_signaled % printed after 3 seconds
% Example code for signaling on a record-object
wait_for_message(Handle, Message) :-
with_mutex(Handle, wait_for_message_locked(Handle, Message)).
wait_for_message_locked(Handle, Message) :-
( erase(Handle, Message) ->
true
;
condition_wait(Handle, block),
wait_for_message_locked(Handle, Message)
).
produce_message(Handle, Message) :-
with_mutex(Handle, produce_message_locked(Handle, Message)).
produce_message_locked(Handle, Message) :-
recordz(Handle, Message),
condition_signal(Handle, all).
% Query using the above code
?- record_create(Handle),
engine_create(E, [thread]),
engine_resume_thread(E, (
wait_for_message(Handle, Message),
writeln(thread_received_message(Message))
)),
sleep(3),
produce_message(Handle, "hello from main").
thread_received_message(hello from main) % printed after 3 seconds