3 个不稳定版本

0.2.1 2024 年 6 月 3 日
0.2.0 2024 年 5 月 15 日
0.1.0 2023 年 7 月 16 日

异步 中排名 #65

Download history 4239/week @ 2024-05-02 4322/week @ 2024-05-09 4141/week @ 2024-05-16 2852/week @ 2024-05-23 4715/week @ 2024-05-30 5259/week @ 2024-06-06 3544/week @ 2024-06-13 3526/week @ 2024-06-20 3950/week @ 2024-06-27 4918/week @ 2024-07-04 6672/week @ 2024-07-11 6199/week @ 2024-07-18 5745/week @ 2024-07-25 5226/week @ 2024-08-01 6567/week @ 2024-08-08 4564/week @ 2024-08-15

每月下载量 23,201
22 个crate中使用(直接使用 9 个)

MIT/Apache 许可

64KB
874

async-event

高效的异步条件变量,用于无锁算法,也称为 "eventcount"。

Cargo Documentation License

概述

Eventcount 类型的原语对于将某些操作应用于无锁结构非常有用,例如将有限队列转换为有限通道。这种原语允许感兴趣的任务在每次收到通知时检查谓词,直到谓词被满足为止而阻塞。

虽然功能上类似于 event_listener crate,但此实现更具有意见性,并且仅限于 async 情况。然而,它通过限制对互斥保护的通知列表的锁定操作的数量来提高效率:通常只锁定一次,每次等待者被阻塞和通知时,从而减少了同步操作的需求。最后,只有在不常见的情况下才会生成虚假唤醒。

请注意,如果您只需要向单个任务发送通知,则可以使用 Diatomic Waker crate 以获得更好的性能。

这个库是 Asynchronix 的一个分支,Asynchronix 是一个用于系统模拟的高性能异步计算框架的持续努力。它也用于 Tachyonix MPSC 通道。

使用方法

将以下内容添加到您的 Cargo.toml

[dependencies]
async-event = "0.2.1"

event_listener 的区别

Event 原语在一般情况下预计比 event_listener crate 更快。然而,具体效果可能会根据您的特定应用程序而有所不同,因此您可能需要对两者进行基准测试。

API 更具有意见性,并且设计用于防止潜在的误用,例如

  • 在请求通知后忘记再次检查谓词,即在对 Event::listen() 进行调用后,在 event_listener 包中async-event 提供了 Event::wait_until 方法,该方法会在必要时检查谓词,以防止竞态条件。
  • event_listener 包中,notifynotify_additional 之间的混淆。我们的经验和其他类似库的 API 表明,后者几乎总是用户所需要的,因此此包中 notify* 方法的行为实际上类似于 notify_additional
  • 谓词的原子同步不足notify*wait_until 方法始终插入原子栅栏以确保适当的同步:没有与 notify_additional_relaxed 相当的等效项。

示例

异步发送非零值

use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use std::thread;

use futures_executor::block_on;

use async_event::Event;

let value = Arc::new(AtomicUsize::new(0));
let event = Arc::new(Event::new());

// Set a non-zero value concurrently.
thread::spawn({
    let value = value.clone();
    let event = event.clone();

    move || {
        // A relaxed store is sufficient here: `Event::notify*` methods insert
        // atomic fences to warrant adequate synchronization.
        value.store(42, Ordering::Relaxed);
        event.notify_one();
    }
});

// Wait until the value is set.
block_on(async move {
    let v = event
        .wait_until(|| {
            // A relaxed load is sufficient here: `Event::wait_until` inserts
            // atomic fences to warrant adequate synchronization.
            let v = value.load(Ordering::Relaxed);
            if v != 0 { Some(v) } else { None }
        })
        .await;

     assert_eq!(v, 42);
});

非零值的单槽 MPMC 通道

请参阅 示例实现,位于 examples 目录中。

安全性

这是一个低级原语,因此其实现依赖于 unsafe。测试套件广泛使用了 Loom 和 MIRI 来评估其正确性。然而,尽管它们很神奇,但 Loom 和 MIRI 不能正式证明数据竞争的不存在,因此可能会出现可靠性问题。

许可证

此软件根据您的选择,许可在 Apache License, Version 2.0MIT 许可证 下。

贡献

除非您明确声明,否则根据 Apache-2.0 许可证定义,您提交的任何有意提交以包含在作品中的贡献,都将按上述方式双许可,而不附加任何额外条款或条件。

依赖项

~0–27MB
~330K SLoC