The Thread_safe
module has functions that are safe to call from threads outside
Async, such as the ones spawned by In_thread.run
.
This is in contrast with the rest of Async
library which is generally not
thread-safe.
All the Thread_safe.block*
and Thread_safe.run*
functions wake up the Async
scheduler to ensure that it continues in a timely manner with whatever jobs got
started. Some functions take an optional ?wakeup_scheduler:bool
argument, which
defaults to true
. One can cause the scheduler to not be woken up by supplying
~wakeup_scheduler:false
, which can reduce CPU use, but increase latency, because the
scheduler may not wake up for a while to process jobs.
val am_holding_async_lock : unit ‑> bool
am_holding_async_lock ()
returns true if the currently running thread is holding the
Async lock.
val deferred : unit ‑> 'a Async_kernel.Deferred.t * ('a ‑> unit)
deferred ()
returns (d, fill)
where d
is a deferred that will become determined
with value v
once fill v
is called.
It is ok to call deferred
from inside or outside Async. fill
must be called from
outside Async.
val run_in_async_with_optional_cycle : ?wakeup_scheduler:bool ‑> (unit ‑> [ `Run_a_cycle | `Do_not_run_a_cycle ] * 'a) ‑> ('a, exn) Core.Result.t
run_in_async_with_optional_cycle f
acquires the Async lock and runs f ()
while
holding the lock. Depending on the result of f
, it may also run a cycle.
val run_in_async : ?wakeup_scheduler:bool ‑> (unit ‑> 'a) ‑> ('a, exn) Core.Result.t
run_in_async f
acquires the Async lock and runs f ()
while holding the lock. It
returns the result of f ()
to the outside world. The scheduler is woken up to
ensure the code that depends on f ()
is run soon enough.
run_in_async
doesn't run a cycle.
run_in_async
does not automatically start the Async scheduler. You still need to
call Scheduler.go
elsewhere in your program.
val block_on_async : (unit ‑> 'a Async_kernel.Deferred.t) ‑> ('a, exn) Core.Result.t
block_on_async f
runs f ()
in the Async world and blocks until the result becomes
determined. This function can be called from the main thread (before Async is
started) or from a thread outside Async.
block_on_async
will run a cycle if the deferred isn't determined, in the hope that
running the cycle will cause the deferred to become determined.
block_on_async
will automatically start the scheduler if it isn't already
running.
val block_on_async_exn : (unit ‑> 'a Async_kernel.Deferred.t) ‑> 'a
val run_in_async_wait : (unit ‑> 'a Async_kernel.Deferred.t) ‑> ('a, exn) Core.Result.t
run_in_async_wait f
is like block_on_async f
, except that it must be called from a
thread outside Async. Upon returning from run_in_async_wait
, it is guaranteed that
the caller does not have the Async lock.
val run_in_async_wait_exn : (unit ‑> 'a Async_kernel.Deferred.t) ‑> 'a
val reset_scheduler : unit ‑> unit
reset_scheduler
stops the scheduler thread and any associated threads, and resets
Async's global state to its initial state. This is useful if you need to first use
Async to compute a value and then to daemonize (in which case you should daemonize
with ~allow_threads_to_have_been_created:true
).
reset_scheduler
can be called from the main thread (before Async is started) or from
a thread outside Async. reset_scheduler
is known to be imperfect, and to have races
in which there are still threads running after it returns.