Package bordeaux-threads

bordeaux-threads is a proposed standard for a minimal MP/threading interface.

About This Package

Overview
Introduction
Thread Creation
Resource contention: locks and recursive locks
Resource contention: condition variables
Introspection/debugging

Overview

Author
Based on original Bordeaux-MP spec by Dan Barlow <dan@telent.net>

Contributors:
  • Attila Lendvai <attila.lendvai@gmail.com>
    - better handling of unsupported Lisps
  • Vladimir Sekissov <svg@surnet.ru>
    - fixes for CMUCL implementation
  • Pierre Thierry <nowhere.man@levallois.eu.org>
    - added license information
  • Stelian Ionescu <sionescu@cddr.org>
    - finished conversion from generic functions
    - enabled running thread-safe code in unthreaded lisps
  • Douglas Crosher <dtc@scieneer.com>
    - added Scieneer Common Lisp support
Version
This is a documentation of Version 0.8.2.

Homepage
http://common-lisp.net/project/bordeaux-threads/

Mailing List
bordeaux-threads-devel for developers
bordeaux-threads-announce for announcements
bordeaux-threads-ticket for bug updates

Download
Releases are available at http://common-lisp.net/project/bordeaux-threads/releases/

Source Code
You can browse the repository or download the current development tree at common-lisp.net or gitorious

Dependencies
bordeaux-threads needs the package alexandria.

License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Introduction

bordeaux-threads is similar to the CLIM-SYS threading and lock support, but for the following broad differences:
  1. Some behaviours are defined in additional detail: attention has been given to special variable interaction, whether and when cleanup forms are run. Some behaviours are defined in less detail: an implementation that does not support multiple threads is not required to use a new list (nil) for a lock, for example.
  2. Many functions which would be difficult, dangerous or inefficient to provide on some implementations have been removed. Chiefly these are functions such as thread-wait which expect for efficiency that the thread scheduler is written in Lisp and "hookable", which can not sensibly be done if the scheduler is external to the Lisp image, or the system has more than one CPU.
  3. Unbalanced acquire-lock and release-lock functions have been added.
  4. Posix-style condition variables have been added, as it is not otherwise possible to implement them correctly using the other operations that are specified.
Threads may be implemented using whatever applicable techniques are provided by the operating system: user-space scheduling, kernel-based LWPs or anything else that does the job.

Some parts of this specification can also be implemented in a Lisp that does not support multiple threads. Thread creation and some thread inspection operations will not work, but the locking functions are still present (though they may do nothing) so that thread-safe code can be compiled on both multithread and single-thread implementations without need of conditionals.

To avoid conflict with existing MP/threading interfaces in implementations, these symbols live in the bordeaux-threads package. Implementations and/or users may also make them visible or exported in other more traditionally named packages.

Thread Creation

Creates and returns a thread named name, which will call the function function with no arguments: when function returns, the thread terminates. ...

Returns the thread object for the calling thread. ...

Returns true if object is a thread, otherwise nil.

Returns the name of the thread, as supplied to make-thread.

Resource contention: locks and recursive locks

Creates a lock (a mutex) whose name is name. ...

Acquire the lock lock for the calling thread. ...

Release lock. ...

Create and return a recursive lock whose name is name. ...

As for acquire-lock, but for recursive locks.

Release the recursive lock. ...

Resource contention: condition variables

A condition variable provides a mechanism for threads to put themselves to sleep while waiting for the state of something to change, then to be subsequently woken by another thread which has changed the state.

A condition variable must be used in conjunction with a lock to protect access to the state of the object of interest. The procedure is as follows:

Suppose two threads A and B, and some kind of notional event channel C. A is consuming events in C, and B is producing them. CV is a condition-variable
  1. A acquires the lock that safeguards access to C
  2. A threads and removes all events that are available in C
  3. When C is empty, A calls CONDITION-WAIT, which atomically releases the lock and puts A to sleep on CV
  4. Wait to be notified; CONDITION-WAIT will acquire the lock again before returning
  5. Loop back to step 2, for as long as threading should continue
When B generates an event E, it
  1. acquires the lock guarding C
  2. adds E to the channel
  3. calls CONDITION-NOTIFY on CV to wake any sleeping thread
  4. releases the lock
To avoid the "lost wakeup" problem, the implementation must guarantee that CONDITION-WAIT in thread A atomically releases the lock and sleeps. If this is not guaranteed there is the possibility that thread B can add an event and call CONDITION-NOTIFY between the lock release and the sleep - in this case the notify call would not see A, which would be left sleeping despite there being an event available.

Allows other threads to run. ...

Returns a new condition-variable object for use with condition-wait and condition-notify.

Atomically release lock and enqueue the calling thread waiting for condition-variable. ...

Notify at least one of the threads waiting for condition-variable. ...

Introspection/debugging

The following functions may be provided for debugging purposes, but are not advised to be called from normal user code.

Returns a sequence of all of the threads. This may not be freshly-allocated, so the caller should not modify it.

Interrupt thread and cause it to evaluate function before continuing with the interrupted path of execution. ...

Terminates the thread thread, which is an object as returned by make-thread. ...

Returns true if thread is alive, that is, if destroy-thread has not been called on it.

Wait until thread terminates. If thread has already terminated, return immediately.

Exported Symbol Index

*default-special-bindings*, Variable
*standard-io-bindings*, Variable
*supports-threads-p*, Variable
acquire-lock, Function
acquire-recursive-lock, Function
all-threads, Function
condition-notify, Function
condition-wait, Function
current-thread, Function
destroy-thread, Function
interrupt-thread, Function
join-thread, Function
make-condition-variable, Function
make-lock, Function
make-recursive-lock, Function
make-thread, Function
release-lock, Function
release-recursive-lock, Function
start-multiprocessing, Function
thread, Symbol
thread-alive-p, Function
thread-name, Function
thread-yield, Function
threadp, Function
timeout, Symbol
with-lock-held, Macro
with-recursive-lock-held, Macro
with-timeout, Macro