8.5 Thread-support library(threadutil)

This library defines a couple of useful predicates for demonstrating and debugging multi-threaded applications. This library is certainly not complete.

Lists all current threads and their status.
Join all terminated threads. For normal applications, dealing with terminated threads must be part of the application logic, either detaching the thread before termination or making sure it will be joined. The predicate join_threads/0 is intended for interactive sessions to reclaim resources from threads that died unexpectedly during development.
Create a new console and run the Prolog top-level in this new console. See also attach_console/0. In the Windows version a new interactor can also be created from the Run/New thread menu.

8.5.1 Debugging threads

Support for debugging threads is still very limited. Debug and trace mode are flags that are local to each thread. Individual threads can be debugged either using the graphical debugger described in section 3.5 (see tspy/1 and friends) or by attaching a console to the thread and running the traditional command-line debugger (see attach_console/0). When using the graphical debugger, the debugger must be loaded from the main thread (for example using guitracer) before gtrace/0 can be called from a thread.

If the current thread has no console attached yet, attach one and redirect the user streams (input, output, and error) to the new console window. On Unix systems the console is an xterm application. On Windows systems this requires the GUI version plwin.exe rather than the console based plcon.exe.

This predicate has a couple of useful applications. One is to separate (debugging) I/O of different threads. Another is to start debugging a thread that is running in the background. If thread 10 is running, the following sequence starts the tracer on this thread:

?- thread_signal(10, (attach_console, trace)).
Prepare ThreadId for debugging using the graphical tracer. This implies installing the tracer hooks in the thread and switching the thread to debug-mode using debug/0. The call is injected into the thread using thread_signal/2. We refer to the documentation of this predicate for asynchronous interaction with threads. New threads created inherit their debug-mode from the thread that created them.
Call tdebug/1 in all running threads.
Disable debugging thread ThreadId.
Disable debugging in all threads.
tspy(:Spec, +ThreadId)
Set a spy-point as spy/1 and enable the thread for debugging using tdebug/1. Note that a spy-point is a global flag on a predicate that is visible from all threads. Spy points are honoured in all threads that are in debug-mode and ignored in threads that are in nodebug mode.
Set a spy-point as spy/1 and enable debugging in all threads using tdebug/0. Note that removing spy-points can be done using nospy/1. Disabling spy-points in a specific thread is achieved by tnodebug/1.

8.5.2 Profiling threads

In the current implementation, at most one thread can be profiled at any moment. Any thread can call profile/1 to profile the execution of some part of its code. The predicate tprofile/1 allows for profiling the execution of another thread until the user stops collecting profile data.

Start collecting profile data in ThreadId and ask the user to hit <return> to stop the profiler. See section 4.40 for details on the execution profiler.