#timer #sleep #thread #deadlines #events #periodic #sync

minuteurs

一个用于在周期性事件上同步线程的小型库

3 个版本 (稳定版)

1.0.1 2023年6月30日
1.0.0 2023年4月27日
0.1.0 2023年4月9日

#4 in #deadlines


employees 使用

MIT 许可证

28KB
397

minuteurs

一个非常轻量级的库,以尽可能细粒度的方式为用户提供对线程执行时间控制,成本最低。

截止时间

Deadline 允许用户阻塞线程执行,直到从截止时间创建以来经过一定时间,除非截止时间已过期。

它有两种形式

  • Deadline::once() 返回一个只能触发一次的 Deadline,这意味着一旦此类截止时间过期,它就再也不能阻塞了。
  • Deadline::repeat() 返回一个可以多次触发的 Deadline。在这种情况下,如果两次 Deadline::wait() 调用之间经过的时间过长,它会尝试赶上。

示例

基本示例

use std::time::{Duration, Instant};
use minuteurs::Deadline;

// Create a new deadline of 1 second.
let mut deadline = Deadline::once(Duration::from_secs(1));
let mut now = Instant::now();

// This sleep represents some heavy computation.
std::thread::sleep(Duration::from_millis(750));

// Blocks the thread if less than 1 second have passed since the deadline's creation.
deadline.wait();

// Until this point, at least 1 second have passed no matter what happened
// between the creation and the wait.
let elapsed = now.elapsed();
assert!(elapsed > Duration::from_secs(1));
println!("elapsed: {elapsed:?}");

可能的输出

elapsed: 1.00010838s

使用截止时间来同步多个线程

use std::time::{Duration, Instant};
use minuteurs::Deadline;

// Create a repeatable deadline of 1 second.
let mut deadline = Deadline::repeat(Duration::from_secs(1));
let now = Instant::now();

// Spawn two threads with the same deadline.
// They should prints approximatively every 1s.
let thread1 = std::thread::spawn(move || {
    for _ in 0..5 {
        deadline.wait();
        let elapsed = now.elapsed();
        println!("thread1 ticked at {elapsed:?}",)
    }
});
let thread2 = std::thread::spawn(move || {
    for _ in 0..5 {
        deadline.wait();
        let elapsed = now.elapsed();
        println!("thread2 ticked at {elapsed:?}",)
    }
});

// Obligatory clean up.
let _ = thread1.join();
let _ = thread2.join();

可能的输出

thread2 ticked at 1.000112249s
thread1 ticked at 1.000112289s
thread2 ticked at 2.000107337s
thread1 ticked at 2.0001086s
thread2 ticked at 3.000101815s
thread1 ticked at 3.000641802s
thread1 ticked at 4.000100891s
thread2 ticked at 4.000100911s
thread2 ticked at 5.000106159s
thread1 ticked at 5.000112471s

计时器

Timer 与可重复的 Deadline 不同,因为计时器专门用于在周期性事件上同步多个线程,更精确且优化更好。

通常,计时器在自己的线程中以循环方式运行,而监视器则在另一个线程中传递。计时器周期性地滴答作响,并通知一个或多个监视器。

示例

use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::time::{Duration, Instant};
use minuteurs::Timer;

// Create a timer that ticks every seconds and get a watcher from it.
let mut timer = Timer::new(Duration::from_secs(1));
let mut watcher1 = timer.watcher();

// Watchers are clonable and cloned ones are associated to the orignal watcher's timer.
// The timer will then notify the watcher2 as well.
let mut watcher2 = watcher1.clone();

let now = Instant::now();
let stop = Arc::new(AtomicBool::default());

// Spawn two threads.
// They should prints approximatively every 1s.
let stop_clone = Arc::clone(&stop);
let thread1 = std::thread::spawn(move || {
    while !stop_clone.load(Ordering::SeqCst) {
        if watcher1.has_ticked() {
            let elapsed = now.elapsed();
            println!("thread1 ticked at {elapsed:?}",)
        }
    }
});

let stop_clone = Arc::clone(&stop);
let thread2 = std::thread::spawn(move || {
    while !stop_clone.load(Ordering::SeqCst) {
        if watcher2.has_ticked() {
            let elapsed = now.elapsed();
            println!("thread2 ticked at {elapsed:?}",)
        }
    }
});

for _ in 0..5 {
    timer.tick();
}

stop.store(true, Ordering::SeqCst);

// Obligatory clean up.
let _ = thread1.join();
let _ = thread2.join();

可能的输出

thread1 ticked at 1.00087579s
thread2 ticked at 1.000878295s
thread1 ticked at 2.000870603s
thread2 ticked at 2.000873087s
thread2 ticked at 3.000875413s
thread1 ticked at 3.000876254s
thread2 ticked at 4.000874293s
thread1 ticked at 4.000875034s
thread2 ticked at 5.000874695s
thread1 ticked at 5.000875316s

许可证

根据 MIT 许可证条款许可。有关详细信息,请参阅 LICENSE

无运行时依赖