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
done
More examples available in the examples
directory.
val create : ('a -> 'b) -> 'a -> 'b fiber
create f arg
creates a fiber.A fiber can be in one of the following states:
sleeping
,running
ordead
. A fiber will initially be in statesleeping
. Uponresume
, the fiber will executef arg
. Whenf
returns the fiber enters statedead
. return value off
can 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
raise
exception inside a fiber and catch it with atry ... with ...
. Uncaught exception in a fiber will terminate the whole program.
val yield : unit -> unit
yield
yields control to the caller (the fiber which issuedresume
). Consequently, it is an error to callyield
from initial context, since there is no caller.
val resume : 'a fiber -> unit
resume fb
resumes 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 option
run f arg
starts the event loop and executesf arg
inside a newly created fiber. ReturnsNone
ifbreak
is called during execution off
.
val break : unit -> unit
break
stops event loop and exits fromrun
.
val wake : 'a fiber -> unit
wake fb
register a wakeup for a fiberfb
. A fiberfb
will be resumed in the next iteration of the event loop.
val cancel_wake : 'a fiber -> unit
cancel_wake fb
cancels pending wakeup forfb
.
val join : 'a fiber -> 'a
join fb
suspends the current fiber untilfb
is dead and returns the return value of it. It is permitted to calljoin fb
several times.
val wait_io_ready : Unix.file_descr -> event -> unit
wait_io_ready fd ev
suspends the current fiber until reading or writing from file descriptorfd
can 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 ... end
module Condition : sig ... end
module MVar : sig ... end