1 ;;;; -*- Mode: LISP; Syntax: ANSI-Common-lisp; Base: 10; Package: BORDEAUX-THREADS-2 -*-
2 ;;;; The above modeline is required for Genera. Do not change.
4 (in-package :bordeaux-threads-2
)
6 (defun native-lock-p (object)
7 (typep object
'native-lock
))
10 ((name :initarg
:name
:reader lock-name
)
11 (native-lock :initarg
:native-lock
:reader lock-native-lock
))
12 (:documentation
"Wrapper for a native non-recursive lock."))
14 (defmethod print-object ((lock lock
) stream
)
15 (print-unreadable-object (lock stream
:type t
:identity t
)
16 (format stream
"~S" (lock-name lock
))))
19 "Returns T if OBJECT is a non-recursive lock; returns NIL otherwise."
22 (defun make-lock (&key name
)
23 "Creates a lock (a mutex) whose name is NAME."
24 (check-type name
(or null string
))
27 :native-lock
(%make-lock name
)))
29 (defun acquire-lock (lock &key
(wait t
) timeout
)
30 "Acquire the lock LOCK for the calling thread.
32 WAIT governs what happens if the lock is not available: if WAIT
33 is true, the calling thread will wait until the lock is available
34 and then acquire it; if WAIT is NIL, ACQUIRE-LOCK will return
37 If WAIT is true, TIMEOUT may specify a maximum amount of seconds to
38 wait for the lock to become available.
40 ACQUIRE-LOCK returns T if the lock was acquired and NIL
43 This specification does not define what happens if a thread
44 attempts to acquire a lock that it already holds. For applications
45 that require locks to be safe when acquired recursively, see instead
46 MAKE-RECURSIVE-LOCK and friends."
47 (check-type timeout
(or null
(real 0)))
48 (%acquire-lock
(lock-native-lock lock
) (bool wait
) timeout
))
50 (defun release-lock (lock)
51 "Release LOCK. It is an error to call this unless
52 the lock has previously been acquired (and not released) by the same
53 thread. If other threads are waiting for the lock, the
54 ACQUIRE-LOCK call in one of them will now be able to continue.
57 (%release-lock
(lock-native-lock lock
))
60 (defmacro with-lock-held
((place &key timeout
)
61 &body body
&environment env
)
62 "Evaluates BODY with the lock named by PLACE, the value of which
63 is a lock created by MAKE-LOCK. Before the forms in BODY are
64 evaluated, the lock is acquired as if by using ACQUIRE-LOCK. After the
65 forms in BODY have been evaluated, or if a non-local control transfer
66 is caused (e.g. by THROW or SIGNAL), the lock is released as if by
69 Note that if the debugger is entered, it is unspecified whether the
70 lock is released at debugger entry or at debugger exit when execution
72 (declare (ignorable place timeout
))
73 (if (fboundp '%with-lock
)
75 `(%with-lock
((lock-native-lock ,place
) ,timeout
)
78 `(when (acquire-lock ,place
:wait t
:timeout
,timeout
)
81 (release-lock ,place
)))))
83 (defun native-recursive-lock-p (object)
84 (typep object
'native-recursive-lock
))
86 (defclass recursive-lock
()
87 ((name :initarg
:name
:reader lock-name
)
88 (native-lock :initarg
:native-lock
:reader lock-native-lock
))
89 (:documentation
"Wrapper for a native recursive lock."))
91 (defmethod print-object ((lock recursive-lock
) stream
)
92 (print-unreadable-object (lock stream
:type t
:identity t
)
93 (format stream
"~S" (lock-name lock
))))
95 (defun recursive-lock-p (object)
96 "Returns T if OBJECT is a recursive lock; returns NIL otherwise."
97 (typep object
'recursive-lock
))
99 (defun make-recursive-lock (&key name
)
100 "Create and return a recursive lock whose name is NAME.
102 A recursive lock differs from an ordinary lock in that a thread that
103 already holds the recursive lock can acquire it again without
104 blocking. The thread must then release the lock twice before it
105 becomes available for another thread (acquire and release operations
107 (check-type name
(or null string
))
108 (make-instance 'recursive-lock
110 :native-lock
(%make-recursive-lock name
)))
112 (defun acquire-recursive-lock (lock &key
(wait t
) timeout
)
113 "Acquire the lock LOCK for the calling thread.
115 WAIT governs what happens if the lock is not available: if WAIT is
116 true, the calling thread will wait until the lock is available and
117 then acquire it; if WAIT is NIL, ACQUIRE-RECURSIVE-LOCK will return
120 If WAIT is true, TIMEOUT may specify a maximum amount of seconds to
121 wait for the lock to become available.
123 ACQUIRE-LOCK returns true if the lock was acquired and NIL
126 This operation will return immediately if the lock is already owned
127 by the current thread. Acquire and release operations must be
129 (check-type lock recursive-lock
)
130 (check-type timeout
(or null
(real 0)))
131 (%acquire-recursive-lock
(lock-native-lock lock
) (bool wait
) timeout
))
133 (defun release-recursive-lock (lock)
134 "Release LOCK. It is an error to call this unless
135 the lock has previously been acquired (and not released) by the same
139 (%release-recursive-lock
(lock-native-lock lock
))
142 (defmacro with-recursive-lock-held
((place &key timeout
)
143 &body body
&environment env
)
144 "Evaluates BODY with the recursive lock named by PLACE, which is a
145 reference to a recursive lock created by MAKE-RECURSIVE-LOCK.
147 (declare (ignorable place timeout
))
148 (if (fboundp '%with-recursive-lock
)
150 `(%with-recursive-lock
((lock-native-lock ,place
) ,timeout
)
153 `(when (acquire-recursive-lock ,place
:wait t
:timeout
,timeout
)
156 (release-recursive-lock ,place
)))))