Mutexes are used for controlling access to a shared resource. One thread is allowed to hold the mutex, others which attempt to take it will be made to wait until it's free. Threads are woken in the order that they go to sleep.
There isn't a timeout on mutex acquisition, but the usual WITH-TIMEOUT macro (which throws a TIMEOUT condition after n seconds) can be used if you want a bounded wait.
(defpackage :demo (:use "CL" "SB-THREAD" "SB-EXT")) (in-package :demo) (defvar *a-mutex* (make-mutex :name "my lock")) (defun thread-fn () (format t "Thread ~A running ~%" *current-thread*) (with-mutex (*a-mutex*) (format t "Thread ~A got the lock~%" *current-thread*) (sleep (random 5))) (format t "Thread ~A dropped lock, dying now~%" *current-thread*)) (make-thread #'thread-fn) (make-thread #'thread-fn)
Name of a
queue
. Can be assingned to usingsetf
. Queue names can be arbitrary printable objects, and need not be unique.
Current owner of the mutex,
nil
if the mutex is free. May return a stale value, usemutex-owner
instead.
Acquire
mutex
fornew-owner
, which must be a thread ornil
. Ifnew-owner
isnil
, it defaults to the current thread. Ifwaitp
is non-NIL and the mutex is in use, sleep until it is available.Note: using
get-mutex
to assign amutex
to another thread then the current one is not recommended, and liable to be deprecated.
get-mutex
is not interrupt safe. The correct way to call it is:(WITHOUT-INTERRUPTS ... (ALLOW-WITH-INTERRUPTS (GET-MUTEX ...)) ...)
without-interrupts
is necessary to avoid an interrupt unwinding the call while the mutex is in an inconsistent state whileallow-with-interrupts
allows the call to be interrupted from sleep.It is recommended that you use
with-mutex
instead of callingget-mutex
directly.
Release
mutex
by setting it tonil
. Wake up threads waiting for this mutex.
release-mutex
is not interrupt safe: interrupts should be disabled around calls to it.If the current thread is not the owner of the mutex then it silently returns without doing anything (if
if-not-owner
is :PUNT), signals awarning
(ifif-not-owner
is :WARN), or releases the mutex anyway (ifif-not-owner
is :FORCE).
Acquire
mutex
for the dynamic scope ofbody
, setting it tovalue
or some suitable default value ifnil
. Ifwait-p
is non-NIL and the mutex is in use, sleep until it is available
Acquires
mutex
for the dynamic scope ofbody
. Within that scope further recursive lock attempts for the same mutex succeed. It is allowed to mixwith-mutex
andwith-recursive-lock
for the same mutex provided the default value is used for the mutex.