A low-level library to build event driven applications. The core of the
library is [poll
], which polls multiple event sources for readiness
events. Based on these readiness events the application will continue, e.g.
by running a Future
.
A number of readiness event sources are provided:
- [
OsQueue
]: a readiness event queue backed by the OS (epoll or kqueue). - [
Queue
]: a single threaded, user space queue. - [
Timers
]: a single threaded, deadline based readiness queue.
Getting started
Using the crate starts by creating one or more [event::Source
]s.
# use gaea::{OsQueue, Queue};
# fn main() -> std::io::Result<()> {
// `OsQueue` implements `event::Source` and is backed by epoll or kqueue.
let os_queue = OsQueue::new()?;
// `Queue` is a user space readiness event queue, which also implements
// `event::Source`.
let queue = Queue::new();
# drop((os_queue, queue));
# Ok(())
# }
As the name suggest event::Source
s are the sources of readiness events,
these can be polled for readiness events (we'll get back to this later).
This crate provides three [OsQueue
], [Queue
] and [Timers
]. But as
event::Source
is a trait it can be implemented outside of this crate.
Next an [event::Sink
] is required, this used to store the readiness events
from the event sources.
// `Vec`tor implements `event::Sink`.
let events = Vec::new();
# drop::<Vec<gaea::Event>>(events);
Just like event::Source
, event::Sink
is also a trait. When, for example,
building some kind of runtime event::Source
can be directly implemented on
the scheduler type and instead of adding an [Event
] to a collection it
will schedule a process/Future
/task to run. For convenience Vec
tors
also implement event::Sink
.
Both the event::Source
s and event::Sink
should only be created once and
reused in each call to [poll
]. After we created both we can start
polling the event::Source
s.
# use std::io;
# use std::time::Duration;
# use gaea::{poll, OsQueue, Queue};
# fn main() -> io::Result<()> {
# let mut os_queue = OsQueue::new()?;
# let mut queue = Queue::new();
# // Let poll return quickly.
# queue.add(gaea::Event::new(gaea::event::Id(0), gaea::Ready::READABLE));
# let mut events = Vec::new();
// Poll both `os_queue` and `queue` for readiness events, with a maximum
// timeout of 1 seconds. Here we use an `io::Error` as error, see `poll`
// docs for more information on handling errors from different event
// sources.
poll::<_, io::Error>(&mut [&mut os_queue, &mut queue], &mut events,
Some(Duration::from_secs(1)))?;
# Ok(())
# }
After the event::Source
s are polled our event::Sink
will be filled with
readiness events, if there are any. These can be used to continue
processing. Stick all the above in a loop and you've got yourself an event
loop, congratulations!
use std::io;
use std::time::Duration;
use gaea::{poll, OsQueue, Queue};
# fn main() -> std::io::Result<()> {
// Create our `event::Source`s.
let mut os_queue = OsQueue::new()?;
let mut queue = Queue::new();
# // Let poll return quickly.
# queue.add(gaea::Event::new(gaea::event::Id(0), gaea::Ready::READABLE));
// And our `event::Sink`.
let mut events = Vec::new();
// TODO: add events and such here...
// Our event loop.
loop {
// Poll for readiness events.
poll::<_, io::Error>(&mut [&mut os_queue, &mut queue], &mut events,
Some(Duration::from_secs(1)))?;
// And process each event.
for event in events.drain(..) {
println!("Got event: id={}, readiness={:?}", event.id(),
event.readiness());
}
# return Ok(());
}
# }
Examples
More complete examples of how to use the crate can be found in the examples directory of the source code (on GitHub).