summaryrefslogtreecommitdiff
path: root/doc/ref/api-scheduling.texi
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2017-03-07 20:57:59 +0100
committerAndy Wingo <wingo@pobox.com>2017-03-07 21:15:39 +0100
commitfb8c91a35c0a1c357aab96a6721a8b65c93368b0 (patch)
tree2071a8a79753305d413ce2c70c084902e9cd7044 /doc/ref/api-scheduling.texi
parent84a740d86a5afd235f1b47ac66c88db010b1d56b (diff)
downloadguile-fb8c91a35c0a1c357aab96a6721a8b65c93368b0.tar.gz
Add thread local fluids
* libguile/fluids.h (struct scm_dynamic_state): Add thread_local_values table. Thread locals are flushed to a separate thread-local table. The references are strong references since the table never escapes the thread. (scm_make_thread_local_fluid, scm_fluid_thread_local_p): New functions. * libguile/fluids.c (FLUID_F_THREAD_LOCAL): (SCM_I_FLUID_THREAD_LOCAL_P): New macros. (restore_dynamic_state): Add comment about precondition. (save_dynamic_state): Flush thread locals. (scm_i_fluid_print): Print thread locals nicely. (new_fluid): Add flags arg. (scm_make_fluid, scm_make_fluid_with_default, scm_make_unbound_fluid): Adapt. (scm_make_thread_local_fluid, scm_fluid_thread_local_p): New functions. (fluid_set_x): Special flushing logic for thread-locals. (fluid_ref): Special cache miss logic for thread locals. * libguile/stacks.c (scm_init_stacks): * libguile/throw.c (scm_init_throw): %stacks and %exception-handler are thread-locals. * libguile/threads.c (guilify_self_2): Init thread locals table. * test-suite/tests/fluids.test ("dynamic states"): Add test. * doc/ref/api-control.texi (Fluids and Dynamic States): Add link to Thread-Local Variables. * doc/ref/api-scheduling.texi (Thread Local Variables): Update with real thread-locals. * NEWS: Update.
Diffstat (limited to 'doc/ref/api-scheduling.texi')
-rw-r--r--doc/ref/api-scheduling.texi54
1 files changed, 35 insertions, 19 deletions
diff --git a/doc/ref/api-scheduling.texi b/doc/ref/api-scheduling.texi
index ff8473ae2..7b39a03d6 100644
--- a/doc/ref/api-scheduling.texi
+++ b/doc/ref/api-scheduling.texi
@@ -9,7 +9,7 @@
@menu
* Threads:: Multiple threads of execution.
-* Thread Local Variables:: Guile doesn't really have these.
+* Thread Local Variables:: Some fluids are thread-local.
* Asyncs:: Asynchronous interrupts.
* Atomics:: Atomic references.
* Mutexes and Condition Variables:: Synchronization primitives.
@@ -169,9 +169,7 @@ information.
@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.
+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
@@ -191,26 +189,44 @@ 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:
+value from multiple threads, then using vanilla fluids or parameters is
+not appropriate. For this purpose, Guile has @dfn{thread-local fluids}.
+A fluid created with @code{make-thread-local-fluid} won't be captured by
+@code{current-dynamic-state} and won't be propagated to new threads.
-@example
-(define (get-my-sensitive-data-structure)
- ...)
+@deffn {Scheme Procedure} make-thread-local-fluid [dflt]
+@deffnx {C Function} scm_make_thread_local_fluid (dflt)
+Return a newly created fluid, whose initial value is @var{dflt}, or
+@code{#f} if @var{dflt} is not given. Unlike fluids made with
+@code{make-fluid}, thread local fluids are not captured by
+@code{make-dynamic-state}. Similarly, a newly spawned child thread does
+not inherit thread-local fluid values from the parent thread.
+@end deffn
+
+@deffn {Scheme Procedure} fluid-thread-local? fluid
+@deffnx {C Function} scm_fluid_thread_local_p (fluid)
+Return @code{#t} if the fluid @var{fluid} is is thread-local, or
+@code{#f} otherwise.
+@end deffn
+
+For example:
-(define %thread-local (make-weak-key-hash-table))
+@example
+(define %thread-local (make-thread-local-fluid))
-(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)))
+(with-fluids ((%thread-local (compute-data)))
+ ... (fluid-ref %thread-local) ...)
@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.
+You can also make a thread-local parameter out of a thread-local fluid
+using the normal @code{fluid->parameter}:
+
+@example
+(define param (fluid->parameter (make-thread-local-fluid)))
+
+(parameterize ((param (compute-data)))
+ ... (param) ...)
+@end example
@node Asyncs