Private.Async_funAsynchronous function internals and effects.
These definitions are subject to change even between minor versions of the library.
Note. You should never use these definitions or handle these effects in the scope of a function given to Affect.Fun.Async.main. These definitions are exposed to allow Affect.Fun.Async asynchronous function calls to be handled by other schedulers. See an example here.
module Call_handler = Call_handlermodule Schedule = Schedulemodule Call = Callval make :
?notify_finish:('a Async.t -> unit) ->
handler:Call_handler.t ->
schedule:Schedule.t ->
parent:Call.t ->
unit ->
'a Async.tmake handler ~schedule ~parent () is an asynchronous function call with given properties. This takes care of composing the call handler of parent with handler and register the call in parent's children. For the root asynchronous function use Call.none for the parent.
notify_finish is called once with the created call when the asynchronous function's result has been computed and all its asynchronous calls have returned just before the parent or entities blocked on geting the function result get unblocked.
Note that this is just data about the call, it doesn't carry the actual computation. It provides however the location where the function result is stored.
val run : 'a Async.t -> (unit -> 'a) -> unitrun af f runs the asynchronous function af with the body f wrapped in the call handler of af. Takes care of structured concurrency and calling the notfiy_finish given in make when it's time to do so.
val id_int : 'a Async.t -> intid_int af is Type.Id.uid (id af).
val set_priority : 'a Async.t -> Schedule.priority -> unitset_priority af p sets the priority of af to p.
val result : 'a Async.t -> 'a Action.Private.Action.Result.t optionresult af is the result of af. This is guaranteed to be Some _ after notify_finish given to make has been called. Normally this is only needed to get the result of the root asynchronous function.
val do_sys_break : Call.t -> unitdo_sys_break c can be used by a scheduler if it receives a Sys.break while running c. At that point you no longer have a body to run for c so the function cancels c and moves it state to return a Cancelled exception if it's still running or waiting to return.
val unblock_action_invoke :
Call.t ->
'b Action.Private.Action.Primitive.t optionunblock_action_invoke call is the primitive action (if any) that needs to be given to Action.Private.Action.Invocation.make when you handle an Action.Private.Action.Invoke effect for call. It has the whole logic (including masking) to handle the cancellation model of asynchronous functions.
type Stdlib.Effect.t += | Call : Call_handler.t * Schedule.t * (unit -> 'a) -> 'a Async.t Stdlib.Effect.t| Yield : unit Stdlib.Effect.t| Get_current_call : Call.t Stdlib.Effect.t| Get_parallel_count : int Stdlib.Effect.tEffects for handling asynchronous functions.
These effects assume that your scheduler is maintaining the currently executing asynchronous function on the current processor in a current variable. Given that here is how you must handle these effects:
Call (handle, schedule, f) you must must create an asynchronous call af with make ~handle ~schedule ~parent:current and arrange for f to be scheduled for execution in parallel or concurrently (with current set as Call.of_async_fun af) and immediately continue with af. current must not change, the caller must not be suspended.Yield, unless no other call is ready for execution, you must arrange for current to be scheduled later and execute another call ready for execution as current.Get_current_call you must immediately continue with current.Get_parallel_count you must immediately continue with a strictly positive parallel count you find suitable to answer to a call to Fun.Async.parallel_count. Note that the handling of this effect is user-overidable from the API with Fun.Async.parallel_count_override.Sys.Break you should call do_sys_break on current and execute another call ready for execution as current. Unless you think there's something smarter to do.Important. Additionaly when you handle the effects for action invocations for current you must use the value of unblock_action_invoke current and pass it as the unblock argument of the Action.Private.Action.Invocation.make you create. This makes sure that the asynchronous function cancellation model is handled correctly.