Sometimes you want to establish a variable binding that is only valid for a given thread: a “thread-local variable”.
You would think that fluids or parameters would be Guile’s answer for
thread-local variables, since establishing a new fluid binding doesn’t
affect bindings in other threads. See Fluids and Dynamic States, or
See Parameters. However, new threads inherit the fluid bindings that
were in place in their creator threads. In this way, a binding
established using a fluid (or a parameter) in a thread can escape to
other threads, which might not be what you want. Or, it might escape
via explicit reification via current-dynamic-state
.
Of course, this dynamic scoping might be exactly what you want; that’s why fluids and parameters work this way, and is what you want for many common parameters such as the current input and output ports, the current locale conversion parameters, and the like. Perhaps this is the case for most parameters, even. If your use case for thread-local bindings comes from a desire to isolate a binding from its setting in unrelated threads, then fluids and parameters apply nicely.
On the other hand, if your use case is to prevent concurrent access to a
value from multiple threads, then using vanilla fluids or parameters is
not appropriate. For this purpose, Guile has thread-local fluids.
A fluid created with make-thread-local-fluid
won’t be captured by
current-dynamic-state
and won’t be propagated to new threads.
Return a newly created fluid, whose initial value is dflt, or
#f
if dflt is not given. Unlike fluids made with
make-fluid
, thread local fluids are not captured by
make-dynamic-state
. Similarly, a newly spawned child thread does
not inherit thread-local fluid values from the parent thread.
Return #t
if the fluid fluid is thread-local, or
#f
otherwise.
For example:
(define %thread-local (make-thread-local-fluid)) (with-fluids ((%thread-local (compute-data))) ... (fluid-ref %thread-local) ...)
You can also make a thread-local parameter out of a thread-local fluid
using the normal fluid->parameter
:
(define param (fluid->parameter (make-thread-local-fluid))) (parameterize ((param (compute-data))) ... (param) ...)