#时钟 #模拟 #实时时钟 #时间 #经过时间

pausable_clock

一个可暂停和继续的时间信息源

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

MIT/Apache

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