use nb;
use core::cell::UnsafeCell;
use core::mem::swap;
use bare_metal::CriticalSection;
pub unsafe trait NonReentrant {
}
unsafe impl NonReentrant for CriticalSection {
}
struct NonReentrantToken {
_0: (),
}
impl NonReentrantToken {
unsafe fn new() -> Self {
NonReentrantToken { _0: () }
}
}
unsafe impl NonReentrant for NonReentrantToken {
}
#[derive(Debug)]
pub struct Channel<'a, T: 'a> {
buffer: UnsafeCell<&'a mut [Option<T>]>,
send_index: UnsafeCell<usize>,
recv_index: UnsafeCell<usize>,
}
impl<'a, T: 'a> Channel<'a, T> {
pub fn new(buffer: &'a mut [Option<T>]) -> Self {
for el in buffer.iter_mut() {
*el = None;
}
Channel {
buffer: UnsafeCell::new(buffer),
send_index: UnsafeCell::new(0),
recv_index: UnsafeCell::new(0),
}
}
pub fn len(&self) -> usize {
unsafe { (*self.buffer.get()).len() }
}
pub fn recv(&self, _nr: &NonReentrant) -> nb::Result<T, !> {
let empty = unsafe { *self.send_index.get() == *self.recv_index.get() };
if empty {
Err(nb::Error::WouldBlock)
}
else {
let mut val: Option<T> = None;
unsafe {
let index = *self.recv_index.get();
swap(&mut val, &mut (*self.buffer.get())[index]);
*self.recv_index.get() = (index + 1) % self.len();
}
match val {
None => Err(nb::Error::WouldBlock),
Some(v) => Ok(v),
}
}
}
pub fn send(&self, value: T, nr: &NonReentrant) -> nb::Result<(), !> {
self.send_lossless(value, nr).0
}
pub fn send_lossless(&self, value: T, _nr: &NonReentrant) -> (nb::Result<(), !>, Option<T>) {
let full = unsafe { ((*self.send_index.get()) + 1) % (self.len()) == *self.recv_index.get() };
if full {
(Err(nb::Error::WouldBlock), Some(value))
}
else {
let mut val: Option<T> = Some(value);
unsafe {
let index = *self.send_index.get();
swap(&mut val, &mut (*self.buffer.get())[index]);
*self.send_index.get() = (index + 1) % self.len();
}
(Ok(()), None)
}
}
}
impl<'a, 'b: 'a, T: 'b> Channel<'b, T> {
pub fn split(&'a mut self) -> (Receiver<'a, 'b, T>, Sender<'a, 'b, T>) {
(Receiver::new(self), Sender::new(self))
}
}
unsafe impl<'a, T: 'a> Sync for Channel<'a, T> {
}
#[derive(Debug)]
pub struct Receiver<'a, 'b: 'a, T: 'b> {
inner: &'a Channel<'b, T>,
}
impl<'a, 'b: 'a, T: 'b> Receiver<'a, 'b, T> {
fn new(channel: &'a Channel<'b, T>) -> Self {
Receiver { inner: channel }
}
pub fn recv(&mut self) -> nb::Result<T, !> {
let nr = unsafe { NonReentrantToken::new() };
self.inner.recv(&nr)
}
}
unsafe impl<'a, 'b: 'a, T: Send + 'b> Send for Receiver<'a, 'b, T> {
}
impl<'a, 'b: 'a, T: 'b> !Sync for Receiver<'a, 'b, T> {
}
#[derive(Debug)]
pub struct Sender<'a, 'b: 'a, T: 'b> {
inner: &'a Channel<'b, T>,
}
impl<'a, 'b: 'a, T: 'b> Sender<'a, 'b, T> {
fn new(channel: &'a Channel<'b, T>) -> Self {
Sender { inner: channel }
}
pub fn send(&mut self, value: T) -> nb::Result<(), !> {
self.send_lossless(value).0
}
pub fn send_lossless(&mut self, value: T) -> (nb::Result<(), !>, Option<T>) {
let nr = unsafe { CriticalSection::new() };
self.inner.send_lossless(value, &nr)
}
pub fn send_with_completion(self, value: T) -> SendCompletion<'a, 'b, T> {
SendCompletion::new(self, value)
}
}
unsafe impl<'a, 'b: 'a, T: Send + 'b> Send for Sender<'a, 'b, T> {
}
impl<'a, 'b: 'a, T: 'b> !Sync for Sender<'a, 'b, T> {
}
pub struct SendCompletion<'a, 'b: 'a, T: 'b> {
sender: Sender<'a, 'b, T>,
value: Option<T>,
}
impl<'a, 'b: 'a, T: 'b> SendCompletion<'a, 'b, T> {
fn new(sender: Sender<'a, 'b, T>, value: T) -> Self {
SendCompletion { sender: sender, value: Some(value), }
}
pub fn poll(&mut self) -> nb::Result<(), !> {
match self.value {
Some(_) => {
let mut value: Option<T> = None;
swap(&mut value, &mut self.value);
let nr = unsafe { CriticalSection::new() };
let (result, mut value) = self.sender.inner.send_lossless(value.unwrap(), &nr);
swap(&mut value, &mut self.value);
result
},
None => Ok(()),
}
}
pub fn done(self) -> (Sender<'a, 'b, T>, Option<T>) {
match self.value {
Some(value) => (self.sender, Some(value)),
_ => (self.sender, None),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use nb;
struct NonClone {
_0: ()
}
impl NonClone {
fn new() -> Self {
NonClone { _0: () }
}
}
#[test]
fn basic() {
let mut arry: [Option<u8>; 4] = [None; 4];
let len = arry.len();
let mut channel = Channel::new(&mut arry);
assert_eq!(channel.len(), len);
let (mut receiver, mut sender) = channel.split();
assert_eq!(receiver.recv(), Err(nb::Error::WouldBlock));
assert_eq!(sender.send(4), Ok(()));
assert_eq!(receiver.recv(), Ok(4));
assert_eq!(receiver.recv(), Err(nb::Error::WouldBlock));
}
#[test]
fn completion() {
let mut arry: [Option<NonClone>; 5] = [None, None, None, None, None];
let len = arry.len();
let mut channel = Channel::new(&mut arry);
assert_eq!(channel.len(), len);
let (mut receiver, mut sender) = channel.split();
match receiver.recv() {
Err(nb::Error::WouldBlock) => {},
_ => assert!(false),
}
let mut completion = sender.send_with_completion(NonClone::new());
match receiver.recv() {
Err(nb::Error::WouldBlock) => {},
_ => assert!(false),
}
match completion.poll() {
Ok(_) => {},
_ => assert!(false),
}
match receiver.recv() {
Ok(_) => {},
_ => assert!(false),
}
match completion.poll() {
Ok(_) => {},
_ => assert!(false),
}
match receiver.recv() {
Err(nb::Error::WouldBlock) => {},
_ => assert!(false),
}
let (s, r) = completion.done();
sender = s;
match r {
None => {},
_ => assert!(false),
}
match receiver.recv() {
Err(nb::Error::WouldBlock) => {},
_ => assert!(false),
}
completion = sender.send_with_completion(NonClone::new());
let (_, r) = completion.done();
match r {
Some(_) => {},
_ => assert!(false),
}
}
#[test]
fn sync_blocking() {
let mut arry: [Option<u8>; 4] = [None; 4];
let len = arry.len();
let mut channel = Channel::new(&mut arry);
assert_eq!(channel.len(), len);
let (mut receiver, mut sender) = channel.split();
for _rep in 0..10 {
for i in 0..(len - 1) {
println!("Sending");
assert_eq!(sender.send(i as u8), Ok(()));
}
assert_eq!(sender.send(255), Err(nb::Error::WouldBlock));
assert_eq!(receiver.recv(), Ok(0));
assert_eq!(sender.send(255), Ok(()));
for i in 1..(len - 1) {
assert_eq!(receiver.recv(), Ok(i as u8));
}
assert_eq!(receiver.recv(), Ok(255));
assert_eq!(receiver.recv(), Err(nb::Error::WouldBlock));
}
}
}