5 个版本 (2 个稳定版)
1.0.1 | 2024年2月20日 |
---|---|
1.0.0 | 2022年11月3日 |
0.2.2 | 2022年3月27日 |
0.2.1 | 2022年3月27日 |
0.1.0 | 2021年7月5日 |
#42 在 并发
36,460 每月下载量
用于 7 个 Crates (2 个直接使用)
68KB
1K SLoC
async-condvar-fair
异步 Rust 的条件变量。特性
-
公平的。
notify_one
总是唤醒等待时间最长的等待者。 -
新颖的
Baton
功能,帮助避免异步任务取消时可能出现的通知丢失。 -
适用于任何异步运行时。
-
可以与任何类型的互斥锁(同步或异步)一起工作。
-
100% 安全的代码。 (内部使用
parking_lot
和dlv-list
。) -
可以处理多个不同互斥锁与多个不同条件变量的交互,如果您喜欢这种类型的话。
主入口点
此库的主入口点是 Condvar
。请参阅其文档以了解构造函数和方法详情。
示例
// async-condvar-fair = { version = "0.2", features = "parking_lot_0_12" }
// parking_lot = { version = "0.12", features = ["send_guard"] }
# #[cfg(feature = "parking_lot_0_12")] mod demo {
use std::collections::VecDeque;
use async_condvar_fair::{Condvar, BatonExt};
use parking_lot::Mutex;
struct Shared {
cv: Condvar,
queue: Mutex<VecDeque<String>>,
}
impl Shared {
pub async fn procssor(&self) {
let mut guard = self.queue.lock();
let mut baton = None;
loop {
while let Some(entry) = guard.pop_front() {
println!("processing {:?}", &entry);
}
baton.dispose();
let got = self.cv.wait_baton(guard).await;
guard = got.0;
baton = got.1;
}
}
}
# }
互斥锁 - 选择互斥锁,同步与异步
请注意,可以拥有异步条件变量,但使用同步互斥锁来保护共享状态。如果持有互斥锁期间的操作很快(特别是不执行 I/O),这通常是最佳选择。
parking_lot::Mutex
是此类同步互斥锁的一个好选择,并且由 async-condvar-fair
方便地支持。您可能需要启用 parking_lot
的 send_guard
功能。
如果您使用同步互斥锁,您可能不打算在持有互斥锁时等待,因此您可能可以使用普通的 wait
(而不是 wait_baton
)。
如果在持有互斥锁期间进行的操作很慢,您应该使用异步运行时提供的异步互斥锁。在这种情况下,如果您使用notify_one
,您应该考虑使用wait_baton
以避免任务取消导致丢失通知:请参阅Baton
。
互斥锁保护,线程间Send
传输
在多线程异步运行时中,任务可以在线程之间移动。这意味着互斥锁保护需要是Send
。多线程异步运行时提供的异步互斥锁保护都是Send
。同步互斥锁保护通常不是。
例如,std::sync::MutexGuard
,它只能与非多线程运行时的Condvar
一起使用,因为具有这种保护器的局部变量的futures将不会是Send
。相反,使用启用了send_guard
的parking_lot
。
互斥锁 - 如何将互斥锁传递给wait_baton等
Condvar::wait_baton
和wait
原则上可以与任何互斥锁一起工作。但它们需要知道如何重新锁定互斥锁。
对于最方便的互斥锁,如parking_lot::Mutex
,您可以只需将保护器传递给wait
。当唤醒时,Condvar
将使用保护器来解锁互斥锁,然后再次重新锁定它。
但对于许多互斥锁,这是不可能的,因为保护器类型不提供获取解锁互斥锁引用的方式。例如,这是std::sync::Mutex
的情况。
对于这些不便的互斥锁,您可以传递一个元组给wait_baton
或wait
,或者使用wait_no_relock
并自行重新锁定互斥锁。
内置互斥锁支持以及async-condvar-fair
软件包功能
功能 | 互斥锁类型 | 传递给wait / wait_baton |
---|---|---|
始终启用 | std::sync::Mutex |
(MutexGuard, &Mutex) [2] |
parking_lot_N |
parking_lot::Mutex |
MutexGuard [1] |
parking_lot_N |
parking_lot::FairMutex |
FairMutexGuard [1] |
tokio |
tokio::sync::Mutex |
(MutexGuard, &Mutex) |
tokio |
Arc < tokio::sync::Mutex > |
(OwnedMutexGuard, Arc<Mutex>) |
tokio |
tokio::sync::RwLock |
(RwLockReadGuard, &Mutex) |
tokio |
tokio::sync::RwLock |
(RwLockWriteGuard, &Mutex) |
tokio |
Arc < tokio::sync::RwLock > |
(OwnedRwLockReadGuard, Arc<RwLock>) |
tokio |
Arc < tokio::sync::RwLock > |
(OwnedRwLockWriteGuard, Arc<RwLock>) |
smol |
smol::lock::Mutex |
MutexGuard |
smol |
smol::lock::RwLock |
(RwLockReadGuard, &RwLock) |
smol |
smol::lock::RwLock |
(RwLockWriteGuard, &RwLock) |
smol |
Arc < smol::lock::Mutex > |
MutexGuardArc |
注意:以下所有功能默认均未启用,因为每个功能都意味着对相应crate的依赖。
- 启用与您使用的
parking_lot
版本对应的parking_lot_N
功能(在您的Cargo.toml
中指定)。为使用多线程运行时启用parking_lot
的send_guard
功能。 - 仅限单线程运行时。
与其他互斥锁一起使用
上述支持都是通过提供的 RelockMutexGuard
trait 的实现实现的。
如果您想使用在 async-condvar-wait
中没有内置支持的互斥锁类型,请使用 RelockMutexGuard!
宏来定义合适的实现,手动定义该实现,或使用 wait_no_relock
并自行重新锁定互斥锁。
传递守卫和互斥锁元组的示例
# fn main() {
# #[cfg(feature = "parking_lot_0_12")] {
# use std::collections::VecDeque;
# use async_condvar_fair::{Condvar, BatonExt};
use std::sync::Mutex;
struct Shared {
cv: Condvar,
queue: Mutex<VecDeque<String>>,
}
#
# impl Shared {
# pub async fn procssor(&self) {
# let mut guard = self.queue.lock().unwrap();
# let mut baton = None;
loop {
while let Some(entry) = guard.pop_front() {
println!("processing {:?}", &entry);
if entry.is_empty() { break }
}
baton.dispose();
let got = self.cv.wait_baton((guard, &self.queue)).await;
guard = got.0;
baton = got.1;
}
# }
# } } }
变更日志 - 破坏性变更和重大错误修复
-
1.0.1 2024-02-20:
- 没有API或功能更改。
- 放松
dlv-list
依赖(向上和向下)。 - 明确声明我们的MSRV(1.56)。
- 对文档的一些小修复。
- 测试改进。
- 将 Cargo.lock.example 重命名为 Cargo.lock。
-
1.0.0 2022-10-11:
- 将我们的版本更新到 1.x。
- 增加
dlv-list
依赖。没有API或功能更改。
-
0.2.2 2022-03-27:
- 增加
dlv-list
依赖。没有API或功能更改。
- 增加
-
0.2.1 2022-03-27:
- 破坏性变更:为提供特定
parking_lot
版本的RelockMutexGuard
实现提供新的parking_lot_N
功能。在从 0.1.0 升级时,指定新的功能parking_lot_0_11
。 - 支持
parking_lot
0.9、0.10、0.12。
- 破坏性变更:为提供特定
-
0.2.0:版本号未使用。
-
0.1.0, 2021-07-05
- 初始发布。
版权、许可证和免责声明
版权属于 Ian Jackson 和 Rust 软件包 async-condvar-fair 的贡献者。没有任何保证。请参阅源树中的 GPL-3
和 LICENCE
文件。
SPDX-许可证-标识符: GPL-3.0-或-更新的
依赖关系
~0.6–14MB
~124K SLoC