3个不稳定版本
0.2.1 | 2024年7月25日 |
---|---|
0.2.0 | 2024年7月19日 |
0.1.0 | 2024年7月16日 |
268 在 数据结构
每月下载量 391
51KB
798 行代码(不包括注释)
Locker Room
为您的集合中单个单元格提供读写访问!
LockerRoom 和 LockerRoomAsync
该crate的核心功能由这些结构实现。更具体地说,它们提供了以下功能
- 使用
LockerRoom::read_cell
和LockerRoomAsync::read_cell
提供对集合单个单元格的共享读取访问; - 使用
LockerRoom::write_cell
和LockerRoomAsync::write_cell
提供对集合单个单元格的独占写入访问; - 使用
LockerRoom::lock_room
和LockerRoomAsync::lock_room
提供对整个集合的独占写入访问。
但 LockerRoomAsync
是可选的 - 您需要启用 async
功能才能使用它。它依赖于 tokio
的 RwLock
。
LockerRoom 示例
let v = vec![0, 1, 2, 3, 4, 5];
let locker_room: LockerRoom<_> = v.into();
let locker_room = Arc::new(locker_room);
thread::scope(|scope| {
scope.spawn(|| *locker_room.write_cell(0).unwrap() += 1);
scope.spawn(|| *locker_room.write_cell(0).unwrap() += 2);
});
assert_eq!(3, *locker_room.read_cell(0).unwrap());
LockerRoomAsync 示例
let v = vec![0, 1, 2, 3, 4, 5];
let locker_room: LockerRoomAsync<_> = v.into();
let locker_room = Arc::new(locker_room);
let locker_room_cloned = Arc::clone(&locker_room);
let join1 = spawn(async move { *locker_room_cloned.write_cell(0).await.unwrap() += 1 });
let locker_room_cloned = Arc::clone(&locker_room);
let join2 = spawn(async move { *locker_room_cloned.write_cell(0).await.unwrap() += 2 });
join!(join1, join2);
assert_eq!(3, *locker_room.read_cell(0).await.unwrap());
死锁示例
小心在单个作用域中阻塞多个单元格。否则,可能会出现这种情况
// Thread 1 | // Thread 2
let _w1 = locker_room.write_cell(0); |
| let _w1 = locker_room.write_cell(1);
// will block
let _w2 = locker_room.write_cell(1); |
| // will deadlock
| let _w2 = locker_room.write_cell(0);
集合?
默认情况下,您可以从 array
、Vec
、VecDeque
、HashMap
和 BTreeMap
创建 LockerRoom
和 LockerRoomAsync
。
但是,该crate提供了一些特质,通过实现这些特质,您可以使您的集合与 LockerRoom
和 LockerRoomAsync
兼容。
集合
该crate的关键部分,帮助您的集合与 LockerRoom
和 LockerRoomAsync
兼容。
只需将其实现到您的集合中,一切都会正常工作!
示例
让我们为 Index
的 示例 中的结构实现该特质
enum Nucleotide {
C,
A,
G,
T,
}
struct NucleotideCount {
pub a: usize,
pub c: usize,
pub g: usize,
pub t: usize,
}
impl Collection for NucleotideCount {
type Output = usize;
type Idx = Nucleotide;
type ShadowLocks = NucleotideShadowLocks;
fn index(&self, index: impl Borrow<Self::Idx>) -> Option<&Self::Output> {
Some(match index.borrow() {
Nucleotide::A => &self.a,
Nucleotide::C => &self.c,
Nucleotide::G => &self.g,
Nucleotide::T => &self.t,
})
}
fn index_mut(&mut self, index: impl Borrow<Self::Idx>) -> Option<&mut Self::Output> {
Some(match index.borrow() {
Nucleotide::A => &mut self.a,
Nucleotide::C => &mut self.c,
Nucleotide::G => &mut self.g,
Nucleotide::T => &mut self.t,
})
}
fn indices(&self) -> impl Iterator<Item = Self::Idx> {
[Nucleotide::A, Nucleotide::C, Nucleotide::G, Nucleotide::T].into_iter()
}
fn shadow_locks(&self) -> Self::ShadowLocks {
Default::default()
}
}
struct NucleotideShadowLocks {
a: RwLock<()>,
c: RwLock<()>,
g: RwLock<()>,
t: RwLock<()>,
}
impl ShadowLocksCollection for NucleotideShadowLocks {
type Idx = Nucleotide;
fn index(&self, index: impl Borrow<Self::Idx>) -> Option<&RwLock<()>> {
Some(match index.borrow() {
Nucleotide::A => &self.a,
Nucleotide::C => &self.c,
Nucleotide::G => &self.g,
Nucleotide::T => &self.t,
})
}
fn update_indices(&mut self, _indices: impl Iterator<Item = Self::Idx>) {
// No need to reindex because NucleotideShadowLocks has static structure.
}
}
如果启用功能 async
,则 Collection
必须包括 Collection::ShadowLocksAsync
类型和 Collection::shadow_locks_async
方法。因此,必须实现 ShadowLocksCollectionAsync
。
impl Collection for NucleotideCount {
// ...
type ShadowLocksAsync = NucleotideShadowLocksAsync;
// ...
fn shadow_locks_async(&self) -> Self::ShadowLocksAsync {
Default::default()
}
}
struct NucleotideShadowLocksAsync {
a: tokio::sync::RwLock<()>,
c: tokio::sync::RwLock<()>,
g: tokio::sync::RwLock<()>,
t: tokio::sync::RwLock<()>,
}
impl ShadowLocksCollectionAsync for NucleotideShadowLocksAsync {
type Idx = Nucleotide;
fn index(&self, index: impl Borrow<Self::Idx>) -> Option<&tokio::sync::RwLock<()>> {
Some(match index.borrow() {
Nucleotide::A => &self.a,
Nucleotide::C => &self.c,
Nucleotide::G => &self.g,
Nucleotide::T => &self.t,
})
}
fn update_indices(&mut self, _indices: impl Iterator<Item = Self::Idx>) {
// No need to reindex because NucleotideShadowLocksAsync has static structure.
}
}
依赖项
~0–1.1MB
~19K SLoC