# Threads

Allegro includes a simple cross-platform threading interface.
It is a thin layer on top of two threading APIs: Windows threads
and POSIX Threads (pthreads).  Enforcing a consistent semantics on all
platforms would be difficult at best, hence the behaviour of the following
functions will differ subtly on different platforms (more so than usual).
Your best bet is to be aware of this and code to the intersection of the
semantics and avoid edge cases.

These functions are declared in the main Allegro header file:

~~~~c
 #include <allegro5/allegro.h>
~~~~


## API: ALLEGRO_THREAD

An opaque structure representing a thread.



## API: ALLEGRO_MUTEX

An opaque structure representing a mutex.



## API: ALLEGRO_COND

An opaque structure representing a condition variable.



## API: al_create_thread

Spawn a new thread which begins executing `proc`.  The new thread is passed
its own thread handle and the value `arg`.

Returns a pointer to the thread on success.
Otherwise, returns NULL if there was an error.

See also: [al_start_thread], [al_join_thread].



## API: al_start_thread

When a thread is created, it is initially in a suspended state.
Calling [al_start_thread] will start its actual execution.

Starting a thread which has already been started does nothing.

See also: [al_create_thread].



## API: al_join_thread

Wait for the thread to finish executing.  This implicitly calls
[al_set_thread_should_stop] first.

If `ret_value` is non-`NULL`, the value returned by the thread function
will be stored at the location pointed to by `ret_value`.

See also: [al_set_thread_should_stop], [al_get_thread_should_stop],
[al_destroy_thread].



## API: al_set_thread_should_stop

Set the flag to indicate `thread` should stop.  Returns immediately.

See also: [al_join_thread], [al_get_thread_should_stop].



## API: al_get_thread_should_stop

Check if another thread is waiting for `thread` to stop.  Threads which run
in a loop should check this periodically and act on it when convenient.

Returns true if another thread has called [al_join_thread] or
[al_set_thread_should_stop] on this thread.

See also: [al_join_thread], [al_set_thread_should_stop].

> *Note:*
We don't support forceful killing of threads.



## API: al_destroy_thread

Free the resources used by a thread.  Implicitly performs [al_join_thread]
on the thread if it hasn't been done already.

Does nothing if `thread` is NULL.

See also: [al_join_thread].


## API: al_run_detached_thread

Runs the passed function in its own thread, with `arg` passed to it as only
parameter. This is similar to calling [al_create_thread], [al_start_thread]
and (after the thread has finished) [al_destroy_thread] - but you don't have
the possibility of ever calling [al_join_thread] on the thread any longer.


## API: al_create_mutex

Create the mutex object (a mutual exclusion device).  The mutex may or
may not support "recursive" locking.

Returns the mutex on success or `NULL` on error.

See also: [al_create_mutex_recursive].



## API: al_create_mutex_recursive

Create the mutex object (a mutual exclusion device), with support for
"recursive" locking.  That is, the mutex will count the number of times it
has been locked by the same thread.  If the caller tries to acquire a lock
on the mutex when it already holds the lock then the count is incremented.
The mutex is only unlocked when the thread releases the lock on the mutex an
equal number of times, i.e. the count drops down to zero.

See also: [al_create_mutex].



## API: al_lock_mutex

Acquire the lock on `mutex`.  If the mutex is already locked by another
thread, the call will block until the mutex becomes available and locked.

If the mutex is already locked by the calling thread, then the behaviour
depends on whether the mutex was created with [al_create_mutex] or
[al_create_mutex_recursive].  In the former case, the behaviour is undefined;
the most likely behaviour is deadlock.  In the latter case, the count in the
mutex will be incremented and the call will return immediately.

See also: [al_unlock_mutex].

**We don't yet have al_mutex_trylock.**



## API: al_unlock_mutex

Release the lock on `mutex` if the calling thread holds the lock on it.

If the calling thread doesn't hold the lock, or if the mutex is not locked,
undefined behaviour results.

See also: [al_lock_mutex].



## API: al_destroy_mutex

Free the resources used by the mutex.  The mutex should be unlocked.
Destroying a locked mutex results in undefined behaviour.

Does nothing if `mutex` is `NULL`.



## API: al_create_cond

Create a condition variable.

Returns the condition value on success or `NULL` on error.



## API: al_destroy_cond

Destroy a condition variable.

Destroying a condition variable which has threads block on it results in
undefined behaviour.

Does nothing if `cond` is `NULL`.



## API: al_wait_cond

On entering this function, `mutex` must be locked by the calling thread.
The function will atomically release `mutex` and block on `cond`.  The
function will return when `cond` is "signalled", acquiring the lock on the
mutex in the process.

Example of proper use:

~~~~c
al_lock_mutex(mutex);
while (something_not_true) {
   al_wait_cond(cond, mutex);
}
do_something();
al_unlock_mutex(mutex);
~~~~

The mutex should be locked before checking the condition, and should be
rechecked [al_wait_cond] returns.  [al_wait_cond] can return for other
reasons than the condition becoming true (e.g. the process was signalled).
If multiple threads are blocked on the condition variable, the condition may
no longer be true by the time the second and later threads are unblocked.
Remember not to unlock the mutex prematurely.

See also: [al_wait_cond_until], [al_broadcast_cond], [al_signal_cond].



## API: al_wait_cond_until

Like [al_wait_cond] but the call can return if the absolute time passes
`timeout` before the condition is signalled.

Returns zero on success, non-zero if the call timed out.

See also: [al_wait_cond]



## API: al_broadcast_cond

Unblock all threads currently waiting on a condition variable.  That is,
broadcast that some condition which those threads were waiting for has
become true.

See also: [al_signal_cond].

> *Note:*
The pthreads spec says to lock the mutex associated with `cond` before
signalling for predictable scheduling behaviour.



## API: al_signal_cond

Unblock at least one thread waiting on a condition variable.

Generally you should use [al_broadcast_cond] but [al_signal_cond] may be
more efficient when it's applicable.

See also: [al_broadcast_cond].
