diff --git a/util/io/src/service.rs b/util/io/src/service.rs index a47e84e56..c75efbdb6 100644 --- a/util/io/src/service.rs +++ b/util/io/src/service.rs @@ -53,6 +53,7 @@ pub enum IoMessage where Message: Send + Clone + Sized { handler_id: HandlerId, token: TimerToken, delay: u64, + once: bool, }, RemoveTimer { handler_id: HandlerId, @@ -89,12 +90,24 @@ impl IoContext where Message: Send + Clone + 'static { } } - /// Register a new IO timer. 'IoHandler::timeout' will be called with the token. + /// Register a new recurring IO timer. 'IoHandler::timeout' will be called with the token. pub fn register_timer(&self, token: TimerToken, ms: u64) -> Result<(), IoError> { try!(self.channel.send_io(IoMessage::AddTimer { token: token, delay: ms, handler_id: self.handler, + once: false, + })); + Ok(()) + } + + /// Register a new IO timer once. 'IoHandler::timeout' will be called with the token. + pub fn register_timer_once(&self, token: TimerToken, ms: u64) -> Result<(), IoError> { + try!(self.channel.send_io(IoMessage::AddTimer { + token: token, + delay: ms, + handler_id: self.handler, + once: true, })); Ok(()) } @@ -160,6 +173,7 @@ impl IoContext where Message: Send + Clone + 'static { struct UserTimer { delay: u64, timeout: Timeout, + once: bool, } /// Root IO handler. Manages user handlers, messages and IO timers. @@ -228,8 +242,14 @@ impl Handler for IoManager where Message: Send + Clone + Sync let handler_index = token.as_usize() / TOKENS_PER_HANDLER; let token_id = token.as_usize() % TOKENS_PER_HANDLER; if let Some(handler) = self.handlers.get(handler_index) { - if let Some(timer) = self.timers.read().get(&token.as_usize()) { - event_loop.timeout_ms(token, timer.delay).expect("Error re-registering user timer"); + let option = self.timers.read().get(&token.as_usize()).cloned(); + if let Some(timer) = option { + if timer.once { + self.timers.write().remove(&token_id); + event_loop.clear_timeout(timer.timeout); + } else { + event_loop.timeout_ms(token, timer.delay).expect("Error re-registering user timer"); + } self.worker_channel.push(Work { work_type: WorkType::Timeout, token: token_id, handler: handler.clone(), handler_id: handler_index }); self.work_ready.notify_all(); } @@ -257,10 +277,10 @@ impl Handler for IoManager where Message: Send + Clone + Sync event_loop.clear_timeout(timer.timeout); } }, - IoMessage::AddTimer { handler_id, token, delay } => { + IoMessage::AddTimer { handler_id, token, delay, once } => { let timer_id = token + handler_id * TOKENS_PER_HANDLER; let timeout = event_loop.timeout_ms(Token(timer_id), delay).expect("Error registering user timer"); - self.timers.write().insert(timer_id, UserTimer { delay: delay, timeout: timeout }); + self.timers.write().insert(timer_id, UserTimer { delay: delay, timeout: timeout, once: once }); }, IoMessage::RemoveTimer { handler_id, token } => { let timer_id = token + handler_id * TOKENS_PER_HANDLER;