This is the mail archive of the kawa@sources.redhat.com mailing list for the Kawa project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Gargage collected top-level bindings?


Thanks for the explanation.

Let me step back for a second.

I started using "define-variable" as a work-around to a problem we were having with "define" variables used with fluid-let. The attached example shows what I was seeing.

It uses (define ...) to define a variable and a procedure in one module:

----------
(module-static #t)

(define VAR 'hello)

(define (getVAR)
  VAR)
----------

and another module uses fluid-let on the variable:

----------
(define (fn)
  (set! VAR 'hello)
  (fluid-let ((VAR 'goodbye))
    (display (format "1. VAR: ~A~%" VAR))
    (display (format "2. VAR: ~A~%" (getVAR)))))
----------

With an older version of Kawa, I always get "goodbye":

----------
CLASSPATH=.:~/kawa/cvs/kawa-pure-8-31-2004-build/kawa-1.7.90.jar java ModA
1. VAR: goodbye
2. VAR: goodbye
----------

but with the latest code, the procedure call returns "hello" instead:

----------
CLASSPATH=.:~/kawa/cvs/kawa-pure-build/kawa-1.7.91.jar java ModA
1. VAR: goodbye
2. VAR: hello
----------

Which is the expected result? In the places in our code where we use fluid-let, we expect the goodbye/goodbye behavior. Using "define-variable" to define VAR gets me that result, but has this UnboundLocationException issue in the presence of unrelated threads.

What do you think?

Oh, and here's how I'm compiling this:

----------
java kawa.repl --warn-undefined-variable --module-static-run -C ModB.scm
(compiling ModB.scm)
java kawa.repl --warn-undefined-variable --module-static-run --main -C ModA.scm
(compiling ModA.scm)
----------


Dean


Per Bothner wrote:
Dean Ferreyra wrote:

I CVS updated this morning. There is one problem I've run into that is still leading to UnboundLocationExceptions in our code around the use of define-variable.

I can see it in my test case, too---just define VAR with "define-variable" like so:


I don't think this is a bug.
'define-variable VAR' means "lookup VAR dynamically" - i.e. in the
per-thread dynamic environment.
Since the module is static, there is only a single "instance", and
top-level actions are only performed once.  That creates bindings
in one thread.
Since the two threads aren't in an inheritance relationship, the second
thread won't and shouldn't see the definition in the first thread.

It may be possible to change define-variable so it sets the "default"
binding of VAR, rather than the current thread's.  But I don't think
that would be right.  The difference with (define VAR ...) is that it
declares a static binding, while define-variable explicitly says to
use dynamic lookup.  Thus (define VAR ...) creates an anonymous
ThreadLocation for VAR, in that just (eval 'VAR) won't find it.

So:
  (define VAR xx)
  ... VAR ...
gets translated to:
  static public final VAR = new ThreadLocation();
  static { VAR.set(xx); }
  ...VAR.get()...

If we do:
  (define-variable VAR xx)
  ... VAR ...
then the latter is equivalent to:
  (eval 'VAR)
though we do cache a ThreadLocation for performance.
I don't think an *unrelated* thread should be able to do (eval 'VAR).

Note I wrote "unrelated" thread.  It might be useful to add a mechanism
so "related" threads could inherit from a shared Environment.  But where
do we draw the line: how do we control it so that some but not all
threads share a "global" Environment?  Make use of ThreadGroups?
Make use of ClassLoaders?

--- /dev/null	Tue Oct  7 04:48:06 2003
+++ ModA.scm	Mon May  9 19:10:46 2005
@@ -0,0 +1,11 @@
+(module-static #t)
+
+(require <ModB>)
+
+(define (fn)
+  (set! VAR 'hello)
+  (fluid-let ((VAR 'goodbye))
+    (display (format "1. VAR: ~A~%" VAR))
+    (display (format "2. VAR: ~A~%" (getVAR)))))
+
+(fn)
--- /dev/null	Tue Oct  7 04:48:06 2003
+++ ModB.scm	Mon May  9 19:10:54 2005
@@ -0,0 +1,6 @@
+(module-static #t)
+
+(define VAR 'hello)
+
+(define (getVAR)
+  VAR)

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]