From 94fecb08300d005219b5c9c84857975fc4b062cf Mon Sep 17 00:00:00 2001 From: HarkonenBade Date: Thu, 10 Jan 2019 20:57:23 +0000 Subject: [PATCH 1/3] Adds Shared a wrapper for sharing data between handlers --- src/lib.rs | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 8b8efeb..817b16f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,7 +8,10 @@ )] #![no_std] -use core::cell::UnsafeCell; +use core::{ + cell::{RefCell, UnsafeCell}, + ops::{Deref, DerefMut}, +}; /// A peripheral #[derive(Debug)] @@ -123,3 +126,61 @@ pub unsafe trait Nr { // to prevent sending non-Sendable stuff (e.g. access tokens) across different // execution contexts (e.g. interrupts) unsafe impl Sync for Mutex where T: Send {} + +/// A shared value wrapper +/// +/// Uses `Mutex` internally, so the same caveats about multi-core systems apply +pub struct Shared { + inner: Mutex>>, +} + +impl Shared { + /// Creates a new empty shared value + #[cfg(feature = "const-fn")] + pub const fn new() -> Self { + Shared { + inner: Mutex::new(RefCell::new(None)), + } + } + + /// Creates a new empty shared value + #[cfg(not(feature = "const-fn"))] + pub fn new() -> Self { + Shared { + inner: Mutex::new(RefCell::new(None)), + } + } + + /// Loads new contents into a shared value, if the value already contained + /// data the old value is returned + pub fn load(&self, cs: &CriticalSection, value: T) -> Option { + self.inner.borrow(cs).replace(Some(value)) + } + + /// Attempts to get a reference to the data in the shared value, may fail + /// if there are current mutable references, or if the value is empty + pub fn get<'a>(&'a self, cs: &'a CriticalSection) -> Option> { + self.inner + .borrow(cs) + .try_borrow() + .ok() + .and_then(|inner| match inner.deref() { + Some(_) => Some(core::cell::Ref::map(inner, |v| v.as_ref().unwrap())), + None => None, + }) + } + + /// Attempts to get a reference to the data in the shared value, may fail + /// if there are current mutable or immutable references, or if the value + /// is empty + pub fn get_mut<'a>(&'a self, cs: &'a CriticalSection) -> Option> { + self.inner + .borrow(cs) + .try_borrow_mut() + .ok() + .and_then(|mut inner| match inner.deref_mut() { + Some(_) => Some(core::cell::RefMut::map(inner, |v| v.as_mut().unwrap())), + None => None, + }) + } +} From 20047b986592c04dc9b882376ea067bde3bc789e Mon Sep 17 00:00:00 2001 From: HarkonenBade Date: Thu, 10 Jan 2019 23:05:56 +0000 Subject: [PATCH 2/3] Simplify implementation slightly with help from @therealprof --- src/lib.rs | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 817b16f..84207cb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,10 +8,7 @@ )] #![no_std] -use core::{ - cell::{RefCell, UnsafeCell}, - ops::{Deref, DerefMut}, -}; +use core::cell::{RefCell, UnsafeCell}; /// A peripheral #[derive(Debug)] @@ -164,10 +161,8 @@ impl Shared { .borrow(cs) .try_borrow() .ok() - .and_then(|inner| match inner.deref() { - Some(_) => Some(core::cell::Ref::map(inner, |v| v.as_ref().unwrap())), - None => None, - }) + .filter(|inner| inner.is_some()) + .map(|inner| core::cell::Ref::map(inner, |v| v.as_ref().unwrap())) } /// Attempts to get a reference to the data in the shared value, may fail @@ -178,9 +173,7 @@ impl Shared { .borrow(cs) .try_borrow_mut() .ok() - .and_then(|mut inner| match inner.deref_mut() { - Some(_) => Some(core::cell::RefMut::map(inner, |v| v.as_mut().unwrap())), - None => None, - }) + .filter(|inner| inner.is_some()) + .map(|inner| core::cell::RefMut::map(inner, |v| v.as_mut().unwrap())) } } From 37563a96179c473378c1ac7937bff35cfacc10e2 Mon Sep 17 00:00:00 2001 From: HarkonenBade Date: Thu, 10 Jan 2019 23:06:16 +0000 Subject: [PATCH 3/3] Change `load` to `put` to better match with `get` and `get_mut` --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 84207cb..9d60436 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -150,7 +150,7 @@ impl Shared { /// Loads new contents into a shared value, if the value already contained /// data the old value is returned - pub fn load(&self, cs: &CriticalSection, value: T) -> Option { + pub fn put(&self, cs: &CriticalSection, value: T) -> Option { self.inner.borrow(cs).replace(Some(value)) }