[Openmcl-devel] Managing multi-threaded access to list

David L. Rager ragerdl at cs.utexas.edu
Thu May 25 09:14:38 PDT 2006


Hi Joseph,

You are missing a basic building block: the semaphore.  Also, you should use
the exported function (ccl:make-lock) instead of the non-exported
make-read-write-lock.  

A semaphore allows for efficient (fast) signaling between threads.  From the
"make-semaphore" documentation:

"Creates and returns an object of type CCL:SEMAPHORE. A semaphore has an
associated "count" which may be incremented and decremented atomically;
incrementing it represents sending a signal, and decrementing it represents
handling that signal. semaphore has an initial count of 0."

When you "increment" a semaphore's count, exactly one thread that's waiting
to decrement it is immediately awakened and decrements the count.  This fast
awakening is how you "signal" that a resource may be available.  Also,
semaphores effectively "store" signals.  If you signal a semaphore 10 times,
a thread can "wait" on that semaphore and immediately progress in its code.
If an 11th thread "waits" on the semaphore, it will have to wait for it to
be signaled by the producer. 

Wikipedia link:
http://en.wikipedia.org/wiki/Semaphore_%28programming%29


Instead of a semaphore, you could use condition variables.  Semaphores can
act as both locks and condition variables, so OpenMCL hasn't implemented
condition variables.


I inserted the semaphore signaling and semaphore waiting that you need.
It's possible I missed some details, like misnaming a function, but your
code looks like you can figure those out.  Also, since you use semaphores,
you probably won't need the data-available function.  Here's the
multi-threading interface:
http://openmcl.clozure.com/Doc/Threads-Dictionary.html#Threads-Dictionary

David


(defparameter *packet-list-lock* (ccl::make-lock)) 
(defparameter *packet-list* nil)
(defparameter *packet-list-semaphore* (ccl:make-semaphore))


(defun reading-packets ()
  "Function to read packets and putting them on *packet-list*"
  (loop
    (let ((pkt (read-packet-from-socket)))
     (when (acceptable-packet pkt)
        (progn
          (ccl:with-lock (*packet-list-lock*)
            (setf *packet-list* (append *packet-list* (list pkt))))
          (ccl:signal-semaphore *packet-list-semaphore*)))))

(defun start-reader-process ()
   "Start a producer thread"
    (ccl:process-run-function "Network Reader Process" #'reading-packets))


(defun consume-packet-hang ()
  "Pick a packet off the packet list, or return nil if none is available"
  (progn (ccl:wait-on-semaphore *packet-list-semaphore*)
         (ccl:with-lock (*packet-list-lock*)
           (pop *packet-list*))))





More information about the Openmcl-devel mailing list