% This LaTeX document was generated using the LaTeX backend of PlDoc, % The SWI-Prolog documentation system \section{library(thread_pool): Resource bounded thread management} \label{sec:threadpool} \begin{tags} \tag{See also} \predref{http_handler}{3} and \predref{http_spawn}{2}. \end{tags} The module \file{library(thread_pool)} manages threads in pools. A pool defines properties of its member threads and the maximum number of threads that can coexist in the pool. The call \predref{thread_create_in_pool}{4} allocates a thread in the pool, just like \predref{thread_create}{3}. If the pool is fully allocated it can be asked to wait or raise an error. The library has been designed to deal with server applications that receive a variety of requests, such as HTTP servers. Simply starting a thread for each request is a bit too simple minded for such servers: \begin{itemize} \item Creating many CPU intensive threads often leads to a slow-down rather than a speedup. \item Creating many memory intensive threads may exhaust resources \item Tasks that require little CPU and memory but take long waiting for external resources can run many threads. \end{itemize} Using this library, one can define a pool for each set of tasks with comparable characteristics and create threads in this pool. Unlike the worker-pool model, threads are not started immediately. Depending on the design, both approaches can be attractive. The library is implemented by means of a manager thread with the fixed thread id \verb$__thread_pool_manager$. All state is maintained in this manager thread, which receives and processes requests to create and destroy pools, create threads in a pool and handle messages from terminated threads. Thread pools are \textit{not} saved in a saved state and must therefore be recreated using the \predref{initialization}{1} directive or otherwise during startup of the application.\vspace{0.7cm} \begin{description} \predicate[det]{thread_pool_create}{3}{+Pool, +Size, +Options} Create a pool of threads. A pool of threads is a declaration for creating threads with shared properties (stack sizes) and a limited number of threads. Threads are created using \predref{thread_create_in_pool}{4}. If all threads in the pool are in use, the behaviour depends on the \const{wait} option of \predref{thread_create_in_pool}{4} and the \const{backlog} option described below. \arg{Options} are passed to \predref{thread_create}{3}, except for \begin{description} \termitem{backlog}{+MaxBackLog} Maximum number of requests that can be suspended. Default is \const{infinite}. Otherwise it must be a non-negative integer. Using \verb$backlog(0)$ will never delay thread creation for this pool. \end{description} The pooling mechanism does \textit{not} interact with the \const{detached} state of a thread. Threads can be created both \const{detached} and normal and must be joined using \predref{thread_join}{2} if they are not detached. \predicate[det]{thread_pool_destroy}{1}{+Name} Destroy the thread pool named \arg{Name}. \begin{tags} \tag{Errors} \verb$existence_error(thread_pool, Name)$. \end{tags} \predicate[nondet]{current_thread_pool}{1}{?Name} True if \arg{Name} refers to a defined thread pool. \predicate[nondet]{thread_pool_property}{2}{?Name, ?Property} True if \arg{Property} is a property of thread pool \arg{Name}. Defined properties are: \begin{description} \termitem{options}{Options} Thread creation options for this pool \termitem{free}{Size} Number of free slots on this pool \termitem{size}{Size} Total number of slots on this pool \termitem{members}{ListOfIDs} \arg{ListOfIDs} is the list or threads running in this pool \termitem{running}{Running} Number of running threads in this pool \termitem{backlog}{Size} Number of delayed thread creations on this pool \end{description} \predicate[det]{thread_create_in_pool}{4}{+Pool, :Goal, -Id, +Options} Create a thread in \arg{Pool}. \arg{Options} overrule default thread creation options associated to the pool. In addition, the following option is defined: \begin{description} \termitem{wait}{+Boolean} If \const{true} (default) and the pool is full, wait until a member of the pool completes. If \const{false}, throw a resource_error. \end{description} \begin{tags} \mtag{Errors}- \verb$resource_error(threads_in_pool(Pool))$ is raised if wait is \const{false} or the backlog limit has been reached. \\- \verb$existence_error(thread_pool, Pool)$ if \arg{Pool} does not exist. \end{tags} \predicate{worker_exitted}{3}{+PoolName, +WorkerId, :AtExit} It is possible that '__thread_pool_manager' no longer exists while closing down the process because the manager was killed before the worker. \begin{tags} \tag{To be done} Find a way to discover that we are terminating Prolog. \end{tags} \predicate[semidet,multifile]{create_pool}{1}{+PoolName} Hook to create a thread pool lazily. The hook is called if \predref{thread_create_in_pool}{4} discovers that the thread pool does not exist. If the hook succeeds, \predref{thread_create_in_pool}{4} retries creating the thread. For example, we can use the following declaration to create threads in the pool \const{media}, which holds a maximum of 20 threads. \begin{code} :- multifile thread_pool:create_pool/1. thread_pool:create_pool(media) :- thread_pool_create(media, 20, []). \end{code} \end{description}