Thread_wait/2 and empty database

I was surprised that, starting from clean toplevel:

:- dynamic(foo/1).
:- thread_wait(write(x),[wait_preds([+(foo/1)]), modified(L)]).

doesn’t really wait but immediatelly succeeds with output and L=[]. Is this a bug? (It behaves the same if I start it in separate thread).

Ha! Adding module(user) to the list of options works. But what is the assumed module in the above case then? Maybe wait_preds should require module option? e.g. become wait_preds(Module, List)?

I have to retract this, it seems that something else caused thread_wait to behave

thread_wait/2 waits until Goal becomes true. So, the first thing it does is checking Goal, and write(x) is always true. The options are there to define when to retry evaluating Goal. In your case that is on an assert to foo/1. If you want to wait on any assert to foo/1, you could use

?- thread_wait(L=[foo/1], [wait_preds([+(foo/1)]), modified(L)]).

If the database is empty and you want to wait until there is a fact, use

?- thread_wait(foo(_), [wait_preds([+(foo/1)])]).

Note that the implementation is based on POSIX condition variables. Their semantics imply that spurious wakeups are possible. That is why you need a condition and you must be aware that the condition may be called while nothing really changed.

1 Like

Thank you for this idea, quite brilliant :slight_smile:

But in the end you are right - I realized that it would be better to refactor code away from “wait for facts to be asserted, then continue” to a “guard”-like predicate that is safe to be called multiple times.