package picos_std
Sample libraries for Picos
Install
Dune Dependency
Authors
Maintainers
Sources
picos-0.6.0.tbz
sha256=3f5a08199cf65c2dae2f7d68f3877178f1da8eabf5376e15114e5a8958087dfa
sha512=ad24910c47ce614268c4268874bb918da7f8b5f03b3ad706bbf30323635262e94ddab6be24eaebbca706bfa82c0a517d4272b396459e020c185942125c9bdb7b
doc/src/picos_std.finally/picos_std_finally.ml.html
Source file picos_std_finally.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 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
open Picos type ('a, _) tdt = | Transferred : ('a, [> `Transferred ]) tdt | Borrowed : ('a, [> `Borrowed ]) tdt | Dropped : ('a, [> `Dropped ]) tdt | Resource : { mutable resource : 'a; release : 'a -> unit; transferred_or_dropped : Trigger.t; } -> ('a, [> `Resource ]) tdt type 'a instance = ('a, [ `Transferred | `Borrowed | `Dropped | `Resource ]) tdt Atomic.t (* *) let[@inline never] error (case : (_, [< `Transferred | `Borrowed | `Dropped ]) tdt) = invalid_arg (match case with | Transferred -> "transferred" | Dropped -> "dropped" | Borrowed -> "borrowed") let[@inline never] check_released () = (* In case of cancelation we do not consider being released an error as the resource was released by (the |an)other party involved in the [move]. *) Fiber.check (Fiber.current ()); error Dropped (* *) let forbidden release x = match Fiber.current () with | fiber -> begin if Fiber.exchange fiber ~forbid:true then release x else match release x with | () -> Fiber.set fiber ~forbid:false | exception exn -> Fiber.set fiber ~forbid:false; raise exn end | exception _exn -> (* This should only happen when not running under a scheduler. However, we don't match on a specific exception, because it depends on the OCaml version. We also do not reraise the exception! *) release x let[@inline never] release_and_reraise exn x release = let bt = Printexc.get_raw_backtrace () in forbidden release x; Printexc.raise_with_backtrace exn bt let[@inline never] release_and_return value x release = forbidden release x; value (* *) let rec drop instance = match Atomic.get instance with | Transferred | Dropped -> () | Borrowed as case -> error case | Resource r as before -> if Atomic.compare_and_set instance before Dropped then begin forbidden r.release r.resource; Trigger.signal r.transferred_or_dropped end else drop instance let[@inline never] drop_and_reraise_as bt instance exn = drop instance; Printexc.raise_with_backtrace exn bt let[@inline never] drop_and_reraise exn instance = let bt = Printexc.get_raw_backtrace () in drop_and_reraise_as bt instance exn (* *) let await_transferred_or_dropped instance result = match Atomic.get instance with | Transferred | Dropped -> result | Borrowed as case -> (* This should be impossible as [let@ _ = borrow _ in _] should have restored the state. *) error case | Resource r -> begin match Trigger.await r.transferred_or_dropped with | None -> (* We release in case we could not wait. *) drop instance; result | Some (exn, bt) -> (* We have been canceled, so we release. *) drop_and_reraise_as bt instance exn end let[@inline never] instantiate instance scope = match scope instance with | result -> await_transferred_or_dropped instance result | exception exn -> drop_and_reraise exn instance let[@inline never] instantiate release acquire scope = let instance = Sys.opaque_identity begin let transferred_or_dropped = Trigger.create () in let state = Resource { resource = Obj.magic (); release; transferred_or_dropped } in Atomic.make state end in (* After this point there must be no allocations before [acquire ()]. *) let (Resource r : (_, [ `Resource ]) tdt) = Obj.magic (Atomic.get instance) in r.resource <- acquire (); instantiate instance scope (* *) let[@inline never] rec transfer from scope = match Atomic.get from with | (Transferred | Borrowed) as case -> error case | Dropped -> check_released () | Resource r as before -> let into = Atomic.make Transferred in if Atomic.compare_and_set from before Transferred then begin Atomic.set into before; match Trigger.signal r.transferred_or_dropped; scope into with | result -> await_transferred_or_dropped into result | exception exn -> drop_and_reraise exn into end else transfer from scope (* *) let[@inline never] rec borrow instance scope = match Atomic.get instance with | (Transferred | Dropped | Borrowed) as case -> error case | Resource r as before -> if Atomic.compare_and_set instance before Borrowed then begin match scope r.resource with | result -> Atomic.set instance before; result | exception exn -> (* [Atomic.set] should not disturb the stack trace. *) Atomic.set instance before; raise exn end else borrow instance scope (* *) let[@inline never] rec move from scope = match Atomic.get from with | (Transferred | Borrowed) as case -> error case | Dropped -> check_released () | Resource r as before -> if Atomic.compare_and_set from before Transferred then begin match Trigger.signal r.transferred_or_dropped; scope r.resource with | result -> forbidden r.release r.resource; result | exception exn -> release_and_reraise exn r.resource r.release end else move from scope (* *) let[@inline never] finally x scope release = match scope x with | y -> release_and_return y x release | exception exn -> release_and_reraise exn x release let[@inline never] finally release acquire scope = let x = acquire () in finally x scope release let[@inline never] lastly action scope = match scope () with | value -> release_and_return value () action | exception exn -> release_and_reraise exn () action external ( let@ ) : ('a -> 'b) -> 'a -> 'b = "%apply"
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>