[Openmcl-devel] Thread-local bindings

martin brooks.martin at sympatico.ca
Sat Jun 15 13:14:47 PDT 2019


Thanks; I stand corrected on both counts.

I am guessing the last call to process-run-function is supposed to have :thread-3 throughout.
Assuming this is so, what I see is:

THREAD1 GLOBAL-FOO 1
MAIN-THREAD GLOBAL-FOO 2
THREAD2 THREAD-2-FOO 3
THREAD3 THREAD-3-FOO 1
THREAD1 GLOBAL-FOO 4
MAIN-THREAD GLOBAL-FOO 5
THREAD2 THREAD-2-FOO 6
THREAD3 THREAD-3-FOO 2
THREAD1 GLOBAL-FOO 7
MAIN-THREAD GLOBAL-FOO 8
THREAD2 THREAD-2-FOO 9
THREAD3 THREAD-3-FOO 3

Thread-1, thread-2 and main-thread take turns incrementing the global binding of *cnt*, whereas thread-3 increments its local binding.
So, yes — the global binding is shared across the top level — was that your point?!?

I am looking for words; perhaps this is better:

      The dynamic extent of special lambda bindings has no meaning except in the thread that established those bindings.

The point upon which I initially hit my head was the case where a new thread is launched from within the extent of such special lambda bindings. 
Those bindings have no meaning for the new thread.

Except  … unless the new thread’s function is specially designed to promulgate those bindings, so that code in the new thread proceeds in the dynamic context of the parent thread:

  (process-run-function :my-thread #’(lambda (special-var) …) special-var)

Martin

> On Jun 15, 2019, at 12:08 PM, Ron Garret <ron at flownet.com> wrote:
> 
> 
> On Jun 15, 2019, at 6:43 AM, martin <brooks.martin at sympatico.ca> wrote:
> 
>> — “Dynamic extent” refers to time within a single thread, and does have meaning across multiple threads.
> 
> My guess is that you meant to say that it does NOT have meaning across multiple threads, but this is not correct.  It does.  See below.
> 
>> — Funcall is a function; process-run-function is a special form.
> 
> No, they are both functions:
> 
> ? #'funcall
> #<Compiled-function FUNCALL #x30000007F9FF>
> ? #'process-run-function
> #<Compiled-function PROCESS-RUN-FUNCTION #x300000401C7F>
> 
> Try this:
> 
> (defvar *foo* 'global-foo)
> (defvar *cnt* 0)
> 
> (let ((lock (make-lock))
>      (stream (if (find-package :hemlock-ext)
>                (funcall (find-symbol "TOP-LISTENER-OUTPUT-STREAM" :hemlock-ext))
>                *terminal-io*)))
>  (defun out (s &rest args)
>    (with-lock-grabbed (lock)
>      (apply 'format stream s args)
>      (terpri stream))))
> 
> (defun print-foo (thread-id)
>  (dotimes (i 3)
>    (out "~A ~A ~A" thread-id *foo* (incf *cnt*))
>    (sleep 0.1)))
> 
> (defun test ()
>  (process-run-function :thread-1 (lambda () (print-foo :thread1)))
>  (process-run-function :thread-2 (lambda () (let ((*foo* :thread-2-foo))
>                                               (print-foo :thread2))))
>  (process-run-function :thread-2 (lambda () (let ((*foo* :thread-3-foo)
>                                                   (*cnt* 0))
>                                               (print-foo :thread2))))
>  (print-foo :main-thread)
>  (sleep 0.1)
>  *cnt*)
> 




More information about the Openmcl-devel mailing list