\chapter{Multithreaded applications} \label{sec:threads} SWI-Prolog multithreading is based on standard C language multithreading support. It is not like {\em ParLog} or other parallel implementations of the Prolog language. Prolog threads have their own stacks and only share the Prolog \emph{heap}: predicates, records, flags and other global non-backtrackable data. SWI-Prolog thread support is designed with the following goals in mind. \begin{itemlist} \item[Multithreaded server applications] Today's computing services often focus on (internet) server applications. Such applications often have need for communication between services and/or fast non-blocking service to multiple concurrent clients. The shared heap provides fast communication, and thread creation is relatively cheap.% \footnote{On an Intel i7-2600K, running Ubuntu Linux 12.04, SWI-Prolog 6.2 creates and joins 32,000 threads per second elapsed time.} \item[Interactive applications] Interactive applications often need to perform extensive computation. If such computations are executed in a new thread, the main thread can process events and allow the user to cancel the ongoing computation. User interfaces can also use multiple threads, each thread dealing with input from a distinct group of windows. See also \secref{mt-xpce}. \item[Natural integration with foreign code] Each Prolog thread runs in a native thread of the operating system, automatically making them cooperate with \jargon{MT-safe} foreign code. In addition, any foreign thread can create its own Prolog engine for dealing with calling Prolog from C code. \end{itemlist} SWI-Prolog multithreading is based on the POSIX thread standard \cite{Butenhof:1997:PPT} used on most popular systems except for MS-Windows. On Windows it uses the \href{http://sources.redhat.com/pthreads-win32/}{pthread-win32} emulation of POSIX threads mixed with the Windows native API for smoother and faster operation. The SWI-Prolog thread implementation has been discussed in the ISO WG17 working group and is largely adopted by YAP and XSB Prolog.\footnote{The latest version of the ISO draft can be found at \url{http://logtalk.org/plstd/threads.pdf}. It appears to have dropped from the ISO WG17 agenda.} \section{Creating and destroying Prolog threads} \label{sec:threadcreate} \begin{description} \predicate{thread_create}{2}{:Goal, -Id} Shorthand for \exam{thread_create(Goal, Id, [])}. See \index{thread_create/3}\predref{thread_create}{3}. \predicate{thread_create}{3}{:Goal, -Id, +Options} Create a new Prolog thread (and underlying operating system thread) and start it by executing \arg{Goal}. If the thread is created successfully, the thread identifier of the created thread is unified to \arg{Id}. \arg{Id} is the \emph{alias} name if the option \term{alias}{name} is given. Otherwise it is a \jargon{blob} of type \const{thread}. The anonymous blobs are subject to atom garbage collection. If a thread handle is garbage collected and the thread is not \jargon{detached}, it is \jargon{joined} if it has already terminated (see \index{thread_join/2}\predref{thread_join}{2}) and detached otherwise (see \index{thread_detach/1}\predref{thread_detach}{1}).\footnote{Up to version 7.3.23, anonymous thread handles were integers. Using integers did not allow for safe checking of the thread's status as the thread may have died and the handle may have been reused and did not allow for garbage collection to take care of forgotten threads.} The thread identifier blobs are printed as \verb$($\arg{I},\arg{Ptr}\verb$)$, where \arg{I} is the internal thread identifier and \arg{Ptr} is the unique address of the identifier. The \arg{I} is accepted as input argument for all thread APIs that accept a thread identifier for convenient interaction from the toplevel. See also \index{thread_property/2}\predref{thread_property}{2}. \arg{Options} is a list of options. The currently defined options are below. Stack size options can also take the value \const{inf} or \const{infinite}, which is mapped to the maximum stack size supported by the platform. \begin{description} \termitem{affinity}{+CpuSet} Specify that the thread should only run on the specified CPUs (cores). \arg{CpuSet} is a list of integers between 0 (zero) and the known number of CPUs (see \prologflag{cpu_count}). If \arg{CpuSet} is empty a \const{domain_error} is raised. Referring to CPUs equal to or higher than the known number of CPUs returns an \const{existence_error}. This option is currently implemented for systems that provide pthread_attr_setaffinity_np(). The option is silently ignored on other systems.\bug{There is currently no way to discover whether this option is supported.} \termitem{alias}{AliasName} Associate an `alias name' with the thread. This name may be used to refer to the thread and remains valid until the thread is joined (see \index{thread_join/2}\predref{thread_join}{2}). If the OS supports it (e.g., Linux), the operating system thread is named as well. \termitem{at_exit}{:AtExit} Register \arg{AtExit} as using \index{thread_at_exit/1}\predref{thread_at_exit}{1} before entering the thread goal. Unlike calling \index{thread_at_exit/1}\predref{thread_at_exit}{1} as part of the normal \arg{Goal}, this \emph{ensures} the \arg{AtExit} is called. Using \index{thread_at_exit/1}\predref{thread_at_exit}{1}, the thread may be signalled or run out of resources before \index{thread_at_exit/1}\predref{thread_at_exit}{1} is reached. See \index{thread_at_exit/1}\predref{thread_at_exit}{1} for details. \termitem{debug}{+Bool} Enable/disable debugging the new thread. If \const{false} (default \const{true}), the new thread is created with the property \term{debug}{false} and debugging is disabled before the new thread is started. The thread debugging predicates such as \index{tspy/1}\predref{tspy}{1} and \index{tdebug/0}\predref{tdebug}{0} do not signal threads with the debug property set to \const{false}.\footnote{Currently, the flag is only used as a hint for the various debugging primitives, i.e., the system does not really enforce that the target thread stays in \jargon{nodebug} mode.} \termitem{detached}{Bool} If \const{false} (default), the thread can be waited for using \index{thread_join/2}\predref{thread_join}{2}. \index{thread_join/2}\predref{thread_join}{2} must be called on this thread to reclaim all resources associated with the thread. If \const{true}, the system will reclaim all associated resources automatically after the thread finishes. Please note that thread identifiers are freed for reuse after a detached thread finishes or a normal thread has been joined. See also \index{thread_join/2}\predref{thread_join}{2} and \index{thread_detach/1}\predref{thread_detach}{1}. If a detached thread dies due to failure or exception of the initial goal, the thread prints a message using \index{print_message/2}\predref{print_message}{2}. If such termination is considered normal, the code must be wrapped using \index{ignore/1}\predref{ignore}{1} and/or \index{catch/3}\predref{catch}{3} to ensure successful completion. \termitem{inherit_from}{+ThreadId} Inherit defaults from the given \arg{ThreadId} instead of the calling thread. This option was added to ensure that the \const{__thread_pool_manager} (see \index{thread_create_in_pool/4}\predref{thread_create_in_pool}{4}), which is created lazily, has a predictable state. The following properties are inherited: \begin{itemize} \item The prompt (see \index{prompt/2}\predref{prompt}{2}) \item The \jargon{typein} module (see \index{module/1}\predref{module}{1}) \item The standard streams (\const{user_input}, etc.) \item The default encoding (see \prologflag{encoding}) \item The default locale (see \index{set_locale/1}\predref{set_locale}{1}) \item All prolog flags \item The stack limit (see Prolog flag \prologflag{stack_limit}). \end{itemize} \termitem{queue_max_size}{Size} Enforces a maximum to the number of terms in the input queue. See \index{message_queue_create/2}\predref{message_queue_create}{2} with the \term{max_size} option for details. \termitem{stack_limit}{Bytes} Set the size limit for the Prolog stacks. See the Prolog flag \prologflag{stack_limit}. The default is inherited from the calling thread or the thread specified using \term{inherit_from}{ThreadId}. \termitem{c_stack}{K-Bytes} Set the limit to which the C~stack of this thread may grow. The default, minimum and maximum values are system-dependent. \end{description} The \arg{Goal} argument is \emph{copied} to the new Prolog engine. This implies that further instantiation of this term in either thread does not have consequences for the other thread: Prolog threads do not share data from their stacks. \predicate{thread_self}{1}{-Id} Get the Prolog thread identifier of the running thread. If the thread has an alias, the alias name is returned. \predicate{thread_join}{1}{+Id} Calls \index{thread_join/2}\predref{thread_join}{2} and succeeds if thread \arg{Id} terminated with success. Otherwise the exception \term{error}{\term{thread_error}{Id, Status}, _} is raised, where \arg{Status} is the status as returned by \index{thread_join/2}\predref{thread_join}{2}. \predicate{thread_join}{2}{+Id, -Status} Wait for the termination of the thread with the given \arg{Id}. Then unify the result status of the thread with \arg{Status}. After this call, \arg{Id} becomes invalid and all resources associated with the thread are reclaimed. It is not allowed for two threads to join the same thread and the thread being joined cannot be \jargon{detached} (see the \term{detached}{true} option for \index{thread_create/3}\predref{thread_create}{3} and \index{thread_detach/1}\predref{thread_detach}{1}). A thread that has been completed without \index{thread_join/2}\predref{thread_join}{2} being called on it is partly reclaimed: the Prolog stacks are released and the C thread is destroyed. A small data structure representing the exit status of the thread is retained until \index{thread_join/2}\predref{thread_join}{2} is called on the thread. Defined values for \arg{Status} are: \begin{description} \termitem{true}{} The goal has been proven successfully. \termitem{false}{} The goal has failed. \termitem{exception}{Term} The thread is terminated on an exception. See \index{print_message/2}\predref{print_message}{2} to turn system exceptions into readable messages. \termitem{exited}{Term} The thread is terminated on \index{thread_exit/1}\predref{thread_exit}{1} using the argument \arg{Term}. \end{description} Note that the pthread primitive pthread_join() cannot be interrupted. Some systems provide pthread_timedjoin_np(). If this is provided \index{thread_join/2}\predref{thread_join}{2} is implemented as a loop of timed joins with a 0.25 sec timeout while signals are being tested after each timeout. Such systems allow combining \index{thread_join/2}\predref{thread_join}{2} with \index{call_with_time_limit/2}\predref{call_with_time_limit}{2} as well as signalling threads blocked in \index{thread_join/2}\predref{thread_join}{2} using \index{thread_signal/2}\predref{thread_signal}{2}. \predicate{thread_alias}{1}{+Alias} Set the alias name of the calling thread to \arg{Alias}. An error is raised if the calling thread already has an alias or \arg{Alias} is in use for a thread or message queue. \predicate{thread_detach}{1}{+Id} Switch thread into detached state (see \term{detached}{Bool} option at \index{thread_create/3}\predref{thread_create}{3}) at runtime. \arg{Id} is the identifier of the thread placed in detached state. This may be the result of \index{thread_self/1}\predref{thread_self}{1}. One of the possible applications is to simplify debugging. Threads that are created as \jargon{detached} leave no traces if they crash. For non-detached threads the status can be inspected using \index{thread_property/2}\predref{thread_property}{2}. Threads nobody is waiting for may be created normally and detach themselves just before completion. This way they leave no traces on normal completion and their reason for failure can be inspected. \predicate[deprecated]{thread_exit}{1}{+Term} Terminates the thread immediately, leaving \term{exited}{Term} as result state for \index{thread_join/2}\predref{thread_join}{2}. If the thread has the attribute \term{detached}{true} it terminates, but its exit status cannot be retrieved using \index{thread_join/2}\predref{thread_join}{2}, making the value of \arg{Term} irrelevant. The Prolog stacks and C thread are reclaimed. The current implementation does not guarantee proper releasing of all mutexes and proper cleanup in \index{setup_call_cleanup/3}\predref{setup_call_cleanup}{3}, etc. Please use the exception mechanism (\index{throw/1}\predref{throw}{1}) to abort execution using non-standard control.\bug{The Windows port does not properly cleanup for \jargon{detached} threads while the cleanup for other threads is executed by the thread running \index{thread_join/2}\predref{thread_join}{2} using the exited thread as \jargon{engine}. This is due to a bug in the \href{https://sourceforge.net/p/mingw-w64/bugs/469/}{MinGW pthread implementation}.} \predicate{thread_initialization}{1}{:Goal} Run \arg{Goal} when thread is started. This predicate is similar to \index{initialization/1}\predref{initialization}{1}, but is intended for initialization operations of the runtime stacks, such as setting global variables as described in \secref{gvar}. \arg{Goal} is run on four occasions: at the call to this predicate, after loading a saved state, on starting a new thread and on creating a Prolog engine through the C interface. On loading a saved state, \arg{Goal} is executed \emph{after} running the \index{initialization/1}\predref{initialization}{1} hooks. \predicate{thread_at_exit}{1}{:Goal} Run \arg{Goal} just before releasing the thread resources. This is to be compared to \index{at_halt/1}\predref{at_halt}{1}, but only for the current thread. These hooks are run regardless of why the execution of the thread has been completed. When these hooks are run, the return code is already available through \index{thread_property/2}\predref{thread_property}{2} using the result of \index{thread_self/1}\predref{thread_self}{1} as thread identifier. Note that there are two scenarios for using exit hooks. Using \index{thread_at_exit/1}\predref{thread_at_exit}{1} is typically used if the thread creates a side-effect that must be reverted if the thread dies. Another scenario is where the creator of the thread wants to be informed when the thread ends. That cannot be guaranteed by means of \index{thread_at_exit/1}\predref{thread_at_exit}{1} because it is possible that the thread cannot be created or dies almost instantly due to a signal or resource error. The \term{at_exit}{Goal} option of \index{thread_create/3}\predref{thread_create}{3} is designed to deal with this scenario. The \arg{Goal} is executed with signal processing disabled. This avoids that e.g., \exam{thread_signal(Thread, abort)} kills the exit handler rather than the thread in the case the body of \arg{Thread} has just finished when the signal arrives. \predicate{thread_setconcurrency}{2}{-Old, +New} \index{Solaris}% Determine the concurrency of the process, which is defined as the maximum number of concurrently active threads. `Active' here means they are using CPU time. This option is provided if the thread implementation provides pthread_setconcurrency(). Solaris is a typical example of this family. On other systems this predicate unifies \arg{Old} to 0 (zero) and succeeds silently. \predicate{thread_affinity}{3}{+ThreadID, -Current, +New} True when \arg{Current} is unified with the current thread affinity and the thread affinity is successfully set to \arg{New}. The \jargon{thread affinity} specifies the set of CPUs on which this thread is allowed to run. The affinity is represented as a list of non-negative integers. See also the option \term{affinity}{+Affinity} of \index{thread_create/3}\predref{thread_create}{3}. This predicate is only present if this functionality can be supported and has been ported to the target operating system. Currently, only Linux support is provided. \end{description} \section{Monitoring threads} \label{sec:thmonitor} Normal multithreaded applications should not need the predicates from this section because almost any usage of these predicates is unsafe. For example checking the existence of a thread before signalling it is of no use as it may vanish between the two calls. Catching exceptions using \index{catch/3}\predref{catch}{3} is the only safe way to deal with thread-existence errors. These predicates are provided for diagnosis and monitoring tasks. See also \secref{thutil}, describing more high-level primitives. \begin{description} \predicate{is_thread}{1}{@Term} True if \arg{Term} is a handle to an existing thread. \predicate{thread_property}{2}{?Id, ?Property} True if thread \arg{Id} has \arg{Property}. Either or both arguments may be unbound, enumerating all relations on backtracking. Calling \index{thread_property/2}\predref{thread_property}{2} does not influence any thread. See also \index{thread_join/2}\predref{thread_join}{2}. For threads that have an alias name, this name is returned in \arg{Id} instead of the opaque thread identifier. Defined properties are: \begin{description} \termitem{alias}{Alias} \arg{Alias} is the alias name of thread \arg{Id}. \termitem{detached}{Boolean} Current detached status of the thread. \termitem{id}{Integer} Integer identifier for the thread. Can be used as argument to the thread predicates, but applications must be aware that these references are reused. \termitem{status}{Status} Current status of the thread. \arg{Status} is one of: \begin{description} \termitem{running}{} The thread is running. This is the initial status of a thread. Please note that threads waiting for something are considered running too. \termitem{suspended}{} Only if the thread is an engine (see \secref{engines}). Indicates that the engine is currently not associated with an OS thread. \termitem{false}{} The \arg{Goal} of the thread has been completed and failed. \termitem{true}{} The \arg{Goal} of the thread has been completed and succeeded. \termitem{exited}{Term} The \arg{Goal} of the thread has been terminated using \index{thread_exit/1}\predref{thread_exit}{1} with \arg{Term} as argument. If the underlying native thread has exited (using pthread_exit()) \arg{Term} is unbound. \termitem{exception}{Term} The \arg{Goal} of the thread has been terminated due to an uncaught exception (see \index{throw/1}\predref{throw}{1} and \index{catch/3}\predref{catch}{3}). \end{description} \termitem{engine}{Boolean} If the thread is an engine (see \chapref{engines}), \arg{Boolean} is \const{true}. Otherwise the property is not present. \termitem{thread}{ThreadId} If the thread is an engine that is currently attached to a thread, \arg{ThreadId} is the thread that executes the engine. \termitem{size}{Bytes} The amount of memory associated with this thread. This includes the thread structure, its stacks, its default message queue, its clauses in its thread local dynamic predicates (see \index{thread_local/1}\predref{thread_local}{1}) and memory used for representing thread-local answer tries (see \secref{tabling}). \termitem{system_thread_id}{Integer} Thread identifier used by the operating system for the calling thread. Not available on all OSes. This is the same as the Prolog flag \prologflag{system_thread_id} for the calling thread. Access to the system thread identifier can, on some systems, be used to gain additional control over or information about Prolog threads. \end{description} See also \index{thread_statistics/3}\predref{thread_statistics}{3} to obtain resource usage information and \index{message_queue_property/2}\predref{message_queue_property}{2} to get the number of queued messages for a thread. \predicate{thread_statistics}{3}{+Id, +Key, -Value} Obtains statistical information on thread \arg{Id} as \index{statistics/2}\predref{statistics}{2} does in single-threaded applications. This call supports all keys of \index{statistics/2}\predref{statistics}{2}, although only stack sizes, \const{cputime}, \const{inferences}, \const{epoch}, \const{errors} and \const{warnings} yield different values for each thread. For \const{errors} and \const{warnings} \index{statistics/2}\predref{statistics}{2} gives the global process count and this predicate gives the counts for the calling thread.% \footnote{There is no portable interface to obtain thread-specific CPU time and some operating systems provide no access to this information at all. On such systems the total process CPU is returned. Thread CPU time is supported on MS-Windows, Linux and MacOSX.} \predicate{mutex_statistics}{0}{} Print usage statistics on internal mutexes and mutexes associated with dynamic predicates. For each mutex two numbers are printed: the number of times the mutex was acquired and the number of \jargon{collisions}: the number of times the calling thread has to wait for the mutex. The output is written to \const{current_output} and can thus be redirected using \index{with_output_to/2}\predref{with_output_to}{2}. \end{description} \section{Thread communication} \label{sec:threadcom} \subsection{Message queues} \label{sec:msgqueue} Prolog threads can exchange data using dynamic predicates, database records, and other globally shared data. These provide no suitable means to wait for data or a condition as they can only be checked in an expensive polling loop. \jargon{Message queues} provide a means for threads to wait for data or conditions without using the CPU. Each thread has a message queue attached to it that is identified by the thread. Additional queues are created using \index{message_queue_create/1}\predref{message_queue_create}{1}. Explicitly created queues come in two flavours. When given an \jargon{alias}, they must be destroyed by the user. \jargon{Anonymous} message queues are identified by a \jargon{blob} (see \secref{blob}) and subject to garbage collection. \begin{description} \predicate{thread_send_message}{2}{+QueueOrThreadId, +Term} Place \arg{Term} in the given queue or default queue of the indicated thread (which can even be the message queue of itself, see \index{thread_self/1}\predref{thread_self}{1}). Any term can be placed in a message queue, but note that the term is copied to the receiving thread and variable bindings are thus lost. This call returns immediately. If more than one thread is waiting for messages on the given queue and at least one of these is waiting with a partially instantiated \arg{Term}, the waiting threads are \emph{all} sent a wake-up signal, starting a rush for the available messages in the queue. This behaviour can seriously harm performance with many threads waiting on the same queue as all-but-the-winner perform a useless scan of the queue. If there is only one waiting thread or all waiting threads wait with an unbound variable, an arbitrary thread is restarted to scan the queue.% \footnote{See the documentation for the POSIX thread functions pthread_cond_signal() v.s.\ pthread_cond_broadcast() for background information.} \predicate[semidet]{thread_send_message}{3}{+Queue, +Term, +Options} As \index{thread_send_message/2}\predref{thread_send_message}{2}, but providing additional \arg{Options}. These are to deal with the case that the queue has a finite maximum size and is full: whereas \index{thread_send_message/2}\predref{thread_send_message}{2} will block until the queue has drained sufficiently to accept a new message, \index{thread_send_message/3}\predref{thread_send_message}{3} can accept a time-out or deadline analogously to \index{thread_get_message/3}\predref{thread_get_message}{3}. The options are: \begin{description} \termitem{deadline}{+AbsTime} The call fails (silently) if no space has become available before \arg{AbsTime}. See \index{get_time/1}\predref{get_time}{1} for the representation of absolute time. If \arg{AbsTime} is earlier then the current time, \index{thread_send_message/3}\predref{thread_send_message}{3} fails immediately. Both resolution and maximum wait time is platform-dependent.\footnote{The implementation uses MsgWaitForMultipleObjects() on MS-Windows and pthread_cond_timedwait() on other systems.} \termitem{timeout}{+Time} \arg{Time} is a float or integer and specifies the maximum time to wait in seconds. This is a relative-time version of the \const{deadline} option. If both options are provided, the earlier time is effective. If \arg{Time} is 0 or 0.0, \index{thread_send_message/3}\predref{thread_send_message}{3} examines the queue and sends the message if space is available, but does not suspend if no space is available, failing immediately instead. If \arg{Time} $< 0$, \index{thread_send_message/3}\predref{thread_send_message}{3} fails immediately without sending the message. \end{description} \predicate{thread_get_message}{1}{?Term} Examines the thread message queue and if necessary blocks execution until a term that unifies to \arg{Term} arrives in the queue. After a term from the queue has been unified to \arg{Term}, the term is deleted from the queue. Please note that non-unifying messages remain in the queue. After the following has been executed, thread 1 has the term \term{b}{gnu} in its queue and continues execution using \arg{A}~=~\const{gnat}. \begin{code} thread_get_message(a(A)), thread_send_message(Thread_1, b(gnu)), thread_send_message(Thread_1, a(gnat)), \end{code} \noindent \arg{Term} may contain attributed variables (see \secref{clp}), in which case only terms for which the constraints successfully execute are returned. Handle constraints applies for all predicates that extract terms from message queues. For example, we can get the even numbers from a queue using this code: \begin{code} get_matching_messages(Queue, Pattern, [H|T]) :- copy_term(Pattern, H), thread_get_message(Queue, H, [timeout(0)]), !, get_matching_messages(Queue, Pattern, T). get_matching_messages(_, _, []). even_numbers(Q, List) :- freeze(Even, Even mod 2 =:= 0), get_matching_messages(Q, Even, List). \end{code} \noindent See also \index{thread_peek_message/1}\predref{thread_peek_message}{1}. \predicate{thread_peek_message}{1}{?Term} Examines the thread message queue and compares the queued terms with \arg{Term} until one unifies or the end of the queue has been reached. In the first case the call succeeds, possibly instantiating \arg{Term}. If no term from the queue unifies, this call fails. I.e., \index{thread_peek_message/1}\predref{thread_peek_message}{1} never waits and does not remove any term from the queue. See also \index{thread_get_message/3}\predref{thread_get_message}{3}. \predicate{message_queue_create}{1}{?Queue} Equivalent to \exam{message_queue_create(Queue,[])}. For compatibility, calling \term{message_queue_create}{+Atom} is equivalent to \term{message_queue_create}{Queue, [alias(Atom)]}. New code should use \index{message_queue_create/2}\predref{message_queue_create}{2} to create a named queue. \predicate{message_queue_create}{2}{-Queue, +Options} Create a message queue from \arg{Options}. Defined options are: \begin{description} \termitem{alias}{+Alias} Create a message queue that is identified by the atom \arg{Alias}. Message queues created this way must be explicitly destroyed by the user. If the alias option is omitted, an \emph{Anonymous} queue is created that is identified by a \jargon{blob} (see \secref{blob}) and subject to garbage collection.\footnote{Garbage collecting anonymous message queues is not part of the ISO proposal and most likely not a widely implemented feature.} \termitem{max_size}{+Size} Maximum number of terms in the queue. If this number is reached, \index{thread_send_message/2}\predref{thread_send_message}{2} will suspend until the queue is drained. The option can be used if the source, sending messages to the queue, is faster than the drain, consuming the messages. \end{description} \predicate[det]{message_queue_destroy}{1}{+Queue} Destroy a message queue created with \index{message_queue_create/1}\predref{message_queue_create}{1}. A permission error is raised if \arg{Queue} refers to (the default queue of) a thread. Other threads that are waiting for \arg{Queue} using \index{thread_get_message/2}\predref{thread_get_message}{2} receive an existence error. \predicate[det]{thread_get_message}{2}{+Queue, ?Term} As \index{thread_get_message/1}\predref{thread_get_message}{1}, operating on a given queue. It is allowed (but not advised) to get messages from the queue of other threads. This predicate raises an existence error exception if \arg{Queue} doesn't exist or is destroyed using \index{message_queue_destroy/1}\predref{message_queue_destroy}{1} while this predicate is waiting. \predicate[semidet]{thread_get_message}{3}{+Queue, ?Term, +Options} As \index{thread_get_message/2}\predref{thread_get_message}{2}, but providing additional \arg{Options}: \begin{description} \termitem{deadline}{+AbsTime} The call fails (silently) if no message has arrived before \arg{AbsTime}. See \index{get_time/1}\predref{get_time}{1} for the representation of absolute time. If \arg{AbsTime} is earlier then the current time, \index{thread_get_message/3}\predref{thread_get_message}{3} fails immediately. Both resolution and maximum wait time is platform-dependent.\footnote{The implementation uses MsgWaitForMultipleObjects() on MS-Windows and pthread_cond_timedwait() on other systems.} \termitem{timeout}{+Time} \arg{Time} is a float or integer and specifies the maximum time to wait in seconds. This is a relative-time version of the \const{deadline} option. If both options are provided, the earlier time is effective. If \arg{Time} is 0 or 0.0, \index{thread_get_message/3}\predref{thread_get_message}{3} examines the queue but does not suspend if no matching term is available. Note that unlike \index{thread_peek_message/2}\predref{thread_peek_message}{2}, a matching term is removed from the queue. If \arg{Time} $< 0$, \index{thread_get_message/3}\predref{thread_get_message}{3} fails immediately without removing any message from the queue. \end{description} \predicate[semidet]{thread_peek_message}{2}{+Queue, ?Term} As \index{thread_peek_message/1}\predref{thread_peek_message}{1}, operating on a given queue. It is allowed to peek into another thread's message queue, an operation that can be used to check whether a thread has swallowed a message sent to it. \predicate{message_queue_property}{2}{?Queue, ?Property} True if \arg{Property} is a property of \arg{Queue}. Defined properties are: \begin{description} \termitem{alias}{Alias} Queue has the given alias name. \termitem{max_size}{Size} Maximum number of terms that can be in the queue. See \index{message_queue_create/2}\predref{message_queue_create}{2}. This property is not present if there is no limit (default). \termitem{size}{Size} Queue currently contains \arg{Size} terms. Note that due to concurrent access the returned value may be outdated before it is returned. It can be used for debugging purposes as well as work distribution purposes. \termitem{waiting}{-Count} Number of threads waiting for this queue. This property is not present if no threads waits for this queue. \end{description} The \term{size}{Size} property is always present and may be used to enumerate the created message queues. Note that this predicate does \emph{not enumerate} threads, but can be used to query the properties of the default queue of a thread. \predicate{message_queue_set}{2}{+Queue, +Property} Set a property on the queue. Supported properties are: \begin{description} \termitem{max_size}{+Size} Change the number of terms that may appear in the message queue before the next \index{thread_send_message/[2,3]}\predref{thread_send_message}{[2,3]} blocks on it. If the value is higher then the current maximum and the queue has writers waiting, wakeup the writers. The value can be lower than the current number of terms in the queue. In that case writers will block until the queue is drained below the new maximum. \end{description} \end{description} Explicit message queues are designed with the \jargon{worker-pool} model in mind, where multiple threads wait on a single queue and pick up the first goal to execute. Below is a simple implementation where the workers execute arbitrary Prolog goals. Note that this example provides no means to tell when all work is done. This must be realised using additional synchronisation. \begin{code} %% create_workers(?Id, +N) % % Create a pool with Id and number of workers. % After the pool is created, post_job/1 can be used to % send jobs to the pool. create_workers(Id, N) :- message_queue_create(Id), forall(between(1, N, _), thread_create(do_work(Id), _, [])). do_work(Id) :- repeat, thread_get_message(Id, Goal), ( catch(Goal, E, print_message(error, E)) -> true ; print_message(error, goal_failed(Goal, worker(Id))) ), fail. %% post_job(+Id, +Goal) % % Post a job to be executed by one of the pool's workers. post_job(Id, Goal) :- thread_send_message(Id, Goal). \end{code} \noindent \subsection{Waiting for events} \label{sec:thread-wait} \index{blackboard}% While message queues realizes communicating \jargon{agents} sharing the same program and optionally dynamic data, the predicate \index{thread_wait/2}\predref{thread_wait}{2} facilitates agents that communicate based on a \jargon{shared blackboard}. An important difference is were message queues require the sender and receiver to know about the queue used to communicate and every message can wakeup at most one thread, the blackboard model allows any number (including zero) of threads to \jargon{listen} to changes on the blackboard. Any module can act as a blackboard. The blackboard can be updated using the standard Prolog database update predicates (\index{assert/1}\predref{assert}{1}, \index{retract/1}\predref{retract}{1} and friends). \index{condition variable}% Waiting is implemented using a POSIX \jargon{condition variable} and matching \jargon{mutex}. On a matching database change the condition variable is signalled using a \jargon{broadcast}, waking up all threads waiting in \index{thread_wait/2}\predref{thread_wait}{2}. Multiple database updates can be grouped and cause a single wakeup using \index{thread_update/2}\predref{thread_update}{2}. This predicate also allows signalling the module condition variable without updating the database and controlling whether all or a single thread is activated. The blackboard architecture is a good match for an intelligent agent system that has to react on a changing world. Input threads gather sensor data from the world and update a shared world view in a set of dynamic predicates in one or more modules. Agent threads listen to this data or a subset thereof and trigger actions. This is notably a good match with \jargon{tabling}, in particular incremental tabling (see \secref{tabling-incremental}) and \jargon{Well Founded Semantics} (see \secref{WFS}).\footnote{Future versions may provide additional triggers, for example to learn about invalidated tables. Please share your experience.} \begin{description} \predicate{thread_wait}{2}{:Goal, :Options} Block execution of the calling thread until \arg{Goal} becomes true. The application must be prepared to handle spurious calls to \arg{Goal}, i.e., more calls than asked for based on the \arg{Options} list. A possible exception in \arg{Goal} is propagated and thus terminates \index{thread_wait/2}\predref{thread_wait}{2}. The wait is associated with a module. This module is derived from the \arg{Options} argument. The \arg{Options} list specifies when \arg{Goal} is re-evaluated and optionally when the call terminates due to a timeout. \begin{description} \termitem{deadline}{+AbsTime} \nodescription \termitem{timeout}{+Time} Timeout and deadline handling. See \index{thread_get_message/3}\predref{thread_get_message}{3} for details. This predicate fails when it terminates due to one of these options. \termitem{retry_every}{+Time} Retry goal every \arg{Time} seconds regardless of whether an event happened. The default is 1 second. This ensures that signals (see \index{thread_signal/2}\predref{thread_signal}{2}) and time limits are respected with an optional delay.\footnote{Some operating systems process such signals immediately, while others only check for such events synchronously.} \termitem{db}{+Boolean} Wakeup on arbitrary changes to any dynamic predicate that is defined in the associated module. This is the default if \term{wait_preds}{+Preds} is not provided. \termitem{wait_preds}{+List} Only call \arg{Goal} if at least one of the predicates in \arg{List} has been modified. Each element of \arg{List} is a \jargon{predicate indicator} (\textit{Name/Arity} or \textit{Name//Arity} that is resolved to a predicate in the module this wait is associated with. If the element is \term{\Splus}{PI}\footnote{Note that \exam{+\index{p/1}\predref{p}{1}} is read as /(+(p),1).}, \arg{Goal} is only triggered if a clause was added (\index{assert/1}\predref{assert}{1}). If the element is \term{\Sminus}{PI}, \arg{Goal} is only triggered if a clause was retracted (\index{retract/1}\predref{retract}{1} or \index{erase/1}\predref{erase}{1}). Default is to wakeup on both assert and retract. \termitem{modified}{-List} The \arg{List} variable normally also appears in \arg{Goal} and is unified with a list of predicates from the \const{wait_preds} option that have been modified. \arg{List} must be unbound at entry. \termitem{module}{+Module} Specifies the module to act on explicitly. \end{description} The execution of \arg{Goal} is synchronized between all threads calling this predicate on the same module, changes to dynamic predicates in this module and calls to \index{thread_update/2}\predref{thread_update}{2} on the same module. This predicate raises a \const{permision_error} exception when called recursively or called from inside a transaction. See \secref{transaction-impact} for details about interaction with transactions. \predicate{thread_update}{2}{:Goal, :Options} Update a module (typically using \index{assert/1}\predref{assert}{1} and/or \index{retract/1}\predref{retract}{1} and friends) and on completion signal threads waiting for this module using \index{thread_wait/2}\predref{thread_wait}{2} to reevaluate their \arg{Goal}. \arg{Goal} is synchronized between updating and waiting threads. \arg{Options}: \begin{description} \termitem{module}{+Module} Determines the module to operate on. Default is the context module associated with the \arg{Options} argument. \termitem{notify}{+Atom} Determines whether all waiting threads are activated (\const{broadcast}, default) or a single thread (\const{signal}). \end{description} \end{description} \textit{Compatibility} The \index{thread_wait/2}\predref{thread_wait}{2} predicate is modelled after the \href{http://staff.itee.uq.edu.au/pjr/HomePages/QuPrologHome.html}{Qu-Prolog} predicate \index{thread_wait_on_goal/2}\predref{thread_wait_on_goal}{2}. It is largely compatible. Our current implementation does not support predicate time stamps.\footnote{See \index{predicate_property/2}\predref{predicate_property}{2}, property \const{generation}.} We made this predicate act on a specific module rather than the entire database. The timeout specification follows that of the other thread waiting predicates and may be combined with the \const{retry_every} option. The default retry-time is also 1 second rather than \textit{infinite}. \subsection{Signalling threads} \label{sec:thread-signal} The predicates in this section provide \jargon{signalling} between threads. A thread signal inserts any goal as an \jargon{interrupt} into the control flow of any target thread. The target thread processes the goal at the first safe opportunity. The mechanism was introduced with two goals in mind: (1) running a goal inside a thread for debugging purposes such as enabling the status or get access thread-specific data and (2) force a thread to abort its current goal by inserting an exeption into its control flow. Over time, more complicated use cases have been identified that may result in multiple signals that occur (nearly) simultaneous. As of version 8.5.1 the interface has been extended and the interaction with other built-in predicates has been specified in much more detail. \begin{description} \predicate[det]{thread_signal}{2}{+ThreadId, :Goal} Make thread \arg{ThreadId} execute \arg{Goal} at the first opportunity. The predicate \index{thread_signal/2}\predref{thread_signal}{2} itself places \arg{Goal} into the signalled thread's signal queue and returns immediately. \arg{ThreadId} executes \arg{Goal} as an \jargon{interrupt} at the first opportunity. Defined opportunities are: \begin{itemize} \item At the \jargon{call port} of any predicate except for predicates with the property \const{sig_atomic}. Currently this only applies to \index{sig_atomic/1}\predref{sig_atomic}{1}. \item Before retrying a foreign predicate. \item Before backtracking to the next clause of a Prolog predicate. \item When a foreign predicate calls \cfuncref{PL_handle_signals}{}. Foreign predicates that take long to complete should call \cfuncref{PL_handle_signals}{} regularly and return with \const{FALSE} after \cfuncref{PL_handle_signals}{} returned -1, indicating an exception was raised. \item Foreign predicates calling \jargon{blocking system calls} should attempt to make these system calls interruptible. To enable this on POSIX systems, SWI-Prolog sends a \const{SIGUSR2} to the signalled thread while the handler is an empty function. This causes most blocking system calls to return with \const{EINTR}. See also the commandline option \cmdlineoption{--sig-alert}. On Windows, \cfuncref{PL_handle_signals}{} is called when the user processes Windows messages. \item For some blocking (thread) APIs we use a timed version with a 0.25 sec timeout to achieve a \jargon{polling loop}. \end{itemize} If one or more signals are queued, the queue is processed. Processing the queue skips signals blocked due to \index{sig_block/1}\predref{sig_block}{1} and stops after the queue does not contain any more non-blocked signals or processing a signal results in an exception. After an exception, other signals remain in the queue and will be processed after unwinding to the matching \index{catch/3}\predref{catch}{3}. Typically these queued signals will be processed during the \arg{Recover} goal of the \index{catch/3}\predref{catch}{3}. Note that \index{sig_atomic/1}\predref{sig_atomic}{1} may be used to protect the recovery goal. The \index{thread_signal/2}\predref{thread_signal}{2} mechanism is primarily used by the system to insert debugging goals into the target thread (\index{tspy/1}\predref{tspy}{1}, \index{tbacktrace/1}\predref{tbacktrace}{1}, etc.) or to interrupt a thread using e.g., \exam{thread_signal(Thread, abort)}. Predicates from library \pllib{thread} use signals to stop workers for e.g. \index{concurrent_maplist/2}\predref{concurrent_maplist}{2} if some call fails. Applications may use it, typically for similar purposes such as asynchronously stopping tasks or inspecting the status of a task. Below we describe the behaviour of thread signalling in more detail. The following notes apply for \arg{Goal} executing in \arg{ThreadId} \begin{itemize} \item The execution is protected by \index{sig_atomic/1}\predref{sig_atomic}{1} and thus signal execution is \emph{not nested}. \item If \arg{Goal} \emph{succeeds}, possible choice points are discarded. Changes to the Prolog stacks such as changes to backtrackable global variables remain. \item If \arg{Goal} \emph{fails}, no action is taken, i.e., failure is not considered a special condition. \item If \arg{Goal} \emph{raises an exception} the exeception is propagated into the environment. This allows for forcefully stopping the target thread. The system uses this to implement \index{abort/0}\predref{abort}{0} and \index{call_with_time_limit/2}\predref{call_with_time_limit}{2}. \item Code into which signals may be injected must make sure to use \index{setup_call_cleanup/3}\predref{setup_call_cleanup}{3} and friends to ensure proper cleanup in the case of an exception. This is good practice anyway to guard against unpredicatable exceptions such as resource exhaustion. \item \arg{Goal} may use stack inspection such as \index{prolog_frame_attribute/3}\predref{prolog_frame_attribute}{3} to determine what the thread is doing. \end{itemize} \predicate[det]{sig_pending}{1}{-List} True when \arg{List} contains all signals submitted using \index{thread_signal/2}\predref{thread_signal}{2} that are not yet processed. This includes signals blocked by \index{sig_block/1}\predref{sig_block}{1}. \predicate[det]{sig_remove}{2}{:Pattern, -List} Remove all signals that unify with \arg{Pattern} from the signal queue and make the removed signals available in \arg{List} \predicate[det]{sig_block}{1}{:Pattern} Block thread signals queued using \index{thread_signal/2}\predref{thread_signal}{2} that match \arg{Pattern}. \predicate[det]{sig_unblock}{1}{:Pattern} Remove any effect of \index{sig_block/1}\predref{sig_block}{1} for patterns that are more specific (see \index{subsumes_term/2}\predref{subsumes_term}{2}). If any patterns are removed, reschedule blocked signals. Note that \index{sig_unblock/1}\predref{sig_unblock}{1} normally causes all unblocked signals to be executed immediately. \predicate[semidet]{sig_atomic}{1}{:Goal} Execute \arg{Goal} as \index{once/1}\predref{once}{1} while blocking both thread signals (see \index{thread_signal/2}\predref{thread_signal}{2}) and OS signals (see \index{on_signal/3}\predref{on_signal}{3}). The system executes some goals while blocking signals. These are: \begin{itemize} \item The goal injected using \index{thread_signal/2}\predref{thread_signal}{2}, i.e., signals do not interrupt a running signal handler. \item The \arg{Setup} call of \index{setup_call_cleanup/3}\predref{setup_call_cleanup}{3} and friends. \item The \arg{Cleanup} call of \index{call_cleanup/2}\predref{call_cleanup}{2} and friends. \item Compiling a file or loading a \jargon{quick load file}. \end{itemize} The call port of \index{sig_atomic/1}\predref{sig_atomic}{1} does not handle signals. This may notably be used to prevent interruption of the \index{catch/3}\predref{catch}{3} \arg{Recover} goal. For example, we may ensure the recovery goal of a timeout is called using the code below. Without this precaution another signal may run before \index{writeln/1}\predref{writeln}{1} and raise an exception to prevent its execution. Note that \index{catch/3}\predref{catch}{3} should generally \emph{not} be used for cleanup of resources in case of an exception and thus it is typically fine if its \arg{Recover} goal is interrupted. Use \index{setup_call_cleanup/3}\predref{setup_call_cleanup}{3} or one of the other predicates from the \index{call_cleanup/2}\predref{call_cleanup}{2} family for cleanup. \begin{code} ..., catch(call_with_time_limit(Time, Goal), time_limit_exceeded, sig_atomic(writeln('Time limit exceeded'))). \end{code} \noindent \end{description} \subsection{Threads and dynamic predicates} \label{sec:threadlocal} Besides queues (\secref{msgqueue}) threads can share and exchange data using dynamic predicates. The multithreaded version knows about two types of dynamic predicates. By default, a predicate declared \jargon{dynamic} (see \index{dynamic/1}\predref{dynamic}{1}) is shared by all threads. Each thread may assert, retract and run the dynamic predicate. Synchronisation inside Prolog guarantees the consistency of the predicate. Updates are \jargon{logical}: visible clauses are not affected by assert/retract after a query started on the predicate. In many cases primitives from \secref{threadsync} should be used to ensure that application invariants on the predicate are maintained. Besides shared predicates, dynamic predicates can be declared with the \index{thread_local/1}\predref{thread_local}{1} directive. Such predicates share their attributes, but the clause list is different in each thread. \begin{description} \prefixop{thread_local}{+Functor/+Arity, \ldots} This directive is related to the \index{dynamic/1}\predref{dynamic}{1} directive. It tells the system that the predicate may be modified using \index{assert/1}\predref{assert}{1}, \index{retract/1}\predref{retract}{1}, etc., during execution of the program. Unlike normal shared dynamic data, however, each thread has its own clause list for the predicate. As a thread starts, this clause list is empty. If there are still clauses when the thread terminates, these are automatically reclaimed by the system (see also \index{volatile/1}\predref{volatile}{1}). The thread_local property implies the properties \jargon{dynamic} and \jargon{volatile}. Thread-local dynamic predicates are intended for maintaining thread-specific state or intermediate results of a computation. It is not recommended to put clauses for a thread-local predicate into a file, as in the example below, because the clause is only visible from the thread that loaded the source file. All other threads start with an empty clause list. \begin{code} :- thread_local foo/1. foo(gnat). \end{code} \noindent \textbf{DISCLAIMER} Whether or not this declaration is appropriate in the sense of the proper mechanism to reach the goal is still debated. If you have strong feelings in favour or against, please share them in the SWI-Prolog mailing list. \end{description} \section{Thread synchronisation} \label{sec:threadsync} All internal Prolog operations are thread-safe. This implies that two Prolog threads can operate on the same dynamic predicate without corrupting the consistency of the predicate. This section deals with user-level \jargon{mutexes} (called \jargon{monitors} in ADA or \jargon{critical sections} by Microsoft). A mutex is a {\bf MUT}ual {\bf EX}clusive device, which implies that at most one thread can \jargon{hold} a mutex. Mutexes are used to realise related updates to the Prolog database. With `related', we refer to the situation where a `transaction' implies two or more changes to the Prolog database. For example, we have a predicate \nopredref{address}{2}, representing the address of a person and we want to change the address by retracting the old and asserting the new address. Between these two operations the database is invalid: this person has either no address or two addresses, depending on the assert/retract order. The code below provides a solution to this problem based on \index{with_mutex/2}\predref{with_mutex}{2}. It also illustrates the problem of mutexes. The predicate \index{with_mutex/2}\predref{with_mutex}{2} behaves as \index{once/1}\predref{once}{1} with respect to the guarded goal. This means that our predicate \nopredref{address}{2} is no longer a nice logical non-deterministic relation. This could be solved by explicit locking and unlocking a mutex using \index{setup_call_cleanup/3}\predref{setup_call_cleanup}{3}, but at the risk of deadlocking the program if the choice point is left open by accident. \begin{code} change_address(Id, Address) :- with_mutex(addressbook, ( retractall(address_db(Id, _)), asserta(address_db(Id, Address)) )). address(Id, Address) :- with_mutex(addressbook, address_db(Id, Address)). \end{code} \noindent Message queues (see \index{message_queue_create/2}\predref{message_queue_create}{2}) often provide simpler and more robust ways for threads to communicate. Still, mutexes can be a sensible solution and are therefore provided. \begin{description} \predicate{mutex_create}{1}{?MutexId} Create a mutex. If \arg{MutexId} is an atom, a \jargon{named} mutex is created. If it is a variable, an anonymous mutex reference is returned. Anonymous mutexes are subject to (atom) garbage collection. \predicate{mutex_create}{2}{-MutexId, +Options} Create a mutex using options. Defined options are: \begin{description} \termitem{alias}{Alias} Set the alias name. Using \term{mutex_create}{X, [alias(name)]} is preferred over the equivalent \term{mutex_create}{name}. \end{description} \predicate{mutex_destroy}{1}{+MutexId} Destroy a mutex. If the mutex is not locked, it is destroyed and further access yields an \except{existence_error} exception. As of version 7.1.19, this behaviour is reliable. If the mutex is locked, the mutex is scheduled for \emph{delayed destruction}: it will be destroyed when it becomes unlocked. \predicate{with_mutex}{2}{+MutexId, :Goal} Execute \arg{Goal} while holding \arg{MutexId}. If \arg{Goal} leaves choice points, these are destroyed (as in \index{once/1}\predref{once}{1}). The mutex is unlocked regardless of whether \arg{Goal} succeeds, fails or raises an exception. An exception thrown by \arg{Goal} is re-thrown after the mutex has been successfully unlocked. See also \index{mutex_create/1}\predref{mutex_create}{1} and \index{setup_call_cleanup/3}\predref{setup_call_cleanup}{3}. Although described in the thread section, this predicate is also available in the single-threaded version, where it behaves simply as \index{once/1}\predref{once}{1}. \predicate{mutex_lock}{1}{+MutexId} Lock the mutex. Prolog mutexes are \jargon{recursive} mutexes: they can be locked multiple times by the same thread. Only after unlocking it as many times as it is locked does the mutex become available for locking by other threads. If another thread has locked the mutex the calling thread is suspended until the mutex is unlocked. If \arg{MutexId} is an atom, and there is no current mutex with that name, the mutex is created automatically using \index{mutex_create/1}\predref{mutex_create}{1}. This implies named mutexes need not be declared explicitly. Please note that locking and unlocking mutexes should be paired carefully. Especially make sure to unlock mutexes even if the protected code fails or raises an exception. For most common cases, use \index{with_mutex/2}\predref{with_mutex}{2}, which provides a safer way for handling Prolog-level mutexes. The predicate \index{setup_call_cleanup/3}\predref{setup_call_cleanup}{3} is another way to guarantee that the mutex is unlocked while retaining non-determinism. \predicate{mutex_trylock}{1}{+MutexId} As \index{mutex_lock/1}\predref{mutex_lock}{1}, but if the mutex is held by another thread, this predicates fails immediately. \predicate{mutex_unlock}{1}{+MutexId} Unlock the mutex. This can only be called if the mutex is held by the calling thread. If this is not the case, a \except{permission_error} exception is raised. \predicate[deprecated]{mutex_unlock_all}{0}{} Unlock all mutexes held by the current thread. This predicate should not be needed if mutex unlocking is guaranteed with \index{with_mutex/2}\predref{with_mutex}{2} or \index{setup_call_cleanup/3}\predref{setup_call_cleanup}{3}.\footnote{The also deprecated \index{thread_exit/1}\predref{thread_exit}{1} bypasses the automatic cleanup.} \predicate{mutex_property}{2}{?MutexId, ?Property} True if \arg{Property} is a property of \arg{MutexId}. Defined properties are: \begin{description} \termitem{alias}{Alias} Mutex has the defined alias name. See \index{mutex_create/2}\predref{mutex_create}{2} using the `alias' option. \termitem{status}{Status} Current status of the mutex. One of \const{unlocked} if the mutex is currently not locked, or \term{locked}{Owner, Count} if mutex is locked \arg{Count} times by thread \arg{Owner}. Note that unless \arg{Owner} is the calling thread, the locked status can change at any time. There is no useful application of this property, except for diagnostic purposes.% \bug{As \arg{Owner} and \arg{Count} are fetched separately from the mutex, the values may be inconsistent.} \end{description} \end{description} \section{Thread support library(threadutil)} \label{sec:thutil} This library defines a couple of useful predicates for demonstrating and debugging multithreaded applications. This library is certainly not complete. \begin{description} \predicate{threads}{0}{} Lists all current threads and their status. \predicate{join_threads}{0}{} 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 \index{join_threads/0}\predref{join_threads}{0} is intended for interactive sessions to reclaim resources from threads that died unexpectedly during development. \predicate{interactor}{0}{} Create a new console and run the Prolog top level in this new console. See also \index{attach_console/0}\predref{attach_console}{0}. In the Windows version a new interactor can also be created from the {\sf Run/New thread} menu. \end{description} \subsection{Debugging threads} \label{sec:threaddebug} 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 \secref{guitracer} (see \index{tspy/1}\predref{tspy}{1} and friends) or by attaching a console to the thread and running the traditional command line debugger (see \index{attach_console/0}\predref{attach_console}{0}). When using the graphical debugger, the debugger must be \emph{loaded} from the main thread (for example using guitracer) before \index{gtrace/0}\predref{gtrace}{0} can be called from a thread. \begin{description} \predicate{attach_console}{0}{} 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 \program{xterm} application. On Windows systems this requires the GUI version \program{swipl-win.exe} rather than the console-based \program{swipl.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: \begin{code} ?- thread_signal(10, (attach_console, trace)). \end{code} \noindent \predicate{tdebug}{1}{+ThreadId} Prepare \arg{ThreadId} for debugging using the graphical tracer. This implies installing the tracer hooks in the thread and switching the thread to debug mode using \index{debug/0}\predref{debug}{0}. The call is injected into the thread using \index{thread_signal/2}\predref{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. \predicate{tdebug}{0}{} Call \index{tdebug/1}\predref{tdebug}{1} in all running threads. \predicate{tnodebug}{1}{+ThreadId} Disable debugging thread \arg{ThreadId}. \predicate{tnodebug}{0}{} Disable debugging in all threads. \predicate{tspy}{2}{:Spec, +ThreadId} Set a spy point as \index{spy/1}\predref{spy}{1} and enable the thread for debugging using \index{tdebug/1}\predref{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. \predicate{tspy}{1}{:Spec} Set a spy point as \index{spy/1}\predref{spy}{1} and enable debugging in all threads using \index{tdebug/0}\predref{tdebug}{0}. Note that removing spy points can be done using \index{nospy/1}\predref{nospy}{1}. Disabling spy points in a specific thread is achieved by \index{tnodebug/1}\predref{tnodebug}{1}. \end{description} \subsection{Profiling threads} \label{sec:tprofile} In the current implementation, at most one thread can be profiled at any moment. Any thread can call \index{profile/1}\predref{profile}{1} to profile the execution of some part of its code. The predicate \index{tprofile/1}\predref{tprofile}{1} allows for profiling the execution of another thread until the user stops collecting profile data. \begin{description} \predicate{tprofile}{1}{+ThreadId} Start collecting profile data in \arg{ThreadId} and ask the user to hit \bnfmeta{return} to stop the profiler. See \secref{profile} for details on the execution profiler. \end{description} \section{Multithreaded mixed C and Prolog applications} \label{sec:foreignthread} All foreign code linked to the multithreading version of SWI-Prolog should be thread-safe (\jargon{reentrant}) or guarded in Prolog using \index{with_mutex/2}\predref{with_mutex}{2} from simultaneous access from multiple Prolog threads. If you want to write mixed multithreaded C and Prolog applications you should first familiarise yourself with writing multithreaded applications in C (C++). If you are using SWI-Prolog as an embedded engine in a multithreaded application you can access the Prolog engine from multiple threads by creating an \jargon{engine} in each thread from which you call Prolog. Without creating an engine, a thread can only use functions that do \emph{not} use the \type{term_t} type (for example \cfuncref{PL_new_atom}{}). The system supports two models. \Secref{threadoneone} describes the original one-to-one mapping. In this schema a native thread attaches a Prolog thread if it needs to call Prolog and detaches it when finished, as opposed to the model from \secref{threadmanymany}, where threads temporarily use a Prolog engine. \subsection{A Prolog thread for each native thread (one-to-one)} \label{sec:threadoneone} In the one-to-one model, the thread that called \cfuncref{PL_initialise}{} has a Prolog engine attached. If another C thread in the system wishes to call Prolog it must first attach an engine using \cfuncref{PL_thread_attach_engine}{} and call \cfuncref{PL_thread_destroy_engine}{} after all Prolog work is finished. This model is especially suitable with long running threads that need to do Prolog work regularly. See \secref{threadmanymany} for the alternative many-to-many model. \begin{description} \cfunction{int}{PL_thread_self}{} Returns the integer Prolog identifier of the engine or -1 if the calling thread has no Prolog engine. This function is also provided in the single-threaded version of SWI-Prolog, where it returns -2. \cfunction{int}{PL_unify_thread_id}{term_t t, int i} Unify \arg{t} with the Prolog thread identifier for thread \arg{i}. Thread identifiers are normally returned from \cfuncref{PL_thread_self}{}. Returns -1 if the thread does not exist or the unification fails. \cfunction{int}{PL_thread_attach_engine}{const PL_thread_attr_t *attr} Creates a new Prolog engine in the calling thread. If the calling thread already has an engine the reference count of the engine is incremented. The \arg{attr} argument can be \const{NULL} to create a thread with default attributes. Otherwise it is a pointer to a structure with the definition below.\footnote{The structure layout changed in version 7.7.14.} For any field with value `0', the default is used. The \const{cancel} field may be filled with a pointer to a function that is called when \cfuncref{PL_cleanup}{} terminates the running Prolog engines. If this function is not present or returns \const{FALSE} pthread_cancel() is used. The \const{flags} field defines the following flags: \begin{description} \termitem{PL_THREAD_NO_DEBUG}{} If this flag is present, the thread starts in normal no-debug status. By default, the debug status is inherited from the main thread. \termitem{PL_THREAD_NOT_DETACHED}{} By default the new thread is created in \jargon{detached} mode. With this flag it is created normally, allowing Prolog to \jargon{join} the thread. \end{description} \begin{code} typedef struct { size_t stack_limit; /* Total stack limit (bytes) */ size_t table_space; /* Total tabling space limit (bytes) */ char * alias; /* alias name */ int (*cancel)(int thread); /* cancel function */ intptr_t flags; /* PL_THREAD_* flags */ size_t max_queue_size; /* Max size of associated queue */ } PL_thread_attr_t; \end{code} \noindent The structure may be destroyed after \cfuncref{PL_thread_attach_engine}{} has returned. On success it returns the Prolog identifier for the thread (as returned by \cfuncref{PL_thread_self}{}). If an error occurs, -1 is returned. If this Prolog is not compiled for multithreading, -2 is returned. \cfunction{int}{PL_thread_destroy_engine}{} Destroy the Prolog engine in the calling thread. Only takes effect if \cfuncref{PL_thread_destroy_engine}{} is called as many times as \cfuncref{PL_thread_attach_engine}{} in this thread. Returns \const{TRUE} on success and \const{FALSE} if the calling thread has no engine or this Prolog does not support threads. Please note that construction and destruction of engines are relatively expensive operations. Only destroy an engine if performance is not critical and memory is a critical resource. \cfunction{int}{PL_thread_at_exit}{void (*function)(void *), void *closure, int global} Register a handle to be called as the Prolog engine is destroyed. The handler function is called with one \ctype{void *} argument holding \arg{closure}. If \arg{global} is \const{TRUE}, the handler is installed \emph{for all threads}. Globally installed handlers are executed after the thread-local handlers. If the handler is installed local for the current thread only (\arg{global} == \const{FALSE}) it is stored in the same FIFO queue as used by \index{thread_at_exit/1}\predref{thread_at_exit}{1}. \end{description} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % MANY-TO-MANY % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Pooling Prolog engines (many-to-many)} \label{sec:threadmanymany} In this model Prolog engines live as entities that are independent from threads. If a thread needs to call Prolog it takes one of the engines from the pool and returns the engine when done. This model is suitable in the following identified cases: \begin{itemlist} \item [Compatibility with the single-threaded version] In the single-threaded version, foreign threads must serialise access to the one and only thread engine. Functions from this section allow sharing one engine among multiple threads. \item [Many native threads with infrequent Prolog work] Prolog threads are expensive in terms of memory and time to create and destroy them. For systems that use a large number of threads that only infrequently need to call Prolog, it is better to take an engine from a pool and return it there. \item [Prolog status must be handed to another thread] This situation has been identified by Uwe Lesta when creating a .NET interface for SWI-Prolog. .NET distributes work for an active internet connection over a pool of threads. If a Prolog engine contains the state for a connection, it must be possible to detach the engine from a thread and re-attach it to another thread handling the same connection. \end{itemlist} \begin{description} \cfunction{PL_engine_t}{PL_create_engine}{PL_thread_attr_t *attributes} Create a new Prolog engine. \arg{attributes} is described with \cfuncref{PL_thread_attach_engine}{}. Any thread can make this call after \cfuncref{PL_initialise}{} returns success. The returned engine is not attached to any thread and lives until \cfuncref{PL_destroy_engine}{} is used on the returned handle. In the single-threaded version this call always returns \const{NULL}, indicating failure. \cfunction{int}{PL_destroy_engine}{PL_engine_t e} Destroy the given engine. Destroying an engine is only allowed if the engine is not attached to any thread or attached to the calling thread. On success this function returns \const{TRUE}, on failure the return value is \const{FALSE}. \cfunction{int}{PL_set_engine}{PL_engine_t engine, PL_engine_t *old} Make the calling thread ready to use \arg{engine}. If \arg{old} is non-\const{NULL} the current engine associated with the calling thread is stored at the given location. If \arg{engine} equals \const{PL_ENGINE_MAIN} the initial engine is attached to the calling thread. If \arg{engine} is \const{PL_ENGINE_CURRENT} the engine is not changed. This can be used to query the current engine. This call returns \const{PL_ENGINE_SET} if the engine was switched successfully, \const{PL_ENGINE_INVAL} if \arg{engine} is not a valid engine handle and \const{PL_ENGINE_INUSE} if the engine is currently in use by another thread. Engines can be changed at any time. For example, it is allowed to select an engine to initiate a Prolog goal, detach it and at a later moment execute the goal from another thread. Note, however, that the \ctype{term_t}, \ctype{qid_t} and \ctype{fid_t} types are interpreted relative to the engine for which they are created. Behaviour when passing one of these types from one engine to another is undefined. In the single-threaded version this call only succeeds if \arg{engine} refers to the main engine. \end{description} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % XPCE % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Multithreading and the XPCE graphics system} \label{sec:mt-xpce} \label{sec:xpcethread} GUI applications written in XPCE can benefit from Prolog threads if they need to do expensive computations that would otherwise block the UI. The XPCE message passing system is guarded with a single \jargon{mutex}, which synchronises both access from Prolog and activation through the GUI. In MS-Windows, GUI events are processed by the thread that created the window in which the event occurred, whereas in Unix/X11 they are processed by the thread that dispatches messages. In practice, the most feasible approach to graphical Prolog implementations is to control XPCE from a single thread and deploy other threads for (long) computations. Traditionally, XPCE runs in the foreground (\const{main}) thread. We are working towards a situation where XPCE can run comfortably in a separate thread. A separate XPCE thread can be created using \index{pce_dispatch/1}\predref{pce_dispatch}{1}. It is also possible to create this thread as the \pllib(pce) is loaded by setting the \prologflag{xpce_threaded} to \const{true}. Threads other than the thread in which XPCE runs are provided with two predicates to communicate with XPCE. \begin{description} \predicate[det]{in_pce_thread}{1}{:Goal} Assuming XPCE is running in the foreground thread, this call gives background threads the opportunity to make calls to the XPCE thread. A call to \index{in_pce_thread/1}\predref{in_pce_thread}{1} succeeds immediately, copying \arg{Goal} to the XPCE thread. \arg{Goal} is added to the XPCE event queue and executed synchronous to normal user events like typing and clicking. \predicate[semidet]{in_pce_thread_sync}{1}{:Goal} Same as \index{in_pce_thread/1}\predref{in_pce_thread}{1}, but wait for \arg{Goal} to be completed. Success depends on the success of executing \arg{Goal}. Variable bindings inside \arg{Goal} are visible to the caller, but it should be noted that the values are being \emph{copied}. If \arg{Goal} throws an exception, this exception is re-thrown by \index{in_pce_thread/1}\predref{in_pce_thread}{1}. If the calling thread is the `pce thread', \index{in_pce_thread_sync/1}\predref{in_pce_thread_sync}{1} executes a direct meta-call. See also \index{in_pce_thread/1}\predref{in_pce_thread}{1}. Note that \index{in_pce_thread_sync/1}\predref{in_pce_thread_sync}{1} is expensive because it requires copying and thread communication. For example, \exam{in_pce_thread_sync{true}} runs at approximately 50,000 calls per second (AMD Phenom 9600B, Ubuntu 11.04). \predicate{pce_dispatch}{1}{+Options} Create a Prolog thread with the alias name \const{pce} for XPCE event handling. In the X11 version this call creates a thread that executes the X11 event-dispatch loop. In MS-Windows it creates a thread that executes a windows event-dispatch loop. The XPCE event-handling thread has the alias \const{pce}. \arg{Options} specifies the thread attributes as \index{thread_create/3}\predref{thread_create}{3}. \end{description}