Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > media > contrib-release > by-pkgid > 723830890bac44da3d113209b14e090b > files > 664

sbcl-1.0.31-1mdv2010.0.i586.rpm

<html lang="en">
<head>
<title>Waitqueue/condition variables - SBCL 1.0.31 User Manual</title>
<meta http-equiv="Content-Type" content="text/html">
<meta name="description" content="SBCL 1.0.31 User Manual">
<meta name="generator" content="makeinfo 4.13">
<link title="Top" rel="start" href="index.html#Top">
<link rel="up" href="Threading.html#Threading" title="Threading">
<link rel="prev" href="Semaphores.html#Semaphores" title="Semaphores">
<link rel="next" href="Sessions_002fDebugging.html#Sessions_002fDebugging" title="Sessions/Debugging">
<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
<!--

     This manual is part of the SBCL software system. See the `README'
     file for more information.

     This manual is largely derived from the manual for the CMUCL
     system, which was produced at Carnegie Mellon University and later
     released into the public domain. This manual is in the public
     domain and is provided with absolutely no warranty. See the
     `COPYING' and `CREDITS' files for more information.
   -->
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
  pre.display { font-family:inherit }
  pre.format  { font-family:inherit }
  pre.smalldisplay { font-family:inherit; font-size:smaller }
  pre.smallformat  { font-family:inherit; font-size:smaller }
  pre.smallexample { font-size:smaller }
  pre.smalllisp    { font-size:smaller }
  span.sc    { font-variant:small-caps }
  span.roman { font-family:serif; font-weight:normal; } 
  span.sansserif { font-family:sans-serif; font-weight:normal; } 
--></style>
</head>
<body>
<div class="node">
<a name="Waitqueue%2fcondition-variables"></a>
<a name="Waitqueue_002fcondition-variables"></a>
<p>
Next:&nbsp;<a rel="next" accesskey="n" href="Sessions_002fDebugging.html#Sessions_002fDebugging">Sessions/Debugging</a>,
Previous:&nbsp;<a rel="previous" accesskey="p" href="Semaphores.html#Semaphores">Semaphores</a>,
Up:&nbsp;<a rel="up" accesskey="u" href="Threading.html#Threading">Threading</a>
<hr>
</div>

<!-- node-name,  next,  previous,  up -->
<h3 class="section">12.5 Waitqueue/condition variables</h3>

<p>These are based on the POSIX condition variable design, hence the
annoyingly CL-conflicting name. For use when you want to check a
condition and sleep until it's true. For example: you have a shared
queue, a writer process checking &ldquo;queue is empty&rdquo; and one or more
readers that need to know when &ldquo;queue is not empty&rdquo;. It sounds
simple, but is astonishingly easy to deadlock if another process runs
when you weren't expecting it to.

   <p>There are three components:

     <ul>
<li>the condition itself (not represented in code)

     <li>the condition variable (a.k.a waitqueue) which proxies for it

     <li>a lock to hold while testing the condition
</ul>

   <p>Important stuff to be aware of:

     <ul>
<li>when calling condition-wait, you must hold the mutex. condition-wait
will drop the mutex while it waits, and obtain it again before
returning for whatever reason;

     <li>likewise, you must be holding the mutex around calls to
condition-notify;

     <li>a process may return from condition-wait in several circumstances: it
is not guaranteed that the underlying condition has become true. You
must check that the resource is ready for whatever you want to do to
it.

   </ul>

<pre class="lisp">     (defvar *buffer-queue* (make-waitqueue))
     (defvar *buffer-lock* (make-mutex :name "buffer lock"))
     
     (defvar *buffer* (list nil))
     
     (defun reader ()
       (with-mutex (*buffer-lock*)
         (loop
          (condition-wait *buffer-queue* *buffer-lock*)
          (loop
           (unless *buffer* (return))
           (let ((head (car *buffer*)))
             (setf *buffer* (cdr *buffer*))
             (format t "reader ~A woke, read ~A~%"
                     *current-thread* head))))))
     
     (defun writer ()
       (loop
        (sleep (random 5))
        (with-mutex (*buffer-lock*)
          (let ((el (intern
                     (string (code-char
                              (+ (char-code #\A) (random 26)))))))
            (setf *buffer* (cons el *buffer*)))
          (condition-notify *buffer-queue*))))
     
     (make-thread #'writer)
     (make-thread #'reader)
     (make-thread #'reader)
</pre>
   <p><a name="Structure-sb_002dthread_003awaitqueue"></a>

<div class="defun">
&mdash; Structure: <b>sb-thread:waitqueue</b><var><a name="index-sb_002dthread_003awaitqueue-491"></a></var><br>
<blockquote><p><a name="index-sb_002dthread_003awaitqueue-492"></a>Class precedence list: <code>waitqueue, structure-object, t</code>

        <p>Waitqueue type. 
</p></blockquote></div>

   <p><a name="Function-sb_002dthread_003amake_002dwaitqueue"></a>

<div class="defun">
&mdash; Function: <b>sb-thread:make-waitqueue</b><var> &amp;key name<a name="index-sb_002dthread_003amake_002dwaitqueue-493"></a></var><br>
<blockquote><p><a name="index-sb_002dthread_003amake_002dwaitqueue-494"></a>Create a waitqueue. 
</p></blockquote></div>

   <p><a name="Function-sb_002dthread_003awaitqueue_002dname"></a>

<div class="defun">
&mdash; Function: <b>sb-thread:waitqueue-name</b><var> instance<a name="index-sb_002dthread_003awaitqueue_002dname-495"></a></var><br>
<blockquote><p><a name="index-sb_002dthread_003awaitqueue_002dname-496"></a>Name of a <code>queue</code>. Can be assingned to using <code>setf</code>. Queue names
can be arbitrary printable objects, and need not be unique. 
</p></blockquote></div>

   <p><a name="Function-sb_002dthread_003acondition_002dwait"></a>

<div class="defun">
&mdash; Function: <b>sb-thread:condition-wait</b><var> queue mutex<a name="index-sb_002dthread_003acondition_002dwait-497"></a></var><br>
<blockquote><p><a name="index-sb_002dthread_003acondition_002dwait-498"></a>Atomically release <code>mutex</code> and enqueue ourselves on <code>queue</code>.  Another
thread may subsequently notify us using <code>condition-notify</code>, at which
time we reacquire <code>mutex</code> and return to the caller. 
</p></blockquote></div>

   <p><a name="Function-sb_002dthread_003acondition_002dnotify"></a>

<div class="defun">
&mdash; Function: <b>sb-thread:condition-notify</b><var> queue &amp;optional n<a name="index-sb_002dthread_003acondition_002dnotify-499"></a></var><br>
<blockquote><p><a name="index-sb_002dthread_003acondition_002dnotify-500"></a>Notify <code>n</code> threads waiting on <code>queue</code>. The same mutex that is used in
the corresponding <code>condition-wait</code> must be held by this thread during
this call. 
</p></blockquote></div>

   <p><a name="Function-sb_002dthread_003acondition_002dbroadcast"></a>

<div class="defun">
&mdash; Function: <b>sb-thread:condition-broadcast</b><var> queue<a name="index-sb_002dthread_003acondition_002dbroadcast-501"></a></var><br>
<blockquote><p><a name="index-sb_002dthread_003acondition_002dbroadcast-502"></a>Notify all threads waiting on <code>queue</code>. 
</p></blockquote></div>

   </body></html>