While looking for the 'right' way to get a SCBL thread to wait for a specified condition as part of an attempt to update port from the CLOCC, I came across this gem in the McCLIM sources.
(declaim (inline yield)) (defun yield () (declare (optimize speed (safety 0))) (sb-alien:alien-funcall (sb-alien:extern-alien "sched_yield" (function sb-alien:int))) (values))
(defun process-wait (reason predicate) (let ((old-state (process-whostate *current-process*))) (unwind-protect (progn (setf old-state (process-whostate *current-process*) (process-whostate *current-process*) reason) (loop (let ((it (funcall predicate))) (when it (return it))) ;(sleep .01) (yield))) (setf (process-whostate *current-process*) old-state))))
Now this will work, but my understanding is when calling sched_yeild, a thread gets completely expired and put at the back of the scheduling queue. What was/is wrong with sleep?
On Tue, Feb 14, 2006 at 09:58:10AM +0000, John Connors wrote:
While looking for the 'right' way to get a SCBL thread to wait for a specified condition as part of an attempt to update port from the CLOCC, I came across this gem in the McCLIM sources.
Really, there _is_ no 'right' way. Threads in SBCL (as with threads in OpenMCL and any other implementation using "native" threads) are scheduled by the operating system, and the operating system, as a rule, can't evaluate arbitrary bits of Lisp to decide if a thread is runnable or not. So it has to run it to find out if it wants to run or not, which is not what I or anyone would really consider an efficient use of resources.
Most of the uses of process-wait in the wild are for implementing higher-level synchronisation constructs like mutexes/semaphores/queues, and most of the Lisps with OS-scheduled threads already have efficient implementations of these that play nicely with the kernel scheduler (or at least have the potential to, which a Lisp-based solution will never have[*]). It would make far more sense to encourage people to use the higher-level constructs than provide them with a hacky workaround to shore up shonky code. See e.g. http://www.cliki.net/BORDEAUX-MP for one possible "standard" interface that includes mutexes and posix-style condition variables
Now this will work, but my understanding is when calling sched_yeild, a thread gets completely expired and put at the back of the scheduling queue.
The semantics of sched_yield have changed (possibly even more than once) from one Linux version to the next, and I can't even remember what it's suppsoed to do these days. I rather suspect that in the grand scheme of things it doesn't matter too much, as this approach is never going to be particularly efficient whatever you do.
-dan