| Did you know ... | Search Documentation: | 
|  | Multithreaded mixed C and Prolog applications | 
All foreign code linked to the multithreading version of SWI-Prolog should be thread-safe (reentrant) or guarded in Prolog using 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 engine in each thread from which you call Prolog. 
Without creating an engine, a thread can only use functions that do
not use the term_t type (for example PL_new_atom()).
The system supports two models. Section 10.6.1 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 section 10.6.2, where threads temporarily use a Prolog engine.
In the one-to-one model, the thread that called 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 PL_thread_attach_engine() and call 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 section 10.6.2 for the alternative many-to-many model.
NULL to create a thread 
with default attributes. Otherwise it is a pointer to a structure with 
the definition below. For any field with value‘0’, the 
default is used. The
cancel field may be filled with a pointer to a function 
that is called when PL_cleanup() 
terminates the running Prolog engines. If this function is not present 
or returns FALSE pthread_cancel() is used. The new 
thread inherits is properties from Prolog's main thread. 
The flags field defines the following flags:
current_input and current_output 
are set to user_input and user_output of the 
main thread. Using this flag, these streams are copied from the main 
thread. See also the inherited_from option of thread_create/3.
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;
The structure may be destroyed after PL_thread_attach_engine() has returned. On success it returns the Prolog identifier for the thread (as returned by PL_thread_self()). If an error occurs, -1 is returned. If this Prolog is not compiled for multithreading, -2 is returned.
TRUE on success and 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.
void * argument holding
closure. If global is TRUE, the 
handler is installed
for all threads. Globally installed handlers are executed after 
the thread-local handlers. If the handler is installed local for the 
current thread only (global == FALSE) it is 
stored in the same FIFO queue as used by thread_at_exit/1.
Prolog engines live as entities that are independent from threads. 
They are always supported in the multi-threaded version and may be 
enabled in the single threaded version by providing -DENGINES=ON 
during the
cmake configuration. Multiple threads may use a pool of engines 
for handling calls to Prolog. A single thread may use multiple engines 
to achieve coroutining. Engines are suitable in the following 
identified cases:
NULL if 
the thread has no Prolog engine.
In the single-threaded version this call always returns NULL, 
indicating failure.
TRUE, on failure the 
return value is FALSE.NULL the current engine associated with the calling 
thread is stored at the given location. If engine equals
PL_ENGINE_MAIN the initial engine is attached to the 
calling thread. If engine is PL_ENGINE_CURRENT 
the engine is not changed. This can be used to query the current engine. 
This call returns
PL_ENGINE_SET if the engine was switched successfully,
PL_ENGINE_INVAL if engine is not a valid engine 
handle and
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
term_t, qid_t and 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. 
The engine to which a query belongs can be requested using PL_query_engine()
In versions that do not support engines this call only succeeds if engine refers to the main engine.
break to terminate the body 
early. The user may not use return. Using return 
does not reset the old engine.