@@ -12,10 +12,11 @@ type _ tdt =
1212 }
1313 -> [> `Bundle ] tdt
1414
15- let config_terminated_bit = 0x01
16- and config_callstack_mask = 0x3E
17- and config_callstack_shift = 1
18- and config_one = 0x40 (* memory runs out before overflow *)
15+ let config_on_return_terminate_bit = 0x01
16+ and config_on_terminate_raise_bit = 0x02
17+ and config_callstack_mask = 0x6C
18+ and config_callstack_shift = 2
19+ and config_one = 0x80 (* memory runs out before overflow *)
1920
2021let flock_key : [ `Bundle | `Nothing ] tdt Fiber.FLS.t = Fiber.FLS. create ()
2122
@@ -35,6 +36,8 @@ let error ?callstack (Bundle r as t : t) exn bt =
3536 terminate ?callstack t;
3637 Control.Errors. push r.errors exn bt
3738 end
39+ else if Atomic. get r.config land config_on_terminate_raise_bit <> 0 then
40+ terminate ?callstack t
3841
3942let decr (Bundle r : t ) =
4043 let n = Atomic. fetch_and_add r.config (- config_one) in
@@ -48,6 +51,10 @@ type _ pass = FLS : unit pass | Arg : t pass
4851
4952let [@ inline never] no_flock () = invalid_arg " no flock"
5053
54+ let [@ inline] on_terminate = function
55+ | None | Some `Ignore -> `Ignore
56+ | Some `Raise -> `Raise
57+
5158let get_flock fiber =
5259 match Fiber.FLS. get fiber flock_key ~default: Nothing with
5360 | Bundle _ as t -> t
@@ -75,7 +82,7 @@ let[@inline never] raised exn t fiber packed canceler outer =
7582let [@ inline never] returned value (Bundle r as t : t ) fiber packed canceler
7683 outer =
7784 let config = Atomic. get r.config in
78- if config land config_terminated_bit <> 0 then begin
85+ if config land config_on_return_terminate_bit <> 0 then begin
7986 let callstack =
8087 let n = (config land config_callstack_mask) lsr config_callstack_shift in
8188 if n = 0 then None else Some n
@@ -90,25 +97,31 @@ let join_after_realloc x fn t fiber packed canceler outer =
9097 | value -> returned value t fiber packed canceler outer
9198 | exception exn -> raised exn t fiber packed canceler outer
9299
93- let join_after_pass (type a ) ?callstack ?on_return (fn : a -> _ ) ( pass : a pass )
94- =
100+ let join_after_pass (type a ) ?callstack ?on_return ? on_terminate (fn : a -> _ )
101+ ( pass : a pass ) =
95102 (* The sequence of operations below ensures that nothing is leaked. *)
96103 let (Bundle r as t : t ) =
97- let terminated =
104+ let config =
98105 match on_return with
99- | None | Some `Wait -> 0
100- | Some `Terminate -> config_terminated_bit
106+ | None | Some `Wait -> config_one
107+ | Some `Terminate -> config_one lor config_on_return_terminate_bit
101108 in
102- let callstack =
109+ let config =
110+ match on_terminate with
111+ | None | Some `Ignore -> config
112+ | Some `Raise -> config lor config_on_terminate_raise_bit
113+ in
114+ let config =
103115 match callstack with
104- | None -> 0
116+ | None -> config
105117 | Some n ->
106- if n < = 0 then 0
118+ if n < = 0 then config
107119 else
108- Int. min n (config_callstack_mask lsr config_callstack_shift)
109- lsl config_callstack_shift
120+ config
121+ lor Int. min n (config_callstack_mask lsr config_callstack_shift)
122+ lsl config_callstack_shift
110123 in
111- let config = Atomic. make (config_one lor callstack lor terminated) in
124+ let config = Atomic. make config in
112125 let bundle = Computation. Packed (Computation. create ~mode: `LIFO () ) in
113126 let errors = Control.Errors. create () in
114127 let finished = Trigger. create () in
@@ -208,8 +221,8 @@ let fork_pass (type a) (Bundle r as t : t) thunk (pass : a pass) =
208221let is_running (Bundle { bundle = Packed bundle ; _ } : t ) =
209222 Computation. is_running bundle
210223
211- let join_after ?callstack ?on_return fn =
212- join_after_pass ?callstack ?on_return fn Arg
224+ let join_after ?callstack ?on_return ? on_terminate fn =
225+ join_after_pass ?callstack ?on_return ?on_terminate fn Arg
213226
214227let fork t thunk = fork_pass t thunk Arg
215228let fork_as_promise t thunk = fork_as_promise_pass t thunk Arg
0 commit comments