# Pendulum [![Build Status](https://travis-ci.org/GGist/pendulum-rs.svg?branch=master)](https://travis-ci.org/GGist/pendulum-rs) [![Build status](https://ci.appveyor.com/api/projects/status/y9udu8r9r4lae291/branch/master?svg=true)](https://ci.appveyor.com/project/GGist/pendulum-rs/branch/master) [![Documentation](https://docs.rs/pendulum/badge.svg)](https://docs.rs/pendulum) [![Crates.io](https://img.shields.io/crates/v/pendulum.svg)](https://crates.io/crates/pendulum) Data structures and runtimes for efficient timer management. ## Usage ```Cargo.toml```: ``` [dependencies] pendulum = "0.3" ``` ```lib.rs/main.rs```: ``` extern crate pendulum; ``` ## Examples Usage of the futures base `Timer` runtime: ```rust extern crate pendulum; extern crate futures; use std::time::Duration; use futures::Stream; use futures::sync::mpsc; use pendulum::HashedWheelBuilder; use pendulum::future::{TimerBuilder, TimedOut}; #[derive(Debug, PartialEq, Eq)] enum PeerMessage { KeepAlive, DoSomething } impl From for PeerMessage { fn from(_: TimedOut) -> PeerMessage { PeerMessage::KeepAlive } } fn main() { // Create a timer with the default configuration let timer = TimerBuilder::default() .build(HashedWheelBuilder::default().build()); // Assume some other part of the application sends messages to some peer let (send, recv) = mpsc::unbounded(); // Application sent the peer a single message send.unbounded_send(PeerMessage::DoSomething) .unwrap(); // Wrap the receiver portion (a `Stream`), in a `Heartbeat` stream let mut heartbeat = timer.heartbeat(Duration::from_millis(100), recv) .unwrap() .wait(); // Should receive the applications message assert_eq!(PeerMessage::DoSomething, heartbeat.next().unwrap().unwrap()); // Application only sent one message, timer will continuously send keep alives // if 100 ms goes by without the original receiver receiving any messages assert_eq!(PeerMessage::KeepAlive, heartbeat.next().unwrap().unwrap()); assert_eq!(PeerMessage::KeepAlive, heartbeat.next().unwrap().unwrap()); } ``` Usage of the `Pendulum` data structure: ```rust extern crate pendulum; use std::time::Duration; use std::thread; use pendulum::{Pendulum, HashedWheelBuilder}; #[derive(Debug, PartialEq, Eq)] struct SomeData(usize); fn main() { // Create a pendulum with mostly default configration let mut wheel = HashedWheelBuilder::default() // Tick duration defines the resolution for our timer (all timeouts will be a multiple of this) .with_tick_duration(Duration::from_millis(100)) .build(); // Insert a timeout and store the token, we can use this to cancel the timeout let token = wheel.insert_timeout(Duration::from_millis(50), SomeData(5)).unwrap(); // Tick our wheel after the given duration (100 ms) thread::sleep(wheel.tick_duration()); // Tell the wheel that it can perform a tick wheel.tick(); // Retrieve any expired timeouts while let Some(timeout) = wheel.expired_timeout() { assert_eq!(SomeData(5), timeout); } // If we tried to remove the timeout using the token, we get None (already expired) assert_eq!(None, wheel.remove_timeout(token)); } ``` ## References * tokio-timer: https://github.com/tokio-rs/tokio-timer ## License Licensed under either of * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. ## Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.