[Openmcl-devel] Equivalent of process-initial-bindings in ACL?
gb at clozure.com
Sun Apr 13 16:23:21 PDT 2003
On Sun, 13 Apr 2003, Ram Krishnan wrote:
> On Saturday, April 12, 2003, at 07:22 PM, Gary Byers wrote:
> > On Sat, 12 Apr 2003, Ram Krishnan wrote:
> >> Hello,
> >> Is there something equivalent to Allegro CL's process-initial-bindings
> >> in OpenMCL?
> > There actually is in 0.14 (for which documentation is being written,
> > even as we speak. Honest.)
> That's wonderful. However, I ftp'ed the binary distribution of 0.14 and
> tried to use it to bootstrap from the CVS (Pre_0_14) sources but got
> the following exception in `(ccl::compile-ccl)':
> ;Compiling "/src/ccl/level-1/ppc-trap-support.lisp"...
> > Error in process listener(2): Unknown foreign type: :UCONTEXT
> > While executing: %PARSE-FOREIGN-TYPE
> > Type :POP to abort.
> Type :? for other options.
> 1 >
> The only definition of the UCONTEXT structure was in:
> library/solaris-records.lisp:242:(defrecord ucontext
> Am I missing a file somewhere?
Another thing that needs to be documented re: 0.14: read the file
"README-jaguar-interfaces" in the /testing directory. 0.14 now references
some OS 10.2-specific functionality; there's a "jaguar-interfaces.tar.gz"
archive in the /testing directory.
> >> I'm trying to figure out a way to have a thread inherit some dynamic
> >> bindings (mostly the standard i/o streams) from its parent thread
> >> (i.e.
> >> the thread from which the new thread is forked). Unfortunately, this
> >> seems to be something that isn't covered by the somewhat standard MP
> >> package interface.
> > There are a handful of cases in which the CL special operator PROGV
> > is useful, and this is one of them. One way to do this is:
> > (let* ((bindings-alist '((*a* . 1) (*b* . 2))))
> > (process-run-function "example"
> > #'(lambda ()
> > (progv (mapcar #'car bindings-alist)
> > (mapcar #'cdr bindings-alist)
> > (format t "~&in new thread, *a* = ~s,
> > *b* = ~s"
> > *a* *b*)))))
> The only issue with this approach is that the run-function of the new
> thread has to be instrumented using the PROGV and it also means any
> subsequent threads forked by the child thread won't get this binding
> without similar instrumentation.
> The context in which I'm trying to get this dynamic binding to work is
> in a socket based communication interface between Emacs and OpenMCL
> which serves as a multi-threaded interaction channel that augments
> ILISP. The ideas is that the standard i/o streams of different threads
> can be multiplexed over a single socket connection .. much like Franz's
> ELI/LEP package. In this application, the interaction handler acts as a
> REPL of sorts but binds the *standard-output* and *standard-input*
> streams to the socket stream (actually a multiplexing stream wrapper on
> the socket stream) and then evaluates the s-expression it received from
> Emacs. Now, if that s-expression form forks a thread, I'd like that
> thread (and any threads that it might in turn fork) to inherit the
> multiplexing-stream as its standard i/o.
> Ideally, I'd like to get this working under the 0.13 and 0.14 code
> bases, unless 0.14 is going to supersede 0.13 imminently.
The plan is to continue to maintain 0.13.x - as an "alternate current
version" - for some time after 0.14 is out.
There isn't any architectural reason for 0.13.x not having an
:INITIAL-BINDINGS argument to process-creation functions and some
arguments (compatibility and general utility) in favor of adding the
functionality to 0.13.x as well.
> >> Any pointers would be greatly appreciated.
> > Hope this makes sense.
> Yes, it does, thanks. I've been searching Google and the comp.lang.lisp
> archives on this subject, and it looks like it may be nearly impossible
> to come up with a portable way of achieving this "bindings inheritance"
> behavior which is a bit disheartening.
One thing that might be helpful is a review of how special bindings
interact with threads (in 0.13, 0.14, and in every other MP-aware lisp
implementation that I'm familiar with.)
There are generally two ways in which bindings (mappings between a
global symbol and a value) can be established:
1) "statically" - typically via DEFVAR/DEFPARAMETER/...
2) "dynamically" - via LET/LET*/LAMBDA/PROGV/...
Dynamic bindings are thread-private: a thread will "see" the most recent
dynamic binding of a special variable that that thread has established.
If a thread hasn't established a dynamic binding of a variable, it "sees"
any static, global bindings that're in effect. (As do all other threads
that don't have thread-specific bindings.)
When a thread is first created, it has no dynamic bindings of its own;
the only kind of binding inheritance that's involved is that all threads
"inherit" the static, global binding environment. A newly created thread
does not inherit any part of the thread-private dynamic binding environment
of the creating thread.
It's certainly desirable to have a standard way to establish new
initial dynamic bindings for a newly created thread, and I think that
the concept of "standard initial bindings" of things like *PACKAGE*,
*READTABLE*, etc. is also useful. These are both useful-enough
mechanisms that process-creation functions should ideally provide
convenient syntactic sugar for them. (Underneath that syntactic layer
there's likely to be a PROGV or something like it.)
Suppose that there was some implementation-dependent function that
returned a high-level representation of the calling thread's dynamic
bindings at a given point in time:
(let* ((*a* 1)
=> ((*a* . 1) (*b* . 2) ... (*terminal-io* . #<stream>) ...)
Let's ignore the fact that there may be some things in that alist that
we don't want to inherit (like the binding of CCL:*CURRENT-PROCESS*, for
instance ...). You could then do:
(process-run-function "clone" #'(lambda () ...)
Is that sort of what you'd like to be able to do ?
Openmcl-devel mailing list
Openmcl-devel at clozure.com
More information about the Openmcl-devel