diff --git a/r9/src/lib.rs b/r9/src/lib.rs index 3fced15..3681044 100644 --- a/r9/src/lib.rs +++ b/r9/src/lib.rs @@ -1,7 +1,11 @@ pub mod xtimer; pub mod listhead; pub mod queue; +pub mod listheadlock; +pub mod queuelock; pub use xtimer::XTimer; pub use listhead::ListHead; pub use queue::Queue; +pub use listheadlock::*; +pub use queuelock::*; diff --git a/r9/src/listheadlock.rs b/r9/src/listheadlock.rs new file mode 100644 index 0000000..6c5a3d5 --- /dev/null +++ b/r9/src/listheadlock.rs @@ -0,0 +1,98 @@ +use std::sync::{Arc, Weak, Mutex}; +use std::ptr; +use r9_macro::SharedFromSelfLock; +use r9_macro_derive::SharedFromSelfLock; + +#[derive(Default)] +#[derive(SharedFromSelfLock)] +pub struct ListHeadLock { + prev: Weak::>, + next: Weak::>, + data: Weak::>, + _self_wp: Weak::>, +} + +unsafe impl Send for ListHeadLock {} +unsafe impl Sync for ListHeadLock {} + +impl ListHeadLock { + + fn new(data: Weak::>) -> Arc::> { + let this = Arc::new(Mutex::new(Self{ + prev: Default::default(), + next: Default::default(), + data: data, + _self_wp: Default::default(), + })); + this.lock().unwrap()._self_wp = Arc::downgrade(&this); + this.lock().unwrap().init(); + return this; + } + + pub fn new_head() -> Arc::> { + return Self::new(Default::default()); + } + + pub fn new_node(data: Weak::>) -> Arc::> { + return Self::new(data); + } + + fn init(&mut self) { + self.prev = Arc::downgrade(&self.shared_from_self_lock()); + self.next = Arc::downgrade(&self.shared_from_self_lock()); + } + + pub fn data(&self) -> Weak::> { + return self.data.clone(); + } + + pub fn del_init(&mut self) { + self.next.upgrade().unwrap().lock().unwrap()._self_wp = self.prev.clone(); + self.prev.upgrade().unwrap().lock().unwrap().next = self.next.clone(); + self.init(); + } + + pub fn empty(&self) -> bool { + return ptr::eq(self.next.as_ptr(),Arc::as_ptr(&self.shared_from_self_lock())); + } + + pub fn add_tail(head: &Arc::>, pnew: &Arc::>) { + let prev = &head.lock().unwrap().prev.clone(); + let next = head; + + next.lock().unwrap().prev = Arc::downgrade(pnew); + pnew.lock().unwrap().next = Arc::downgrade(&next); + pnew.lock().unwrap().prev = prev.clone(); + prev.upgrade().unwrap().lock().unwrap().next = Arc::downgrade(pnew); + } + + pub fn first_entry(&self) -> Weak::> { + if self.empty() { + panic!(""); + } + return self.next.upgrade().unwrap().lock().unwrap().data(); + } + + pub fn replace_init(head: &Arc::>, pnew: &Arc::>) { + if head.lock().unwrap().empty() { + return; + } + pnew.lock().unwrap().next = head.lock().unwrap().next.clone(); + pnew.lock().unwrap().next.upgrade().unwrap().lock().unwrap().prev = Arc::downgrade(pnew); + pnew.lock().unwrap().prev = head.lock().unwrap().prev.clone(); + pnew.lock().unwrap().prev.upgrade().unwrap().lock().unwrap().next = Arc::downgrade(pnew); + head.lock().unwrap().init(); + } + + pub fn for_each(&self, cb: fn (&Weak::>) -> bool) { + let mut pos = self.next.clone(); + let self_weak = Arc::downgrade(&self.shared_from_self_lock()); + while !Weak::ptr_eq(&pos, &self_weak) { + if !cb(&pos.upgrade().unwrap().lock().unwrap().data()) { + break; + } + pos = pos.upgrade().unwrap().lock().unwrap().next.clone(); + } + } + +} diff --git a/r9/src/queuelock.rs b/r9/src/queuelock.rs new file mode 100644 index 0000000..01035b0 --- /dev/null +++ b/r9/src/queuelock.rs @@ -0,0 +1,51 @@ +use std::sync::Mutex; +use std::sync::Arc; +use r9_macro::SharedFromSelf; +use r9_macro_derive::SharedFromSelf; +use std::default::Default; + +pub struct QueueLock { + msg_list: Mutex>>>, + pub work_list: Mutex>>>, +} + +unsafe impl Send for QueueLock {} +unsafe impl Sync for QueueLock {} + +impl QueueLock { + + pub fn new() -> Arc::> { + let this = Arc::new(Mutex::new(Self{ + msg_list: Mutex::new(crate::ListHeadLock::::new_head()), + work_list: Mutex::new(crate::ListHeadLock::::new_head()), + })); + return this; + } + + pub fn new_ex() -> Arc::> { + let this = Arc::new(Mutex::new(Self{ + msg_list: Mutex::new(crate::ListHeadLock::::new_head()), + work_list: Mutex::new(crate::ListHeadLock::::new_head()), + })); + return this; + } + + pub fn push(&self, node: &Arc::>>) { + crate::ListHeadLock::::add_tail(&self.msg_list.lock().unwrap(), node); + } + + pub fn fetch(&self) { + if !self.msg_list.lock().unwrap().lock().unwrap().empty() && + self.work_list.lock().unwrap().lock().unwrap().empty() { + crate::ListHeadLock::replace_init(&self.msg_list.lock().unwrap(), &self.work_list.lock().unwrap()); + } + } + + pub fn empty(&self) -> bool { + if !self.work_list.lock().unwrap().lock().unwrap().empty() { + return false + } + return self.msg_list.lock().unwrap().lock().unwrap().empty() + } + +} diff --git a/r9_macro/src/lib.rs b/r9_macro/src/lib.rs index 819424e..2c81398 100644 --- a/r9_macro/src/lib.rs +++ b/r9_macro/src/lib.rs @@ -1,4 +1,6 @@ use std::rc::Rc; +use std::sync::Arc; +use std::sync::Mutex; use std::cell::RefCell; #[cfg(test)] @@ -14,5 +16,9 @@ pub trait SharedFromSelf { fn shared_from_self(&self) -> Rc::>; } +pub trait SharedFromSelfLock { + fn shared_from_self_lock(&self) -> Arc::>; +} + pub trait Singleton { } diff --git a/r9_macro_derive/src/lib.rs b/r9_macro_derive/src/lib.rs index 28520d4..605ff40 100644 --- a/r9_macro_derive/src/lib.rs +++ b/r9_macro_derive/src/lib.rs @@ -32,6 +32,27 @@ fn impl_shared_from_self_macro(ast: &syn::DeriveInput) -> TokenStream { gen.into() } +#[proc_macro_derive(SharedFromSelfLock, attributes(helper))] +pub fn shared_from_self_lock_derive(input: TokenStream) -> TokenStream { + let ast = syn::parse(input).unwrap(); + + // Build the trait implementation + crate::impl_shared_from_self_lock_macro(&ast) +} + +fn impl_shared_from_self_lock_macro(ast: &syn::DeriveInput) -> TokenStream { + let name = &ast.ident; + let (impl_generics, _, _) = ast.generics.split_for_impl(); + let gen = quote! { + impl #impl_generics SharedFromSelfLock for #name #impl_generics { + fn shared_from_self_lock(&self) -> Arc::> { + return self._self_wp.upgrade().unwrap(); + } + } + }; + gen.into() +} + #[proc_macro_derive(Singleton)] pub fn singleton_derive(input: TokenStream) -> TokenStream { let ast = syn::parse(input).unwrap();