erin 0.1.0

A very simple I/O reactor that allows creating green thread-like processes.
Documentation

mod error;
#[doc(inline)]
pub use error::Error;

mod runtime;
#[doc(inline)]
pub use runtime::{Events, IoToken, TimerToken, ProcessHandle, Runtime, RuntimeHandle};

mod timeouts;

pub use popol::{interest, Interest};


use std::io;
use std::sync::Arc;

/// A waker to wake up a process that was added to the [Runtime].
///
/// Can be safely cloned.
#[derive(Clone)]
pub struct Waker(Arc<popol::Waker>);

impl Waker {
	fn new<K: Eq + Clone>(sources: &mut popol::Sources<K>, key: K) -> Result<Waker, io::Error> {
		let w = popol::Waker::new(sources, key)?;
		Ok(Waker(Arc::new(w)))
	}

	/// Wake up the process this waker is associated with.
	pub fn wake(&self) {
		//TODO(stevenroose) is this fine?
		let _ = self.0.wake();
	}
}

pub struct Exit;

impl<E: std::error::Error> From<E> for Exit {
	fn from(_: E) -> Exit {
		Exit
	}
}

//TODO(stevenroose) support downstreaming the "Error" return somehow
/// A process that can be run in erin's [Runtime].
pub trait Process: Send + 'static {
	/// This function is called when an event happened that the process is interested in.
	/// Use the handle to register/deregister for new events.
	/// This method should return an error if the process should exit.
	fn wakeup(&mut self, handle: &RuntimeHandle, events: Events) -> Result<(), Exit>;

	/// Called when the process is added to the runtime.
	///
	/// Allows the process to register initial I/O sources and timers.
	/// This method should return an error if the process should exit.
	///
	/// The default implementation of this is empty.
	fn setup(&mut self, _handle: &RuntimeHandle) -> Result<(), Exit> { Ok(()) }

	/// Called on shutdown.
	///
	/// The process object will be dropped right after this call and can
	/// be left in a broken state.
	///
	/// Note that it is not required to deregister I/O sources, the runtime
	/// will do that automatically.
	///
	/// This method is not called when [wakeup] or [setup] return an error.
	///
	/// The default implementation of this is empty.
	// NB taking `self` here is impossible as it requires the Sized trait bound
	// and then this trait is no longer boxable. For some reason.
	fn shutdown(&mut self) {}
}