[plt-scheme] Re: Parameterizing Modules with variables

From: Robby Findler (robby at cs.uchicago.edu)
Date: Mon Apr 21 19:52:20 EDT 2003

Programming with shared state and concurrency is very difficult and
when you do (inevitably) make mistakes, it is very difficult to debug
them, due to the nondeterminism in the system.

At least consider using the new concurrency primitives in mzscheme
(channels and waitables, etc). They are based on John Reppy's CML
primitives and he has written a book about them (and several papers).


At Mon, 21 Apr 2003 18:41:46 -0400, Eli Barzilay wrote:
>   For list-related administrative tasks:
>   http://list.cs.brown.edu/mailman/listinfo/plt-scheme
> On Apr 21, Ed Cavazos wrote:
> > 
> > So I read about parameters and they are "thread specific". I can of
> > course see how this is a virtue in many cases, and a benfit over
> > variables. However, in the above case, after spawning off a thread I
> > lose contact with those parameters from my REPL. Right now I'm
> > thinking that I should launch a GUI from within the thread which
> > will be my tether to the parameters. Or perhaps a way to launch a
> > REPL that introspects into the environment of a spawned thread.
> I don't think there's anything wrong with such global variables,
> especially if you mark them with **'s -- after all, they do exactly
> what you want them to do, which is share modifiable information
> between threads...  (You might want to add a semaphore protection if
> there's a way to get to a bogus configuration.)
> If you still insist on a parameter, then one option would be to have a
> parameter-like function that will access a global but will be shared
> since it will not be a parameter, for example, one that has a
> parameter-like-function inside it.  I had a similar problem with my
> webserver -- I wanted to have "special" parameters that when they are
> created, they are shared among all sub-threads.  This is the code that
> I use:
> ----------------------------------------------------------------------
> (define (make-connection-parameter . default)
>   ;; This returns a parameter-like function that uses a parameter to store an
>   ;; actual value-function and use that.  The effect is that once we set the
>   ;; value, all created threads will share that value.  Note that since
>   ;; check-parameter-procedure accept any function of 0/1 args, this will also
>   ;; behave with parameterize.
>   (define param (make-parameter #f))
>   (define (connection-parameter . args)
>     (let ((p (param)))
>       (cond
>        ((and p (null? args)) (p))
>        (p (p (car args)))
>        ((null? args)
>         (if (null? default)
>           (error 'connection-parameter "accessing uninitialized parameter")
>           (car default)))
>        ;; don't create a parameter that will be used in the global thread
>        ((eq? (current-thread) *toplevel-thread*) (set! default args))
>        (else (param
>               (let ((v (1st args)))
>                 (define (p . args)
>                   (if (null? args) v (set! v (car args))))
>                 (if (promise? v)
>                   ;; this is so only initial promises are possible and nothing
>                   ;; else gets the penalty of `promise?'
>                   (lambda args (set! v (force v)) (param p) (apply p args))
>                   p)))))))
>   connection-parameter)
> ----------------------------------------------------------------------
> But it is very tricky to get the details right, and I'm not sure how
> stable the whole thing is.  I think that for you a global is enough.
> -- 
>           ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
>                   http://www.barzilay.org/                 Maze is Life!

Posted on the users mailing list.