Compare commits

..

No commits in common. "main" and "v0.1" have entirely different histories.
main ... v0.1

5 changed files with 8 additions and 61 deletions

View file

@ -1,8 +1,5 @@
# 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.
The goal of this library is to provide a uniform abstraction over multiple

View file

@ -1,16 +1,4 @@
(** 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. *)
(** Nano event loop *)
type t
@ -41,46 +29,31 @@ module Impl : sig
run_after_s: 'a 'b. 'st -> float -> 'a -> 'b -> ('a -> 'b -> unit) -> unit;
step: 'st -> unit;
}
(** A nanoev event loop provides a set of operations on a hidden state ['st].
*)
val build : 'a ops -> 'a -> t
(** Build a [Nanoev.t] from operations and hidden state. *)
end
val clear : t -> unit
(** Reset the state, similar to creating a new event loop from scratch *)
(** Reset the state *)
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
(** Run one step of the event loop until something happens. This can potentially
block the caller for an interdeterminate duration. *)
(** Run one step of the event loop until something happens *)
val close : t -> Unix.file_descr -> unit
(** Close the file descriptor and clean it up inside the event loop. Callbacks
registered on this FD will be called with [~closed:true]. *)
(** Close the file descriptor and clean it up *)
val max_fds : t -> int
(** 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). *)
(** Maximum number of file descriptors that can be observed at once. *)
val on_readable :
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 :
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
(** [run_after_s nanoev [duration] x y f] registers [f x y] to be called after
[duration] seconds have elapsed. *)
(**/**)

View file

@ -1,8 +1,7 @@
(library
(name nanoev_posix)
(public_name nanoev-posix)
(enabled_if
(= %{os_type} "Unix"))
(enabled_if (= %{os_type} "Unix"))
(synopsis "posix backend (poll/ppoll+mtime)")
(private_modules heap)
(libraries threads nanoev unix iomux mtime mtime.clock.os))

View file

@ -382,32 +382,12 @@ let step (self : st) : unit =
try Fd_tbl.find self.fds fd with Not_found -> assert false
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 (
let r = fd_data.r in
fd_data.r <- Nil;
perform_cbs ~closed:false r
);
(* 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 (
if Flags.mem Flags.pollout flags then (
let w = fd_data.w in
fd_data.w <- Nil;
perform_cbs ~closed:false w

View file

@ -1,9 +1,7 @@
(** Nanoev implementation based on [Unix.select] *)
(** Nano event loop *)
include module type of struct
include Nanoev
end
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. *)