% 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 \verb$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[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}

