package eio
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
Effect-based direct-style IO API for OCaml
Install
dune-project
Dependency
Authors
Maintainers
Sources
eio-0.11.tbz
sha256=0c33742074562631677886f4fe4a02f9672cec94297ff85c2ed854db5baa71aa
sha512=590843cb5fb3906fd5ab9911d29206172d164a53c48e635871a23c95d4cdce8ae0999480471187fdddee8c9c523148911ca140feabde6a826c317671a3b33090
doc/src/eio/eio_mutex.ml.html
Source file eio_mutex.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 119type state = | Unlocked (* can be locked *) | Locked (* is locked; threads may be waiting *) | Poisoned of exn (* disabled due to exception in critical section *) exception Poisoned of exn type t = { id : Ctf.id; mutex : Mutex.t; mutable state : state; (* Owned by [t.mutex] *) waiters : [`Take | `Error of exn] Waiters.t; (* Owned by [t.mutex] *) } (* Invariant: t.state <> Locked -> is_empty t.waiters *) (* When [t.state = Unlocked], [t] owns the user resource that [t] protects. [mutex t R] means [t] is a share of a reference to a mutex with an invariant R. [locked t] means the holder has the ability to unlock [t]. *) (* {R} t = create () {mutex t R} *) let create () = let id = Ctf.mint_id () in Ctf.note_created id Ctf.Mutex; { id; mutex = Mutex.create (); state = Unlocked; (* Takes ownership of R *) waiters = Waiters.create (); } (* {mutex t R * locked t * R} unlock t {mutex t R} If [t] is in an invalid state, it raises an exception and nothing changes. *) let unlock t = Mutex.lock t.mutex; (* We now have ownership of [t.state] and [t.waiters]. *) Ctf.note_signal t.id; match t.state with | Unlocked -> Mutex.unlock t.mutex; let ex = Sys_error "Eio.Mutex.unlock: already unlocked!" in t.state <- Poisoned ex; raise ex | Locked -> begin match Waiters.wake_one t.waiters `Take with | `Ok -> () (* We transferred [locked t * R] to a waiter; [t] remains [Locked]. *) | `Queue_empty -> t.state <- Unlocked (* The state now owns R. *) end; Mutex.unlock t.mutex | Poisoned ex -> Mutex.unlock t.mutex; raise (Poisoned ex) (* {mutex t R} lock t {mutex t R * locked t * R} *) let lock t = Mutex.lock t.mutex; match t.state with | Locked -> Ctf.note_try_read t.id; begin match Waiters.await ~mutex:(Some t.mutex) t.waiters t.id with | `Error ex -> raise ex (* Poisoned; stop waiting *) | `Take -> (* The unlocker didn't change the state, so it's still Locked, as required. {locked t * R} *) () end | Unlocked -> Ctf.note_read t.id; t.state <- Locked; (* We transfer R from the state to our caller. *) (* {locked t * R} *) Mutex.unlock t.mutex | Poisoned ex -> Mutex.unlock t.mutex; raise (Poisoned ex) (* {mutex t R} v = try_lock t { mutex t R * if v then locked t * R else [] } *) let try_lock t = Mutex.lock t.mutex; match t.state with | Locked -> Ctf.note_try_read t.id; Mutex.unlock t.mutex; false | Unlocked -> Ctf.note_read t.id; t.state <- Locked; (* We transfer R from the state to our caller. *) Mutex.unlock t.mutex; (* {locked t * R} *) true | Poisoned ex -> Mutex.unlock t.mutex; raise (Poisoned ex) (* {mutex t R * locked t} poison t ex {mutex t R} *) let poison t ex = Mutex.lock t.mutex; t.state <- Poisoned ex; Waiters.wake_all t.waiters (`Error (Poisoned ex)); Mutex.unlock t.mutex (* {locked t * R} fn () {locked t * R} -> {mutex t R} use_ro t fn {mutex t R} *) let use_ro t fn = lock t; (* {mutex t R * locked t * R} *) match fn () with | x -> unlock t; x | exception ex -> unlock t; raise ex (* {locked t * R} v = match fn () with _ -> true | exception _ -> false {locked t * if v then R else []} -> {mutex t R} use_rw ~protect t fn {mutex t R} *) let use_rw ~protect t fn = lock t; (* {mutex t R * locked t * R} *) match if protect then Cancel.protect fn else fn () with | x -> unlock t; x | exception ex -> (* {mutex t R * locked t} *) poison t ex; raise ex
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>