forked from ocaml/ocaml
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy paththread_local_storage.mli
More file actions
83 lines (67 loc) · 3.61 KB
/
thread_local_storage.mli
File metadata and controls
83 lines (67 loc) · 3.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
(**************************************************************************)
(* *)
(* OCaml *)
(* *)
(* KC Sivaramakrishnan, Indian Institute of Technology, Madras *)
(* Stephen Dolan, University of Cambridge *)
(* Tom Kelly, OCaml Labs Consultancy *)
(* *)
(* Copyright 2019 Indian Institute of Technology, Madras *)
(* Copyright 2014 University of Cambridge *)
(* Copyright 2021 OCaml Labs Consultancy Ltd *)
(* *)
(* All rights reserved. This file is distributed under the terms of *)
(* the GNU Lesser General Public License version 2.1, with the *)
(* special exception on linking described in the file LICENSE. *)
(* *)
(**************************************************************************)
(** Thread-local Storage.
{b Note:} Thread-local storage is designed for fast, constant-time
access to a small number of keys, typically declared at the
top-level of the module. It is not designed to be fast in cases
where keys are created dynamically.
@since TODO *)
type 'a t
(** Type of a thread-local storage key. *)
val make : ?split_from_parent:('a -> 'a) -> (unit -> 'a) -> 'a t
(** [make f] returns a new key bound to initialiser [f] for accessing
thread-local variables.
If [split_from_parent] is not provided, the value for a new
thread will be computed on-demand by the new thread: the first
[get] call will call the initializer [f] and store that value.
{b Warning.} [f] may be called several times if another call
to [get] occurs during initialization on the same thread. Only
the 'first' value computed will be used, the other now-useless
values will be discarded. Your initialization function should
support this situation, or contain logic to detect this case
and fail.
If [split_from_parent] is provided, spawning a thread will
derive the child value (for this key) from the parent
value. This computation happens in the parent thread and it
always happens, regardless of whether the child thread will
use it.
If the splitting function is expensive or requires
child-side computation, consider using ['a Lazy.t key]:
{[
let init () = ...
let split_from_parent parent_value =
... parent-side computation ...;
lazy (
... child-side computation ...
)
let key = Thread_local_storage.make ~split_from_parent init
let get () = Lazy.force (Thread_local_storage.get key)
]}
In this case a part of the computation happens on the child
thread; in particular, it can access [parent_value]
concurrently with the parent thread, which may require
explicit synchronization.
*)
val get : 'a t -> 'a
(** [get k] returns [v] if a value [v] is associated to the key [k] on
the calling thread's thread-local state. Sets [k]'s value with its
initialiser and returns it otherwise. *)
val set : 'a t -> 'a -> unit
(** [set k v] updates the calling thread's thread-local state to associate
the key [k] with value [v]. It overwrites any previous values associated
to [k], which cannot be restored later. *)