#cell #once-cell #take #value #taken

无需 std takecell

一种只能取值一次的单元格类型

2 个版本

0.1.1 2022年1月23日
0.1.0 2021年10月31日

#412并发

Download history 2549/week @ 2024-03-14 2230/week @ 2024-03-21 2354/week @ 2024-03-28 2358/week @ 2024-04-04 2706/week @ 2024-04-11 2659/week @ 2024-04-18 2416/week @ 2024-04-25 2565/week @ 2024-05-02 2222/week @ 2024-05-09 2176/week @ 2024-05-16 1997/week @ 2024-05-23 2335/week @ 2024-05-30 2152/week @ 2024-06-06 2350/week @ 2024-06-13 2813/week @ 2024-06-20 2653/week @ 2024-06-27

10,286 每月下载量
用于 54 个包 (6 个直接使用)

MIT 许可证

23KB
215 代码行

takecell

lib.rs docs

takecell 提供了两种新的类似单元格的类型,TakeCellTakeOwnCell。两者都可以存储任意非 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:

此包提供了两种新的类似单元格的类型,TakeCellTakeOwnCell。两者都可以存储任意非 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> { ... }
}

请注意,与 RefCellMutex 类似,take 方法只需要共享引用。由于单次读取限制,take 可以返回 &mut TT 而不是 RefMut<T>MutexGuard<T>。在某种意义上,TakeCell 可以被视为一个无需解锁的 Mutex(或者更确切地说,解锁需要独占访问 Mutex,请参阅 heal)。

此包是 #![no_std],并且仅通过 8 位原子进行少量同步。

使用示例

单例

TakeCellSync(当 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 {
        // ...
    }
}

无运行时依赖