@@ -16,18 +16,17 @@ type t = [ `Bundle ] tdt
1616
1717external config_as_atomic : t -> int Atomic .t = " %identity"
1818
19- let config_terminated_bit = 0x01
20- and config_callstack_mask = 0x3E
21- and config_callstack_shift = 1
22- and config_one = 0x40 (* memory runs out before overflow *)
19+ let config_on_return_terminate_bit = 0x01
20+ and config_on_terminate_raise_bit = 0x02
21+ and config_callstack_mask = 0x6C
22+ and config_callstack_shift = 2
23+ and config_one = 0x80 (* memory runs out before overflow *)
2324
2425let flock_key : [ `Bundle | `Nothing ] tdt Fiber.FLS.t = Fiber.FLS. create ()
2526
26- let terminate_as callstack (Bundle { bundle = Packed bundle ; _ } : t ) =
27- Computation. cancel bundle Control. Terminate callstack
28-
29- let terminate ?callstack t =
30- terminate_as (Control. get_callstack_opt callstack) t
27+ let terminate ?callstack (Bundle { bundle = Packed bundle ; _ } : t ) =
28+ Computation. cancel bundle Control. Terminate
29+ (Control. get_callstack_opt callstack)
3130
3231let terminate_after ?callstack (Bundle { bundle = Packed bundle ; _ } : t )
3332 ~seconds =
@@ -39,25 +38,33 @@ let error ?callstack (Bundle r as t : t) exn bt =
3938 terminate ?callstack t;
4039 Control.Errors. push r.errors exn bt
4140 end
41+ else if
42+ Atomic. get (config_as_atomic t) land config_on_terminate_raise_bit <> 0
43+ then terminate ?callstack t
4244
4345let decr (Bundle r as t : t ) =
4446 let n = Atomic. fetch_and_add (config_as_atomic t) (- config_one) in
4547 if n < config_one * 2 then begin
46- terminate_as Control. empty_bt t;
4748 Trigger. signal r.finished
4849 end
4950
5051type _ pass = FLS : unit pass | Arg : t pass
5152
5253let [@ inline never] no_flock () = invalid_arg " no flock"
5354
55+ let [@ inline] on_terminate = function
56+ | None | Some `Ignore -> `Ignore
57+ | Some `Raise -> `Raise
58+
5459let get_flock fiber =
5560 match Fiber.FLS. get fiber flock_key ~default: Nothing with
5661 | Bundle _ as t -> t
5762 | Nothing -> no_flock ()
5863
5964let await (Bundle r as t : t ) fiber packed canceler outer =
6065 Fiber. set_computation fiber packed;
66+ if Fiber.FLS. get fiber flock_key ~default: Nothing != outer then
67+ Fiber.FLS. set fiber flock_key outer;
6168 let forbid = Fiber. exchange fiber ~forbid: true in
6269 let n = Atomic. fetch_and_add (config_as_atomic t) (- config_one) in
6370 if config_one * 2 < = n then begin
@@ -66,14 +73,22 @@ let await (Bundle r as t : t) fiber packed canceler outer =
6673 write from being delayed after the [Trigger.await] below. *)
6774 if config_one < = Atomic. fetch_and_add (config_as_atomic t) 0 then
6875 Trigger. await r.finished |> ignore
69- end
70- else terminate_as Control. empty_bt t;
76+ end ;
7177 Fiber. set fiber ~forbid ;
72- if Fiber.FLS. get fiber flock_key ~default: Nothing != outer then
73- Fiber.FLS. set fiber flock_key outer;
7478 let (Packed parent) = packed in
7579 Computation. detach parent canceler;
7680 Control.Errors. check r.errors;
81+ begin
82+ let (Packed bundle) = r.bundle in
83+ match Computation. peek_exn bundle with
84+ | _ -> ()
85+ | exception Computation. Running ->
86+ Computation. cancel bundle Control. Terminate Control. empty_bt
87+ | exception Control .Terminate
88+ when Atomic. get (config_as_atomic t) land config_on_terminate_raise_bit
89+ = 0 ->
90+ ()
91+ end ;
7792 Fiber. check fiber
7893
7994let [@ inline never] raised exn t fiber packed canceler outer =
@@ -84,7 +99,7 @@ let[@inline never] raised exn t fiber packed canceler outer =
8499
85100let [@ inline never] returned value (t : t ) fiber packed canceler outer =
86101 let config = Atomic. get (config_as_atomic t) in
87- if config land config_terminated_bit <> 0 then begin
102+ if config land config_on_return_terminate_bit <> 0 then begin
88103 let callstack =
89104 let n = (config land config_callstack_mask) lsr config_callstack_shift in
90105 if n = 0 then None else Some n
@@ -99,25 +114,30 @@ let join_after_realloc x fn t fiber packed canceler outer =
99114 | value -> returned value t fiber packed canceler outer
100115 | exception exn -> raised exn t fiber packed canceler outer
101116
102- let join_after_pass (type a ) ?callstack ?on_return (fn : a -> _ ) ( pass : a pass )
103- =
117+ let join_after_pass (type a ) ?callstack ?on_return ? on_terminate (fn : a -> _ )
118+ ( pass : a pass ) =
104119 (* The sequence of operations below ensures that nothing is leaked. *)
105120 let (Bundle r as t : t ) =
106- let terminated =
121+ let config =
107122 match on_return with
108- | None | Some `Wait -> 0
109- | Some `Terminate -> config_terminated_bit
123+ | None | Some `Wait -> config_one
124+ | Some `Terminate -> config_one lor config_on_return_terminate_bit
110125 in
111- let callstack =
126+ let config =
127+ match on_terminate with
128+ | None | Some `Ignore -> config
129+ | Some `Raise -> config lor config_on_terminate_raise_bit
130+ in
131+ let config =
112132 match callstack with
113- | None -> 0
133+ | None -> config
114134 | Some n ->
115- if n < = 0 then 0
135+ if n < = 0 then config
116136 else
117- Int. min n (config_callstack_mask lsr config_callstack_shift)
118- lsl config_callstack_shift
137+ config
138+ lor Int. min n (config_callstack_mask lsr config_callstack_shift)
139+ lsl config_callstack_shift
119140 in
120- let config = config_one lor callstack lor terminated in
121141 let bundle = Computation. Packed (Computation. create ~mode: `LIFO () ) in
122142 let errors = Control.Errors. create () in
123143 let finished = Trigger. signaled in
@@ -219,8 +239,8 @@ let fork_pass (type a) (Bundle r as t : t) thunk (pass : a pass) =
219239let is_running (Bundle { bundle = Packed bundle ; _ } : t ) =
220240 Computation. is_running bundle
221241
222- let join_after ?callstack ?on_return fn =
223- join_after_pass ?callstack ?on_return fn Arg
242+ let join_after ?callstack ?on_return ? on_terminate fn =
243+ join_after_pass ?callstack ?on_return ?on_terminate fn Arg
224244
225245let fork t thunk = fork_pass t thunk Arg
226246let fork_as_promise t thunk = fork_as_promise_pass t thunk Arg
0 commit comments