mirror of
https://github.com/c-cube/nanoev.git
synced 2025-12-07 19:55:45 -05:00
Compare commits
5 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
10700a3962 | ||
|
|
dc7f2ec92e | ||
|
|
8e809c8b8f | ||
|
|
ca8121d361 | ||
|
|
d72a1c5d90 |
5 changed files with 61 additions and 8 deletions
|
|
@ -1,5 +1,8 @@
|
||||||
# nanoev
|
# nanoev
|
||||||
|
|
||||||
|
**NOTE (2025-09-29)**: I ended up not using this. Instead I reuse Lwt and Lwt_engine. I recommend not using this as there are some timer-related bugs.
|
||||||
|
|
||||||
|
|
||||||
A minimalistic but modular abstraction for IO event loops.
|
A minimalistic but modular abstraction for IO event loops.
|
||||||
|
|
||||||
The goal of this library is to provide a uniform abstraction over multiple
|
The goal of this library is to provide a uniform abstraction over multiple
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,16 @@
|
||||||
(** Nano event loop *)
|
(** Nano event loop.
|
||||||
|
|
||||||
|
{1 Summary}
|
||||||
|
|
||||||
|
Nanoev is a small abstraction over non-blocking IO event loops offered by
|
||||||
|
most operating systems (e.g kqueue on BSD/macOS, poll on posix systems,
|
||||||
|
epoll on linux, completion ports on windows).
|
||||||
|
|
||||||
|
The idea is that a [Nanoev.t] encapsulates a single event loop in a reusable
|
||||||
|
form, and can be used in higher-level concurrency packages or to write async
|
||||||
|
IO code directly. See {!Nanoev_unix} for a [Unix.select]-based
|
||||||
|
implementation and {!Nanoev_posix} for a [poll]-based (better)
|
||||||
|
implementation. *)
|
||||||
|
|
||||||
type t
|
type t
|
||||||
|
|
||||||
|
|
@ -29,31 +41,46 @@ module Impl : sig
|
||||||
run_after_s: 'a 'b. 'st -> float -> 'a -> 'b -> ('a -> 'b -> unit) -> unit;
|
run_after_s: 'a 'b. 'st -> float -> 'a -> 'b -> ('a -> 'b -> unit) -> unit;
|
||||||
step: 'st -> unit;
|
step: 'st -> unit;
|
||||||
}
|
}
|
||||||
|
(** A nanoev event loop provides a set of operations on a hidden state ['st].
|
||||||
|
*)
|
||||||
|
|
||||||
val build : 'a ops -> 'a -> t
|
val build : 'a ops -> 'a -> t
|
||||||
|
(** Build a [Nanoev.t] from operations and hidden state. *)
|
||||||
end
|
end
|
||||||
|
|
||||||
val clear : t -> unit
|
val clear : t -> unit
|
||||||
(** Reset the state *)
|
(** Reset the state, similar to creating a new event loop from scratch *)
|
||||||
|
|
||||||
val wakeup_from_outside : t -> unit
|
val wakeup_from_outside : t -> unit
|
||||||
|
(** Wakeup a sleeping event loop from the outside (another thread, a signal
|
||||||
|
handler, etc.). This must be thread-safe. *)
|
||||||
|
|
||||||
val step : t -> unit
|
val step : t -> unit
|
||||||
(** Run one step of the event loop until something happens *)
|
(** Run one step of the event loop until something happens. This can potentially
|
||||||
|
block the caller for an interdeterminate duration. *)
|
||||||
|
|
||||||
val close : t -> Unix.file_descr -> unit
|
val close : t -> Unix.file_descr -> unit
|
||||||
(** Close the file descriptor and clean it up *)
|
(** Close the file descriptor and clean it up inside the event loop. Callbacks
|
||||||
|
registered on this FD will be called with [~closed:true]. *)
|
||||||
|
|
||||||
val max_fds : t -> int
|
val max_fds : t -> int
|
||||||
(** Maximum number of file descriptors that can be observed at once. *)
|
(** Maximum number of file descriptors that can be observed at once. This
|
||||||
|
depends on the syscall underlying the event loop, as well as other system
|
||||||
|
limits (see [ulimit -n] to change this limit on linux, for example). *)
|
||||||
|
|
||||||
val on_readable :
|
val on_readable :
|
||||||
t -> Unix.file_descr -> 'a -> 'b -> (closed:bool -> 'a -> 'b -> unit) -> unit
|
t -> Unix.file_descr -> 'a -> 'b -> (closed:bool -> 'a -> 'b -> unit) -> unit
|
||||||
|
(** [on_readable nanoev fd x y f] registers [f x y] to be called when [fd]
|
||||||
|
becomes readable. An additional [closed] parameter is passed to [f] to
|
||||||
|
inform it of whether [fd] is {i known} to be closed. *)
|
||||||
|
|
||||||
val on_writable :
|
val on_writable :
|
||||||
t -> Unix.file_descr -> 'a -> 'b -> (closed:bool -> 'a -> 'b -> unit) -> unit
|
t -> Unix.file_descr -> 'a -> 'b -> (closed:bool -> 'a -> 'b -> unit) -> unit
|
||||||
|
(** Same as {!on_readable} but calls [f] when the FD is writable. *)
|
||||||
|
|
||||||
val run_after_s : t -> float -> 'a -> 'b -> ('a -> 'b -> unit) -> unit
|
val run_after_s : t -> float -> 'a -> 'b -> ('a -> 'b -> unit) -> unit
|
||||||
|
(** [run_after_s nanoev [duration] x y f] registers [f x y] to be called after
|
||||||
|
[duration] seconds have elapsed. *)
|
||||||
|
|
||||||
(**/**)
|
(**/**)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
(library
|
(library
|
||||||
(name nanoev_posix)
|
(name nanoev_posix)
|
||||||
(public_name nanoev-posix)
|
(public_name nanoev-posix)
|
||||||
(enabled_if (= %{os_type} "Unix"))
|
(enabled_if
|
||||||
|
(= %{os_type} "Unix"))
|
||||||
(synopsis "posix backend (poll/ppoll+mtime)")
|
(synopsis "posix backend (poll/ppoll+mtime)")
|
||||||
(private_modules heap)
|
(private_modules heap)
|
||||||
(libraries threads nanoev unix iomux mtime mtime.clock.os))
|
(libraries threads nanoev unix iomux mtime mtime.clock.os))
|
||||||
|
|
|
||||||
|
|
@ -382,12 +382,32 @@ let step (self : st) : unit =
|
||||||
try Fd_tbl.find self.fds fd with Not_found -> assert false
|
try Fd_tbl.find self.fds fd with Not_found -> assert false
|
||||||
in
|
in
|
||||||
|
|
||||||
|
(* errors *)
|
||||||
|
if Flags.mem Flags.pollnval flags || Flags.mem Flags.pollerr flags then (
|
||||||
|
(* pollerr: error
|
||||||
|
pollnval: fd is invalid, which we take as meaning that it's been closed. *)
|
||||||
|
let r = fd_data.r in
|
||||||
|
fd_data.r <- Nil;
|
||||||
|
perform_cbs ~closed:true r;
|
||||||
|
let r = fd_data.r in
|
||||||
|
fd_data.r <- Nil;
|
||||||
|
perform_cbs ~closed:true r
|
||||||
|
);
|
||||||
|
|
||||||
|
(* reads *)
|
||||||
if Flags.mem Flags.pollin flags then (
|
if Flags.mem Flags.pollin flags then (
|
||||||
let r = fd_data.r in
|
let r = fd_data.r in
|
||||||
fd_data.r <- Nil;
|
fd_data.r <- Nil;
|
||||||
perform_cbs ~closed:false r
|
perform_cbs ~closed:false r
|
||||||
);
|
);
|
||||||
if Flags.mem Flags.pollout flags then (
|
|
||||||
|
(* writes *)
|
||||||
|
if Flags.mem Flags.pollhup flags then (
|
||||||
|
(* incompatible with pollout *)
|
||||||
|
let r = fd_data.w in
|
||||||
|
fd_data.w <- Nil;
|
||||||
|
perform_cbs ~closed:false r
|
||||||
|
) else if Flags.mem Flags.pollout flags then (
|
||||||
let w = fd_data.w in
|
let w = fd_data.w in
|
||||||
fd_data.w <- Nil;
|
fd_data.w <- Nil;
|
||||||
perform_cbs ~closed:false w
|
perform_cbs ~closed:false w
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
(** Nano event loop *)
|
(** Nanoev implementation based on [Unix.select] *)
|
||||||
|
|
||||||
include module type of struct
|
include module type of struct
|
||||||
include Nanoev
|
include Nanoev
|
||||||
end
|
end
|
||||||
|
|
||||||
val create : unit -> t
|
val create : unit -> t
|
||||||
|
(** Create a [Nanoev.t] based on [Unix.select]. This is fairly limited and only
|
||||||
|
works in processes that have fewer than 1024 FDs open in total. *)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue