roundabout 0.2.0

An message oriented concurrent runtime
Documentation
use roundabout::prelude::*;
use std::time::Instant;

pub struct InitEvent;
pub struct PingEvent(u64);
pub struct PongEvent(u64);

const INIT_N: usize = 3;

pub struct PingState {
    start: Instant,
    count: u64,
}

fn ping_handler(
    builder: OpenMessageHandlerBuilder<PingState>,
    start: Instant,
) -> InitMessageHandlerBuilder<PingState> {
    builder
        .on::<InitEvent>(|_state, context, _init| {
            println!("init ping");
            for _ in 0..INIT_N {
                context.sender().send(PingEvent(1));
            }
        })
        .on::<PingEvent>(|state, context, ping| {
            state.count += ping.0;
            if state.count % 10000 == 0 {
                let elapsed = state.start.elapsed();
                println!(
                    "Ping: {} @ {:.2}/s, ",
                    state.count,
                    state.count as f64 / elapsed.as_secs_f64()
                );
            }

            context.sender().send(PongEvent(1));
        })
        .init(PingState { start, count: 0 })
}

pub struct PongState {
    start: Instant,
    count: u64,
}

fn pong_handler(
    builder: OpenMessageHandlerBuilder<PongState>,
    start: Instant,
) -> InitMessageHandlerBuilder<PongState> {
    builder
        .on::<InitEvent>(|_state, context, _init| {
            println!("init pong");
            for _ in 0..INIT_N {
                context.sender().send(PongEvent(1));
            }
        })
        .on::<PongEvent>(|state, context, pong| {
            state.count += pong.0;
            if state.count % 10000 == 0 {
                let elapsed = state.start.elapsed();
                println!(
                    "Pong: {} @ {:.2}/s, ",
                    state.count,
                    state.count as f64 / elapsed.as_secs_f64()
                );
            }

            context.sender().send(PingEvent(1));
        })
        .init(PongState { start, count: 0 })
}

fn main() {
    let start = Instant::now();
    let runtime = Runtime::builder(128)
        .add_group(|mut group| {
            let ping_builder = group.register(|b| ping_handler(b, start));
            let pong_builder = group.register(|b| pong_handler(b, start));

            group.init(move |recv, mut context| {
                let mut ping = ping_builder.finish(&context).unwrap();
                let mut pong = pong_builder.finish(&context).unwrap();

                recv.stream(move |message| {
                    ping.handle(&mut context, message);
                    pong.handle(&mut context, message);
                });
            })
        })
        .finish();

    let mut shutdown_switch = runtime.get_shutdown_switch();
    ctrlc::set_handler(move || {
        shutdown_switch.request_shutdown();
    })
    .expect("Error setting Ctrl-C handler");

    runtime.start(InitEvent);
}