Module Concurrent_in_async.Portable

Capabilities for submitting jobs to the async scheduler from other threads

scheduler () is a handle that allows spawning concurrent tasks in the Async scheduler from other threads. It uses the thread-safe external job queue in the async scheduler under the hood, so is less efficient than the non-portable scheduler if you don't need to spawn tasks from arbitrary threads.

Usage example

  open! Core
  open! Async
  open! Await

  let print_endline = Capsule.Initial.Data.wrap Async_unix.Print.print_endline

  let () =
    let scheduler = Concurrent_in_async.Portable.scheduler () in
    Mdx_async.run (fun () ->
      Concurrent_in_async.schedule_with_concurrent Terminator.never ~f:(fun conc ->
        Concurrent.with_scope
          conc
          (* Use the scheduler as our scope context to avoid allocating a closure *)
          scheduler
          ~f:(fun s ->
            (* Spawn a thread, given the handle to the scheduler *)
            Concurrent.spawn
              (Concurrent_in_thread.spawn_into s)
              ~f:(fun scope _ _ ->
                (* Recover the scheduler *)
                let scheduler = Concurrent.Scope.context scope in
                (* We can now spawn tasks into the async scheduler *)
                Concurrent.Scheduler.spawn scheduler scope ~f:(fun _ access _ ->
                  (* Those tasks get access to the initial capsule, which they can
                     use to call functions that use async *)
                  let print_endline =
                    Capsule.Data.unwrap
                      ~access:(Capsule.Access.unbox access)
                      print_endline
                  in
                  print_endline "Hello from async!")
                [@nontail])
            [@nontail])))
  ;;