Move embassy-net-driver-channel::zerocopy_channel to embassy_sync::zero_copy_channel
This commit is contained in:
parent
3295ec94e5
commit
a2656f402b
3 changed files with 223 additions and 224 deletions
|
@ -14,6 +14,7 @@ use embassy_net_driver::{Capabilities, LinkState, Medium};
|
||||||
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
|
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
|
||||||
use embassy_sync::blocking_mutex::Mutex;
|
use embassy_sync::blocking_mutex::Mutex;
|
||||||
use embassy_sync::waitqueue::WakerRegistration;
|
use embassy_sync::waitqueue::WakerRegistration;
|
||||||
|
use embassy_sync::zero_copy_channel;
|
||||||
|
|
||||||
pub struct State<const MTU: usize, const N_RX: usize, const N_TX: usize> {
|
pub struct State<const MTU: usize, const N_RX: usize, const N_TX: usize> {
|
||||||
rx: [PacketBuf<MTU>; N_RX],
|
rx: [PacketBuf<MTU>; N_RX],
|
||||||
|
@ -34,8 +35,8 @@ impl<const MTU: usize, const N_RX: usize, const N_TX: usize> State<MTU, N_RX, N_
|
||||||
}
|
}
|
||||||
|
|
||||||
struct StateInner<'d, const MTU: usize> {
|
struct StateInner<'d, const MTU: usize> {
|
||||||
rx: zerocopy_channel::Channel<'d, NoopRawMutex, PacketBuf<MTU>>,
|
rx: zero_copy_channel::Channel<'d, NoopRawMutex, PacketBuf<MTU>>,
|
||||||
tx: zerocopy_channel::Channel<'d, NoopRawMutex, PacketBuf<MTU>>,
|
tx: zero_copy_channel::Channel<'d, NoopRawMutex, PacketBuf<MTU>>,
|
||||||
shared: Mutex<NoopRawMutex, RefCell<Shared>>,
|
shared: Mutex<NoopRawMutex, RefCell<Shared>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,8 +48,8 @@ struct Shared {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Runner<'d, const MTU: usize> {
|
pub struct Runner<'d, const MTU: usize> {
|
||||||
tx_chan: zerocopy_channel::Receiver<'d, NoopRawMutex, PacketBuf<MTU>>,
|
tx_chan: zero_copy_channel::Receiver<'d, NoopRawMutex, PacketBuf<MTU>>,
|
||||||
rx_chan: zerocopy_channel::Sender<'d, NoopRawMutex, PacketBuf<MTU>>,
|
rx_chan: zero_copy_channel::Sender<'d, NoopRawMutex, PacketBuf<MTU>>,
|
||||||
shared: &'d Mutex<NoopRawMutex, RefCell<Shared>>,
|
shared: &'d Mutex<NoopRawMutex, RefCell<Shared>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,11 +59,11 @@ pub struct StateRunner<'d> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RxRunner<'d, const MTU: usize> {
|
pub struct RxRunner<'d, const MTU: usize> {
|
||||||
rx_chan: zerocopy_channel::Sender<'d, NoopRawMutex, PacketBuf<MTU>>,
|
rx_chan: zero_copy_channel::Sender<'d, NoopRawMutex, PacketBuf<MTU>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TxRunner<'d, const MTU: usize> {
|
pub struct TxRunner<'d, const MTU: usize> {
|
||||||
tx_chan: zerocopy_channel::Receiver<'d, NoopRawMutex, PacketBuf<MTU>>,
|
tx_chan: zero_copy_channel::Receiver<'d, NoopRawMutex, PacketBuf<MTU>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, const MTU: usize> Runner<'d, MTU> {
|
impl<'d, const MTU: usize> Runner<'d, MTU> {
|
||||||
|
@ -243,8 +244,8 @@ pub fn new<'d, const MTU: usize, const N_RX: usize, const N_TX: usize>(
|
||||||
let state_uninit: *mut MaybeUninit<StateInner<'d, MTU>> =
|
let state_uninit: *mut MaybeUninit<StateInner<'d, MTU>> =
|
||||||
(&mut state.inner as *mut MaybeUninit<StateInner<'static, MTU>>).cast();
|
(&mut state.inner as *mut MaybeUninit<StateInner<'static, MTU>>).cast();
|
||||||
let state = unsafe { &mut *state_uninit }.write(StateInner {
|
let state = unsafe { &mut *state_uninit }.write(StateInner {
|
||||||
rx: zerocopy_channel::Channel::new(&mut state.rx[..]),
|
rx: zero_copy_channel::Channel::new(&mut state.rx[..]),
|
||||||
tx: zerocopy_channel::Channel::new(&mut state.tx[..]),
|
tx: zero_copy_channel::Channel::new(&mut state.tx[..]),
|
||||||
shared: Mutex::new(RefCell::new(Shared {
|
shared: Mutex::new(RefCell::new(Shared {
|
||||||
link_state: LinkState::Down,
|
link_state: LinkState::Down,
|
||||||
hardware_address,
|
hardware_address,
|
||||||
|
@ -282,8 +283,8 @@ impl<const MTU: usize> PacketBuf<MTU> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Device<'d, const MTU: usize> {
|
pub struct Device<'d, const MTU: usize> {
|
||||||
rx: zerocopy_channel::Receiver<'d, NoopRawMutex, PacketBuf<MTU>>,
|
rx: zero_copy_channel::Receiver<'d, NoopRawMutex, PacketBuf<MTU>>,
|
||||||
tx: zerocopy_channel::Sender<'d, NoopRawMutex, PacketBuf<MTU>>,
|
tx: zero_copy_channel::Sender<'d, NoopRawMutex, PacketBuf<MTU>>,
|
||||||
shared: &'d Mutex<NoopRawMutex, RefCell<Shared>>,
|
shared: &'d Mutex<NoopRawMutex, RefCell<Shared>>,
|
||||||
caps: Capabilities,
|
caps: Capabilities,
|
||||||
}
|
}
|
||||||
|
@ -328,7 +329,7 @@ impl<'d, const MTU: usize> embassy_net_driver::Driver for Device<'d, MTU> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RxToken<'a, const MTU: usize> {
|
pub struct RxToken<'a, const MTU: usize> {
|
||||||
rx: zerocopy_channel::Receiver<'a, NoopRawMutex, PacketBuf<MTU>>,
|
rx: zero_copy_channel::Receiver<'a, NoopRawMutex, PacketBuf<MTU>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, const MTU: usize> embassy_net_driver::RxToken for RxToken<'a, MTU> {
|
impl<'a, const MTU: usize> embassy_net_driver::RxToken for RxToken<'a, MTU> {
|
||||||
|
@ -345,7 +346,7 @@ impl<'a, const MTU: usize> embassy_net_driver::RxToken for RxToken<'a, MTU> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TxToken<'a, const MTU: usize> {
|
pub struct TxToken<'a, const MTU: usize> {
|
||||||
tx: zerocopy_channel::Sender<'a, NoopRawMutex, PacketBuf<MTU>>,
|
tx: zero_copy_channel::Sender<'a, NoopRawMutex, PacketBuf<MTU>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, const MTU: usize> embassy_net_driver::TxToken for TxToken<'a, MTU> {
|
impl<'a, const MTU: usize> embassy_net_driver::TxToken for TxToken<'a, MTU> {
|
||||||
|
@ -361,215 +362,3 @@ impl<'a, const MTU: usize> embassy_net_driver::TxToken for TxToken<'a, MTU> {
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod zerocopy_channel {
|
|
||||||
use core::cell::RefCell;
|
|
||||||
use core::future::poll_fn;
|
|
||||||
use core::marker::PhantomData;
|
|
||||||
use core::task::{Context, Poll};
|
|
||||||
|
|
||||||
use embassy_sync::blocking_mutex::raw::RawMutex;
|
|
||||||
use embassy_sync::blocking_mutex::Mutex;
|
|
||||||
use embassy_sync::waitqueue::WakerRegistration;
|
|
||||||
|
|
||||||
pub struct Channel<'a, M: RawMutex, T> {
|
|
||||||
buf: *mut T,
|
|
||||||
phantom: PhantomData<&'a mut T>,
|
|
||||||
state: Mutex<M, RefCell<State>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, M: RawMutex, T> Channel<'a, M, T> {
|
|
||||||
pub fn new(buf: &'a mut [T]) -> Self {
|
|
||||||
let len = buf.len();
|
|
||||||
assert!(len != 0);
|
|
||||||
|
|
||||||
Self {
|
|
||||||
buf: buf.as_mut_ptr(),
|
|
||||||
phantom: PhantomData,
|
|
||||||
state: Mutex::new(RefCell::new(State {
|
|
||||||
len,
|
|
||||||
front: 0,
|
|
||||||
back: 0,
|
|
||||||
full: false,
|
|
||||||
send_waker: WakerRegistration::new(),
|
|
||||||
recv_waker: WakerRegistration::new(),
|
|
||||||
})),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn split(&mut self) -> (Sender<'_, M, T>, Receiver<'_, M, T>) {
|
|
||||||
(Sender { channel: self }, Receiver { channel: self })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Sender<'a, M: RawMutex, T> {
|
|
||||||
channel: &'a Channel<'a, M, T>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, M: RawMutex, T> Sender<'a, M, T> {
|
|
||||||
pub fn borrow(&mut self) -> Sender<'_, M, T> {
|
|
||||||
Sender { channel: self.channel }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn try_send(&mut self) -> Option<&mut T> {
|
|
||||||
self.channel.state.lock(|s| {
|
|
||||||
let s = &mut *s.borrow_mut();
|
|
||||||
match s.push_index() {
|
|
||||||
Some(i) => Some(unsafe { &mut *self.channel.buf.add(i) }),
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn poll_send(&mut self, cx: &mut Context) -> Poll<&mut T> {
|
|
||||||
self.channel.state.lock(|s| {
|
|
||||||
let s = &mut *s.borrow_mut();
|
|
||||||
match s.push_index() {
|
|
||||||
Some(i) => Poll::Ready(unsafe { &mut *self.channel.buf.add(i) }),
|
|
||||||
None => {
|
|
||||||
s.recv_waker.register(cx.waker());
|
|
||||||
Poll::Pending
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn send(&mut self) -> &mut T {
|
|
||||||
let i = poll_fn(|cx| {
|
|
||||||
self.channel.state.lock(|s| {
|
|
||||||
let s = &mut *s.borrow_mut();
|
|
||||||
match s.push_index() {
|
|
||||||
Some(i) => Poll::Ready(i),
|
|
||||||
None => {
|
|
||||||
s.recv_waker.register(cx.waker());
|
|
||||||
Poll::Pending
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
unsafe { &mut *self.channel.buf.add(i) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn send_done(&mut self) {
|
|
||||||
self.channel.state.lock(|s| s.borrow_mut().push_done())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub struct Receiver<'a, M: RawMutex, T> {
|
|
||||||
channel: &'a Channel<'a, M, T>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, M: RawMutex, T> Receiver<'a, M, T> {
|
|
||||||
pub fn borrow(&mut self) -> Receiver<'_, M, T> {
|
|
||||||
Receiver { channel: self.channel }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn try_recv(&mut self) -> Option<&mut T> {
|
|
||||||
self.channel.state.lock(|s| {
|
|
||||||
let s = &mut *s.borrow_mut();
|
|
||||||
match s.pop_index() {
|
|
||||||
Some(i) => Some(unsafe { &mut *self.channel.buf.add(i) }),
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn poll_recv(&mut self, cx: &mut Context) -> Poll<&mut T> {
|
|
||||||
self.channel.state.lock(|s| {
|
|
||||||
let s = &mut *s.borrow_mut();
|
|
||||||
match s.pop_index() {
|
|
||||||
Some(i) => Poll::Ready(unsafe { &mut *self.channel.buf.add(i) }),
|
|
||||||
None => {
|
|
||||||
s.send_waker.register(cx.waker());
|
|
||||||
Poll::Pending
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn recv(&mut self) -> &mut T {
|
|
||||||
let i = poll_fn(|cx| {
|
|
||||||
self.channel.state.lock(|s| {
|
|
||||||
let s = &mut *s.borrow_mut();
|
|
||||||
match s.pop_index() {
|
|
||||||
Some(i) => Poll::Ready(i),
|
|
||||||
None => {
|
|
||||||
s.send_waker.register(cx.waker());
|
|
||||||
Poll::Pending
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
unsafe { &mut *self.channel.buf.add(i) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn recv_done(&mut self) {
|
|
||||||
self.channel.state.lock(|s| s.borrow_mut().pop_done())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct State {
|
|
||||||
len: usize,
|
|
||||||
|
|
||||||
/// Front index. Always 0..=(N-1)
|
|
||||||
front: usize,
|
|
||||||
/// Back index. Always 0..=(N-1).
|
|
||||||
back: usize,
|
|
||||||
|
|
||||||
/// Used to distinguish "empty" and "full" cases when `front == back`.
|
|
||||||
/// May only be `true` if `front == back`, always `false` otherwise.
|
|
||||||
full: bool,
|
|
||||||
|
|
||||||
send_waker: WakerRegistration,
|
|
||||||
recv_waker: WakerRegistration,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl State {
|
|
||||||
fn increment(&self, i: usize) -> usize {
|
|
||||||
if i + 1 == self.len {
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
i + 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_full(&self) -> bool {
|
|
||||||
self.full
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_empty(&self) -> bool {
|
|
||||||
self.front == self.back && !self.full
|
|
||||||
}
|
|
||||||
|
|
||||||
fn push_index(&mut self) -> Option<usize> {
|
|
||||||
match self.is_full() {
|
|
||||||
true => None,
|
|
||||||
false => Some(self.back),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn push_done(&mut self) {
|
|
||||||
assert!(!self.is_full());
|
|
||||||
self.back = self.increment(self.back);
|
|
||||||
if self.back == self.front {
|
|
||||||
self.full = true;
|
|
||||||
}
|
|
||||||
self.send_waker.wake();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pop_index(&mut self) -> Option<usize> {
|
|
||||||
match self.is_empty() {
|
|
||||||
true => None,
|
|
||||||
false => Some(self.front),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pop_done(&mut self) {
|
|
||||||
assert!(!self.is_empty());
|
|
||||||
self.front = self.increment(self.front);
|
|
||||||
self.full = false;
|
|
||||||
self.recv_waker.wake();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -17,3 +17,4 @@ pub mod pipe;
|
||||||
pub mod pubsub;
|
pub mod pubsub;
|
||||||
pub mod signal;
|
pub mod signal;
|
||||||
pub mod waitqueue;
|
pub mod waitqueue;
|
||||||
|
pub mod zero_copy_channel;
|
||||||
|
|
209
embassy-sync/src/zero_copy_channel.rs
Normal file
209
embassy-sync/src/zero_copy_channel.rs
Normal file
|
@ -0,0 +1,209 @@
|
||||||
|
use core::cell::RefCell;
|
||||||
|
use core::future::poll_fn;
|
||||||
|
use core::marker::PhantomData;
|
||||||
|
use core::task::{Context, Poll};
|
||||||
|
|
||||||
|
use crate::blocking_mutex::raw::RawMutex;
|
||||||
|
use crate::blocking_mutex::Mutex;
|
||||||
|
use crate::waitqueue::WakerRegistration;
|
||||||
|
|
||||||
|
pub struct Channel<'a, M: RawMutex, T> {
|
||||||
|
buf: *mut T,
|
||||||
|
phantom: PhantomData<&'a mut T>,
|
||||||
|
state: Mutex<M, RefCell<State>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, M: RawMutex, T> Channel<'a, M, T> {
|
||||||
|
pub fn new(buf: &'a mut [T]) -> Self {
|
||||||
|
let len = buf.len();
|
||||||
|
assert!(len != 0);
|
||||||
|
|
||||||
|
Self {
|
||||||
|
buf: buf.as_mut_ptr(),
|
||||||
|
phantom: PhantomData,
|
||||||
|
state: Mutex::new(RefCell::new(State {
|
||||||
|
len,
|
||||||
|
front: 0,
|
||||||
|
back: 0,
|
||||||
|
full: false,
|
||||||
|
send_waker: WakerRegistration::new(),
|
||||||
|
recv_waker: WakerRegistration::new(),
|
||||||
|
})),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn split(&mut self) -> (Sender<'_, M, T>, Receiver<'_, M, T>) {
|
||||||
|
(Sender { channel: self }, Receiver { channel: self })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Sender<'a, M: RawMutex, T> {
|
||||||
|
channel: &'a Channel<'a, M, T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, M: RawMutex, T> Sender<'a, M, T> {
|
||||||
|
pub fn borrow(&mut self) -> Sender<'_, M, T> {
|
||||||
|
Sender { channel: self.channel }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_send(&mut self) -> Option<&mut T> {
|
||||||
|
self.channel.state.lock(|s| {
|
||||||
|
let s = &mut *s.borrow_mut();
|
||||||
|
match s.push_index() {
|
||||||
|
Some(i) => Some(unsafe { &mut *self.channel.buf.add(i) }),
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn poll_send(&mut self, cx: &mut Context) -> Poll<&mut T> {
|
||||||
|
self.channel.state.lock(|s| {
|
||||||
|
let s = &mut *s.borrow_mut();
|
||||||
|
match s.push_index() {
|
||||||
|
Some(i) => Poll::Ready(unsafe { &mut *self.channel.buf.add(i) }),
|
||||||
|
None => {
|
||||||
|
s.recv_waker.register(cx.waker());
|
||||||
|
Poll::Pending
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn send(&mut self) -> &mut T {
|
||||||
|
let i = poll_fn(|cx| {
|
||||||
|
self.channel.state.lock(|s| {
|
||||||
|
let s = &mut *s.borrow_mut();
|
||||||
|
match s.push_index() {
|
||||||
|
Some(i) => Poll::Ready(i),
|
||||||
|
None => {
|
||||||
|
s.recv_waker.register(cx.waker());
|
||||||
|
Poll::Pending
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
unsafe { &mut *self.channel.buf.add(i) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send_done(&mut self) {
|
||||||
|
self.channel.state.lock(|s| s.borrow_mut().push_done())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub struct Receiver<'a, M: RawMutex, T> {
|
||||||
|
channel: &'a Channel<'a, M, T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, M: RawMutex, T> Receiver<'a, M, T> {
|
||||||
|
pub fn borrow(&mut self) -> Receiver<'_, M, T> {
|
||||||
|
Receiver { channel: self.channel }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_recv(&mut self) -> Option<&mut T> {
|
||||||
|
self.channel.state.lock(|s| {
|
||||||
|
let s = &mut *s.borrow_mut();
|
||||||
|
match s.pop_index() {
|
||||||
|
Some(i) => Some(unsafe { &mut *self.channel.buf.add(i) }),
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn poll_recv(&mut self, cx: &mut Context) -> Poll<&mut T> {
|
||||||
|
self.channel.state.lock(|s| {
|
||||||
|
let s = &mut *s.borrow_mut();
|
||||||
|
match s.pop_index() {
|
||||||
|
Some(i) => Poll::Ready(unsafe { &mut *self.channel.buf.add(i) }),
|
||||||
|
None => {
|
||||||
|
s.send_waker.register(cx.waker());
|
||||||
|
Poll::Pending
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn recv(&mut self) -> &mut T {
|
||||||
|
let i = poll_fn(|cx| {
|
||||||
|
self.channel.state.lock(|s| {
|
||||||
|
let s = &mut *s.borrow_mut();
|
||||||
|
match s.pop_index() {
|
||||||
|
Some(i) => Poll::Ready(i),
|
||||||
|
None => {
|
||||||
|
s.send_waker.register(cx.waker());
|
||||||
|
Poll::Pending
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
unsafe { &mut *self.channel.buf.add(i) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn recv_done(&mut self) {
|
||||||
|
self.channel.state.lock(|s| s.borrow_mut().pop_done())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct State {
|
||||||
|
len: usize,
|
||||||
|
|
||||||
|
/// Front index. Always 0..=(N-1)
|
||||||
|
front: usize,
|
||||||
|
/// Back index. Always 0..=(N-1).
|
||||||
|
back: usize,
|
||||||
|
|
||||||
|
/// Used to distinguish "empty" and "full" cases when `front == back`.
|
||||||
|
/// May only be `true` if `front == back`, always `false` otherwise.
|
||||||
|
full: bool,
|
||||||
|
|
||||||
|
send_waker: WakerRegistration,
|
||||||
|
recv_waker: WakerRegistration,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl State {
|
||||||
|
fn increment(&self, i: usize) -> usize {
|
||||||
|
if i + 1 == self.len {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
i + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_full(&self) -> bool {
|
||||||
|
self.full
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_empty(&self) -> bool {
|
||||||
|
self.front == self.back && !self.full
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_index(&mut self) -> Option<usize> {
|
||||||
|
match self.is_full() {
|
||||||
|
true => None,
|
||||||
|
false => Some(self.back),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_done(&mut self) {
|
||||||
|
assert!(!self.is_full());
|
||||||
|
self.back = self.increment(self.back);
|
||||||
|
if self.back == self.front {
|
||||||
|
self.full = true;
|
||||||
|
}
|
||||||
|
self.send_waker.wake();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pop_index(&mut self) -> Option<usize> {
|
||||||
|
match self.is_empty() {
|
||||||
|
true => None,
|
||||||
|
false => Some(self.front),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pop_done(&mut self) {
|
||||||
|
assert!(!self.is_empty());
|
||||||
|
self.front = self.increment(self.front);
|
||||||
|
self.full = false;
|
||||||
|
self.recv_waker.wake();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue