7 个版本 (2 个稳定版)
1.0.1 | 2021 年 6 月 23 日 |
---|---|
1.0.0 | 2021 年 6 月 22 日 |
0.3.2 | 2020 年 9 月 29 日 |
0.2.0 | 2020 年 8 月 24 日 |
0.1.0 | 2020 年 8 月 11 日 |
#272 in 并发
每月 40 次下载
用于 3 crates
58KB
1K SLoC
可暂停时钟
本 crate 提供了一个可以暂停的时钟,你可以以尊重时钟的原子状态和历史的方式获取当前时间。简单来说,可暂停时钟的经过时间与实际时间同步增加,但仅在时钟恢复时。
特性
- 线程安全:(
Send
/Sync
) 时钟上的所有操作都是原子的或使用 std 池 - 恢复通知:当时钟暂停时,
wait_for_resume
方法将阻塞,直到时钟恢复 - 保证:就像
std::time::Instant::now()
保证时间总是增加一样,PausableClock
保证在时钟暂停时返回的时间 >= 时钟暂停之前返回的任何其他瞬间。 - 不可暂停的任务:我们提供了一个名为
run_unpausable
的方法,允许运行防止计时器在它们运行时暂停的任务。
示例
use pausable_clock::PausableClock;
use std::sync::Arc;
use std::thread;
use std::time::{Duration, Instant};
let clock = Arc::new(PausableClock::default());
// With the default parameters, there should be no difference
// between the real time and the clock's time
assert!(Instant::from(clock.now()).elapsed().as_millis() == 0);
// Pause the clock right after creation
clock.pause();
// Clone the arc of the clock to pass to a new thread
let clock_clone = clock.clone();
let t = thread::spawn(move || {
// In the new thread, just wait for resume
clock_clone.wait_for_resume();
});
// Sleep for a sec, then resume the clock
thread::sleep(Duration::from_secs(1));
clock.resume();
// Wait for the spawned thread to unblock
t.join().unwrap();
// After being paused for a second, the clock is now a second behind
// (with a small error margin here because sleep is not super accurate)
assert!((Instant::from(clock.now()).elapsed().as_secs_f64() - 1.).abs() < 0.005);
注意事项
- 我们使用一个
AtomicU64
来包含可暂停时钟的全部状态,因此时钟产生的瞬间的粒度是毫秒。这意味着计时器可以处理的时间约为数百万年。 - 对于
PausableClock::is_paused
的暂停状态读取是通过Ordering::Relaxed
原子完成的。这使得调用稍微更快,但它意味着你不应该将其视为栅栏操作。如果你需要这种保证,可以使用PausableClock::is_paused_ordered
。 - 这个库中存在大量弱顺序原子操作,以确保调用now和不可暂停的任务不需要任何锁。我不能保证它是可以证明正确的,但它在x86_64处理器上已经经过了高度确定的测试。弱顺序系统的测试正在进行中,以及基于
loom
的测试。
依赖关系
~0–26MB
~330K SLoC