mt question/problem

View: New views
15 Messages — Rating Filter:   Alert me  

mt question/problem

by Don Cohen-12 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


I may have asked something like this before, but ...

(mt:make-thread
 (lambda ()
   (format t "testing: ~a"
        (multiple-value-list (ignore-errors (list *print-pretty* c)))))
 :name (format nil "foo" )
 :initial-bindings
 (print (loop for x on
                  (list 'c 'c)
                  by #'cddr collect
                  (cons (car x) (list 'quote (cadr x))))))
 
((C QUOTE C))  
#<THREAD "foo">
Break 2 [11]> testing:  
(NIL
 :LAMBDA: variable C has no value
)

Why is the variable C unbound in the thread when the initial bindings
list seems to contain a value for it?

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
clisp-devel mailing list
clisp-devel@...
https://lists.sourceforge.net/lists/listinfo/clisp-devel

Re: mt question/problem

by Sam Steingold :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

> * Don Cohen <qba-fbheprsbetr-kkm@...> [2009-11-01 17:41:30 -0800]:
>
> I may have asked something like this before, but ...
>
> (mt:make-thread
>  (lambda ()
>    (format t "testing: ~a"
>         (multiple-value-list (ignore-errors (list *print-pretty* c)))))
>  :name (format nil "foo" )
>  :initial-bindings
>  (print (loop for x on
>                   (list 'c 'c)
>                   by #'cddr collect
>                   (cons (car x) (list 'quote (cadr x))))))
>  
> ((C QUOTE C))  
> #<THREAD "foo">
> Break 2 [11]> testing:  
> (NIL
>  :LAMBDA: variable C has no value
> )
>
> Why is the variable C unbound in the thread when the initial bindings
> list seems to contain a value for it?

because initial-bindings are for global specials:


[1]> (defparameter c 23)
C
[2]> (mt:make-thread
 (lambda ()
   (format t "testing: ~a"
        (multiple-value-list (ignore-errors (list *print-pretty* c)))))
 :name (format nil "foo" )
 :initial-bindings
 (print (loop for x on
                  (list 'c 'c)
                  by #'cddr collect
                  (cons (car x) (list 'quote (cadr x))))))

((C QUOTE C))
#<THREAD "foo">
[3]> testing: ((T C))




--
Sam Steingold (http://sds.podval.org/) on Ubuntu 9.04 (jaunty)
http://ffii.org http://camera.org http://pmw.org.il http://iris.org.il
http://www.PetitionOnline.com/tap12009/ http://dhimmi.com
Time would have been the best Teacher, if it did not kill all its students.

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
clisp-devel mailing list
clisp-devel@...
https://lists.sourceforge.net/lists/listinfo/clisp-devel

Re: mt question/problem

by Don Cohen-12 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Sam Steingold writes:
 > > * Don Cohen <qba-fbheprsbetr-kkm@...> [2009-11-01 17:41:30 -0800]:
 > > Why is the variable C unbound in the thread when the initial bindings
 > > list seems to contain a value for it?
 > because initial-bindings are for global specials:
I don't see anything about this in the doc.
What's the difference between a global special and any other kind?
How does :initial-bindings compare to something like
(let ((vars '(a b c))(vals (list a b c)))
 (mt:make-thread
  (lambda ()
   (progv vars vals ...))))

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
clisp-devel mailing list
clisp-devel@...
https://lists.sourceforge.net/lists/listinfo/clisp-devel

Re: mt question/problem

by Vladimir Tzankov :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On 11/2/09, Don Cohen <don-sourceforge-xxz@...> wrote:
> Sam Steingold writes:
>  > > * Don Cohen <qba-fbheprsbetr-kkm@...> [2009-11-01 17:41:30
> -0800]:
>  > > Why is the variable C unbound in the thread when the initial bindings
>  > > list seems to contain a value for it?
>  > because initial-bindings are for global specials:
> I don't see anything about this in the doc.
> What's the difference between a global special and any other kind?

defparameter, defvar and proclaimed specials cause per value cell to
be allocated for symbols. Special variables may have different
bindings in different threads.

> How does :initial-bindings compare to something like
> (let ((vars '(a b c))(vals (list a b c)))
>  (mt:make-thread
>   (lambda ()
>    (progv vars vals ...))))

If A, B and C are not special variables they will not have per thread
allocated value cells - bindings that progv will establish will be
shared between all threads (values of A,B and C in all threads will be
the same).

Note also that vars and vals values will be shared between two threads
(in case above it's not important) - in order to avoid this (let
((vars vars) (vals vals)) (mt:make-thread ...)) may be used.

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
clisp-devel mailing list
clisp-devel@...
https://lists.sourceforge.net/lists/listinfo/clisp-devel

Re: mt question/problem

by Vladimir Tzankov :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On 11/2/09, Don Cohen <don-sourceforge-xxz@...> wrote:
> How does :initial-bindings compare to something like
> (let ((vars '(a b c))(vals (list a b c)))
>  (mt:make-thread
>   (lambda ()
>    (progv vars vals ...))))

The main difference is that forms in initial-bindings are eval-ed in
the context of newly created thread. Thus any reference to thread
specific data (mt:current-thread, mutex ownership change, deferred
interrupts ..) are specific to new thread. Evaluation of these forms
is performed before just before funcall-ing the thread lambda.

Main purpose of initial-bindings is to perform initialization of some
global data that should not be shared between threads -
*random-state*, *readtable*, *defer-interrupts*, etc - not for passing
"arguments" to thread function - see *DEFAULT-SPECIAL-BINDINGS* in
threads.lisp.
When you use initial-bindings it's best to cons your specific data in
front of *DEFAULT-SPECIAL-BINDINGS* or copy and modify it to fit your
needs.

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
clisp-devel mailing list
clisp-devel@...
https://lists.sourceforge.net/lists/listinfo/clisp-devel

Re: mt question/problem

by Don Cohen-12 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


I begin to understand - this all seems to be related to the
implementation choice to use a "shallow binding" scheme.

It seems to me that the "deep binding" scheme has the "obviously
correct" semantics (meaning, what seems obvious to me, but of course
the semantics of lisp was never really defined for multiple threads).
Shallow binding was a clever optimization of deep binding that works
only in a single threaded environment.  

I think you're now trying to use shallow binding but changing the
semantics of special variables.  This is also not entirely clear from
the doc.

 32.5.2.2. Special Variable Values
 Every dynamic variable has a global value that can be shared across
 all MT:THREADs.
 Bindings of dynamic variables (via LET/LET*/MULTIPLE-VALUE-BIND) are
 local to MT:THREADs, i.e. every SYMBOL has a different value cell in
 each MT:THREAD. MT:SYMBOL-VALUE-THREAD can be used to inspect and
 modify these thread local bindings.

Here I would have expected
 (let (c) (declare (special c)) (foo))
to qualify under the above "Bindings of dynamic variables".

One might argue that the very fact that CLHS defines symbol-value
seems to require something like shallow binding, but it strikes me
that it might also be consistent with CLHS to make symbol-value depend
implicitly on (current-thread).  And this would better preserve the
semantics of special variables.

The statement above that every dynamic variable has a global value
could still make sense, but then I'd expect to access that not by
symbol-value, but by a newly invented global-symbol-value.  But I also
don't see that such a global value is necessary.

Vladimir Tzankov writes:
 > > What's the difference between a global special and any other kind?
 > defparameter, defvar and proclaimed specials cause per value cell to
Could you possibly mean "per thread value cell"?
 > be allocated for symbols. Special variables may have different
 > bindings in different threads.
I certainly expect that special variables should be able to have
different values in different threads, but I'd expect this to be
true whether they are proclaimed (or is that now "declaimed"?) special
or only declared special as in (let (c) (declare (special c)) (foo)).

So defvar and defparameter create what you call "global" specials?
But (declare (special ...)) does not, right?
I'm now guessing that (let (x)(declare (special x))...) uses "the
global" value cell in the the symbol x rather than a cell for x in the
current thread.  This violates my intuition/understanding of what
special variables are all about.  Can you see any justification for
such semantics other than ease of implementation?

 > > How does :initial-bindings compare to something like
 > > (let ((vars '(a b c))(vals (list a b c)))
 > >  (mt:make-thread
 > >   (lambda ()
 > >    (progv vars vals ...))))

 > If A, B and C are not special variables they will not have per thread
 > allocated value cells - bindings that progv will establish will be
 > shared between all threads (values of A,B and C in all threads will be
 > the same).
Progv variables are all special.  I think what you mean is that,
because they're not "globally" special (meaning globally declared to
be), they won't act like special variables here.

 > Note also that vars and vals values will be shared between two threads
 > (in case above it's not important) - in order to avoid this (let
 > ((vars vars) (vals vals)) (mt:make-thread ...)) may be used.
I guess you mean if I had done two different make-thread's in the same
(let ((vars ...)(vals ...)) ...)

Vladimir Tzankov writes:
 > On 11/2/09, Don Cohen <don-sourceforge-xxz@...> wrote:
 > > How does :initial-bindings compare to something like
 > > (let ((vars '(a b c))(vals (list a b c)))
 > >  (mt:make-thread
 > >   (lambda ()
 > >    (progv vars vals ...))))
 >
 > The main difference is that forms in initial-bindings are eval-ed in
 > the context of newly created thread.
Whoa!!  This is even more unexpected!  Was that in the doc somewhere?
(Of course, in my example I arranged to evaluate things in the calling
thread and then quote them so it didn't matter where the evaluation
was done.)
It seems to me that the current design makes it unnecessarily
difficult to pass arguments to the new thread.  I'd really like to do
something more like
 (make-thread {optional keyword args if necessary} function . args)
where args are evaluated before the thread is created and the values
are then given as arguments to the function in the new thread.

 >  ... Thus any reference to thread
 > specific data (mt:current-thread, mutex ownership change, deferred
 > interrupts ..) are specific to new thread. Evaluation of these forms
 > is performed before just before funcall-ing the thread lambda.
So far I'm having trouble seeing when/why it's useful to do that
evaluation in the new thread.
I am seeing that this makes it difficult to pass info from the old
thread to the new one.  For instance, I had tried to use initial
bindings to use the same package in the new thread as in the old one,
but it now appears that the "obvious" way of doing this would have
failed.

 > Main purpose of initial-bindings is to perform initialization of some
 > global data that should not be shared between threads -
 > *random-state*, *readtable*, *defer-interrupts*, etc - not for passing
So far I don't see why it's important not to share the random state.
It looks to me like you're really just trying to avoid locking it.
Most of the other things in *DEFAULT-SPECIAL-BINDINGS* seem
unnecessary or worse, e.g., *print-base* - shouldn't the default be
whatever I set the "global" value to?
 
 > "arguments" to thread function - see *DEFAULT-SPECIAL-BINDINGS* in
 > threads.lisp.
 > When you use initial-bindings it's best to cons your specific data in
 > front of *DEFAULT-SPECIAL-BINDINGS* or copy and modify it to fit your
 > needs.

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
clisp-devel mailing list
clisp-devel@...
https://lists.sourceforge.net/lists/listinfo/clisp-devel

Re: mt question/problem

by Vladimir Tzankov :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On 11/3/09, Don Cohen <don-sourceforge-xxz@...> wrote:
> So defvar and defparameter create what you call "global" specials?
> But (declare (special ...)) does not, right?
> I'm now guessing that (let (x)(declare (special x))...) uses "the
> global" value cell in the the symbol x rather than a cell for x in the
> current thread.  This violates my intuition/understanding of what
> special variables are all about.  Can you see any justification for
> such semantics other than ease of implementation?

Actually it worked (almost) the way you describe until 2009-10-25 when
I changed it in cvs. Now rethinking it - looks I wrongly removed it.
Every special declaration should allocate per thread value cell for
the symbol (if it does not have already).
Sam?

>  > On 11/2/09, Don Cohen <don-sourceforge-xxz@...> wrote:
>  > > How does :initial-bindings compare to something like
>  > > (let ((vars '(a b c))(vals (list a b c)))
>  > >  (mt:make-thread
>  > >   (lambda ()
>  > >    (progv vars vals ...))))
>  >
>  > The main difference is that forms in initial-bindings are eval-ed in
>  > the context of newly created thread.
> Whoa!!  This is even more unexpected!  Was that in the doc somewhere?

http://clisp.org/impnotes/mt.html#make-thread

> It seems to me that the current design makes it unnecessarily
> difficult to pass arguments to the new thread.  I'd really like to do
> something more like
>  (make-thread {optional keyword args if necessary} function . args)
> where args are evaluated before the thread is created and the values
> are then given as arguments to the function in the new thread.

what is hard/wrong with:
(defun new-thread (function &rest args)
   (mt:make-thread (lambda () (apply function args))))
or other wrapper that suits your needs?

> So far I'm having trouble seeing when/why it's useful to do that
> evaluation in the new thread.

Whenever (current-thread) value or some mutex ownership involved in
evaluation is important.

> I am seeing that this makes it difficult to pass info from the old
> thread to the new one.  For instance, I had tried to use initial
> bindings to use the same package in the new thread as in the old one,
> but it now appears that the "obvious" way of doing this would have
> failed.

(mt:make-thread
 (lambda () (print *package*))
 :initial-bindings `((*package* . ',*package*) ,@mt:*default-special-bindings*))

Using initial-bindings is easy way to "initialize" special variables
bindings in thread when you are not in control of the thread's main
function or do not want each of your thread functions to start with
let/progv/etc of (probably same) special vars.
And of course you may always pass NIL if you prefer to bind everything
by yourself.

> So far I don't see why it's important not to share the random state.
> It looks to me like you're really just trying to avoid locking it.
yes - avoid locking and races when it is modified.

> Most of the other things in *DEFAULT-SPECIAL-BINDINGS* seem
> unnecessary or worse, e.g., *print-base* - shouldn't the default be
> whatever I set the "global" value to?

We may use symbols global values, creating thread bindings or some
"safe" values - like now. First option looks most natural.
Sam?

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
clisp-devel mailing list
clisp-devel@...
https://lists.sourceforge.net/lists/listinfo/clisp-devel

Re: mt question/problem

by Sam Steingold :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Vladimir Tzankov wrote:

> On 11/3/09, Don Cohen <don-sourceforge-xxz@...> wrote:
>> So defvar and defparameter create what you call "global" specials?
>> But (declare (special ...)) does not, right?
>> I'm now guessing that (let (x)(declare (special x))...) uses "the
>> global" value cell in the the symbol x rather than a cell for x in the
>> current thread.  This violates my intuition/understanding of what
>> special variables are all about.  Can you see any justification for
>> such semantics other than ease of implementation?
>
> Actually it worked (almost) the way you describe until 2009-10-25 when
> I changed it in cvs. Now rethinking it - looks I wrongly removed it.
> Every special declaration should allocate per thread value cell for
> the symbol (if it does not have already).

A vast majority of special variables a global, so this is not terribly important.
However, if a function FOO depends on a special variable BAR and we do

(make-thread (lambda () (let ((bar 1)) (foo))))

and

(make-thread #'foo)

At the same time, them we should NOT have a race, i.e., the behavior of the
second thread should not depend on whether its FOO happened to be executed
while the first thread bound BAR to 1.

So, yes, you are right, a special declaration should only modify the
thread-local value cell.

>> So far I don't see why it's important not to share the random state.
>> It looks to me like you're really just trying to avoid locking it.
> yes - avoid locking and races when it is modified.

another issue is reproducibility, see
http://clisp.podval.org/impnotes/faq.html#faq-random

>> Most of the other things in *DEFAULT-SPECIAL-BINDINGS* seem
>> unnecessary or worse, e.g., *print-base* - shouldn't the default be
>> whatever I set the "global" value to?
>
> We may use symbols global values, creating thread bindings or some
> "safe" values - like now. First option looks most natural.

I am highly ambivalent.
What if *print-base* is set (or bound) in one thread while another thread is
writing a large file?
If all threads use the same global value, part of the file will be written with
one base and the rest with the other.

Sam.

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
clisp-devel mailing list
clisp-devel@...
https://lists.sourceforge.net/lists/listinfo/clisp-devel

Re: mt question/problem

by Vladimir Tzankov :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On 11/3/09, Sam Steingold <sds@...> wrote:

>>> Most of the other things in *DEFAULT-SPECIAL-BINDINGS* seem
>>> unnecessary or worse, e.g., *print-base* - shouldn't the default be
>>> whatever I set the "global" value to?
>>
>> We may use symbols global values, creating thread bindings or some
>> "safe" values - like now. First option looks most natural.
>
> I am highly ambivalent.
> What if *print-base* is set (or bound) in one thread while another thread is
> writing a large file?
> If all threads use the same global value, part of the file will be written
> with one base and the rest with the other.

Every thread on it's creation will bind *print-base* (as it is now) in
order to prevent such cases.
The question is what should be the initial value - now it is 10, but
we may use *print-base* global value instead. In
*default-special-bindings we will have:
(*print-base* . (mt:symbol-value-thread '*print-base* nil))

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
clisp-devel mailing list
clisp-devel@...
https://lists.sourceforge.net/lists/listinfo/clisp-devel

Re: mt question/problem

by Sam Steingold :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Vladimir Tzankov wrote:

> On 11/3/09, Sam Steingold <sds@...> wrote:
>>>> Most of the other things in *DEFAULT-SPECIAL-BINDINGS* seem
>>>> unnecessary or worse, e.g., *print-base* - shouldn't the default be
>>>> whatever I set the "global" value to?
>>> We may use symbols global values, creating thread bindings or some
>>> "safe" values - like now. First option looks most natural.
>> I am highly ambivalent.
>> What if *print-base* is set (or bound) in one thread while another thread is
>> writing a large file?
>> If all threads use the same global value, part of the file will be written
>> with one base and the rest with the other.
>
> Every thread on it's creation will bind *print-base* (as it is now) in
> order to prevent such cases.

precisely my point.

> The question is what should be the initial value - now it is 10, but
> we may use *print-base* global value instead. In
> *default-special-bindings we will have:
> (*print-base* . (mt:symbol-value-thread '*print-base* nil))

can we just use

(*print-base* . *print-base*)

(and the same for all the other variables)?

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
clisp-devel mailing list
clisp-devel@...
https://lists.sourceforge.net/lists/listinfo/clisp-devel

Re: mt question/problem

by Vladimir Tzankov :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On 11/3/09, Sam Steingold <sds@...> wrote:
>> *default-special-bindings we will have:
>> (*print-base* . (mt:symbol-value-thread '*print-base* nil))
>
> can we just use
>
> (*print-base* . *print-base*)
of course!

> (and the same for all the other variables)?
All of them?
What about *gensym-counter* - I am worried that it's possible two
threads to generate same symbol?

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
clisp-devel mailing list
clisp-devel@...
https://lists.sourceforge.net/lists/listinfo/clisp-devel

Re: mt question/problem

by Sam Steingold :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Vladimir Tzankov wrote:
> On 11/3/09, Sam Steingold <sds@...> wrote:
>>> *default-special-bindings we will have:
>>> (*print-base* . (mt:symbol-value-thread '*print-base* nil))
>> can we just use
>> (*print-base* . *print-base*)
> of course!

Good.
You would also need to replace (copy-readtable nil) with (copy-readtable) so
that *readtable* is also inherited.

>> (and the same for all the other variables)?
> All of them?
> What about *gensym-counter* - I am worried that it's possible two
> threads to generate same symbol?

First of all, GENSYM always creates a new uninterned symbol, so even if two
threads have the same counters and create symbols with the same names, they
would still be different symbols, so there is no problem here.
Technically, one can replace all calls to GENSYM in macros with (MAKE-SYMBOL
"") and everything would still work just fine. The only reason we use GENSYM is
for visual debugging of macroexpansions.
Second, I see no reason to bound *GENSYM-COUNTER* at all. Let it always be the
global value, as I explained, there is no problem with sharing.

Sam.

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
clisp-devel mailing list
clisp-devel@...
https://lists.sourceforge.net/lists/listinfo/clisp-devel

Re: mt question/problem

by Don Cohen-12 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Vladimir Tzankov writes:

 > Actually it worked (almost) the way you describe until 2009-10-25 when
 > I changed it in cvs. Now rethinking it - looks I wrongly removed it.
 > Every special declaration should allocate per thread value cell for
 > the symbol (if it does not have already).
I think above means (but I want to verify) that you plan to change
things so that all bindings of special vars are -per-thread.
Let me know when you think it's done and I'll try removing the defvar
I had to add.

 > > So far I'm having trouble seeing when/why it's useful to do that
 > > evaluation in the new thread.
 > Whenever (current-thread) value or some mutex ownership involved in
 > evaluation is important.
Why not
 (mt:make-thread (lambda () (let ((*th* (mt:current-thread))) ...)))
Or for that matter,
 (mt:make-thread (lambda () (let ((*read-base* *read-base*)) ...)))

These seem related to this:
 > (defun new-thread (function &rest args)
 >    (mt:make-thread (lambda () (apply function args))))
in that it feels to me like you're going out of your way (adding
initial bindings arg) to make it easy to do things that I'll rarely
want to do while failing to make it easy to do things that I'll
normally want to do.  I'd expect it to be relatively rare that
programs even mention things in *default-special-bindings*, let alone
change them or rely on having different values in different threads,
whereas one will almost always want to pass arguments to the functions
to be called in new threads.

 > > but it now appears that the "obvious" way of doing this would have
 > > failed.
 > (mt:make-thread
 >  (lambda () (print *package*))
 >  :initial-bindings `((*package* . ',*package*)
                        ,@mt:*default-special-bindings*))
The point is that you need the backquote, whereas what I would have
considered the obvious solution - without the backquote - would have
worked if evaluated in the calling thread.

 > > So far I don't see why it's important not to share the random state.
 > > It looks to me like you're really just trying to avoid locking it.
 > yes - avoid locking and races when it is modified.
You still have to deal with the possibility of using the same
state at the same time in two threads.  So I think you should let
the programmer worry about what state he wants for a new thread just
as he has to worry about that in all other places.  And the same seems
to apply to all the other things in the default list.

I'm guessing that the cost of all these default bindings is much less
than the cost of creating a thread.

 [Sam wrote]
 > A vast majority of special variables a global, so this is not
 > terribly important.
I don't agree with that reasoning.
I'm not even so sure about the premise.
But you do seem to have come to what I think is the right conclusion.

 > another issue is reproducibility, see
 > http://clisp.podval.org/impnotes/faq.html#faq-random
But this issue arises without threads, and the programmer should
expect to have to deal with it.  I don't think you're doing him a
favor by adding default behavior where he might not expect it.

 > > What if *print-base* is set (or bound) in one thread while another
 > > thread is writing a large file?
 > > If all threads use the same global value, part of the file will be written
 > > with one base and the rest with the other.
If it's bound, the proposed (what I called correct) behavior of
binding it only for the thread will solve this problem.
If it's set and not bound in the writing thread, as I propose by
default, then the file will indeed be strange - but this is no
different from all the other global state that could be used by one
thread and altered by another.  Worrying about such things falls
within the normal job description of a programmer.

 > Every thread on it's creation will bind *print-base* (as it is now)
 > in order to prevent such cases.
I now think that default-special-bindings should be empty, and even that
the initial bindings argument should be removed.

 > > What about *gensym-counter* - I am worried that it's possible two
 > > threads to generate same symbol?
I think that gensym ought to be thread safe in the sense that the
increment of the counter should always return a different value.
That seems to require some sort of lock.


------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
clisp-devel mailing list
clisp-devel@...
https://lists.sourceforge.net/lists/listinfo/clisp-devel

[sorry for my failure to edit the mail headers!!]

by Don Cohen-12 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


which is the cause of multiple copies of the last message

------------------------------------------------------------------------------
Come build with us! The BlackBerry(R) Developer Conference in SF, CA
is the only developer event you need to attend this year. Jumpstart your
developing skills, take BlackBerry mobile applications to market and stay
ahead of the curve. Join us from November 9 - 12, 2009. Register now!
http://p.sf.net/sfu/devconference
_______________________________________________
clisp-devel mailing list
clisp-devel@...
https://lists.sourceforge.net/lists/listinfo/clisp-devel

Re: mt question/problem

by Vladimir Tzankov :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On 11/3/09, Don Cohen <don-sourceforge-xxz@...> wrote:
> in that it feels to me like you're going out of your way (adding
> initial bindings arg) to make it easy to do things that I'll rarely
> want to do while failing to make it easy to do things that I'll
> normally want to do.  I'd expect it to be relatively rare that
> programs even mention things in *default-special-bindings*, let alone
> change them or rely on having different values in different threads,
> whereas one will almost always want to pass arguments to the functions
> to be called in new threads.

initial-bindings are not meant as mechanism for passing parameters to
thread function.
I do not expect many people to use them but they serve as easy way to
customize (or isolate) dynamic environments of threads.

>  > > What if *print-base* is set (or bound) in one thread while another
>  > > thread is writing a large file?
>  > > If all threads use the same global value, part of the file will be
> written
>  > > with one base and the rest with the other.
> If it's bound, the proposed (what I called correct) behavior of
> binding it only for the thread will solve this problem.
> If it's set and not bound in the writing thread, as I propose by
> default, then the file will indeed be strange - but this is no
> different from all the other global state that could be used by one
> thread and altered by another.  Worrying about such things falls
> within the normal job description of a programmer.

Sure, but programmers somehow do not want to worry about such things.
I guess that's the reason most implementations provide such feature.
And after all nobody forces you to bind exactly these symbols - you
can customize *default-special-bindings* to suit you needs/style.

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
clisp-devel mailing list
clisp-devel@...
https://lists.sourceforge.net/lists/listinfo/clisp-devel