-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Replace Continuation_already_taken exception with a predefined Invalid_argument exception #11422
Description
When a continuation is attempted to be resumed more than once, we get a Continuation_already_taken exception:
open Effect
open Effect.Deep
type _ Effect.t += E : unit t
let _ =
try_with perform E
{ effc = fun (type a) (eff : a t) ->
match eff with
| E -> Some (fun (k : (a,_) continuation) ->
continue k ();
continue k ()) (* Continuation_already_taken exception raised here *)
| e -> None }Continuation_already_taken is a pre-defined exception, and was introduced to ensure that in the fast path, continue and discontinue functions do not go through the slower allocating C call (see PR ocaml-multicore/ocaml-multicore#437). Before ocaml-multicore/ocaml-multicore#437, the second continue will have raised Invalid_argument "continuation_already_taken" exception. Creating this exception requires an allocation, which this more specialised Continuation_already_taken exception avoids. Unfortunately, Continuation_already_taken needs to be a predefined exception since the assembly stubs refer to it. It seems less hygenic to define a new predefined exception to avoid allocation.
Proposal
An alternative proposal would be to have a global root which defines Invalid_argument "continuation_already_taken" once and for all and use that instead of Continuation_already_taken. This came up since I've been looking at the API around exceptions in Effect module in #11419.