#timer #timeout #runtimes #wheel #future #hashed #base

pendulum

Hashed timer wheel with various runtimes

5 unstable releases

Uses old Rust 2015

0.3.1 Nov 29, 2017
0.3.0 Nov 13, 2017
0.2.1 Nov 11, 2017
0.2.0 Nov 10, 2017
0.1.0 Nov 10, 2017

#5 in #hashed

MIT/Apache

67KB
972 lines

Pendulum

Build Status Build status Documentation Crates.io

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:

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<TimedOut> 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:

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

License

Licensed under either of

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.

Dependencies

~225KB