chicken-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Chicken-users] Re: make-parameter, parameterize & SRFI-39


From: F. Wittenberger
Subject: Re: [Chicken-users] Re: make-parameter, parameterize & SRFI-39
Date: Tue, 12 Aug 2008 12:40:12 +0200

Am Montag, den 11.08.2008, 09:37 -0700 schrieb Elf:
> On Mon, 11 Aug 2008, Jörg F. Wittenberger wrote:
> 
> > Am Montag, den 11.08.2008, 07:28 -0700 schrieb Elf:
> >> absolutely not.

> >> second, your patches will flat out not work in default chicken.
> >>
> >>      B) you are fundamentally changing the representation of parameters.
> >
> > Really?  At least that (supposed to be - modulo bugs I made) all
> > compatible with the old version.
> >
> > It introduces just two more comparison in the value look up.  And one
> > more optional parameter to make-parameter.
> >
> > Does this already qualify as a fundamental change?
> 
> no, but changing from a cons structure to a slotted structure does.  changing
> the meaning of the cells in the cons does as well.

Please educate me, I don't understand well.  At this point I'm loosing
the connection between your wording and the code I wrote.  What detail
are you referring to?  Which difference changes which objects in such a
way?

> >>      D) inconsistent naming scheme
> >
> > Which one would be better?
> 
> is it guard or guard+type?  this was more of a personal pet peeve rather
> than a fundamental flaw, as you changed it one place but kept the previous
> behaviour in the new case.

}:-|   ???  The parameter is now named guard+type, guard and type are
extracted and later only guard and type are referenced.

> i must add two that i missed originally as well, which is 'breaking backward
> compatibility' and 'inconsistent semantics of the cons cell handling'
> 
> >
> >>      E) there are around 300 occurences of parameters in chicken core.  
> >> many
> >>         eggs use large numbers of paramters.  have you tested fully, or 
> >> even
> >>         partially, the effects of changing structure?  mucking about with
> >>         parameters can and will break just about everything.
> >
> > I have tested the implementation.  But to which extend should this be
> > done.  The new case applies only if there's a shared parameter object
> > and it is called from the modified parameterize.  I had preferred to
> > pass some special key, which the user can not produce, but I don't know
> > how to express that in chicken.  The standard case will just ignore the
> > additional argument.
> >
> > Against which possible impact should I test?
> 
> if youre mucking about with parameters, you should test things like http,
> spiffy, various sql bindings, some of the format eggs, sxml, etc.  almost
> everything uses paramters.  you should test to see what happens when you 
> use certain declarations.

"certain declarations" is a bit too general for me to comprehend.

Chicken core works well.

>   you should test all of the functionality listed
> on the 'parameters' page of the manual.

The manual is rather terse on make-parameter as is SRFI-39.  Tested are
backward compatibility and the new procedure.

Becoming an expert of spiffy and various sql bindings is IMHO a litte
bit too much just to test a single eq? test working always the same.

I mean: at one point I should also see that I get my job done.

>   full testsuite.

Again: what's a full testsuite for make-parameter?

> >> third, there has been no consensus and very little discussion regarding
> >> parameter models yet, so methinks you may be jumping the gun.  if you want
> >> a shared variable between threads, dont make it a parameter.
> >
> > The point is: there is a large code base, which is supposed to run under
> > different Schemes.  I'm trying to find the minimal diff.  It's already
> > hard enough and I'm a not entitled to break the deployed version at any
> > time.  (I just spent 3 days without success trying to figure why this
> > test case
> > http://lists.gnu.org/archive/html/chicken-users/2008-08/msg00029.html
> > fails if and only if the thread hangs on tcp *and* there are two nested
> > condition handlers (while other ways to hang or just one condition
> > handler will work as to be expected).
> 
> are you using thread-signal or thread-terminate, btw?  it DOES matter, very 
> much, which you use, i think.

You're wrong on that one.  The comment I put there tries to tell that.
It works slightly different: if one uses thread-signal! the tread will
die with a warning.  Otherwise just terminate.

>   it would probably be advisable to read the
> bloody manual for tcp as well, as there are parameters in place for setting
> timeouts already.  i would also suggest rtfm for srfi-18, as it has timeout 
> args to most of the procedures as well.

I know that the particular case of hanging/interrupting tcp could be
handled better using tcp's timeouts.  That's not the point of the test.

The point is that the primordial thread is supposed to thread-join! with
no timeout and the thread it is asked to join runs forever.  Hence the
primordial should never return.

It does however continue as if there was a join timeout (hey! it's
waiting with no timeout).  If I immediately try the thread-join! again,
it will immediately continue as with join-timeout again, even though the
thread it is asked to join is in blocked state.

The really confusing thing is, that this fake join timeout in the
primordial occurs only if two conditions are met: hang in tcp (or maybe
other states, which I did not yet find) (that is for instance NOT on
mutex as in the alternate/working test case) *and* have two nested
condition handlers in the joined thread (remove one handler and
everything is fine - (test3)).

> >>  if you want
> >> a thread-local variable, parametrise it.  i dont see why this requires 
> >> changing
> >> core structure.
> >
> > All I need: a thread-local variable and a way to set it's default value
> > from a thread, while accessing the thread-local one within parameterize.
> > How should I do that?
> 
> this sentence does not make sense.  does setting the global default change
> the values on all the copies currently in threads?  if so, its not local.
> how does setting the global value affect those already around?

It follows the SRFI-39 semantics the way it's implemented for instance
in RScheme.  Someone explained to me these days this is called the
"shared parameter" design.  Parameters access the thread local value if
there is one, otherwise the global default.  Only "parameterize" extends
the local bindings.  Thus withing parameterize it's local, otherwise the
global default.

Since there are just three parameter designs, I feel adding support for
those to core would be a win, since the alternative would be either to
require patched chickens to be used for code written to a different
parameter design or serious rewrites of said code, which might be not
desirable for whatever reasons.  I started with just one, as I have test
cases for these two designs only and ... expected some critique from
review (so I don't waste my time writing code to be fixed).

> i would probably do something like:
> (make-parameter (vector <data>))
> 
> for shared parameters, since only a shallow copy is done, all values would be
> synchronised.  then you (vector-ref (param)) and (vector-set! (param) 0 
> <val>).

But this would need to be handled by parameterize.  Now the latter would
have to distinguish the parameter type's - which in turn would lead to
the need to really change the structure of parameters.  I'd be a little
afraid of this change.

However I found that a swap of would reduce the overhead for the
standard case to a single comparison.

/Jörg

Here the improved patch.

===================================================================
--- library.scm (Revision 11597)
+++ library.scm (Arbeitskopie)
@@ -2036,8 +2036,14 @@
 
 (define make-parameter
   (let ([count 0])
-    (lambda (init . guard)
-      (let* ([guard (if (pair? guard) (car guard) (lambda (x) x))]
+    (lambda (init . guard+type)
+      (let* ([guard (if (pair? guard+type) (##sys#slot guard+type 0)
(lambda (x) x))]
+            [rest (and (pair? guard+type) (##sys#slot guard+type 1))]
+            [type (if (pair? rest)
+                      (case (##sys#slot rest 0)
+                        ((#:shared) #:shared)
+                        (else (##sys#signal-hook #:syntax-error 
'make-parameter (##sys#slot rest 0))))
+                      #f)]
             [val (guard init)] 
             [i count] )
        (set! count (fx+ count 1))
@@ -2047,7 +2053,13 @@
        (##sys#setslot ##sys#default-parameter-vector i val)
        (lambda arg
          (let ([n (##sys#size ##sys#current-parameter-vector)])
-           (cond [(pair? arg)
+           (cond [(and (eq? type #:shared) (pair? arg) (null? (cdr arg)))
+                  (if (or (fx>= i n)
+                          (eq? (##sys#slot ##sys#current-parameter-vector i) 
##sys#snafu))
+                      (##sys#setslot ##sys#default-parameter-vector i (guard 
(##sys#slot arg 0)))
+                      (##sys#setslot ##sys#current-parameter-vector i (guard 
(##sys#slot arg 0))))
+                  (##core#undefined) ]
+                 [(pair? arg)
                   (when (fx>= i n)
                     (set! ##sys#current-parameter-vector
                       (##sys#grow-vector ##sys#current-parameter-vector (fx+ i 
1) ##sys#snafu) ) )
@@ -2061,6 +2073,8 @@
                         (##sys#slot ##sys#default-parameter-vector i) 
                         val) ) ] ) ) ) ) ) ) )
 
+(define (make-shared-parameter init . guard)
+  (make-parameter init (if (pair? guard) (car guard) (lambda (v) v)) #:shared))
 
 ;;; Input:
 
Index: chicken-more-macros.scm
===================================================================
--- chicken-more-macros.scm     (Revision 11597)
+++ chicken-more-macros.scm     (Arbeitskopie)
@@ -213,7 +213,7 @@
            [aliases2 (##sys#map (lambda (z) (gensym)) params)] )
        `(let ,(##sys#append (map ##sys#list aliases params) (map
##sys#list aliases2 vals))
          (let ((,swap (lambda ()
-                        ,@(map (lambda (a a2) `(let ((t (,a))) (,a ,a2) 
(##core#set! ,a2
t)))
+                        ,@(map (lambda (a a2) `(let ((t (,a))) (,a ,a2 'local)
(##core#set! ,a2 t)))
                                aliases aliases2) ) ) )
            (##sys#dynamic-wind 
                ,swap




reply via email to

[Prev in Thread] Current Thread [Next in Thread]