mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 03:40:34 +02:00
Add thread-local variables manual section.
* doc/ref/api-scheduling.texi (Thread Local Variables): New subsection.
This commit is contained in:
parent
a5f3868e2f
commit
ed19bb63a4
1 changed files with 49 additions and 0 deletions
|
@ -9,6 +9,7 @@
|
|||
|
||||
@menu
|
||||
* Threads:: Multiple threads of execution.
|
||||
* Thread Local Variables:: Guile doesn't really have these.
|
||||
* Asyncs:: Asynchronous interrupts.
|
||||
* Atomics:: Atomic references.
|
||||
* Mutexes and Condition Variables:: Synchronization primitives.
|
||||
|
@ -164,6 +165,54 @@ information.
|
|||
@end deffn
|
||||
|
||||
|
||||
@node Thread Local Variables
|
||||
@subsection Thread-Local Variables
|
||||
|
||||
Sometimes you want to establish a variable binding that is only valid
|
||||
for a given thread: a ``thread-local variable''. Guile doesn't really
|
||||
have this facility, but what it does have can work well for most use
|
||||
cases we know about.
|
||||
|
||||
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. @xref{Fluids and Dynamic States}, or
|
||||
@xref{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 @code{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 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 fluids or parameters is not
|
||||
appropriate. In this case, our current suggestion is to use weak hash
|
||||
tables or object properties whose keys are thread objects. For example:
|
||||
|
||||
@example
|
||||
(define (get-my-sensitive-data-structure)
|
||||
...)
|
||||
|
||||
(define %thread-local (make-weak-key-hash-table))
|
||||
|
||||
(define (current-thread-local)
|
||||
(or (hashq-ref %thread-local (current-thread))
|
||||
(let ((val (get-my-sensitive-data-structure)))
|
||||
(hashq-set! %thread-local (current-thread) val)
|
||||
val)))
|
||||
@end example
|
||||
|
||||
It's not a terribly nice facility and perhaps we should have a better
|
||||
answer, like Racket's ``non-preserved thread cells''. Your input is
|
||||
very welcome; we look forward to hearing from your experience.
|
||||
|
||||
|
||||
@node Asyncs
|
||||
@subsection Asynchronous Interrupts
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue