package ambient-context
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
Abstraction over thread-local / continuation-local storage mechanisms for communication with transitive dependencies
Install
dune-project
Dependency
Authors
Maintainers
Sources
ambient-context-0.1.1.tbz
sha256=069907679bb58548d21236de31dd96b9cd94361b764fe0c6b06a5149d14098a8
sha512=519c47993a89fa8b4ab2b5d9dd63b0b80a2a0831fcad2af1ac413e4682435407a9a7c73524706e8ef5d65582ba01097ca20c93e1b8be2f8c556e70dac0a8de00
doc/src/ambient-context.thread_local/thread_local.ml.html
Source file thread_local.ml
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 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101module A = Ambient_context_atomic.Atomic type key = int let[@inline] get_key_ () : key = Thread.id (Thread.self ()) module Key_map_ = Map.Make (struct type t = key let compare : t -> t -> int = compare end) type 'a t = 'a ref Key_map_.t A.t (** The TLS variable is made of a global atomic reference (which has very low contention: it's modified only when a thread is started/stopped). Inside that atomic variable, is a map from thread ID to a mutable [ref] holding the actual data. Because this [ref] is only ever accessed by the thread with this given ID, it's safe to modify. *) let create () : _ t = A.make Key_map_.empty let[@inline] get_exn (self : _ t) = let m = A.get self in let key = get_key_ () in !(Key_map_.find key m) let[@inline] get self = try Some (get_exn self) with Not_found -> None (* remove reference for the key *) let remove_ref_ self key : unit = while let m = A.get self in let m' = Key_map_.remove key m in not (A.compare_and_set self m m') do Thread.yield () done let set_ref_ self key (r : _ ref) : unit = while let m = A.get self in let m' = Key_map_.add key r m in not (A.compare_and_set self m m') do Thread.yield () done (* get or associate a reference to [key], and return it. Also return a function to remove the reference if we just created it. *) let get_or_create_ref_ (self : _ t) key ~v : _ ref * _ option = try let r = Key_map_.find key (A.get self) in let old = !r in r := v; r, Some old with Not_found -> let r = ref v in set_ref_ self key r; r, None let set (self : _ t) v : unit = let key = get_key_ () in let _, _ = get_or_create_ref_ self key ~v in () let remove (self : _ t) : unit = let key = get_key_ () in remove_ref_ self key let get_or_create ~create (self : 'a t) : 'a = let key = get_key_ () in try let r = Key_map_.find key (A.get self) in !r with Not_found -> Gc.finalise (fun _ -> remove_ref_ self key) (Thread.self ()); let v = create () in let r = ref v in set_ref_ self key r; v let with_ self v f = let key = get_key_ () in let r, old = get_or_create_ref_ self key ~v in let restore_ () : unit = match old with | None -> remove_ref_ self key | Some old -> r := old in try let res = f old in restore_ (); res with e -> restore_ (); raise e
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>