Well, I've been investigating the issue with our clos.lisp not being
thread safe and me seeing NullPointerExceptions. It turns out that
GENSYM was not thread safe in case there were no thread-local special
bindings: the SYMBOL-VALUE wasn't protected against being manipulated
from 2 threads at the same time.
I changed that. Now, even though clos.lisp is not thread safe, I'm not
seeing any NullPointerExceptions anymore.
The NullPointerExceptions were caused by the fact that COMPILE was
running in 2 threads at the same time, generating the same symbol at
the same time. Then, it called REMEMBER from both threads, one
overwriting the value stored by the other. That doesn't cause
NullPointerExceptions by itself, but when each thread loads its
COMPILEd function, the constructor calls Lisp.recall(), which removes
the key from the hash used for temp-storage. The second function then
finds 'null' instead of the value it stored.
So, that's another mystery solved. Fixed in trunk now.
However, what remains is the fact that the remember/recall combo uses
global keys while COMPILE may be generating thread-local key values.
I'm wondering what to do about that. Possibly I should just create a
ThreadLocal which has a temp-storage hash table per thread and
document remember/recall are a thread-local storage mechanism.
Of course, your opinions are welcome as always, especially with
respect to the last paragraph.
Bye,
Erik.