Skip to content

Replace Continuation_already_taken exception with a predefined Invalid_argument exception #11422

@kayceesrk

Description

@kayceesrk

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions