2 个版本
0.1.1 | 2022年1月23日 |
---|---|
0.1.0 | 2021年10月31日 |
#412 在 并发
10,286 每月下载量
用于 54 个包 (6 个直接使用)
23KB
215 代码行
takecell
takecell
提供了两种新的类似单元格的类型,TakeCell
和 TakeOwnCell
。两者都可以存储任意非 Copy
类型,最多只能读取一次,并提供对存储内容的直接唯一访问。核心 API 看起来大致如下
impl<T> TakeCell<T> {
const fn new(v: T) -> Self { ... }
}
impl<T: ?Sized> TakeCell<T> {
fn take(&self) -> Option<&mut T> { ... }
}
impl<T> TakeOwnCell<T> {
const fn new(v: T) -> Self { ... }
fn take(&self) -> Option<T> { ... }
}
要使用此包,请将以下内容添加到您的 Cargo.toml
[dependencies]
takecell = "0.1"
lib.rs
:
此包提供了两种新的类似单元格的类型,TakeCell
和 TakeOwnCell
。两者都可以存储任意非 Copy
类型,最多只能读取一次,并提供对存储内容的直接唯一访问。核心 API 看起来大致如此(还有很多内容,请继续阅读!)
impl<T> TakeCell<T> {
const fn new(v: T) -> Self { ... }
}
impl<T: ?Sized> TakeCell<T> {
fn take(&self) -> Option<&mut T> { ... }
}
impl<T> TakeOwnCell<T> {
const fn new(v: T) -> Self { ... }
fn take(&self) -> Option<T> { ... }
}
请注意,与 RefCell
和 Mutex
类似,take
方法只需要共享引用。由于单次读取限制,take
可以返回 &mut T
或 T
而不是 RefMut<T>
或 MutexGuard<T>
。在某种意义上,TakeCell
可以被视为一个无需解锁的 Mutex
(或者更确切地说,解锁需要独占访问 Mutex
,请参阅 heal
)。
此包是 #![no_std]
,并且仅通过 8 位原子进行少量同步。
使用示例
单例
TakeCell
是 Sync
(当 T: Sync
时)并且因此可以在 static
中使用。这可以用于创建单例。
use takecell::TakeCell;
#[non_exhaustive]
pub struct Peripherals {
pub something: Something,
}
pub static PEREPHERALS: TakeCell<Peripherals> = TakeCell::new(Peripherals {
something: Something,
});
let peripherals: &'static mut _ = PEREPHERALS.take().unwrap();
只做一次工作
use once_cell::sync::OnceCell;
use std::sync::{Arc, Condvar, Mutex};
use takecell::TakeCell;
#[derive(Clone)]
struct Job {
// Input can be a type which requires unique access to be used (e.g.: `dyn Read`)
input: Arc<TakeCell<Input>>,
output: Arc<OnceCell<Output>>,
wait: Arc<(Mutex<bool>, Condvar)>,
}
fn execute(job: Job) -> Output {
match job.input.take() {
Some(input) => {
// Nobody has started executing the job yet, so execute it
let output = input.process();
// Write the output
job.output.set(output);
// Notify other threads that the job is done
let (lock, cvar) = &*job.wait;
let mut done = lock.lock().unwrap();
*done = true;
}
None => {
// Wait for the other thread to do the job
let (lock, cvar) = &*job.wait;
let mut done = lock.lock().unwrap();
// As long as the value inside the `Mutex<bool>` is `false`, we wait
while !*done {
done = cvar.wait(done).unwrap();
}
}
}
// Read the output
job.output.get().unwrap().clone()
}
impl Input {
fn process(&mut self) -> Output {
// ...
}
}