@@ -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