10.7 Multithreading and the XPCE graphics system

GUI applications written in XPCE can benefit from Prolog threads. Where XPCE 6 and earlier allowed only one Prolog thread to interact with XPCE, XPCE 7 and later allow multiple threads, but only one may be processing inside XPCE at any point in time. In other words, sending a message to XPCE requires obtaining the XPCE global lock, but if the method calls out back to Prolog, this lock is released and other Prolog threads may send messages to XPCE. This model is comparable to the Python GIL.

Due to the underlying SDL library, window and display related operations must be executed on the process main thread and GUI events originate from the (SDL) main thread. Other Prolog threads may execute goals in the SDL event loop and (thus) in the main thread using in_pce_thread/1 and in_pce_thread_sync/1.

SWI-Prolog/XPCE can operate in two setups. One is the console application swipl that connects its I/O to a terminal (or Windows console). In this setup, XPCE event processing is interleaved with reading from the terminal. This implies that the GUI is not responsive while a Prolog goal is running. Alternatively, swipl-win is a GUI application that runs the Prolog REPL (toplevel) loop in a Prolog thread connected to a terminal implemented in XPCE (called Epilog). Now, the GUI runs in the process main thread and interactive Prolog queries run in the thread connected to the Epilog terminal, called conN. In this setup the GUI remains responsive while user queries execute. The Epilog terminal:

If SWI-Prolog was started as swipl, it may open an Epilog window by running epilog/0. See also section 4.35.4.

[det]in_pce_thread(:Goal)
This call gives any Prolog thread the opportunity to run calls in the XPCE thread. A call to in_pce_thread/1 succeeds immediately, copying Goal to the XPCE thread. Goal is added to the XPCE event queue and executed synchronous to normal user events like typing, clicking and XPCE timers.
[semidet]in_pce_thread_sync(:Goal)
Same as in_pce_thread/1, but wait for Goal to be completed. Success depends on the success of executing Goal. Variable bindings inside Goal are visible to the caller, but it should be noted that the values are being copied. If Goal throws an exception, this exception is re-thrown by in_pce_thread/1. If the calling thread is the XPCE thread, in_pce_thread_sync/1 executes a direct meta-call. See also in_pce_thread/1.

Note that in_pce_thread_sync/1 is slow and is typically only required for operations that act on windows or the display. A warning is printed if an SDL operation that may only be called from the main thread is called from another thread. Many common operations that require to be called in the main thread are automatically proxied to the main thread.