The attached patch binds the buffer related global vars to fresh values on=
non-recursive (i.e. 'toplevel') read calls if the :sb-thread feature is=20
present. Passing t for recursive-p when it is not really recursive will rai=
and unbound-variable error.
The performance drops a bit, but it is not significant for typical source=20
files. On the other hand reading integers in a loop will be noticeably=20
Other approaches considered/tested:
=2D bind them in make-thread: ugly and silently assumes that the tokeniser=
cannot call read & co in an inappropriate moment
=2D maintain a pool of read buffers with or without weak pointers: test sho=
this solution to be slower (maybe with-mutex is heavier than I thought)
My tests uncovered another thread safety problem with stringify-buffer that=
maintains a cache in *string-output-streams*. It is a bit harder to trigger=
but it can kill sbcl. Removing the cache and creating a new=20
string-output-stream every time it is called obviously fixes the problem.=20
Same goes for read-from-string and *read-from-string-spares*.
I don't know how to provide unit tests that don't take forever to run and=20
produce somewhat dependable results, but attached you can find the small=20
tests I used to break sbcl and compare performance.
Likely there are other thread safety problems in the reader related to case=
handling and maybe *sharp-equal-alist* when calling read-delimited-list.