File: README.md

package info (click to toggle)
rust-io-timer 0.0.1%2Bds-3
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 296 kB
  • sloc: makefile: 2; sh: 1
file content (160 lines) | stat: -rw-r--r-- 4,704 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# I/O Timer

Set of **I/O-free** Rust coroutines to manage timers, based on [io-stream](https://github.com/pimalaya/io-stream).

This library allows you to manage timers using an I/O-agnostic approach, based on 3 concepts:

### Coroutine

A coroutine is an *I/O-free*, *resumable* and *composable* state machine that **emits I/O requests**. A coroutine is considered *terminated* when it does not emit I/O requests anymore.

*See available coroutines at [./src](https://github.com/pimalaya/io-timer/tree/master/src).*

### Runtime

A runtime contains all the I/O logic, and is responsible for **processing I/O requests** emitted by coroutines.

*See available runtimes at [pimalaya/io-stream](https://github.com/pimalaya/io-stream/tree/master/src/runtimes).*

### Loop

The loop is the glue between coroutines and runtimes. It makes the coroutine progress while allowing runtime to process I/O.

## Examples

### Standard blocking client using TCP

```rust,ignore
use std::net::TcpStream;

use io_stream::runtimes::std::handle;
use io_timer::client::coroutines::{GetTimer, StartTimer};

let mut stream = TcpStream::connect("localhost:1234").unwrap();

// start the timer

let mut arg = None;
let mut start = StartTimer::new();

while let Err(io) = start.resume(arg.take()) {
    arg = Some(handle(&mut stream, io).unwrap());
}

// wait few seconds, then get the timer

let mut arg = None;
let mut get = GetTimer::new();

let timer = loop {
    match get.resume(arg.take()) {
        Ok(timer) => break timer,
        Err(io) => arg = Some(handle(&mut stream, io).unwrap()),
    }
};
```

*See complete example at [./examples/std-tcp.rs](https://github.com/pimalaya/io-timer/blob/master/examples/std-tcp.rs).*


### Tokio async server using Unix sockets

```rust,ignore
use std::{sync::Arc, time::Duration};

use io_stream::runtimes::tokio::handle;
use io_timer::{
    server::coroutines::HandleRequest,
    timer::{TimerConfig, TimerCycles, TimerLoop},
    Timer,
};

let config = TimerConfig {
    cycles: TimerCycles::from([("Work", 2).into(), ("Rest", 3).into()]),
    cycles_count: TimerLoop::Infinite,
};

let timer = Arc::new(tokio::sync::Mutex::new(Timer::new(config)));

// use an unbounded channel for receiving timer events
let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel();

// start the timer event notifier
tokio::spawn(async move {
    loop {
        let _event = rx.recv().await.unwrap();
        // do whatever with the event
    }
});

// define and spawn the timer tick
// this is needed to update the internal state of the timer
tokio::spawn({
    let timer = timer.clone();
    let tx = tx.clone();

    async move {
        loop {
            let mut timer = timer.lock().await;
            let events = timer.update();
            drop(timer);

            for event in events {
                tx.send(event).unwrap();
            }

            // the timer can be refreshed every seconds
            tokio::time::sleep(Duration::from_secs(1)).await;
        }
    }
});

// listen to the unix socket for client <-> server communication
let listener = tokio::net::UnixListener::bind("/tmp/timer.sock").unwrap();
let (mut stream, _) = listener.accept().await.unwrap();

loop {
    let mut arg = None;
    let mut handler = HandleRequest::new();

    let events = loop {
        let mut timer = timer.lock().await;
        let output = handler.resume(&mut timer, arg.take());
        drop(timer);

        match output {
            Ok(events) => break events,
            Err(io) => arg = Some(handle(&mut stream, io).await.unwrap()),
        }
    };

    for event in events {
        tx.send(event).unwrap();
    }
}
```

*See complete example at [./examples/tokio-unix.rs](https://github.com/pimalaya/io-timer/blob/master/examples/tokio-unix.rs).*

### More examples

See projects built at the top of this library:

- [comodoro](https://github.com/pimalaya/comodoro): CLI to manage timers

## Sponsoring

Special thanks to the [NLnet foundation](https://nlnet.nl/) and the [European Commission](https://www.ngi.eu/) that helped the project to receive financial support from various programs:

- [NGI Assure](https://nlnet.nl/project/Himalaya/) in 2022
- [NGI Zero Entrust](https://nlnet.nl/project/Pimalaya/) in 2023
- [NGI Zero Core](https://nlnet.nl/project/Pimalaya-PIM/) in 2024 *(still ongoing)*

If you appreciate the project, feel free to donate using one of the following providers:

- [GitHub](https://github.com/sponsors/soywod)
- [Ko-fi](https://ko-fi.com/soywod)
- [Buy Me a Coffee](https://www.buymeacoffee.com/soywod)
- [Liberapay](https://liberapay.com/soywod)
- [thanks.dev](https://thanks.dev/soywod)
- [PayPal](https://www.paypal.com/paypalme/soywod)