A mutex is a thread synchronization object, it can be used by threads to control access to a shared resource. A mutex can be locked to indicate a resource is in use, and other threads can then block on the mutex to wait for the resource (or can just test and do something else if not available). “Mutex” is short for “mutual exclusion”.
There are two types of mutexes in Guile, “standard” and
“recursive”. They're created by
make-recursive-mutex respectively, the operation functions are
then common to both.
Note that for both types of mutex there's no protection against a “deadly embrace”. For instance if one thread has locked mutex A and is waiting on mutex B, but another thread owns B and is waiting on A, then an endless wait will occur (in the current implementation). Acquiring requisite mutexes in a fixed order (like always A before B) in all threads is one way to avoid such problems.
Return a new standard mutex. It is initially unlocked.
Create a new recursive mutex. It is initialloy unlocked.
Lock mutex. If the mutex is already locked by another thread then block and return only when mutex has been acquired.
For standard mutexes (
make-mutex), and error is signalled if the thread has itself already locked mutex.
For a recursive mutex (
make-recursive-mutex), if the thread has itself already locked mutex, then a further
lock-mutexcall increments the lock count. An additional
unlock-mutexwill be required to finally release.
When a system async (see System asyncs) is activated for a thread blocked in
lock-mutex, the wait is interrupted and the async is executed. When the async returns, the wait resumes.
Arrange for mutex to be locked whenever the current dynwind context is entered and to be unlocked when it is exited.
Try to lock mutex as per
lock-mutex. If mutex can be acquired immediately then this is done and the return is
#t. If mutex is locked by some other thread then nothing is done and the return is
Unlock mutex. An error is signalled if mutex is not locked by the calling thread.
Return a new condition variable.
Wait until condvar has been signalled. While waiting, mutex is atomically unlocked (as with
unlock-mutex) and is locked again when this function returns. When time is given, it specifies a point in time where the waiting should be aborted. It can be either a integer as returned by
current-timeor a pair as returned by
gettimeofday. When the waiting is aborted,
#fis returned. When the condition variable has in fact been signalled,
#tis returned. The mutex is re-locked in any case before
When a system async is activated for a thread that is blocked in a call to
wait-condition-variable, the waiting is interrupted, the mutex is locked, and the async is executed. When the async returns, the mutex is unlocked again and the waiting is resumed. When the thread block while re-acquiring the mutex, execution of asyncs is blocked.
Wake up one thread that is waiting for condvar.
Wake up all threads that are waiting for condvar.
The following are higher level operations on mutexes. These are available from
(use-modules (ice-9 threads))
Lock mutex, evaluate the body forms, then unlock mutex. The return value is the return from the last body form.
The lock, body and unlock form the branches of a
dynamic-wind(see Dynamic Wind), so mutex is automatically unlocked if an error or new continuation exits body, and is re-locked if body is re-entered by a captured continuation.
Evaluate the body forms, with a mutex locked so only one thread can execute that code at any one time. The return value is the return from the last body form.
monitorform has its own private mutex and the locking and evaluation is as per
with-mutexabove. A standard mutex (
make-mutex) is used, which means body must not recursively re-enter the
The term “monitor” comes from operating system theory, where it means a particular bit of code managing access to some resource and which only ever executes on behalf of one process at any one time.