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 ;;; Resource contention: condition variables
8 ;;; A condition variable provides a mechanism for threads to put
9 ;;; themselves to sleep while waiting for the state of something to
10 ;;; change, then to be subsequently woken by another thread which has
11 ;;; changed the state.
13 ;;; A condition variable must be used in conjunction with a lock to
14 ;;; protect access to the state of the object of interest. The
15 ;;; procedure is as follows:
17 ;;; Suppose two threads A and B, and some kind of notional event
18 ;;; channel C. A is consuming events in C, and B is producing them.
19 ;;; CV is a condition-variable
21 ;;; 1) A acquires the lock that safeguards access to C
22 ;;; 2) A threads and removes all events that are available in C
23 ;;; 3) When C is empty, A calls CONDITION-WAIT, which atomically
24 ;;; releases the lock and puts A to sleep on CV
25 ;;; 4) Wait to be notified; CONDITION-WAIT will acquire the lock again
27 ;;; 5) Loop back to step 2, for as long as threading should continue
29 ;;; When B generates an event E, it
30 ;;; 1) acquires the lock guarding C
31 ;;; 2) adds E to the channel
32 ;;; 3) calls CONDITION-NOTIFY on CV to wake any sleeping thread
33 ;;; 4) releases the lock
35 ;;; To avoid the "lost wakeup" problem, the implementation must
36 ;;; guarantee that CONDITION-WAIT in thread A atomically releases the
37 ;;; lock and sleeps. If this is not guaranteed there is the
38 ;;; possibility that thread B can add an event and call
39 ;;; CONDITION-NOTIFY between the lock release and the sleep - in this
40 ;;; case the notify call would not see A, which would be left sleeping
41 ;;; despite there being an event available.
43 (defun condition-variable-p (object)
44 "Returns TRUE if OBJECT is a condition variable, and NIL otherwise."
45 (typep object
'condition-variable
))
47 (defun make-condition-variable (&key name
)
48 "Returns a new condition-variable object for use
49 with CONDITION-WAIT and CONDITION-NOTIFY."
50 (check-type name
(or null string
))
51 (%make-condition-variable name
))
53 (defun condition-wait (condition-variable lock
&key timeout
)
54 "Atomically release LOCK and enqueue the calling
55 thread waiting for CONDITION-VARIABLE. The thread will resume when
56 another thread has notified it using CONDITION-NOTIFY; it may also
57 resume if interrupted by some external event or in other
58 implementation-dependent circumstances: the caller must always test
59 on waking that there is threading to be done, instead of assuming
62 It is an error to call this function unless from the thread that
65 If TIMEOUT is nil or not provided, the call blocks until a
66 notification is received.
68 If TIMEOUT is non-nil, the call will return after at most TIMEOUT
69 seconds (approximately), whether or not a notification has occurred.
71 Either NIL or T will be returned. A return of NIL indicates that the
72 timeout has expired without receiving a notification. A return of T
73 indicates that a notification was received."
74 (check-type timeout
(or null
(real 0)))
75 (%condition-wait condition-variable
76 (lock-native-lock lock
)
79 (defun condition-notify (condition-variable)
80 "Notify one of the threads waiting for
83 It is unspecified which thread gets a wakeup and does not
84 necessarily relate to the order that the threads went to sleep in.
86 CONDITION-NOTIFY returns always NIL."
87 (%condition-notify condition-variable
)
90 (defun condition-broadcast (condition-variable)
91 "Notify all threads waiting for CONDITION-VARIABLE.
93 The order of wakeup is unspecified and does not necessarily relate
94 to the order that the threads went to sleep in.
96 CONDITION-BROADCAST returns always NIL."
97 (%condition-broadcast condition-variable
)