mirror of
git://git.code.sf.net/p/sbcl/sbcl
synced 2026-09-10 07:26:40 -04:00
337 lines
15 KiB
Plaintext
337 lines
15 KiB
Plaintext
@c Generated by the sb-manual contrib. Do not edit.
|
|
|
|
@node sb concurrency
|
|
@section sb-concurrency
|
|
|
|
@menu
|
|
* Queue: sb concurrency queue.
|
|
* Mailbox (lock-free): sb concurrency mailbox.
|
|
* Gates: sb concurrency gates.
|
|
* Frlocks, aka Fast Read Locks: sb concurrency frlocks.
|
|
@end menu
|
|
|
|
Additional data structures, synchronization primitives and tools for
|
|
concurrent programming. Similiar to Java's @code{java.util.concurrent}
|
|
package.
|
|
|
|
@node sb concurrency queue
|
|
@subsection Queue
|
|
|
|
@code{sb-concurrency:queue} is a lock-free, thread-safe FIFO queue
|
|
datatype.
|
|
|
|
The implementation is based on @emph{An Optimistic Approach to Lock-Free
|
|
FIFO Queues} by Edya Ladan-Mozes and Nir Shavit.
|
|
|
|
Before SBCL 1.0.38, this implementation resided in its own contrib
|
|
(see @ref{sb queue}), which is still provided for
|
|
backwards-compatibility, but which has since been deprecated.
|
|
|
|
@anchor{Structure sb-concurrency queue}
|
|
@ttindex @sortas{queue sb-concurrency} queue [sb-concurrency]
|
|
@deffn{Structure} sb-concurrency:queue
|
|
Lock-free thread safe FIFO queue.
|
|
|
|
Use @code{enqueue} to add objects to the queue, and @code{dequeue} to remove them.
|
|
@end deffn
|
|
@anchor{Function sb-concurrency dequeue}
|
|
@ffindex @sortas{dequeue sb-concurrency} dequeue [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:dequeue queue
|
|
Retrieves the oldest value in @code{queue} and returns it as the primary value,
|
|
and @code{t} as secondary value. If the queue is empty, returns @code{nil} as both primary
|
|
and secondary value.
|
|
@end deffn
|
|
@anchor{Function sb-concurrency enqueue}
|
|
@ffindex @sortas{enqueue sb-concurrency} enqueue [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:enqueue value queue
|
|
Adds @code{value} to the end of @code{queue}. Returns @code{value}.
|
|
@end deffn
|
|
@anchor{Function sb-concurrency list-queue-contents}
|
|
@ffindex @sortas{list-queue-contents sb-concurrency} list-queue-contents [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:list-queue-contents queue
|
|
Returns the contents of @code{queue} as a list without removing them from the
|
|
@code{queue}. Mainly useful for manual examination of queue state, as the list may be
|
|
out of date by the time it is returned, and concurrent dequeue operations may
|
|
in the worse case force the queue-traversal to be restarted several times.
|
|
@end deffn
|
|
@anchor{Function sb-concurrency make-queue}
|
|
@ffindex @sortas{make-queue sb-concurrency} make-queue [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:make-queue &key name initial-contents
|
|
Returns a new @code{queue} with @code{name} and contents of the @code{initial-contents}
|
|
sequence enqueued.
|
|
@end deffn
|
|
@anchor{Function sb-concurrency queue-count}
|
|
@ffindex @sortas{queue-count sb-concurrency} queue-count [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:queue-count queue
|
|
Returns the number of objects in @code{queue}. Mainly useful for manual
|
|
examination of queue state, and in @code{print-object} methods: inefficient as it
|
|
must walk the entire queue.
|
|
@end deffn
|
|
@anchor{Function sb-concurrency queue-empty-p}
|
|
@ffindex @sortas{queue-empty-p sb-concurrency} queue-empty-p [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:queue-empty-p queue
|
|
Returns @code{t} if @code{queue} is empty, @code{nil} otherwise.
|
|
@end deffn
|
|
@anchor{Function sb-concurrency queue-name}
|
|
@ffindex @sortas{queue-name sb-concurrency} queue-name [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:queue-name instance
|
|
Name of a @code{queue}. Can be assigned to using @code{setf}. Queue names
|
|
can be arbitrary printable objects, and need not be unique.
|
|
@end deffn
|
|
@anchor{Function sb-concurrency queuep}
|
|
@ffindex @sortas{queuep sb-concurrency} queuep [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:queuep object
|
|
Returns true if argument is a @code{queue}, @code{nil} otherwise.
|
|
@end deffn
|
|
@node sb concurrency mailbox
|
|
@subsection Mailbox (lock-free)
|
|
|
|
@code{sb-concurrency:mailbox} is a lock-free message queue where one or
|
|
multiple ends can send messages to one or multiple receivers. The
|
|
difference to @ref{sb concurrency queue} is that the receiving end may
|
|
block until a message arrives.
|
|
|
|
Built on top of the @ref{sb concurrency queue} implementation.
|
|
|
|
@anchor{Structure sb-concurrency mailbox}
|
|
@ttindex @sortas{mailbox sb-concurrency} mailbox [sb-concurrency]
|
|
@deffn{Structure} sb-concurrency:mailbox
|
|
Mailbox aka message queue.
|
|
|
|
@code{send-message} adds a message to the mailbox, @code{receive-message} waits till
|
|
a message becomes available, whereas @code{receive-message-no-hang} is a non-blocking
|
|
variant, and @code{receive-pending-messages} empties the entire mailbox in one go.
|
|
|
|
Messages can be arbitrary objects.
|
|
@end deffn
|
|
@anchor{Function sb-concurrency list-mailbox-messages}
|
|
@ffindex @sortas{list-mailbox-messages sb-concurrency} list-mailbox-messages [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:list-mailbox-messages mailbox
|
|
Returns a fresh list containing all the messages in @code{mailbox}. Does not
|
|
remove messages from the mailbox.
|
|
@end deffn
|
|
@anchor{Function sb-concurrency mailbox-count}
|
|
@ffindex @sortas{mailbox-count sb-concurrency} mailbox-count [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:mailbox-count mailbox
|
|
Returns the number of messages currently in @code{mailbox}.
|
|
@end deffn
|
|
@anchor{Function sb-concurrency mailbox-empty-p}
|
|
@ffindex @sortas{mailbox-empty-p sb-concurrency} mailbox-empty-p [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:mailbox-empty-p mailbox
|
|
Returns true if @code{mailbox} is currently empty, @code{nil} otherwise.
|
|
@end deffn
|
|
@anchor{Function sb-concurrency mailbox-name}
|
|
@ffindex @sortas{mailbox-name sb-concurrency} mailbox-name [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:mailbox-name instance
|
|
Name of a @code{mailbox}. @code{setf}able.
|
|
@end deffn
|
|
@anchor{Function sb-concurrency mailboxp}
|
|
@ffindex @sortas{mailboxp sb-concurrency} mailboxp [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:mailboxp object
|
|
Returns true if argument is a @code{mailbox}, @code{nil} otherwise.
|
|
@end deffn
|
|
@anchor{Function sb-concurrency make-mailbox}
|
|
@ffindex @sortas{make-mailbox sb-concurrency} make-mailbox [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:make-mailbox &key name initial-contents
|
|
Returns a new @code{mailbox} with messages in @code{initial-contents} enqueued.
|
|
@end deffn
|
|
@anchor{Function sb-concurrency receive-message}
|
|
@ffindex @sortas{receive-message sb-concurrency} receive-message [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:receive-message mailbox &key timeout
|
|
Removes the oldest message from @code{mailbox} and returns it as the primary
|
|
value, and a secondary value of @code{t}. If @code{mailbox} is empty waits until a message
|
|
arrives.
|
|
|
|
If @code{timeout} is provided, and no message arrives within the specified interval,
|
|
returns primary and secondary value of @code{nil}.
|
|
@end deffn
|
|
@anchor{Function sb-concurrency receive-message-no-hang}
|
|
@ffindex @sortas{receive-message-no-hang sb-concurrency} receive-message-no-hang [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:receive-message-no-hang mailbox
|
|
The non-blocking variant of @code{receive-message}. Returns two values,
|
|
the message removed from @code{mailbox}, and a flag specifying whether a
|
|
message could be received.
|
|
@end deffn
|
|
@anchor{Function sb-concurrency receive-pending-messages}
|
|
@ffindex @sortas{receive-pending-messages sb-concurrency} receive-pending-messages [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:receive-pending-messages mailbox &optional n
|
|
Removes and returns all (or at most @code{n}) currently pending messages
|
|
from @code{mailbox}, or returns @code{nil} if no messages are pending.
|
|
|
|
@quotation
|
|
@emph{Note}: Concurrent threads may be snarfing messages during the run
|
|
of this function, so even @code{x} and @code{y} appearing right next to each
|
|
other in the result does not necessarily mean that @code{y} was the
|
|
message sent right after @code{x}.
|
|
@end quotation
|
|
@end deffn
|
|
@anchor{Function sb-concurrency send-message}
|
|
@ffindex @sortas{send-message sb-concurrency} send-message [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:send-message mailbox message
|
|
Adds a @code{message} to @code{mailbox}. Message can be any object.
|
|
@end deffn
|
|
@node sb concurrency gates
|
|
@subsection Gates
|
|
|
|
@code{sb-concurrency:gate} is a synchronization object suitable for when
|
|
multiple threads must wait for a single event before proceeding.
|
|
|
|
@anchor{Structure sb-concurrency gate}
|
|
@ttindex @sortas{gate sb-concurrency} gate [sb-concurrency]
|
|
@deffn{Structure} sb-concurrency:gate
|
|
@code{gate} type. Gates are synchronization constructs suitable for making
|
|
multiple threads wait for single event before proceeding.
|
|
|
|
Use @code{wait-on-gate} to wait for a gate to open, @code{open-gate} to open one,
|
|
and @code{close-gate} to close an open gate. @code{gate-open-p} can be used to test
|
|
the state of a gate without blocking.
|
|
@end deffn
|
|
@anchor{Function sb-concurrency close-gate}
|
|
@ffindex @sortas{close-gate sb-concurrency} close-gate [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:close-gate gate
|
|
Closes @code{gate}. Returns @code{t} if the gate was previously open, and @code{nil}
|
|
if the gate was already closed.
|
|
@end deffn
|
|
@anchor{Function sb-concurrency gate-name}
|
|
@ffindex @sortas{gate-name sb-concurrency} gate-name [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:gate-name instance
|
|
Name of a @code{gate}. @code{setf}able.
|
|
@end deffn
|
|
@anchor{Function sb-concurrency gate-open-p}
|
|
@ffindex @sortas{gate-open-p sb-concurrency} gate-open-p [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:gate-open-p gate
|
|
Returns true if @code{gate} is open.
|
|
@end deffn
|
|
@anchor{Function sb-concurrency gatep}
|
|
@ffindex @sortas{gatep sb-concurrency} gatep [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:gatep object
|
|
Returns true if the argument is a @code{gate}.
|
|
@end deffn
|
|
@anchor{Function sb-concurrency make-gate}
|
|
@ffindex @sortas{make-gate sb-concurrency} make-gate [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:make-gate &key name open
|
|
Makes a new gate. Gate will be initially open if @code{open} is true, and closed if @code{open}
|
|
is @code{nil} (the default.) @code{name}, if provided, is the name of the gate, used when printing
|
|
the gate.
|
|
@end deffn
|
|
@anchor{Function sb-concurrency open-gate}
|
|
@ffindex @sortas{open-gate sb-concurrency} open-gate [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:open-gate gate
|
|
Opens @code{gate}. Returns @code{t} if the gate was previously closed, and @code{nil}
|
|
if the gate was already open.
|
|
@end deffn
|
|
@anchor{Function sb-concurrency wait-on-gate}
|
|
@ffindex @sortas{wait-on-gate sb-concurrency} wait-on-gate [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:wait-on-gate gate &key timeout
|
|
Waits for @code{gate} to open, or @code{timeout} seconds to pass. Returns @code{t}
|
|
if the gate was opened in time, and @code{nil} otherwise.
|
|
@end deffn
|
|
@node sb concurrency frlocks
|
|
@subsection Frlocks, aka Fast Read Locks
|
|
|
|
@anchor{Structure sb-concurrency frlock}
|
|
@ttindex @sortas{frlock sb-concurrency} frlock [sb-concurrency]
|
|
@deffn{Structure} sb-concurrency:frlock
|
|
FRlock, aka Fast Read Lock.
|
|
|
|
Fast Read Locks allow multiple readers and one potential writer to operate in
|
|
parallel while providing for consistency for readers and mutual exclusion for
|
|
writers.
|
|
|
|
Readers gain entry to protected regions without waiting, but need to retry if
|
|
a writer operated inside the region while they were reading. This makes frlocks
|
|
very efficient when readers are much more common than writers.
|
|
|
|
FRlocks are @emph{not} suitable when it is not safe at all for readers and writers
|
|
to operate on the same data in parallel: they provide consistency, not
|
|
exclusion between readers and writers. Hence using an frlock to e.g. protect
|
|
an SBCL hash-table is unsafe. If multiple readers operating in parallel with
|
|
a writer would be safe but inconsistent without a lock, frlocks are suitable.
|
|
|
|
The recommended interface to use is @code{frlock-read} and @code{frlock-write}, but those
|
|
needing it can also use a lower-level interface.
|
|
|
|
Example:
|
|
|
|
@example
|
|
;; Values returned by FOO are always consistent so that
|
|
;; the third value is the sum of the two first ones.
|
|
(let ((a 0)
|
|
(b 0)
|
|
(c 0)
|
|
(lk (make-frlock)))
|
|
(defun foo ()
|
|
(frlock-read (lk) a b c))
|
|
(defun bar (x y)
|
|
(frlock-write (lk)
|
|
(setf a x
|
|
b y
|
|
c (+ x y)))))
|
|
@end example
|
|
@end deffn
|
|
@anchor{Macro sb-concurrency frlock-read}
|
|
@ffindex @sortas{frlock-read sb-concurrency} frlock-read [sb-concurrency]
|
|
@deffn{Macro} sb-concurrency:frlock-read (frlock) &body value-forms
|
|
Evaluates @code{value-forms} under @code{frlock} till it obtains a consistent
|
|
set, and returns that as multiple values.
|
|
@end deffn
|
|
@anchor{Macro sb-concurrency frlock-write}
|
|
@ffindex @sortas{frlock-write sb-concurrency} frlock-write [sb-concurrency]
|
|
@deffn{Macro} sb-concurrency:frlock-write (frlock &key wait-p timeout) &body body
|
|
Executes @code{body} while holding @code{frlock} for writing.
|
|
@end deffn
|
|
@anchor{Function sb-concurrency make-frlock}
|
|
@ffindex @sortas{make-frlock sb-concurrency} make-frlock [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:make-frlock &key name
|
|
Returns a new @code{frlock} with @code{name}.
|
|
@end deffn
|
|
@anchor{Function sb-concurrency frlock-name}
|
|
@ffindex @sortas{frlock-name sb-concurrency} frlock-name [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:frlock-name instance
|
|
Name of an @code{frlock}. @code{setf}able.
|
|
@end deffn
|
|
@anchor{Function sb-concurrency frlock-read-begin}
|
|
@ffindex @sortas{frlock-read-begin sb-concurrency} frlock-read-begin [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:frlock-read-begin frlock
|
|
Start a read sequence on @code{frlock}. Returns a read-token and an epoch to be
|
|
validated later.
|
|
|
|
Using @code{frlock-read} instead is recommended.
|
|
@end deffn
|
|
@anchor{Function sb-concurrency frlock-read-end}
|
|
@ffindex @sortas{frlock-read-end sb-concurrency} frlock-read-end [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:frlock-read-end frlock
|
|
Ends a read sequence on @code{frlock}. Returns a token and an epoch. If the token
|
|
and epoch are @code{eql} to the read-token and epoch returned by @code{frlock-read-begin},
|
|
the values read under the @code{frlock} are consistent and can be used: if the values
|
|
differ, the values are inconsistent and the read must be restated.
|
|
|
|
Using @code{frlock-read} instead is recommended.
|
|
|
|
Example:
|
|
|
|
@example
|
|
(multiple-value-bind (t0 e0) (frlock-read-begin *fr*)
|
|
(let ((a (get-a))
|
|
(b (get-b)))
|
|
(multiple-value-bind (t1 e1) (frlock-read-end *fr*)
|
|
(if (and (eql t0 t1) (eql e0 e1))
|
|
(list :a a :b b)
|
|
:aborted))))
|
|
@end example
|
|
@end deffn
|
|
@anchor{Function sb-concurrency grab-frlock-write-lock}
|
|
@ffindex @sortas{grab-frlock-write-lock sb-concurrency} grab-frlock-write-lock [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:grab-frlock-write-lock frlock &key wait-p timeout
|
|
Acquires @code{frlock} for writing, invalidating existing and future read-tokens
|
|
for the duration. Returns @code{t} on success, and @code{nil} if the lock wasn't acquired
|
|
due to e.g. a timeout. Using @code{frlock-write} instead is recommended.
|
|
@end deffn
|
|
@anchor{Function sb-concurrency release-frlock-write-lock}
|
|
@ffindex @sortas{release-frlock-write-lock sb-concurrency} release-frlock-write-lock [sb-concurrency]
|
|
@deffn{Function} sb-concurrency:release-frlock-write-lock frlock
|
|
Releases @code{frlock} after writing, allowing valid read-tokens to be acquired again.
|
|
Signals an error if the current thread doesn't hold @code{frlock} for writing. Using @code{frlock-write}
|
|
instead is recommended.
|
|
@end deffn
|