@@ -12,10 +12,11 @@ type _ tdt =
12
12
}
13
13
-> [> `Bundle ] tdt
14
14
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 *)
19
20
20
21
let flock_key : [ `Bundle | `Nothing ] tdt Fiber.FLS.t = Fiber.FLS. create ()
21
22
@@ -35,6 +36,8 @@ let error ?callstack (Bundle r as t : t) exn bt =
35
36
terminate ?callstack t;
36
37
Control.Errors. push r.errors exn bt
37
38
end
39
+ else if Atomic. get r.config land config_on_terminate_raise_bit <> 0 then
40
+ terminate ?callstack t
38
41
39
42
let decr (Bundle r : t ) =
40
43
let n = Atomic. fetch_and_add r.config (- config_one) in
@@ -48,6 +51,10 @@ type _ pass = FLS : unit pass | Arg : t pass
48
51
49
52
let [@ inline never] no_flock () = invalid_arg " no flock"
50
53
54
+ let [@ inline] on_terminate = function
55
+ | None | Some `Ignore -> `Ignore
56
+ | Some `Raise -> `Raise
57
+
51
58
let get_flock fiber =
52
59
match Fiber.FLS. get fiber flock_key ~default: Nothing with
53
60
| Bundle _ as t -> t
@@ -75,7 +82,7 @@ let[@inline never] raised exn t fiber packed canceler outer =
75
82
let [@ inline never] returned value (Bundle r as t : t ) fiber packed canceler
76
83
outer =
77
84
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
79
86
let callstack =
80
87
let n = (config land config_callstack_mask) lsr config_callstack_shift in
81
88
if n = 0 then None else Some n
@@ -90,25 +97,31 @@ let join_after_realloc x fn t fiber packed canceler outer =
90
97
| value -> returned value t fiber packed canceler outer
91
98
| exception exn -> raised exn t fiber packed canceler outer
92
99
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 ) =
95
102
(* The sequence of operations below ensures that nothing is leaked. *)
96
103
let (Bundle r as t : t ) =
97
- let terminated =
104
+ let config =
98
105
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
101
108
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 =
103
115
match callstack with
104
- | None -> 0
116
+ | None -> config
105
117
| Some n ->
106
- if n < = 0 then 0
118
+ if n < = 0 then config
107
119
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
110
123
in
111
- let config = Atomic. make (config_one lor callstack lor terminated) in
124
+ let config = Atomic. make config in
112
125
let bundle = Computation. Packed (Computation. create ~mode: `LIFO () ) in
113
126
let errors = Control.Errors. create () in
114
127
let finished = Trigger. create () in
@@ -208,8 +221,8 @@ let fork_pass (type a) (Bundle r as t : t) thunk (pass : a pass) =
208
221
let is_running (Bundle { bundle = Packed bundle ; _ } : t ) =
209
222
Computation. is_running bundle
210
223
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
213
226
214
227
let fork t thunk = fork_pass t thunk Arg
215
228
let fork_as_promise t thunk = fork_as_promise_pass t thunk Arg
0 commit comments