Module Fiber
Fast native fibers for OCaml.
Fibers are implemented by tying together libcoro and OCaml's GC hooks. This design allows allocation free context switches with decent performance. For example, i7-8750H running Linux can perform about 13.7M fiber context switches per second. If you want to measure it by yourself just run make all bench from the source directory.
Basic API
The basic API allows creation of a fiber and switching back and forth. It follows closely Lua coroutines.
To give some idea of how it works, here is an example of printing numbers from 1 to 10 in a fiber way:
let fb = Fiber.create (fun () ->
for i = 1 to 10 do
print_int i;
print_newline ();
Fiber.yield ()
done) ()
let _ =
for j = 1 to 10 do
Fiber.resume fb
doneMore examples available in the examples directory.
val create : ('a -> 'b) -> 'a -> 'b fibercreate f argcreates a fiber.A fiber can be in one of the following states:
sleeping,runningordead. A fiber will initially be in statesleeping. Uponresume, the fiber will executef arg. Whenfreturns the fiber enters statedead. return value offcan be obtained by callingjoin.Current implementation allocates 112 pages of stack and 16 pages of guard zone. Graceful stack overflow detection is not (yet) implemented and stack overflow will result in segmentation violation.
Fiber context creation is a relatively expensive process and therefore library caches unused contexts of dead fibers. The cache size is unbound, be careful when creating a lot of short living fibers.
Exception behavior is similar to the vanilla OCaml. You can
raiseexception inside a fiber and catch it with atry ... with .... Uncaught exception in a fiber will terminate the whole program.
val yield : unit -> unityieldyields control to the caller (the fiber which issuedresume). Consequently, it is an error to callyieldfrom initial context, since there is no caller.
val resume : 'a fiber -> unitresume fbresumes the fiberfb, that is: transfer execution context to it. Trying to resume dead fiber will raiseInvalid_argument "Fiber.resume".
Event loop
Integration with libev event loop.
val run : ('a -> 'b) -> 'a -> 'b optionrun f argstarts the event loop and executesf arginside a newly created fiber. ReturnsNoneifbreakis called during execution off.
val break : unit -> unitbreakstops event loop and exits fromrun.
val wake : 'a fiber -> unitwake fbregister a wakeup for a fiberfb. A fiberfbwill be resumed in the next iteration of the event loop.
val cancel_wake : 'a fiber -> unitcancel_wake fbcancels pending wakeup forfb.
val join : 'a fiber -> 'ajoin fbsuspends the current fiber untilfbis dead and returns the return value of it. It is permitted to calljoin fbseveral times.
val wait_io_ready : Unix.file_descr -> event -> unitwait_io_ready fd evsuspends the current fiber until reading or writing from file descriptorfdcan be performed without blocking.Please note, that the library itself doesn't put file descriptor into a nonblocking mode. Therefore, it's advisable to either put file descriptor into nonblocking mode before calling
read(2)andwrite(2)or usesend(2)andrecv(2)with correspondingflags.
Synchronisation
module Mutex : sig ... endmodule Condition : sig ... endmodule MVar : sig ... end