#fifo #同步 #await #future #sync

nightly nb-sync

裸机环境下的非阻塞同步结构

2个不稳定版本

使用旧版Rust 2015

0.2.0 2018年7月1日
0.1.0 2018年5月13日

#40 in #fifo

APSL-2.0 OR MIT

26KB
318

非阻塞轻量级同步结构

Build Status Docs Status

提供基于nbcrate的轻量级同步结构。适用于嵌入式系统上的Rust。这是一个no_stdcrate,不需要堆分配。

许可证

此crate根据您的要求,以下列许可证之一进行许可

  • Apache 2.0
  • MIT

lib.rs:

非阻塞同步结构

此crate设计用于no_std应用程序,其中无法进行堆分配。因此,它不依赖于标准库,所有分配都是调用者的责任。

互斥锁

这里提供的Mutex可以用来提供对值的独占访问。由于此库的非阻塞特性,必须小心操作以避免资源饥饿。锁方法需要一个bare_metal::CriticalSection

通道

`fifo::channel` 提供了一个单生产者单消费者队列,该队列是 `Sync` 的,并且可以选择将其拆分为一个 `fifo::Sender` 和一个 `fifo::Receiver`,这两个都是 `Send`。使用 `Channel` 与 `Sender` 和 `Receiver` 一起使用的关键区别在于,`Channel` 需要一个 `bare_metal::CriticalSection` 才能为其方法提供安全性。而 `Sender` 和 `Receiver` 可以不满足此要求。

Channel 示例

可以使用两种方式使用 `fifo::Channel`

直接使用

直接使用需要传递一个实现 `fifo::NonReentrant` 的对象。

extern crate bare_metal;
extern crate nb_sync;

use nb_sync::fifo::Channel;

//In an actual program this would be obtained safely
let cs = unsafe { bare_metal::CriticalSection::new() };

let mut buffer: [Option<u8>; 4] = [None; 4];
let channel = Channel::new(&mut buffer);

channel.send(10, &cs).unwrap();
channel.recv(&cs).unwrap();

拆分为发送者和接收者

这使用了与上一个示例类似的方法,但不需要 `bare_metal::CriticalSection`。

方法 1:使用可克隆类型的基本 "send" 操作

对于可克隆类型,可以在 `fifo::Sender::send` 方法中直接使用 `await!`。

extern crate nb;
extern crate nb_sync;

use nb_sync::fifo::Channel;

let mut buffer: [Option<u8>; 4] = [None; 4];
let mut channel = Channel::new(&mut buffer);

let (mut receiver, mut sender) = channel.split();

let clonable = 5;
// this loop is "await!(sender.send(clonable)).unwrap()"
loop {
    match sender.send(clonable) {
        Ok(()) => break Ok(()),
        Err(nb::Error::WouldBlock) => {},
        Err(nb::Error::Other(e)) => break Err(e),
    }
}.unwrap();

// recv is also compatible with nb's await! macro
receiver.recv().unwrap();

方法 2:带有完成的发送

可以使用 `fifo::Sender::send_with_completion` 方法发送不可克隆类型。这是基于 `fifo::Sender::send_lossless` 方法的。使用 `fifo::SendCompletion` 使其更直接地与 `await!` 宏一起使用。它将在发送过程中拥有 `Sender` 和传递的值。当调用 `fifo::SendCompletion::done` 时,`Sender` 将返回,并附带一个包含原始值的 `Option`,如果它最终没有发送。

extern crate nb;
extern crate nb_sync;

use nb_sync::fifo::Channel;

struct NonClone {
    _0: (),
}
impl NonClone {
    fn new() -> Self { NonClone { _0: () } }
}

let mut buffer: [Option<NonClone>; 4] = [None, None, None, None];
let mut channel = Channel::new(&mut buffer);

let (mut receiver, mut sender) = channel.split();

let value = NonClone::new();
let completion = sender.send_with_completion(value);
// Completions can be aborted.
let (s, v) = completion.done();
sender = s;
let value = v.unwrap(); //the original, unsent value is returned here

let mut completion = sender.send_with_completion(value);
// This loop is "await!(completion.poll()).unwrap()"
loop {
    match completion.poll() {
        Ok(()) => break Ok(()),
        Err(nb::Error::WouldBlock) => {},
        Err(nb::Error::Other(e)) => break Err(e),
    }
}.unwrap();

let (s, v) = completion.done();
sender = s;
assert!(v.is_none()); //the value has been sent.

receiver.recv().unwrap();

依赖项

~42KB