@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
