use crate::EventFlags;
use std::cell::RefCell;
use std::io;
use std::marker::PhantomData;
use std::os::unix::io::RawFd;
use std::ptr::NonNull;
use std::rc::Rc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::time::Duration;
#[derive(Debug)]
pub struct Fd;
#[derive(Debug)]
pub struct Interval;
#[derive(Debug)]
pub struct Oneshot;
impl Interval {
pub fn new(interval: Duration) -> Event<Inactive<Interval>> {
Inactive::new(None, EventFlags::PERSIST, Some(interval))
}
}
impl Oneshot {
pub fn new(timeout: Duration) -> Event<Inactive<Oneshot>> {
Inactive::new(None, EventFlags::empty(), Some(timeout))
}
}
#[derive(Debug)]
pub(crate) struct EventInner<T> {
inner: NonNull<libevent_sys::event>,
finalizer: libevent_sys::event_finalize_callback_fn,
_phantom: PhantomData<T>,
}
impl<T> EventInner<T> {
pub(crate) fn from_raw(
inner: NonNull<libevent_sys::event>,
finalizer: libevent_sys::event_finalize_callback_fn,
) -> Self {
EventInner {
inner,
finalizer,
_phantom: Default::default(),
}
}
pub(crate) unsafe fn as_raw(&self) -> NonNull<libevent_sys::event> {
self.inner
}
pub fn stop(&mut self) -> io::Result<()> {
if (unsafe { libevent_sys::event_del(self.inner.as_ptr()) }) == 0 {
Ok(())
} else {
Err(io::Error::new(io::ErrorKind::Other, "Failed to stop event"))
}
}
fn __drop_context(
event: NonNull<libevent_sys::event>,
finalizer: libevent_sys::event_finalize_callback_fn,
) {
let ptr = event.as_ptr();
let ctx = unsafe { libevent_sys::event_get_callback_arg(ptr) };
unsafe { (finalizer.unwrap())(event.as_ptr(), ctx) };
}
fn drop_context(&mut self) {
Self::__drop_context(self.inner, self.finalizer);
}
}
#[derive(Debug)]
#[doc(hidden)]
pub struct Inactive<T> {
fd: Option<RawFd>,
flags: EventFlags,
timeout: Option<Duration>,
_phantom: PhantomData<T>,
}
#[derive(Debug)]
#[doc(hidden)]
pub struct Internal<T>(pub(crate) EventInner<T>);
#[derive(Clone, Debug)]
#[doc(hidden)]
pub struct Local<T>(pub(crate) Rc<RefCell<EventInner<T>>>);
#[derive(Debug)]
#[doc(hidden)]
pub struct LocalWeak<T>(pub(crate) std::rc::Weak<RefCell<EventInner<T>>>);
#[derive(Debug)]
#[must_use = "if unused an active event could end by RAII"]
pub struct Event<S> {
pub(crate) inner: S,
pub(crate) in_callback: Arc<AtomicBool>,
pub(crate) stopped: Arc<AtomicBool>,
}
impl<S> Event<S> {
#![allow(dead_code)]
#[inline]
pub(crate) fn in_callback(&self) -> bool {
self.in_callback.load(Ordering::Relaxed)
}
#[inline]
pub(crate) fn stopped(&self) -> bool {
self.stopped.load(Ordering::Relaxed)
}
#[inline]
pub(crate) fn set_in_callback(&self, in_cb: bool) {
self.in_callback.store(in_cb, Ordering::Relaxed);
}
#[inline]
pub(crate) fn set_stopped(&self, stopped: bool) {
self.stopped.store(stopped, Ordering::Relaxed);
}
}
impl Event<Inactive<Fd>> {
pub fn new(fd: RawFd, flags: EventFlags, timeout: Option<Duration>) -> Self {
Inactive::new(Some(fd), flags, timeout)
}
pub(crate) fn __clone(&self) -> Self {
Inactive::new(
self.inactive_fd(),
self.inactive_flags(),
self.inactive_timeout(),
)
}
}
impl<T> Event<Inactive<T>> {
pub(crate) fn inactive_fd(&self) -> Option<RawFd> {
self.inner.fd.as_ref().copied()
}
pub(crate) fn inactive_flags(&self) -> EventFlags {
self.inner.flags
}
pub(crate) fn inactive_timeout(&self) -> Option<Duration> {
self.inner.timeout
}
}
impl<T> Inactive<T> {
fn new(fd: Option<RawFd>, flags: EventFlags, timeout: Option<Duration>) -> Event<Self> {
Event {
inner: Inactive {
fd,
flags,
timeout,
_phantom: Default::default(),
},
in_callback: Arc::new(AtomicBool::new(false)),
stopped: Arc::new(AtomicBool::new(false)),
}
}
}
impl<S: Clone> Clone for Event<S> {
fn clone(&self) -> Self {
Event {
inner: self.inner.clone(),
in_callback: self.in_callback.clone(),
stopped: self.stopped.clone(),
}
}
}
pub(crate) trait Downgrade {
type Weak;
fn downgrade(&self) -> Self::Weak;
}
impl<T> Downgrade for Local<T> {
type Weak = LocalWeak<T>;
fn downgrade(&self) -> Self::Weak {
LocalWeak(Rc::downgrade(&self.0))
}
}
impl<S: Downgrade> Downgrade for Event<S> {
type Weak = Event<S::Weak>;
fn downgrade(&self) -> Self::Weak {
Event {
inner: self.inner.downgrade(),
in_callback: self.in_callback.clone(),
stopped: self.stopped.clone(),
}
}
}
impl<T> From<EventInner<T>> for Event<Internal<T>> {
fn from(inner: EventInner<T>) -> Self {
Event {
inner: Internal(inner),
in_callback: Arc::new(AtomicBool::new(false)),
stopped: Arc::new(AtomicBool::new(false)),
}
}
}
impl<T> From<EventInner<T>> for Event<Local<T>> {
fn from(inner: EventInner<T>) -> Self {
Event {
inner: Local(Rc::new(RefCell::new(inner))),
in_callback: Arc::new(AtomicBool::new(false)),
stopped: Arc::new(AtomicBool::new(false)),
}
}
}
impl<T> Event<Internal<T>> {
fn with_inner<F, O>(&mut self, f: F) -> O
where
F: Fn(&mut EventInner<T>) -> O,
{
let ev = &mut self.inner.0;
f(ev)
}
pub fn stop(&mut self) -> io::Result<()> {
self.set_stopped(true);
self.with_inner(|inner| inner.stop())
}
}
impl<T> Event<Local<T>> {
fn with_inner<F, O>(&self, f: F) -> O
where
F: Fn(&mut EventInner<T>) -> O,
{
let mut ev = self.inner.0.borrow_mut();
f(&mut *ev)
}
pub fn stop(&mut self) -> io::Result<()> {
self.set_stopped(true);
self.with_inner(|inner| inner.stop())
}
}
impl<T> Event<LocalWeak<T>> {
fn with_inner<F, O>(&self, f: F) -> O
where
F: Fn(&mut EventInner<T>) -> O,
{
let upgraded = self.inner.0.upgrade().unwrap();
let mut ev = upgraded.borrow_mut();
f(&mut *ev)
}
pub fn stop(&mut self) -> io::Result<()> {
self.set_stopped(true);
self.with_inner(|inner| inner.stop())
}
}
impl<T> Drop for EventInner<T> {
fn drop(&mut self) {
self.drop_context();
let raw = unsafe { self.as_raw() };
unsafe { libevent_sys::event_free(raw.as_ptr()) };
}
}
pub trait Exec<S, F> {
fn exec(ev: &mut Event<S>, fd: RawFd, flags: EventFlags, cb: &mut F);
}
impl<S, F: FnMut(&mut Event<S>, RawFd, EventFlags)> Exec<S, F> for Fd {
fn exec(ev: &mut Event<S>, fd: RawFd, flags: EventFlags, cb: &mut F) {
cb(ev, fd, flags)
}
}
impl<S, F: FnMut(&mut Event<S>)> Exec<S, F> for Interval {
fn exec(ev: &mut Event<S>, _fd: RawFd, _flags: EventFlags, cb: &mut F) {
cb(ev)
}
}
impl<S, F: FnMut(&mut Event<S>)> Exec<S, F> for Oneshot {
fn exec(ev: &mut Event<S>, _fd: RawFd, _flags: EventFlags, cb: &mut F) {
cb(ev)
}
}