diff --git a/src/lib.rs b/src/lib.rs index d4c592ecc..ae6f3d9cb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -65,3 +65,4 @@ pub mod server; pub mod service; pub mod ssl; pub mod stream; +pub mod lowrestimer; diff --git a/src/lowrestimer.rs b/src/lowrestimer.rs new file mode 100644 index 000000000..320871657 --- /dev/null +++ b/src/lowrestimer.rs @@ -0,0 +1,98 @@ +use std::cell::RefCell; +use std::rc::Rc; +use std::time::{Duration, Instant}; + +use futures::{Future, Poll, Async}; +use futures::future::{ok, FutureResult}; +use tokio_current_thread::spawn; +use tokio_timer::sleep; + +use super::service::{Service, NewService}; + +#[derive(Clone, Debug)] +pub struct LowResTimer(Rc>); + +#[derive(Debug)] +struct Inner { + interval: Duration, + current: Option, +} + +impl Inner { + fn new(interval: Duration) -> Self { + Inner { + interval, + current: None + } + } +} + +impl LowResTimer { + pub fn with_interval(interval: Duration) -> LowResTimer { + LowResTimer(Rc::new(RefCell::new(Inner::new(interval)))) + } +} + +impl Default for LowResTimer { + fn default() -> Self { + LowResTimer(Rc::new(RefCell::new(Inner::new(Duration::from_secs(1))))) + } +} + +impl NewService for LowResTimer { + type Request = (); + type Response = Instant; + type Error = (); + type InitError = (); + type Service = LowResTimerService; + type Future = FutureResult; + + fn new_service(&self) -> Self::Future { + ok(LowResTimerService(self.0.clone())) + } +} + + +#[derive(Clone, Debug)] +pub struct LowResTimerService(Rc>); + +impl LowResTimerService { + pub fn with_interval(interval: Duration) -> LowResTimerService { + LowResTimerService(Rc::new(RefCell::new(Inner::new(interval)))) + } +} + +impl Service for LowResTimerService { + type Request = (); + type Response = Instant; + type Error = (); + type Future = FutureResult; + + fn poll_ready(&mut self) -> Poll<(), Self::Error> { + Ok(Async::Ready(())) + } + + fn call(&mut self, _: ()) -> Self::Future { + let cur = self.0.borrow().current.clone(); + if let Some(cur) = cur { + ok(cur) + } else { + let now = Instant::now(); + let inner = self.0.clone(); + let interval = { + let mut b = inner.borrow_mut(); + b.current = Some(now); + b.interval + }; + + spawn( + sleep(interval) + .map_err(|_| panic!()) + .and_then(move|_| { + inner.borrow_mut().current.take(); + Ok(()) + })); + ok(now) + } + } +}