David Steuber <david@...> writes:
> To quote a line from the SBCL manual:
>
> "Dynamic bindings to symbols are per-thread. Signal handlers are
> per-thread."
>
> Although I have not seen how Lisp does signal handling, it is nice to
> know that the handler will be called in the same thread that the
> signal was raised. That at least means that you can pretend the
Yup.
> thread is its own little world. I'm not quite sure about the dynamic
> bindings. My interpretation is that
>
> (defvar *foo* "bar")
>
> means that every thread has *foo* with the initial value of "bar". If
> a thread does
>
> (setf *foo* "baz")
>
> then /that/ thread and /only/ that thread has *foo* bound to "baz".
> If this is the case, then that is great. I have a sort of thread
> local storage thing going on for free.
As Nikodemus points out, by using SETF you're setting the (global
value of the) variable, not rebinding it. To bind it, use LET.
Once you've bound it, any further setfs will affect only the local
binding, so, yes, you have thread-local storage.
> That then leads me to wonder how to create a shareable object such as
> a hash table (or an a-list) that has serialized access from all the
> threads that need to touch it in some way.
Using a variable declared globally with DEFVAR or DEFPARAMETER, and
a mutex to control access to it.
;; from memory; details probably wrong, but that's what apropos is for
(defvar *foo* 1)
(defvar *foo-lock* (make-mutex))
(with-mutex (*foo-lock*)
(incf *foo*)) ; or whatever
> Then there are other threading issues like waiting on objects (Java
> style) and other scheduling issues. For example, if thread creation
> has too much overhead for a given purpose, I would want to pre-spawn a
> number of threads and have them sleeping in a queue to be woken up as
> needed to handle a request and then go back into the queue when
> finished rather than exiting.
You most probably want to be using the condition variables for this.
Summary: create a waitqueue for the threads to wait on
(make-waitqueue) and a lock to say who has control of it. Now have
queue readers acquire the lock then use condition-wait (which
atomically drops the lock and blocks) when the queue is empty and they
need to wait, and queue writers acquire the lock then use
condition-notify to wake one or more readers when they've added
something worth reading.
In outline, anyway. Better threads docs is on my todo (aka my "yeah,
right, like that'll ever happen") list
-dan
--
"please make sure that the person is your friend before you confirm"
|