Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Page
Library
Module
Module type
Parameter
Class
Class type
Source
cancel.ml1 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 95open Core open Core.O type 'a outcome = | Cancelled of 'a | Not_cancelled type handlers = | End_of_handlers | Handler of { ivar : unit outcome Ivar.t ; mutable next : handlers ; mutable prev : handlers } module State = struct type t = | Cancelled | Not_cancelled of { mutable handlers : handlers } end type t = { mutable state : State.t } let create () = { state = Not_cancelled { handlers = End_of_handlers } } let rec invoke_handlers = function | Handler { ivar; next; prev = _ } -> let* () = Ivar.fill ivar (Cancelled ()) in invoke_handlers next | End_of_handlers -> return () let fire t = of_thunk (fun () -> match t.state with | Cancelled -> return () | Not_cancelled { handlers } -> t.state <- Cancelled; invoke_handlers handlers) let rec fills_of_handlers acc = function | Handler { ivar; next; prev = _ } -> fills_of_handlers (Scheduler.Fill (ivar, Cancelled ()) :: acc) next | End_of_handlers -> List.rev acc let fire' t = match t.state with | Cancelled -> [] | Not_cancelled { handlers } -> t.state <- Cancelled; fills_of_handlers [] handlers let fired t = match t.state with | Cancelled -> true | Not_cancelled _ -> false let with_handler t f ~on_cancel = match t.state with | Cancelled -> let+ x, y = fork_and_join f on_cancel in (x, Cancelled y) | Not_cancelled h -> let ivar = Ivar.create () in let node = Handler { ivar; next = h.handlers; prev = End_of_handlers } in (match h.handlers with | End_of_handlers -> () | Handler first -> first.prev <- node); h.handlers <- node; fork_and_join (fun () -> let* y = f () in match t.state with | Cancelled -> return y | Not_cancelled h -> ( match node with | End_of_handlers -> (* We could avoid this [assert false] with GADT sorcery given that we created [node] just above and we know for sure it is the [Handler _] case, but it's not worth the code complexity. *) assert false | Handler node -> (match node.prev with | End_of_handlers -> h.handlers <- node.next | Handler prev -> prev.next <- node.next); (match node.next with | End_of_handlers -> () | Handler next -> next.prev <- node.prev); let+ () = Ivar.fill ivar Not_cancelled in y)) (fun () -> Ivar.read ivar >>= function | Cancelled () -> let+ x = on_cancel () in Cancelled x | Not_cancelled -> return Not_cancelled)