├── .gitignore ├── Cargo.toml ├── README.md ├── assets ├── logo.png └── logo.psd └── src ├── by.rs ├── error.rs ├── fac ├── iter.rs ├── merge.rs ├── mod.rs ├── of.rs └── timer.rs ├── lib.rs ├── observable.rs ├── observer.rs ├── op ├── filter.rs ├── map.rs ├── merge.rs ├── mod.rs ├── skip.rs ├── start.rs ├── take.rs └── until.rs ├── scheduler ├── current_thread_scheduler.rs ├── event_loop_scheduler.rs ├── mod.rs └── new_thread_scheduler.rs ├── subject ├── behavior_subject.rs ├── mod.rs └── subject.rs ├── sync ├── act.rs ├── any_send_sync.rs ├── mod.rs ├── re_spin_lock.rs ├── re_spin_mutex.rs ├── recur_cell.rs ├── ss_mark.rs └── yesno.rs ├── unsub.rs └── util ├── clones.rs └── mod.rs /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | target/ 4 | .idea/ 5 | /rxrs.iml 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | .DS_Store 13 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rxrs" 3 | version = "0.2.0-beta3" 4 | description="Reactive Extensions for Rust" 5 | license="MIT" 6 | repository="https://github.com/yingDev/rxrs" 7 | authors = ["yingDev "] 8 | edition = "2018" 9 | 10 | [dependencies] 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |
4 | RxRs - Reactive Extensions for Rust 5 |

6 | 7 | 8 | 9 |

10 |
11 | 12 | __WIP: rxrs is under heavy development & not ready for production__ 13 | 14 | 15 | ```rust 16 | use rxrs::*; 17 | 18 | #[test] 19 | pub fn greet() 20 | { 21 | let output = RefCell::new(String::new()); 22 | 23 | let subj = Rc::new(Subject::::new()); 24 | 25 | let evens: impl Observable> = subj.clone() 26 | .filter(|v:&_| v%2 == 0 ) 27 | .take(4) 28 | .map(|v:&_| format!("*{}", v)); 29 | 30 | evens.subscribe( 31 | |v: String| output.borrow_mut().push_str(&v), 32 | |e| output.borrow_mut().push_str("ok") 33 | ); 34 | 35 | for i in 0..10 { 36 | subj.next(i); 37 | } 38 | 39 | assert_eq!("*0*2*4*6ok", &*output.borrow()); 40 | } 41 | 42 | ``` 43 | 44 | 45 | ```bash 46 | src 47 | ├── by.rs 48 | ├── error.rs 49 | ├── fac 50 | │   ├── iter.rs 51 | │   ├── merge.rs 52 | │   ├── mod.rs 53 | │   ├── of.rs 54 | │   └── timer.rs 55 | ├── lib.rs 56 | ├── observable.rs 57 | ├── observer.rs 58 | ├── op 59 | │   ├── filter.rs 60 | │   ├── map.rs 61 | │   ├── merge.rs 62 | │   ├── mod.rs 63 | │   ├── skip.rs 64 | │   ├── start.rs 65 | │   ├── take.rs 66 | │   └── until.rs 67 | ├── scheduler 68 | │   ├── current_thread_scheduler.rs 69 | │   ├── event_loop_scheduler.rs 70 | │   ├── mod.rs 71 | │   └── new_thread_scheduler.rs 72 | ├── subject 73 | │   ├── behavior_subject.rs 74 | │   ├── mod.rs 75 | │   └── subject.rs 76 | ├── sync 77 | │   ├── act.rs 78 | │   ├── any_send_sync.rs 79 | │   ├── mod.rs 80 | │   ├── re_spin_lock.rs 81 | │   ├── re_spin_mutex.rs 82 | │   ├── recur_cell.rs 83 | │   ├── ss_mark.rs 84 | │   └── yesno.rs 85 | ├── unsub.rs 86 | └── util 87 | ├── clones.rs 88 | └── mod.rs 89 | 90 | 91 | ``` -------------------------------------------------------------------------------- /assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yingDev/rxrs/caf53c7720e85323506fba988cfda431666f2576/assets/logo.png -------------------------------------------------------------------------------- /assets/logo.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yingDev/rxrs/caf53c7720e85323506fba988cfda431666f2576/assets/logo.psd -------------------------------------------------------------------------------- /src/by.rs: -------------------------------------------------------------------------------- 1 | pub unsafe trait RefOrVal 2 | { 3 | type V: Sized; 4 | type RAW: Sized; 5 | 6 | fn as_ref(&self) -> &Self::RAW; 7 | fn into_v(self) -> Self::V; 8 | unsafe fn from_v(v: Self::V) -> Self; 9 | } 10 | 11 | pub struct Ref(*const V); 12 | pub struct Val(V); 13 | 14 | unsafe impl RefOrVal for Ref 15 | { 16 | type V = *const V; 17 | type RAW = V; 18 | 19 | #[inline(always)] fn as_ref(&self) -> &V { unsafe{ &*self.0 } } 20 | #[inline(always)] fn into_v(self) -> Self::V { self.0 } 21 | #[inline(always)] unsafe fn from_v(v: Self::V) -> Self { Ref(v) } 22 | } 23 | unsafe impl RefOrVal for Val 24 | { 25 | type V = V; 26 | type RAW = V; 27 | 28 | #[inline(always)] fn as_ref(&self) -> &V { &self.0 } 29 | #[inline(always)] fn into_v(self) -> Self::V { self.0 } 30 | #[inline(always)] unsafe fn from_v(v: Self::V) -> Self { Val(v) } 31 | 32 | } 33 | unsafe impl RefOrVal for () 34 | { 35 | type V = (); 36 | type RAW = (); 37 | 38 | #[inline(always)] fn as_ref(&self) -> &() { &self } 39 | #[inline(always)] fn into_v(self) -> Self::V { self } 40 | #[inline(always)] unsafe fn from_v(_: Self::V) -> Self { () } 41 | } 42 | -------------------------------------------------------------------------------- /src/error.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Display; 2 | use std::fmt::Formatter; 3 | use std::sync::Arc; 4 | use std::error::Error; 5 | 6 | #[derive(Debug)] 7 | pub struct RxError 8 | { 9 | err: Arc, 10 | handled: bool, 11 | } 12 | 13 | 14 | impl Display for RxError 15 | { 16 | fn fmt(&self, f: &mut Formatter) -> std::fmt::Result 17 | { write!(f, "RxError: {:}; handled={}", self.err, self.handled) } 18 | } 19 | 20 | impl Clone for RxError 21 | { 22 | fn clone(&self) -> Self { RxError{ err: self.err.clone(), handled: false } } 23 | } 24 | 25 | impl RxError 26 | { 27 | pub fn new(e: impl Error+'static) -> Self 28 | { 29 | RxError{ err: Arc::new(e), handled: false } 30 | } 31 | 32 | pub fn set_handled(self) -> Self 33 | { 34 | let mut s = self; 35 | s.handled = true; 36 | s 37 | } 38 | 39 | pub fn simple(source: Option>, msg: impl Into) -> Self 40 | { 41 | #[derive(Debug)] 42 | struct StrError(Option>, String); 43 | impl Display for StrError 44 | { 45 | fn fmt(&self, f: &mut Formatter) -> std::fmt::Result 46 | { write!(f, "RxError: {}; source={:?}", self.1, self.0) } 47 | } 48 | impl Error for StrError 49 | { 50 | fn source(&self) -> Option<&(dyn Error+'static)> { 51 | match &self.0 { 52 | Some(arc) => Some(Arc::as_ref(arc)), 53 | None => None 54 | } 55 | } 56 | } 57 | 58 | Self::new(StrError(source, msg.into())) 59 | 60 | } 61 | 62 | pub fn handle(mut self, f: impl Fn(&Error) -> Option) -> Option 63 | { 64 | let out = f(self.err.as_ref()); 65 | self.handled = true; 66 | out 67 | } 68 | } 69 | 70 | impl Drop for RxError 71 | { 72 | fn drop(&mut self) 73 | { 74 | if ! self.handled { 75 | panic!("Unhandled Error: {}", self.err ) 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /src/fac/iter.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | use std::sync::Mutex; 3 | 4 | pub fn iter_clone(it: It) -> Iter 5 | { 6 | Iter{ it } 7 | } 8 | 9 | pub fn iter_once(it: It) -> Iter> 10 | { 11 | Iter{ it: Wrap(Mutex::new(Some(it))) } 12 | } 13 | 14 | pub struct Iter 15 | { 16 | it: It, 17 | } 18 | 19 | pub struct Wrap(Mutex>); 20 | 21 | impl<'o, It: Iterator+'o> 22 | Observable<'o, NO, Val> 23 | for Iter> 24 | { 25 | fn subscribe(&self, next: impl ActNext<'o, NO, Val>, ec: impl ActEc<'o, NO>+'o) -> Unsub<'o, NO> where Self: Sized 26 | { 27 | let it = self.it.0.lock().unwrap().take(); 28 | 29 | if let Some(it) = it { 30 | for v in it { 31 | if next.stopped() { break; } 32 | next.call(v); 33 | } 34 | ec.call_once(None); 35 | } else { 36 | ec.call_once(Some(RxError::simple(None, "Iter has been consumed"))); 37 | } 38 | 39 | Unsub::done() 40 | } 41 | 42 | fn subscribe_dyn(&self, next: Box>>, ec: Box>) -> Unsub<'o, NO> 43 | { self.subscribe(next, ec) } 44 | } 45 | 46 | impl<'o, It: Iterator+'o + Clone> 47 | Observable<'o, NO, Val> 48 | for Iter 49 | { 50 | fn subscribe(&self, next: impl ActNext<'o, NO, Val>, ec: impl ActEc<'o, NO>+'o) -> Unsub<'o, NO> where Self: Sized 51 | { 52 | for v in self.it.clone() { 53 | if next.stopped() { break; } 54 | next.call(v); 55 | } 56 | 57 | ec.call_once(None); 58 | 59 | Unsub::done() 60 | } 61 | 62 | fn subscribe_dyn(&self, next: Box>>, ec: Box>) -> Unsub<'o, NO> 63 | { self.subscribe(next, ec) } 64 | } 65 | 66 | #[cfg(test)] 67 | mod test 68 | { 69 | use crate::*; 70 | use std::cell::Cell; 71 | 72 | #[test] 73 | fn once() 74 | { 75 | let vec = vec![1,2,3]; 76 | let obs = iter_once(vec.into_iter()); 77 | 78 | let n = Cell::new(0); 79 | obs.subscribe(|i|{ n.replace(i); }, |e: Option|{ assert!(e.is_none()); }); 80 | assert_eq!(n.get(), 3); 81 | 82 | n.replace(0); 83 | obs.subscribe(|i|{ n.replace(i); }, |e: Option| { 84 | assert!(e.is_some()); 85 | e.unwrap().set_handled(); 86 | }); 87 | assert_eq!(n.get(), 0); 88 | } 89 | 90 | #[test] 91 | fn clone() 92 | { 93 | let vec = vec![1,2,3]; 94 | let obs = iter_clone(vec.iter()); 95 | 96 | let n = Cell::new(0); 97 | obs.subscribe(|i:&_| n.replace(*i), |_e| n.replace(n.get()+100) ); 98 | assert_eq!(n.get(), 103); 99 | 100 | n.replace(0); 101 | obs.subscribe(|i:&_|{ n.replace(*i); }, |e: Option|{ 102 | assert!(e.is_none()); 103 | n.replace(n.get()+100); 104 | }); 105 | assert_eq!(n.get(), 103); 106 | } 107 | } -------------------------------------------------------------------------------- /src/fac/merge.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | use std::sync::Arc; 3 | use std::cell::UnsafeCell; 4 | use std::sync::atomic::*; 5 | 6 | pub struct Merge<'s, 'o, SS:YesNo, By: RefOrVal> 7 | { 8 | obs: Vec> 9 | } 10 | 11 | impl<'s, 'o, SS:YesNo, By: RefOrVal> Merge<'s, 'o, SS, By> 12 | { 13 | pub fn new(obs: impl Into>>) -> Self 14 | { 15 | Merge{ obs: obs.into() } 16 | } 17 | } 18 | 19 | impl<'s, 'o, SS:YesNo, By: RefOrVal+'o> 20 | Observable<'o, SS, By> 21 | for Merge<'s, 'o, SS, By> 22 | { 23 | fn subscribe(&self, next: impl ActNext<'o, SS, By>, ec: impl ActEc<'o, SS>) -> Unsub<'o, SS> where Self: Sized 24 | { 25 | let unsub = Unsub::::new(); 26 | let next = Arc::new(SSActNextWrap::new(next)); 27 | let state = Arc::new((unsafe{ AnySendSync::new(UnsafeCell::new(Some(ec))) }, AtomicUsize::new(self.obs.len()))); 28 | 29 | for o in self.obs.iter() { 30 | if unsub.is_done() { break; } 31 | 32 | let ec = forward_ec((unsub.clone(), SSWrap::new(state.clone())), |(unsub, state), e| { 33 | unsub.if_not_done(||{ 34 | if e.is_some() { 35 | unsub.unsub(); 36 | unsafe { &mut *state.0.get() }.take().map_or((), |ec| ec.call_once(e)) 37 | } else if state.1.fetch_sub(1, Ordering::Relaxed) == 1 { 38 | unsub.unsub(); 39 | unsafe { &mut *state.0.get() }.take().map_or((), |ec| ec.call_once(e)) 40 | } 41 | }); 42 | }); 43 | unsub.if_not_done(|| { 44 | unsub.add(o.subscribe(next.clone(), ec)); 45 | }); 46 | } 47 | 48 | unsub 49 | } 50 | 51 | fn subscribe_dyn(&self, next: Box>, err_or_comp: Box>) -> Unsub<'o, SS> 52 | { self.subscribe(next, err_or_comp) } 53 | } 54 | 55 | #[cfg(test)] 56 | mod test 57 | { 58 | use crate::*; 59 | use std::rc::Rc; 60 | use crate::util::clones::Clones; 61 | use std::cell::RefCell; 62 | use std::time::Duration; 63 | use std::sync::Arc; 64 | use std::sync::atomic::*; 65 | 66 | #[test] 67 | fn smoke() 68 | { 69 | let vals = Merge::new(vec![Of::::value(123).into_dyn(), Of::::value(456).into_dyn()]); 70 | vals.subscribe(|v:&_| println!("v={}", *v), |_| println!("complete")); 71 | } 72 | 73 | #[test] 74 | fn ops() 75 | { 76 | let (r1, r2, r3) = Rc::new(RefCell::new(String::new())).clones(); 77 | 78 | let a = Of::::value(1).map(|v:&_| *v).into_dyn(); 79 | let b = a.clone().map(|v| v+1); 80 | let c = b.clone().map(|v| v+1); 81 | let d = c.clone().take(0); 82 | 83 | Merge::new(vec![a, b, c, d]).map(|v| format!("{}", v)).subscribe(move |v:String| { 84 | r1.borrow_mut().push_str(&v); 85 | }, move |_| { 86 | r2.borrow_mut().push_str("ok"); 87 | }); 88 | 89 | assert_eq!("123ok", r3.borrow().as_str()); 90 | } 91 | 92 | #[test] 93 | fn asynced() 94 | { 95 | let (n, n1, n2) = Arc::new(AtomicUsize::new(0)).clones(); 96 | let sch = Arc::new(NewThreadScheduler::new(Arc::new(DefaultThreadFac))); 97 | 98 | let a = Of::::value(1).map(|v:&_| *v).into_dyn(); 99 | let b = Timer::new(Duration::from_millis(10), sch.clone()).take(10).into_dyn(); 100 | let c = Of::::value(2).map(|v:&_| *v).into_dyn(); 101 | let d = Timer::new(Duration::from_millis(20), sch.clone()).take(10).into_dyn(); 102 | 103 | Merge::new(vec![a, b, c, d]).subscribe(move |v| { 104 | n1.fetch_add(v, Ordering::SeqCst); 105 | }, move |_| { 106 | n2.store(n2.load(Ordering::SeqCst) * 10, Ordering::SeqCst); 107 | }); 108 | 109 | ::std::thread::sleep(Duration::from_millis(250)); 110 | 111 | assert_eq!(n.load(Ordering::SeqCst), 930); 112 | 113 | } 114 | } -------------------------------------------------------------------------------- /src/fac/mod.rs: -------------------------------------------------------------------------------- 1 | mod of; 2 | mod timer; 3 | mod iter; 4 | mod merge; 5 | 6 | pub use self::of::*; 7 | pub use self::timer::*; 8 | pub use self::iter::*; 9 | pub use self::merge::*; 10 | 11 | //todo: provide a fasade for all facs ... -------------------------------------------------------------------------------- /src/fac/of.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | use std::marker::PhantomData; 3 | 4 | pub struct Of 5 | { 6 | v: Option, 7 | PhantomData: PhantomData 8 | } 9 | 10 | impl Of 11 | { 12 | pub fn value(v: V) -> Self { Of{ v: Some(v), PhantomData }} 13 | pub fn empty() -> Self { Of{ v: None, PhantomData } } 14 | } 15 | 16 | impl<'o, V:'o, SS:YesNo> 17 | Observable<'o, SS, Ref> 18 | for Of 19 | { 20 | fn subscribe(&self, next: impl ActNext<'o, SS, Ref>, ec: impl ActEc<'o, SS>+'o) -> Unsub<'o, SS> where Self: Sized 21 | { 22 | if ! next.stopped() { 23 | if let Some(v) = self.v.as_ref() { 24 | next.call(v); 25 | } 26 | if !next.stopped() { 27 | ec.call_once(None); 28 | } 29 | } 30 | 31 | Unsub::done() 32 | } 33 | 34 | fn subscribe_dyn(&self, next: Box>>, ec: Box>) -> Unsub<'o, SS> 35 | { self.subscribe(next, ec) } 36 | } 37 | 38 | 39 | #[cfg(test)] 40 | mod test 41 | { 42 | use crate::*; 43 | use std::cell::Cell; 44 | 45 | #[test] 46 | fn smoke() 47 | { 48 | let o = Of::value(123);// Of::value(123); 49 | 50 | let n = std::cell::Cell::new(0); 51 | o.subscribe(|v:&_| { n.replace(*v); }, ()); 52 | 53 | assert_eq!(n.get(), 123); 54 | 55 | let n = std::cell::Cell::new(0); 56 | let o = o.into_dyn(); //Of::value_dyn(123); 57 | 58 | 59 | o.subscribe_dyn(box |v:&_| { n.replace(*v + 1); }, box ()); 60 | 61 | Of::value(123).into_dyn().subscribe_dyn(box |v:&_| { n.replace(*v + 1); }, box()); 62 | 63 | assert_eq!(n.get(), 124); 64 | } 65 | 66 | #[test] 67 | fn empty() 68 | { 69 | let n = Cell::new(0); 70 | let o = Of::empty(); 71 | o.subscribe(|_v:&()| assert!(false, "shouldn't happend"), |_e| { n.replace(1); } ); 72 | 73 | assert_eq!(n.get(), 1); 74 | } 75 | 76 | } -------------------------------------------------------------------------------- /src/fac/timer.rs: -------------------------------------------------------------------------------- 1 | use std::time::Duration; 2 | use crate::*; 3 | use std::marker::PhantomData; 4 | use std::sync::atomic::*; 5 | 6 | pub struct Timer> 7 | { 8 | period: Duration, 9 | scheduler: Sch, 10 | PhantomData: PhantomData 11 | } 12 | 13 | impl<'s, SS:YesNo, Sch: SchedulerPeriodic> Timer 14 | { 15 | pub fn new(period: Duration, scheduler: Sch) -> Self 16 | { 17 | Timer{ period, scheduler, PhantomData } 18 | } 19 | } 20 | 21 | 22 | impl> 23 | Observable<'static, SS, Val> 24 | for Timer 25 | { 26 | fn subscribe(&self, next: impl ActNext<'static, SS, Val>, _ec: impl ActEc<'static, SS>) -> Unsub<'static, SS> 27 | { 28 | let count = SSWrap::new(AtomicUsize::new(0)); 29 | let next = SSActNextWrap::new(next); 30 | 31 | self.scheduler.schedule_periodic(self.period, forward_act((next, count), |(next, count), unsub: Ref>|{ 32 | if !next.stopped() { 33 | next.call(count.fetch_add(1, Ordering::Relaxed)); 34 | } 35 | 36 | if next.stopped() { unsub.as_ref().unsub(); } 37 | })) 38 | } 39 | 40 | fn subscribe_dyn(&self, next: Box>>, ec: Box>) -> Unsub<'static, SS> 41 | { self.subscribe(next, ec) } 42 | } 43 | 44 | #[cfg(test)] 45 | mod test 46 | { 47 | use crate::*; 48 | use crate::util::clones::*; 49 | 50 | use std::time::Duration; 51 | use std::sync::Arc; 52 | use std::rc::Rc; 53 | use std::sync::atomic::*; 54 | use std::sync::Mutex; 55 | use std::cell::RefCell; 56 | 57 | #[test] 58 | fn smoke() 59 | { 60 | let sch = Arc::new(NewThreadScheduler::new(Arc::new(DefaultThreadFac))); 61 | 62 | let (n, n1) = Arc::new(AtomicUsize::new(0)).clones(); 63 | let t = Timer::new(Duration::from_millis(33), sch.clone()); 64 | 65 | t.take(10).subscribe(move |v| { n.store(v, Ordering::SeqCst); }, ()); 66 | assert_ne!(n1.load(Ordering::SeqCst), 9); 67 | 68 | 69 | ::std::thread::sleep(Duration::from_millis(1000)); 70 | assert_eq!(n1.load(Ordering::SeqCst), 9); 71 | } 72 | 73 | #[test] 74 | fn ops() 75 | { 76 | let sch = Arc::new(NewThreadScheduler::new(Arc::new(DefaultThreadFac))); 77 | let timer = Timer::new(Duration::from_millis(10), sch.clone()); 78 | 79 | let (out, out1, out3) = Arc::new(Mutex::new(String::new())).clones(); 80 | 81 | timer.filter(|v: &_| v % 2 == 0 ).take(5).map(|v| format!("{}", v)).subscribe( 82 | move |v: String| { out.lock().unwrap().push_str(&*v); }, 83 | move |_e| out3.lock().unwrap().push_str("ok") 84 | ); 85 | 86 | ::std::thread::sleep(Duration::from_millis(1000)); 87 | 88 | assert_eq!(out1.lock().unwrap().as_str(), "02468ok"); 89 | } 90 | 91 | #[test] 92 | fn multiple_times() 93 | { 94 | let sch = Arc::new(NewThreadScheduler::new(Arc::new(DefaultThreadFac))); 95 | let n = Arc::new(Mutex::new(0)); 96 | let t = Arc::new(Timer::new(Duration::from_millis(10), Arc::new(sch))); 97 | 98 | for i in 0..5 { 99 | let (n1, n2) = n.clone().clones(); 100 | let t = t.clone(); 101 | t.take(1).subscribe( 102 | move |_v| *n1.lock().unwrap() += i, 103 | move |_e| *n2.lock().unwrap() += 1 104 | ); 105 | } 106 | 107 | ::std::thread::sleep(Duration::from_millis(500)); 108 | assert_eq!(*n.lock().unwrap(), 10 + 5); 109 | } 110 | 111 | #[test] 112 | fn as_until_sig() 113 | { 114 | let sch = Arc::new(NewThreadScheduler::new(Arc::new(DefaultThreadFac))); 115 | let (n, n1, n2) = Arc::new(Mutex::new(0)).clones(); 116 | let (s, s1) = Arc::new(Subject::::new()).clones(); 117 | let t = Timer::new(Duration::from_millis(100), sch.clone()); 118 | 119 | s.until(t).subscribe( 120 | move |v: &_| *n1.lock().unwrap() += v , 121 | move |_e| *n2.lock().unwrap() += 100 122 | ); 123 | 124 | s1.next(1); 125 | assert_eq!(*n.lock().unwrap(), 1); 126 | 127 | s1.next(2); 128 | assert_eq!(*n.lock().unwrap(), 3); 129 | 130 | ::std::thread::sleep(Duration::from_millis(10)); 131 | s1.next(3); 132 | assert_eq!(*n.lock().unwrap(), 6); 133 | 134 | ::std::thread::sleep(Duration::from_millis(150)); 135 | assert_eq!(*n.lock().unwrap(), 106); 136 | 137 | s1.next(1234); 138 | s1.complete(); 139 | assert_eq!(*n.lock().unwrap(), 106); 140 | } 141 | 142 | #[test] 143 | fn cur_thread() 144 | { 145 | let sch = Arc::new(CurrentThreadScheduler::new()); 146 | let timer = Timer::new(Duration::from_millis(10), sch.clone()); 147 | 148 | let (out, out1, out3) = Rc::new(RefCell::new(String::new())).clones(); 149 | 150 | timer.filter(|v:&_| v % 2 == 0 ).take(5).map(|v| format!("{}", v)).subscribe( 151 | move |v: String| { out.borrow_mut().push_str(&*v); }, 152 | move |_e| out3.borrow_mut().push_str("ok") 153 | ); 154 | 155 | assert_eq!(out1.borrow().as_str(), "02468ok"); 156 | } 157 | } -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![feature(fn_traits, unboxed_closures, integer_atomics, optin_builtin_traits, fnbox, test, cell_update, box_syntax, impl_trait_in_bindings)] 2 | #![allow(non_snake_case)] 3 | 4 | pub use crate::observable::*; 5 | pub use crate::observer::*; 6 | pub use crate::by::*; 7 | pub use crate::unsub::*; 8 | pub use crate::op::*; 9 | pub use crate::sync::*; 10 | pub use crate::fac::*; 11 | pub use crate::scheduler::*; 12 | pub use crate::subject::*; 13 | pub use crate::error::*; 14 | 15 | pub mod util; 16 | 17 | mod observable; 18 | mod observer; 19 | mod error; 20 | mod sync; 21 | mod op; 22 | mod subject; 23 | mod unsub; 24 | mod fac; 25 | mod scheduler; 26 | mod by; 27 | -------------------------------------------------------------------------------- /src/observable.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | 3 | pub trait Observable<'o, SS:YesNo, By: RefOrVal> 4 | { 5 | fn subscribe (&self, next: impl ActNext<'o, SS, By>, err_or_comp: impl ActEc<'o, SS> ) -> Unsub<'o, SS> where Self: Sized; 6 | fn subscribe_dyn(&self, next: Box>, err_or_comp: Box>) -> Unsub<'o, SS>; 7 | 8 | fn into_dyn<'s>(self) -> DynObservable<'s, 'o, SS, By> where Self: Sized+'s { DynObservable::new(self) } 9 | } 10 | 11 | pub struct DynObservable<'s, 'o, SS:YesNo, By: RefOrVal> 12 | { 13 | pub(crate) src: std::sync::Arc + 's>, 14 | } 15 | 16 | impl<'s, 'o, SS:YesNo, By: RefOrVal> Clone for DynObservable<'s, 'o, SS, By> 17 | { 18 | fn clone(&self) -> Self { Self::from_arc(self.src.clone()) } 19 | } 20 | 21 | unsafe impl<'s, 'o, By: RefOrVal> Send for DynObservable<'s, 'o, YES, By>{} 22 | unsafe impl<'s, 'o, By: RefOrVal> Sync for DynObservable<'s, 'o, YES, By>{} 23 | 24 | impl<'s, 'o, SS:YesNo, By: RefOrVal> DynObservable<'s, 'o, SS, By> 25 | { 26 | pub fn new(src: impl Observable<'o, SS, By>+'s) -> Self { DynObservable{ src: std::sync::Arc::new(src) }} 27 | pub fn from_arc(src: std::sync::Arc+'s>) -> Self { DynObservable{ src }} 28 | pub fn from_box(src: Box+'s>) -> Self { DynObservable{ src: src.into() }} 29 | 30 | pub fn as_impl(&self) -> std::sync::Arc+'s> { self.src.clone() } 31 | 32 | pub fn subscribe(&self, next: impl ActNext<'o, SS, By>, err_or_comp: impl ActEc<'o, SS>) -> Unsub<'o, SS> where Self: Sized 33 | { self.src.subscribe_dyn(box next, box err_or_comp) } 34 | 35 | pub fn subscribe_dyn(&self, next: Box>, err_or_comp: Box>) -> Unsub<'o, SS> 36 | { self.src.subscribe_dyn(next, err_or_comp) } 37 | } 38 | 39 | 40 | 41 | impl<'o, By: RefOrVal, O: Observable<'o, SS, By>, SS:YesNo> 42 | Observable<'o, SS, By> 43 | for std::rc::Rc 44 | { 45 | #[inline(always)] 46 | fn subscribe(&self, next: impl ActNext<'o, SS, By>, ec: impl ActEc<'o, SS>) -> Unsub<'o, SS> where Self: Sized 47 | { std::rc::Rc::as_ref(self).subscribe(next, ec) } 48 | 49 | #[inline(always)] 50 | fn subscribe_dyn(&self, next: Box>, ec: Box>) -> Unsub<'o, SS> 51 | { std::rc::Rc::as_ref(self).subscribe_dyn(next, ec) } 52 | } 53 | 54 | impl<'o, By: RefOrVal, O: Observable<'o, SS, By>, SS:YesNo> 55 | Observable<'o, SS, By> 56 | for std::sync::Arc 57 | { 58 | #[inline(always)] 59 | fn subscribe(&self, next: impl ActNext<'o, SS, By>, ec: impl ActEc<'o, SS>) -> Unsub<'o, SS> where Self: Sized 60 | { std::sync::Arc::as_ref(self).subscribe(next, ec) } 61 | 62 | #[inline(always)] 63 | fn subscribe_dyn(&self, next: Box>, ec: Box>) -> Unsub<'o, SS> 64 | { std::sync::Arc::as_ref(self).subscribe_dyn(next, ec) } 65 | 66 | fn into_dyn<'x>(self) -> DynObservable<'x, 'o, SS, By> where Self: Sized+'x 67 | { DynObservable::from_arc(self) } 68 | } 69 | 70 | 71 | impl<'o, By: RefOrVal, O: Observable<'o, SS, By>, SS:YesNo> 72 | Observable<'o, SS, By> 73 | for Box 74 | { 75 | #[inline(always)] 76 | fn subscribe(&self, next: impl ActNext<'o, SS, By>, ec: impl ActEc<'o, SS>) -> Unsub<'o, SS> where Self: Sized 77 | { Box::as_ref(self).subscribe(next, ec) } 78 | 79 | #[inline(always)] 80 | fn subscribe_dyn(&self, next: Box>, ec: Box>) -> Unsub<'o, SS> 81 | { Box::as_ref(self).subscribe_dyn(next, ec) } 82 | 83 | fn into_dyn<'x>(self) -> DynObservable<'x, 'o, SS, By> where Self: Sized+'x 84 | { DynObservable::from_box(self) } 85 | } 86 | 87 | impl<'s, 'o, SS:YesNo, By: RefOrVal> 88 | Observable<'o, SS, By> 89 | for Box+'s> 90 | { 91 | #[inline(always)] 92 | fn subscribe(&self, next: impl ActNext<'o, SS, By>, ec: impl ActEc<'o, SS>) -> Unsub<'o, SS> where Self: Sized 93 | { self.subscribe_dyn(box next, box ec) } 94 | 95 | #[inline(always)] 96 | fn subscribe_dyn(&self, next: Box>, ec: Box>) -> Unsub<'o, SS> 97 | { Box::as_ref(self).subscribe_dyn(next, ec) } 98 | } 99 | 100 | impl<'s, 'o, SS:YesNo, By: RefOrVal> 101 | Observable<'o, SS, By> 102 | for std::sync::Arc+'s> 103 | { 104 | #[inline(always)] 105 | fn subscribe(&self, next: impl ActNext<'o, SS, By>, ec: impl ActEc<'o, SS>) -> Unsub<'o, SS> where Self: Sized 106 | { self.subscribe_dyn(box next, box ec) } 107 | 108 | #[inline(always)] 109 | fn subscribe_dyn(&self, next: Box>, ec: Box>) -> Unsub<'o, SS> 110 | { std::sync::Arc::as_ref(self).subscribe_dyn(next, ec) } 111 | 112 | fn into_dyn<'x>(self) -> DynObservable<'x, 'o, SS, By> where Self: Sized+'x 113 | { DynObservable::from_arc(self) } 114 | } -------------------------------------------------------------------------------- /src/observer.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | use std::marker::PhantomData; 3 | use std::sync::Arc; 4 | 5 | //todo: just use crate::sync::Act's ? 6 | 7 | pub unsafe trait ActNext <'o, SS:YesNo, BY: RefOrVal> : 'o 8 | { 9 | fn call(&self, v: BY::V); 10 | fn stopped(&self) -> bool { false } 11 | } 12 | 13 | pub unsafe trait ActEc<'o, SS:YesNo> : 'o 14 | { 15 | fn call_once(self, e: Option); 16 | } 17 | 18 | pub unsafe trait ActEcBox<'o, SS:YesNo> : 'o 19 | { 20 | fn call_box(self: Box, e: Option); 21 | } 22 | 23 | unsafe impl<'o, SS:YesNo, A: ActEc<'o, SS>> 24 | ActEcBox<'o, SS> 25 | for A 26 | { 27 | fn call_box(self: Box, e: Option) { self.call_once(e) } 28 | } 29 | 30 | unsafe impl<'o, V, R, F: Fn(V)->R+'o> 31 | ActNext<'o, NO, Val> 32 | for F 33 | { 34 | fn call(&self, by: V) { self.call((by,)); } 35 | } 36 | 37 | unsafe impl<'o, V, R, F: Fn(&V)->R+'o> 38 | ActNext<'o, NO, Ref> 39 | for F 40 | { 41 | fn call(&self, by: *const V) { self.call((unsafe{ &*by },)); } 42 | } 43 | 44 | unsafe impl<'o, V, R, F: Fn(V)->R+'o+Send+Sync> 45 | ActNext<'o, YES, Val> 46 | for F 47 | { 48 | fn call(&self, by: V) { self.call((by,)); } 49 | } 50 | 51 | unsafe impl<'o, V, R, F: Fn(&V)->R+'o+Send+Sync> 52 | ActNext<'o, YES, Ref> 53 | for F 54 | { 55 | fn call(&self, by: *const V) { self.call((unsafe { &*by },)); } 56 | } 57 | 58 | unsafe impl<'o, SS:YesNo, By: RefOrVal> 59 | ActNext<'o, SS, By> 60 | for () 61 | { 62 | fn call(&self, _by: By::V) { } 63 | } 64 | 65 | unsafe impl<'o, SS:YesNo, BY: RefOrVal, N: ActNext<'o, SS, BY>, STOP: Act+'o> 66 | ActNext<'o, SS, BY> 67 | for (N, STOP) 68 | { 69 | #[inline(always)]fn call(&self, v: BY::V) { self.0.call(v); } 70 | #[inline(always)]fn stopped(&self) -> bool {self.1.call(()) } 71 | } 72 | 73 | 74 | unsafe impl<'o, R, F:FnOnce(Option)->R+'o> 75 | ActEc<'o, NO> 76 | for F 77 | { 78 | fn call_once(self, e: Option) { self(e); } 79 | } 80 | 81 | unsafe impl<'o, R, F:FnOnce(Option)->R+'o+Send+Sync> 82 | ActEc<'o, YES> 83 | for F 84 | { 85 | fn call_once(self, e: Option) { self(e); } 86 | } 87 | 88 | unsafe impl<'o, SS:YesNo, BY:RefOrVal+'o> 89 | ActNext<'o, SS, BY> 90 | for Box> 91 | { 92 | fn call(&self, v: BY::V) { Box::as_ref(self).call(v) } 93 | fn stopped(&self) -> bool { Box::as_ref(self).stopped() } 94 | } 95 | 96 | unsafe impl<'o, SS:YesNo> 97 | ActEc<'o, SS> 98 | for Box> 99 | { 100 | fn call_once(self, e: Option) { self.call_box(e) } 101 | } 102 | 103 | unsafe impl<'o, SS:YesNo> 104 | ActEc<'o, SS> 105 | for () 106 | { 107 | fn call_once(self, _e: Option) { } 108 | } 109 | 110 | 111 | //todo: ergonomics 112 | 113 | pub struct SSActNextWrap 114 | { 115 | next: A, 116 | PhantomData: PhantomData<(SS, By)> 117 | } 118 | 119 | impl<'o, SS:YesNo, By: RefOrVal, A> SSActNextWrap 120 | { 121 | pub fn new(next: A) -> Self where A: ActNext<'o, SS, By> 122 | { SSActNextWrap{ next, PhantomData } } 123 | } 124 | 125 | unsafe impl<'o, SS:YesNo, By: RefOrVal, A: ActNext<'o, SS, By>> 126 | Ssmark 127 | for SSActNextWrap {} 128 | 129 | unsafe impl<'o, SS:YesNo, By: RefOrVal+'o, A: ActNext<'o, SS, By>> 130 | ActNext<'o, SS, By> 131 | for SSActNextWrap 132 | { 133 | #[inline(always)] fn call(&self, v: ::V) { self.next.call(v) } 134 | #[inline(always)] fn stopped(&self) -> bool { self.next.stopped() } 135 | } 136 | 137 | unsafe impl<'o, SS:YesNo, By: RefOrVal+'o, A: ActNext<'o, SS, By>> 138 | ActNext<'o, SS, By> 139 | for Arc> 140 | { 141 | #[inline(always)] fn call(&self, v: ::V) { Arc::as_ref(self).next.call(v) } 142 | #[inline(always)] fn stopped(&self) -> bool { Arc::as_ref(self).next.stopped() } 143 | } 144 | 145 | pub struct SSActEcWrap 146 | { 147 | pub ec: A, 148 | } 149 | 150 | impl SSActEcWrap 151 | { 152 | pub fn new<'o, SS:YesNo>(ec: A) -> Self where A: ActEc<'o, SS> 153 | { SSActEcWrap{ ec } } 154 | 155 | pub fn into_inner(self) -> A { self.ec } 156 | } 157 | 158 | unsafe impl<'o, SS:YesNo, A: ActEc<'o, SS>> 159 | Ssmark 160 | for SSActEcWrap {} 161 | 162 | 163 | 164 | 165 | //todo: rename & organize 166 | 167 | unsafe impl<'o, SS:YesNo, N: Ssmark+'o, Caps: Ssmark+'o, FBy: RefOrVal+'o> 168 | ActNext<'o, SS, FBy> 169 | for SsForwardbool)> 170 | { 171 | #[inline(always)] 172 | fn call(&self, v: FBy::V) 173 | { 174 | let (next, caps, fnext, _) = &self.captures; 175 | fnext(next, caps, unsafe { FBy::from_v(v) }) 176 | } 177 | 178 | #[inline(always)] 179 | fn stopped(&self) -> bool 180 | { 181 | let (next, caps, _, stop) = &self.captures; 182 | stop(next, caps) 183 | } 184 | } 185 | 186 | #[inline(always)] 187 | pub fn forward_next<'o, SS:YesNo, By: RefOrVal+'o, N: Ssmark+'o, Caps: Ssmark+'o> 188 | (next:N, captures: Caps, fnext: fn(&N, &Caps, By), fstop: fn(&N, &Caps)->bool) 189 | -> SsForwardbool)> 190 | { 191 | SsForward::new((next, captures, fnext, fstop)) 192 | } 193 | 194 | unsafe impl<'o, SS:YesNo, By: RefOrVal+'o, N: Ssmark+'o, Caps: Ssmark+'o> 195 | ActNext<'o, SS, By> 196 | for Arcbool)>> 197 | { 198 | #[inline(always)] fn call(&self, v: ::V) { Arc::as_ref(self).call(v) } 199 | #[inline(always)] fn stopped(&self) -> bool { Arc::as_ref(self).stopped() } 200 | } 201 | 202 | #[inline(always)] 203 | pub fn forward_ec<'o, SS:YesNo, Caps: Ssmark+'o> 204 | (captures: Caps, fec: fn(Caps, Option)) 205 | -> SsForward))> 206 | { 207 | SsForward::new((captures, fec)) 208 | } 209 | 210 | 211 | unsafe impl<'o, SS:YesNo, Caps: Ssmark+'o> 212 | ActEc<'o, SS> 213 | for SsForward))> 214 | { 215 | #[inline(always)] 216 | fn call_once(self, e: Option) 217 | { 218 | let (caps, fec) = self.captures; 219 | fec(caps, e) 220 | } 221 | } 222 | 223 | 224 | #[inline(always)] 225 | pub fn forward_act<'o, SS:YesNo, By: RefOrVal+'o, Caps: Ssmark+'o> 226 | (captures: Caps, fact: fn(&Caps, By)) 227 | -> SsForward 228 | { 229 | SsForward::new((captures, fact)) 230 | } 231 | 232 | 233 | unsafe impl> 234 | Act 235 | for SsForward 236 | { 237 | #[inline(always)] 238 | fn call(&self, v: By::V) 239 | { 240 | let (caps, fec) = &self.captures; 241 | fec(caps, unsafe { By::from_v(v) }) 242 | } 243 | } -------------------------------------------------------------------------------- /src/op/filter.rs: -------------------------------------------------------------------------------- 1 | use std::marker::PhantomData; 2 | use std::sync::Arc; 3 | use crate::*; 4 | 5 | pub struct FilterOp 6 | { 7 | f: Arc, 8 | src: Src, 9 | PhantomData: PhantomData<(SS)> 10 | } 11 | 12 | pub trait ObsFilterOp, bool>> : Sized 13 | { 14 | fn filter(self, f: F) -> FilterOp { FilterOp{ f: Arc::new(f), src: self, PhantomData} } 15 | } 16 | 17 | impl<'o, SS:YesNo, VBy: RefOrVal, Src: Observable<'o, SS, VBy>, F: Act, bool>+'o> 18 | ObsFilterOp 19 | for Src {} 20 | 21 | pub trait DynObsFilterOp<'o, SS: YesNo, VBy: RefOrVal+'o, F: Act, bool>+'o> 22 | { 23 | fn filter(self, f: F) -> Self; 24 | } 25 | 26 | impl<'o, SS:YesNo, VBy: RefOrVal+'o, F: Act, bool>+'o> 27 | DynObsFilterOp<'o, SS, VBy, F> 28 | for DynObservable<'o, 'o, SS, VBy> 29 | { 30 | fn filter(self, f: F) -> Self 31 | { FilterOp{ f: Arc::new(f), src: self.src, PhantomData }.into_dyn() } 32 | } 33 | 34 | impl<'o, SS:YesNo, VBy: RefOrVal+'o, Src: Observable<'o, SS, VBy>, F: Act, bool>+'o> 35 | Observable<'o, SS, VBy> 36 | for FilterOp 37 | { 38 | fn subscribe(&self, next: impl ActNext<'o, SS, VBy>, ec: impl ActEc<'o, SS>) -> Unsub<'o, SS> where Self: Sized 39 | { 40 | let next = SSActNextWrap::new(next); 41 | let f = act_sendsync(self.f.clone()); 42 | let sub = Unsub::::new(); 43 | 44 | sub.clone().added_each(self.src.subscribe( 45 | forward_next(next, (f, sub), |n, (f, sub), v: VBy| { 46 | if f.call(v.as_ref()) { 47 | sub.if_not_done(|| n.call(v.into_v())); 48 | } 49 | }, |s, _| s.stopped()), 50 | ec 51 | )) 52 | } 53 | 54 | fn subscribe_dyn(&self, next: Box>, ec: Box>) -> Unsub<'o, SS> 55 | { self.subscribe(next, ec) } 56 | } 57 | 58 | 59 | #[cfg(test)] 60 | mod test 61 | { 62 | use crate::*; 63 | use crate::util::clones::*; 64 | 65 | use std::cell::Cell; 66 | use std::sync::atomic::*; 67 | use std::rc::Rc; 68 | use std::sync::Arc; 69 | 70 | #[test] 71 | fn smoke() 72 | { 73 | let n = Cell::new(0); 74 | let (input, output) = Rc::new(Subject::::new()).clones(); 75 | 76 | output.filter(|v:&_| v % 2 == 0).subscribe(|v:&_| { n.replace(n.get() + *v); }, ()); 77 | 78 | for i in 0..10 { 79 | input.next(i); 80 | } 81 | 82 | assert_eq!(n.get(), 20); 83 | 84 | let (n, n1) = Arc::new(AtomicUsize::new(0)).clones(); 85 | let (input, output) = Rc::new(Subject::::new()).clones(); 86 | output.into_dyn().filter(|v:&_| v % 2 == 0).subscribe_dyn(box move |_v:&_| { n.fetch_add(1, Ordering::SeqCst); }, box()); 87 | 88 | input.next(1); 89 | input.next(2); 90 | input.next(3); 91 | 92 | assert_eq!(n1.load(Ordering::SeqCst), 1); 93 | } 94 | 95 | #[test] 96 | fn cb_safe() 97 | { 98 | let n = Cell::new(0); 99 | let (input, output, side_effect) = Rc::new(Subject::::new()).clones(); 100 | 101 | output.filter(move |v:&_| { 102 | side_effect.complete(); 103 | v % 2 == 0 104 | }).subscribe(|v:&_| { n.replace(n.get() + *v); }, ()); 105 | 106 | for i in 0..10 { 107 | input.next(i); 108 | } 109 | 110 | assert_eq!(n.get(), 0); 111 | } 112 | 113 | #[test] 114 | fn should_complete() 115 | { 116 | let (n1, n2, n3) = Rc::new(Cell::new(0)).clones(); 117 | let (input, output) = Rc::new(Subject::::new()).clones(); 118 | 119 | output.filter(move |_:&_| true).subscribe( 120 | move |v:&_| { n1.replace(n1.get() + *v); }, 121 | move |_| { n2.replace(n2.get() + 1); }); 122 | 123 | input.next(1); 124 | input.next(2); 125 | 126 | assert_eq!(n3.get(), 3); 127 | 128 | input.complete(); 129 | 130 | assert_eq!(n3.get(), 4); 131 | } 132 | 133 | #[test] 134 | fn thread() 135 | { 136 | let s = Subject::::new(); 137 | let filtered = s.filter(|i:&_| i % 2 == 0 ); 138 | 139 | ::std::thread::spawn(move ||{ 140 | filtered.subscribe(|i:&_| println!("ok{}",i), ()); 141 | }).join().ok(); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/op/map.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | use std::marker::PhantomData; 3 | use std::sync::Arc; 4 | 5 | pub struct MapOp 6 | { 7 | f: Arc, 8 | src: Src, 9 | PhantomData: PhantomData<(SS, AnySendSync)> 10 | } 11 | 12 | pub trait ObsMapOp<'o, SS: YesNo, VBy: RefOrVal, VOut, F: Act+'o> : Sized 13 | { 14 | fn map(self, f: F) -> MapOp { MapOp{ f: Arc::new(f), src: self, PhantomData } } 15 | } 16 | 17 | impl<'o, SS:YesNo, VBy: RefOrVal+'o, VOut, Src: Observable<'o, SS, VBy>+'o, F: Act+'o> 18 | ObsMapOp<'o, SS, VBy, VOut, F> for Src {} 19 | 20 | pub trait DynObsMapOp<'o, SS: YesNo, VBy: RefOrVal+'o, VOut:'o, F: Act+'o> 21 | { 22 | fn map(self, f: F) -> DynObservable<'o, 'o, SS, Val>; 23 | } 24 | 25 | impl<'o, SS:YesNo, VBy: RefOrVal+'o, VOut:'o, F: Act+'o> 26 | DynObsMapOp<'o, SS, VBy, VOut, F> 27 | for DynObservable<'o, 'o, SS, VBy> 28 | { 29 | fn map(self, f: F) -> DynObservable<'o, 'o, SS, Val> 30 | { MapOp{ f: Arc::new(f), src: self.src, PhantomData }.into_dyn() } 31 | } 32 | 33 | 34 | impl<'s, 'o, SS:YesNo, VOut: 'o, VBy: RefOrVal+'o, Src: Observable<'o, SS, VBy>+'s, F: Act+'o> 35 | Observable<'o, SS, Val> 36 | for MapOp 37 | { 38 | fn subscribe(&self, next: impl ActNext<'o, SS, Val>, ec: impl ActEc<'o, SS>) -> Unsub<'o, SS> where Self: Sized 39 | { 40 | let next = SSActNextWrap::new(next); 41 | let f = act_sendsync(self.f.clone()); 42 | let sub = Unsub::new(); 43 | 44 | sub.clone().added_each(self.src.subscribe(forward_next(next, (sub, f), |next, (sub, f), v: VBy| { 45 | let v = f.call(v.into_v()); 46 | sub.if_not_done(|| next.call(v)); 47 | }, |s,_|s.stopped()), ec)) 48 | } 49 | 50 | fn subscribe_dyn(&self, next: Box>>, ec: Box>) -> Unsub<'o, SS> 51 | { self.subscribe(next, ec) } 52 | } 53 | 54 | #[cfg(test)] 55 | mod test 56 | { 57 | use crate::*; 58 | use crate::util::clones::*; 59 | 60 | use std::cell::RefCell; 61 | use std::cell::Cell; 62 | use std::rc::Rc; 63 | use std::sync::Arc; 64 | use std::sync::atomic::*; 65 | 66 | #[test] 67 | fn smoke() 68 | { 69 | let n = Cell::new(0); 70 | let o = Of::value(123); 71 | o.map(|v: &_| *v * 2).subscribe(|v| { n.replace(v);}, ()); 72 | assert_eq!(n.get(), 246); 73 | 74 | let o = Of::value("B".to_owned()); 75 | 76 | let result = RefCell::new(String::new()); 77 | let mapped = o.into_dyn().map(|s:&_| format!("A{}", *s)).map(|s| format!("{}C", s)); 78 | 79 | mapped.subscribe(|v:String| result.borrow_mut().push_str(&v), ()); 80 | 81 | assert_eq!(result.borrow().as_str(), "ABC"); 82 | } 83 | 84 | #[test] 85 | fn unsub() 86 | { 87 | let n = Cell::new(0); 88 | let (i,o) = Rc::new(Subject::::new()).clones(); 89 | let unsub = o.map(|v:&_| *v+1).subscribe(|v| { n.replace(v); }, ()); 90 | 91 | i.next(1); 92 | assert_eq!(n.get(), 2); 93 | 94 | unsub(); 95 | i.next(2); 96 | assert_eq!(n.get(), 2); 97 | } 98 | 99 | #[test] 100 | fn boxed() 101 | { 102 | let o = Of::::value(123).into_dyn().map(|v:&_| v+1).map(|v| v*v); 103 | o.subscribe_dyn(box |v| println!("v={}", v), box ()); 104 | } 105 | 106 | #[test] 107 | fn thread() 108 | { 109 | let (n, n1) = Arc::new(AtomicI32::new(0)).clones(); 110 | let (i, o, send) = Arc::new(Subject::::new()).clones(); 111 | 112 | o.subscribe(|_: &_|{}, ()); 113 | 114 | o.map(|v:&_| v+1).subscribe(move |v:i32| {n.store(v, Ordering::SeqCst); }, ()); 115 | 116 | let s = send.map(|v:&_| v * v); 117 | ::std::thread::spawn(move ||{ 118 | i.next(123); 119 | 120 | s.subscribe(|_|{}, ()); 121 | }).join().ok(); 122 | 123 | assert_eq!(n1.load(Ordering::SeqCst), 124); 124 | } 125 | 126 | #[test] 127 | fn drops_closure() 128 | { 129 | let (r, r1) = Rc::new(0).clones(); 130 | 131 | assert_eq!(Rc::strong_count(&r), 2); 132 | 133 | let o = Of::value(123); 134 | 135 | o.map(move |_:&i32| Rc::strong_count(&r1)).subscribe((), ()); 136 | 137 | assert_eq!(Rc::strong_count(&r), 1); 138 | } 139 | 140 | #[test] 141 | fn should_complete() 142 | { 143 | let (n1, n2, n3) = Rc::new(Cell::new(0)).clones(); 144 | let (input, output) = Rc::new(Subject::::new()).clones(); 145 | 146 | output.map(move |v:&_| *v).subscribe( 147 | move |v| { n1.replace(n1.get() + v); }, 148 | move |_| { n2.replace(n2.get() + 1); }); 149 | 150 | input.next(1); 151 | input.next(2); 152 | 153 | assert_eq!(n3.get(), 3); 154 | 155 | input.complete(); 156 | 157 | assert_eq!(n3.get(), 4); 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /src/op/merge.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | 3 | pub trait ObsMergeOp<'o, SS:YesNo, By: RefOrVal> : Sized 4 | { 5 | fn merge(self, other: impl Observable<'o, SS, By>+'o) -> Merge<'o, 'o, SS, By>; 6 | } 7 | 8 | impl<'o, SS:YesNo, By: RefOrVal+'o, Src: Observable<'o, SS, By>+'o> 9 | ObsMergeOp<'o, SS, By> 10 | for Src 11 | { 12 | fn merge(self, other: impl Observable<'o, SS, By>+'o) -> Merge<'o, 'o, SS, By> 13 | { 14 | Merge::new(vec![self.into_dyn(), other.into_dyn()]) 15 | } 16 | } 17 | 18 | pub trait DynObsMergeOp<'o, SS:YesNo, By: RefOrVal> : Sized 19 | { 20 | fn merge(self, other: impl Observable<'o, SS, By>+'o) -> DynObservable<'o, 'o, SS, By>; 21 | } 22 | 23 | impl<'o, SS:YesNo, By: RefOrVal+'o> 24 | DynObsMergeOp<'o, SS, By> 25 | for DynObservable<'o, 'o, SS, By> 26 | { 27 | fn merge(self, other: impl Observable<'o, SS, By>+'o) -> DynObservable<'o, 'o, SS, By> 28 | { 29 | Merge::new(vec![self, other.into_dyn()]).into_dyn() 30 | } 31 | } 32 | 33 | #[cfg(test)] 34 | mod test 35 | { 36 | use crate::*; 37 | use std::rc::Rc; 38 | use std::cell::RefCell; 39 | use crate::util::clones::Clones; 40 | 41 | #[test] 42 | fn smoke() 43 | { 44 | let (n, n1, n2) = Rc::new(RefCell::new(String::new())).clones(); 45 | 46 | let a = Of::value(123); 47 | let b = Of::::value(456); 48 | 49 | a.merge(b).subscribe(|v:&_|{ 50 | n1.borrow_mut().push_str(&format!("{}", v)); 51 | }, |_| { 52 | n2.borrow_mut().push_str("ok"); 53 | }); 54 | 55 | assert_eq!("123456ok", n.borrow().as_str()); 56 | } 57 | } -------------------------------------------------------------------------------- /src/op/mod.rs: -------------------------------------------------------------------------------- 1 | mod map; 2 | mod filter; 3 | mod until; 4 | mod take; 5 | mod skip; 6 | mod start; 7 | mod merge; 8 | 9 | pub use self::map::*; 10 | pub use self::filter::*; 11 | pub use self::until::*; 12 | pub use self::take::*; 13 | pub use self::skip::*; 14 | pub use self::start::*; 15 | pub use self::merge::*; -------------------------------------------------------------------------------- /src/op/skip.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | use std::marker::PhantomData; 3 | use std::cell::Cell; 4 | 5 | pub struct SkipOp 6 | { 7 | count: usize, 8 | src: Src, 9 | PhantomData: PhantomData<(SS)> 10 | } 11 | 12 | pub trait ObsSkipOp : Sized 13 | { 14 | fn skip(self, count: usize) -> SkipOp { SkipOp{ count, src: self, PhantomData} } 15 | } 16 | 17 | impl<'o, VBy: RefOrVal, Src: Observable<'o, SS, VBy>+'o, SS:YesNo> 18 | ObsSkipOp 19 | for Src {} 20 | 21 | 22 | pub trait DynObsSkipOp<'o, SS: YesNo, VBy: RefOrVal+'o> 23 | { 24 | fn skip(self, count: usize) -> Self; 25 | } 26 | 27 | impl<'o, SS:YesNo, VBy: RefOrVal+'o> 28 | DynObsSkipOp<'o, SS, VBy> 29 | for DynObservable<'o, 'o, SS, VBy> 30 | { 31 | fn skip(self, count: usize) -> Self 32 | { SkipOp{ count, src: self.src, PhantomData }.into_dyn() } 33 | } 34 | 35 | impl<'o, SS:YesNo, VBy: RefOrVal+'o, Src: Observable<'o, SS, VBy>> 36 | Observable<'o, SS, VBy> 37 | for SkipOp 38 | { 39 | fn subscribe(&self, next: impl ActNext<'o, SS, VBy>, ec: impl ActEc<'o, SS>) -> Unsub<'o, SS> where Self: Sized 40 | { 41 | if self.count == 0 { 42 | return self.src.subscribe(next, ec); 43 | } 44 | 45 | let count = unsafe{ AnySendSync::new(Cell::new(self.count)) }; 46 | let next = SSActNextWrap::new(next); 47 | let sub = Unsub::new(); 48 | 49 | sub.added_each(self.src.subscribe( 50 | forward_next(next, SSWrap::new(count), |next, count, v:VBy| { 51 | if count.get() == 0 { 52 | next.call(v.into_v()); 53 | } else { 54 | count.replace(count.get() - 1); 55 | } 56 | }, |s, _| s.stopped()), 57 | 58 | ec 59 | )) 60 | } 61 | 62 | fn subscribe_dyn(&self, next: Box>, ec: Box>) -> Unsub<'o, SS> 63 | { self.subscribe(next, ec) } 64 | } 65 | 66 | #[cfg(test)] 67 | mod test 68 | { 69 | use crate::*; 70 | use crate::util::clones::*; 71 | 72 | use std::cell::Cell; 73 | use std::rc::Rc; 74 | 75 | #[test] 76 | fn smoke() 77 | { 78 | let (n, n1, n2) = Rc::new(Cell::new(0)).clones(); 79 | let (s, s1) = Rc::new(Subject::::new()).clones(); 80 | 81 | s.skip(3).subscribe( 82 | |v:&_| { n.replace(*v); }, 83 | |_e| { n1.replace(n1.get() + 100); } 84 | ); 85 | 86 | s1.next(1); 87 | assert_eq!(n2.get(), 0); 88 | 89 | s1.next(2); 90 | assert_eq!(n2.get(), 0); 91 | 92 | s1.next(3); 93 | assert_eq!(n2.get(), 0); 94 | 95 | s1.next(4); 96 | assert_eq!(n2.get(), 4); 97 | 98 | s1.complete(); 99 | assert_eq!(n2.get(), 104); 100 | } 101 | 102 | #[test] 103 | fn of() 104 | { 105 | let n = Cell::new(0); 106 | Of::value(123).skip(100).subscribe( 107 | |v:&_| { n.replace(*v); }, 108 | |_e| { n.replace(n.get() + 100); } 109 | ); 110 | 111 | assert_eq!(n.get(), 100); 112 | } 113 | 114 | #[test] 115 | fn zero() 116 | { 117 | let n = Cell::new(0); 118 | Of::value(123).skip(0).subscribe( 119 | |v:&_| { n.replace(*v); }, 120 | |_e| { n.replace(n.get() + 100); } 121 | ); 122 | 123 | assert_eq!(n.get(), 223); 124 | } 125 | 126 | } 127 | -------------------------------------------------------------------------------- /src/op/start.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | use self::StartOpType::*; 3 | use std::marker::PhantomData; 4 | use std::sync::Mutex; 5 | 6 | pub mod StartOpType { 7 | pub struct ONCE; 8 | pub struct CLONE; 9 | pub struct FN; 10 | pub struct VALREF; 11 | pub struct REF; 12 | } 13 | 14 | 15 | pub struct StartOp 16 | { 17 | src: Src, 18 | v: V, 19 | PhantomData: PhantomData 20 | } 21 | 22 | pub trait ObsStartValOp<'o, V, SS:YesNo> : Sized 23 | { 24 | fn start_once(self, v: V) -> StartOp>, ONCE>; 25 | fn start(self, v: V) -> StartOp where V: Clone+'o; 26 | fn start_fn(self, f: F) -> StartOp where F: 'o+Fn()->V; 27 | } 28 | 29 | pub trait ObsStartRefOp<'o, V:'o, SS:YesNo> : Sized 30 | { 31 | fn start(self, v: V) -> StartOp; 32 | fn start_ref(self, v: &'o V) -> StartOp; 33 | } 34 | 35 | impl<'o, V, SS:YesNo, Src: Observable<'o, SS, Val>> 36 | ObsStartValOp<'o, V, SS> 37 | for Src 38 | { 39 | fn start_once(self, v: V) -> StartOp>, ONCE> { StartOp{ src: self, v: Mutex::new(Some(v)), PhantomData } } 40 | fn start(self, v: V) -> StartOp where V: Clone + 'o { StartOp{ src: self, v, PhantomData} } 41 | fn start_fn(self, f: F) -> StartOp where F: Fn() -> V + 'o { StartOp{ src: self, v: f, PhantomData} } 42 | } 43 | 44 | impl<'o, V:'o, SS:YesNo, Src: Observable<'o, SS, Ref>> 45 | ObsStartRefOp<'o, V, SS> 46 | for Src 47 | { 48 | fn start(self, v: V) -> StartOp { StartOp{ src: self, v, PhantomData} } 49 | fn start_ref(self, v: &'o V) -> StartOp { StartOp{ src: self, v, PhantomData} } 50 | } 51 | 52 | //dyn === 53 | 54 | pub trait DynObsStartValOp<'o, V, SS:YesNo> : Sized 55 | { 56 | fn start_once(self, v: V) -> DynObservable<'o, 'o, SS, Val>; 57 | fn start(self, v: V) -> DynObservable<'o, 'o, SS, Val> where V: Clone+'o; 58 | fn start_fn(self, f: F) -> DynObservable<'o, 'o, SS, Val> where F: 'o+Fn()->V; 59 | } 60 | 61 | pub trait DynObsStartRefOp<'o, V:'o, SS:YesNo> : Sized 62 | { 63 | fn start(self, v: V) -> DynObservable<'o, 'o, SS, Ref>; 64 | fn start_ref(self, v: &'o V) -> DynObservable<'o, 'o, SS, Ref>; 65 | } 66 | 67 | impl<'o, V:'o, SS:YesNo> 68 | DynObsStartValOp<'o, V, SS> 69 | for DynObservable<'o, 'o, SS, Val> 70 | { 71 | fn start_once(self, v: V) -> DynObservable<'o, 'o, SS, Val> { StartOp{ src: self.src, v: Mutex::new(Some(v)), PhantomData }.into_dyn() } 72 | fn start(self, v: V) -> DynObservable<'o, 'o, SS, Val> where V: Clone + 'o { StartOp{ src: self.src, v, PhantomData}.into_dyn() } 73 | fn start_fn(self, f: F) -> DynObservable<'o, 'o, SS, Val> where F: Fn() -> V + 'o { StartOp{ src: self.src, v: f, PhantomData}.into_dyn() } 74 | } 75 | 76 | impl<'o, V:'o, SS:YesNo> 77 | DynObsStartRefOp<'o, V, SS> 78 | for DynObservable<'o, 'o, SS, Ref> 79 | { 80 | fn start(self, v: V) -> DynObservable<'o, 'o, SS, Ref> { StartOp{ src: self.src, v, PhantomData}.into_dyn() } 81 | fn start_ref(self, v: &'o V) -> DynObservable<'o, 'o, SS, Ref> { StartOp{ src: self.src, v, PhantomData}.into_dyn() } 82 | } 83 | 84 | 85 | 86 | 87 | impl<'o, V:'o, SS:YesNo, Src: Observable<'o, SS, Val>+'o> 88 | Observable<'o, SS, Val> 89 | for StartOp>, ONCE> 90 | { 91 | fn subscribe(&self, next: impl ActNext<'o, SS, Val>, err_or_comp: impl ActEc<'o, SS>) -> Unsub<'o, SS> where Self: Sized { 92 | if ! next.stopped() { 93 | if let Some(v) = self.v.lock().unwrap().take() { 94 | next.call(v); 95 | if ! next.stopped() { 96 | return self.src.subscribe(next, err_or_comp); 97 | } 98 | 99 | } else { 100 | err_or_comp.call_once(Some(RxError::simple(None, "value consumed"))); 101 | } 102 | } 103 | 104 | Unsub::done() 105 | } 106 | 107 | fn subscribe_dyn(&self, next: Box>>, err_or_comp: Box>) -> Unsub<'o, SS> 108 | { self.subscribe(next, err_or_comp) } 109 | } 110 | 111 | impl<'o, V:Clone+'o, SS:YesNo, Src: Observable<'o, SS, Val>+'o> 112 | Observable<'o, SS, Val> 113 | for StartOp 114 | { 115 | fn subscribe(&self, next: impl ActNext<'o, SS, Val>, err_or_comp: impl ActEc<'o, SS>) -> Unsub<'o, SS> where Self: Sized { 116 | if ! next.stopped() { 117 | let v = self.v.clone(); 118 | if !next.stopped() { 119 | next.call(v); 120 | if ! next.stopped() { 121 | return self.src.subscribe(next, err_or_comp); 122 | } 123 | } 124 | } 125 | 126 | Unsub::done() 127 | } 128 | 129 | fn subscribe_dyn(&self, next: Box>>, err_or_comp: Box>) -> Unsub<'o, SS> 130 | { self.subscribe(next, err_or_comp) } 131 | } 132 | 133 | 134 | impl<'o, V:'o, F:'o+Fn()->V, SS:YesNo, Src: Observable<'o, SS, Val>+'o> 135 | Observable<'o, SS, Val> 136 | for StartOp 137 | { 138 | fn subscribe(&self, next: impl ActNext<'o, SS, Val>, err_or_comp: impl ActEc<'o, SS>) -> Unsub<'o, SS> where Self: Sized { 139 | if ! next.stopped() { 140 | let v = (self.v)(); 141 | if !next.stopped() { 142 | next.call(v); 143 | if ! next.stopped() { 144 | return self.src.subscribe(next, err_or_comp); 145 | } 146 | } 147 | } 148 | 149 | Unsub::done() 150 | } 151 | 152 | fn subscribe_dyn(&self, next: Box>>, err_or_comp: Box>) -> Unsub<'o, SS> 153 | { self.subscribe(next, err_or_comp) } 154 | } 155 | 156 | impl<'o, V:'o, SS:YesNo, Src: Observable<'o, SS, Ref>+'o> 157 | Observable<'o, SS, Ref> 158 | for StartOp 159 | { 160 | fn subscribe(&self, next: impl ActNext<'o, SS, Ref>, err_or_comp: impl ActEc<'o, SS>) -> Unsub<'o, SS> where Self: Sized { 161 | if ! next.stopped() { 162 | let v = &self.v; 163 | if !next.stopped() { 164 | next.call(v); 165 | if ! next.stopped() { 166 | return self.src.subscribe(next, err_or_comp); 167 | } 168 | } 169 | } 170 | 171 | Unsub::done() 172 | } 173 | 174 | fn subscribe_dyn(&self, next: Box>>, err_or_comp: Box>) -> Unsub<'o, SS> 175 | { self.subscribe(next, err_or_comp) } 176 | } 177 | 178 | impl<'o, V:'o, SS:YesNo, Src: Observable<'o, SS, Ref>+'o> 179 | Observable<'o, SS, Ref> 180 | for StartOp 181 | { 182 | fn subscribe(&self, next: impl ActNext<'o, SS, Ref>, err_or_comp: impl ActEc<'o, SS>) -> Unsub<'o, SS> where Self: Sized { 183 | if ! next.stopped() { 184 | if !next.stopped() { 185 | next.call(self.v); 186 | if ! next.stopped() { 187 | return self.src.subscribe(next, err_or_comp); 188 | } 189 | } 190 | } 191 | 192 | Unsub::done() 193 | } 194 | 195 | fn subscribe_dyn(&self, next: Box>>, err_or_comp: Box>) -> Unsub<'o, SS> 196 | { self.subscribe(next, err_or_comp) } 197 | } 198 | 199 | 200 | #[cfg(test)] 201 | mod test 202 | { 203 | use crate::*; 204 | use std::cell::RefCell; 205 | 206 | #[test] 207 | fn val_ref() 208 | { 209 | let n = RefCell::new(String::new()); 210 | let o = Of::value(1).start(2); 211 | o.subscribe(|v:&_| n.borrow_mut().push_str(&format!("{}", v)), ()); 212 | assert_eq!(n.borrow().as_str(), "21"); 213 | } 214 | 215 | #[test] 216 | fn chain() 217 | { 218 | let n = RefCell::new(String::new()); 219 | let o = Of::value(1).start(2).start(3).start(4).start(5); 220 | o.subscribe(|v: &_| n.borrow_mut().push_str(&format!("{}", v)), |_e| n.borrow_mut().push_str("*")); 221 | assert_eq!(n.borrow().as_str(), "54321*"); 222 | 223 | o.subscribe(|v: &_| n.borrow_mut().push_str(&format!("{}", v)), ()); 224 | assert_eq!(n.borrow().as_str(), "54321*54321"); 225 | } 226 | 227 | #[test] 228 | fn into_dyn() 229 | { 230 | let n = RefCell::new(String::new()); 231 | let o: DynObservable> = Of::value(1).into_dyn().start(2); 232 | o.subscribe(|v: &_| n.borrow_mut().push_str(&format!("{}", v)), |_e| n.borrow_mut().push_str("*")); 233 | assert_eq!(n.borrow().as_str(), "21*"); 234 | } 235 | } -------------------------------------------------------------------------------- /src/op/take.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | use std::marker::PhantomData; 3 | use std::sync::Arc; 4 | use std::cell::UnsafeCell; 5 | 6 | pub struct TakeOp 7 | { 8 | count: usize, 9 | src: Src, 10 | PhantomData: PhantomData<(SS)> 11 | } 12 | 13 | pub trait ObsTakeOp : Sized 14 | { 15 | fn take(self, count: usize) -> TakeOp { TakeOp{ count, src: self, PhantomData} } 16 | } 17 | 18 | impl<'o, VBy: RefOrVal, Src: Observable<'o, SS, VBy>+'o, SS:YesNo> 19 | ObsTakeOp 20 | for Src {} 21 | 22 | 23 | pub trait DynObsTakeOp<'o, SS: YesNo, VBy: RefOrVal+'o> 24 | { 25 | fn take(self, count: usize) -> Self; 26 | } 27 | 28 | impl<'o, SS:YesNo, VBy: RefOrVal+'o> 29 | DynObsTakeOp<'o, SS, VBy> 30 | for DynObservable<'o, 'o, SS, VBy> 31 | { 32 | fn take(self, count: usize) -> Self 33 | { TakeOp{ count, src: self.src, PhantomData }.into_dyn() } 34 | } 35 | 36 | impl<'o, SS:YesNo, VBy: RefOrVal+'o, Src: Observable<'o, SS, VBy>> 37 | Observable<'o, SS, VBy> 38 | for TakeOp 39 | { 40 | fn subscribe(&self, next: impl ActNext<'o, SS, VBy>, ec: impl ActEc<'o, SS>) -> Unsub<'o, SS> where Self: Sized 41 | { 42 | if self.count == 0 { 43 | ec.call_once(None); 44 | return Unsub::done(); 45 | } 46 | 47 | let next = SSActNextWrap::new(next); 48 | let sub = Unsub::new(); 49 | let state = Arc::new(unsafe{ AnySendSync::new(UnsafeCell::new((self.count, Some(ec)))) }); 50 | 51 | sub.clone().added_each(self.src.subscribe( 52 | forward_next(next, (sub.clone(), SSWrap::new(state.clone())), |next, (sub, state), v:VBy| { 53 | sub.if_not_done(|| { 54 | let state = unsafe{ &mut *state.get() }; 55 | 56 | let mut val = state.0; 57 | if val != 0 { 58 | val -= 1; 59 | state.0 -= 1; 60 | next.call(v.into_v()); 61 | } 62 | if val == 0 { 63 | sub.unsub_then(|| state.1.take().map_or((), |ec| ec.call_once(None))); 64 | } 65 | }); 66 | }, |s, (sub, _state)| (s.stopped() || sub.is_done())), 67 | 68 | forward_ec((sub, SSWrap::new(state)), |(sub, state), e:Option| { 69 | sub.unsub_then(|| unsafe{ &mut *state.get() }.1.take().map_or((), |ec| ec.call_once(e))) 70 | }) 71 | )) 72 | } 73 | 74 | fn subscribe_dyn(&self, next: Box>, ec: Box>) -> Unsub<'o, SS> 75 | { self.subscribe(next, ec) } 76 | } 77 | 78 | #[cfg(test)] 79 | mod test 80 | { 81 | use crate::*; 82 | use crate::util::clones::*; 83 | 84 | use std::cell::Cell; 85 | use std::rc::Rc; 86 | 87 | #[test] 88 | fn smoke() 89 | { 90 | let (n, n1, n2) = Rc::new(Cell::new(0)).clones(); 91 | let (s, s1) = Rc::new(Subject::::new()).clones(); 92 | 93 | s.take(3).subscribe( 94 | |v:&_| { n.replace(*v); }, 95 | |_e| { n1.replace(n1.get() + 100); } 96 | ); 97 | 98 | s1.next(1); 99 | assert_eq!(n2.get(), 1); 100 | 101 | s1.next(2); 102 | assert_eq!(n2.get(), 2); 103 | 104 | s1.next(3); 105 | assert_eq!(n2.get(), 103); 106 | 107 | s1.next(4); 108 | assert_eq!(n2.get(), 103); 109 | 110 | s1.complete(); 111 | assert_eq!(n2.get(), 103); 112 | } 113 | 114 | #[test] 115 | fn of() 116 | { 117 | let n = Cell::new(0); 118 | Of::value(123).take(100).subscribe(|v:&_| { n.replace(*v); }, |_e| { n.replace(n.get() + 100); }); 119 | 120 | assert_eq!(n.get(), 223); 121 | } 122 | 123 | #[test] 124 | fn zero() 125 | { 126 | let n = Cell::new(0); 127 | Of::value(123).take(0).subscribe(|v:&_| { n.replace(*v); }, |_e| { n.replace(n.get() + 100); }); 128 | 129 | assert_eq!(n.get(), 100); 130 | } 131 | 132 | } 133 | -------------------------------------------------------------------------------- /src/op/until.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | use std::sync::Arc; 3 | use std::cell::UnsafeCell; 4 | 5 | pub struct UntilOp<'o, SS:YesNo, Src, SVBy: RefOrVal> 6 | { 7 | src: Src, 8 | sig: DynObservable<'o, 'o, SS, SVBy>, 9 | } 10 | 11 | pub trait ObsUntilOp<'o, SS:YesNo, VBy: RefOrVal, SVBy: RefOrVal> : Sized 12 | { 13 | fn until(self, sig: impl Observable<'o, SS, SVBy>+'o) -> UntilOp<'o, SS, Self, SVBy> 14 | { 15 | UntilOp{ src: self, sig: sig.into_dyn() } 16 | } 17 | } 18 | 19 | impl<'o, SS:YesNo, VBy: RefOrVal, SVBy: RefOrVal+'o, Src: Observable<'o, SS, VBy>> 20 | ObsUntilOp<'o, SS, VBy, SVBy> 21 | for Src {} 22 | 23 | 24 | pub trait DynObsUntilOp<'o, SS:YesNo, VBy: RefOrVal, SVBy: RefOrVal> : Sized 25 | { 26 | fn until(self, signal: impl Observable<'o, SS, SVBy>+'o) -> DynObservable<'o, 'o, SS, VBy>; 27 | } 28 | 29 | impl<'o, SS:YesNo, VBy: RefOrVal+'o+'o, SVBy: RefOrVal+'o> 30 | DynObsUntilOp<'o, SS, VBy, SVBy> 31 | for DynObservable<'o, 'o, SS, VBy> 32 | { 33 | fn until(self, sig: impl Observable<'o, SS, SVBy>+'o) -> DynObservable<'o, 'o, SS, VBy> 34 | { 35 | UntilOp{ src: self.src, sig: sig.into_dyn() }.into_dyn() 36 | } 37 | } 38 | 39 | impl<'o, SS:YesNo, VBy: RefOrVal+'o+'o, SVBy: RefOrVal+'o, Src: Observable<'o, SS, VBy>> 40 | Observable<'o, SS, VBy> 41 | for UntilOp<'o, SS, Src, SVBy> 42 | { 43 | fn subscribe(&self, next: impl ActNext<'o, SS, VBy>, ec: impl ActEc<'o, SS>) -> Unsub<'o, SS> where Self: Sized 44 | { 45 | let next = SSActNextWrap::new(next); 46 | let sub = Unsub::new(); 47 | //no mutex here because access is protected by Unsub's internal lock 48 | let ec = Arc::new(unsafe{ AnySendSync::new(UnsafeCell::new(Some(ec))) }); 49 | 50 | sub.add_each(self.sig.subscribe(forward_next((), (sub.clone(), SSWrap::new(ec.clone())), |(), (sub, ec), _v:SVBy|{ 51 | sub.unsub_then(|| unsafe{ &mut *Arc::as_ref(&*ec).get() }.take().map_or((), |ec| ec.call_once(None))); 52 | }, |(), (sub,_)| sub.is_done()), forward_ec(sub.clone(), |sub, _e| sub.unsub()))); 53 | 54 | if sub.is_done() { return sub; } 55 | 56 | sub.clone().added_each(self.src.subscribe( 57 | forward_next(next, sub.clone(), |next, sub, v: VBy| { 58 | sub.if_not_done(|| next.call(v.into_v())) 59 | }, |next, sub| next.stopped() || sub.is_done()), 60 | 61 | forward_ec((sub.clone(), SSWrap::new(ec)), |(sub, ec), e:Option| { 62 | sub.if_not_done(||unsafe{ &mut *Arc::as_ref(&*ec).get() }.take().map_or((), |ec| ec.call_once(e))) 63 | }) 64 | )) 65 | } 66 | 67 | fn subscribe_dyn(&self, next: Box>, ec: Box>) -> Unsub<'o, SS> 68 | { self.subscribe(next, ec) } 69 | } 70 | 71 | #[cfg(test)] 72 | mod test 73 | { 74 | use crate::*; 75 | use crate::util::clones::*; 76 | 77 | use std::rc::Rc; 78 | use std::cell::Cell; 79 | 80 | #[test] 81 | fn smoke() 82 | { 83 | let n = Cell::new(0); 84 | 85 | let (o, o2) = Rc::new(Of::::value(123)).clones(); 86 | let (sig, sig2) = Rc::new(Subject::::new()).clones(); 87 | 88 | o.until(sig).subscribe(|_:&_| { n.replace(n.get()+1); }, |_| { n.replace(n.get()+1); } ); 89 | assert_eq!(n.get(), 2); 90 | 91 | n.replace(0); 92 | sig2.complete(); 93 | o2.until(sig2).subscribe(|_:&_| { n.replace(n.get()+1); }, |_| { n.replace(n.get()+1); } ); 94 | assert_eq!(n.get(), 0); 95 | 96 | Of::value(123).until(Of::value(456)).subscribe(|_: &_| { n.replace(n.get()+1); }, |_| { n.replace(n.get()+1); } ); 97 | assert_eq!(n.get(), 1); 98 | 99 | n.replace(0); 100 | let (src, src1) = Rc::new(Subject::::new()).clones(); 101 | let (sig, sig1) = Rc::new(Subject::::new()).clones(); 102 | 103 | src.until(sig).subscribe(|_: &_| { n.replace(n.get()+1); }, |_| { n.replace(n.get()+1); } ); 104 | src1.next(1); 105 | assert_eq!(n.get(), 1); 106 | src1.next(1); 107 | assert_eq!(n.get(), 2); 108 | 109 | sig1.next(1); 110 | assert_eq!(n.get(), 3); 111 | sig1.next(1); 112 | assert_eq!(n.get(), 3); 113 | } 114 | 115 | #[test] 116 | fn cycle() 117 | { 118 | let n = Cell::new(0); 119 | let (s1, s2, s3) = Rc::new(Subject::::new()).clones(); 120 | 121 | s1.until(s2).subscribe( 122 | |_: &_| { n.replace(n.get()+1); }, 123 | |_| { n.replace(n.get()+100); } 124 | ); 125 | 126 | s3.next(1); 127 | assert_eq!(n.get(), 100); 128 | 129 | s3.complete(); 130 | assert_eq!(n.get(), 100); 131 | } 132 | 133 | #[test] 134 | fn empty_sig() 135 | { 136 | let sig = Of::::empty(); 137 | let val = Of::::value(123); 138 | 139 | let sub = val.until(sig).subscribe(|_v:&_| assert!(false, "shouldnt next"), |_e| assert!(false, "shouldnt complete")); 140 | 141 | assert!(sub.is_done()); 142 | } 143 | } -------------------------------------------------------------------------------- /src/scheduler/current_thread_scheduler.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | use std::time::Duration; 3 | use std::collections::BinaryHeap; 4 | use std::time::Instant; 5 | use std::rc::Rc; 6 | use std::cell::RefCell; 7 | use std::cell::Cell; 8 | use crate::util::clones::*; 9 | 10 | 11 | type RcActFn = Rc; 12 | 13 | struct ActItem 14 | { 15 | due: Instant, 16 | period: Option, 17 | unsub: Unsub<'static, NO>, 18 | act: RcActFn 19 | } 20 | 21 | pub struct CurrentThreadScheduler 22 | { 23 | running: Cell, 24 | queue: RefCell> 25 | } 26 | 27 | impl CurrentThreadScheduler 28 | { 29 | pub fn new() -> CurrentThreadScheduler 30 | { 31 | CurrentThreadScheduler{ running: Cell::new(false), queue: RefCell::new(BinaryHeap::new()) } 32 | } 33 | 34 | fn run(&self) 35 | { 36 | loop { 37 | let act = self.queue.borrow_mut().pop(); 38 | 39 | if let Some(mut act) = act { 40 | let now = Instant::now(); 41 | if act.due > now { 42 | ::std::thread::sleep(act.due - now); 43 | } 44 | if ! act.unsub.is_done() { 45 | (act.act)(); 46 | } 47 | if ! act.unsub.is_done() { 48 | if let Some(period) = act.period { 49 | act.due += period; 50 | self.queue.borrow_mut().push(act); 51 | } 52 | } 53 | } else { break; } 54 | 55 | 56 | } 57 | } 58 | } 59 | 60 | impl Scheduler for CurrentThreadScheduler 61 | { 62 | fn schedule(&self, due: Option, act: impl ActOnce> + 'static) -> Unsub<'static, NO> where Self: Sized 63 | { 64 | if !self.running.get() { 65 | self.running.replace(true); 66 | due.map(::std::thread::sleep); 67 | let unsub = act.call_once(()); 68 | 69 | self.run(); 70 | 71 | self.running.replace(false); 72 | return unsub; 73 | } 74 | 75 | let (act, act1) = Rc::new(RefCell::new(Some(act))).clones(); 76 | let (sub, sub1) = Unsub::::with(move|| { act1.borrow_mut().take(); }).clones(); 77 | let act = Rc::new(move || { 78 | let act = act.borrow_mut().take(); 79 | act.map_or((), |a| { sub.add_each(a.call_once(())); }) 80 | }); 81 | 82 | self.queue.borrow_mut().push(ActItem{ 83 | due: Instant::now() + due.unwrap_or_else(|| Duration::new(0,0)), 84 | period: None, 85 | unsub: sub1.clone(), 86 | act 87 | }); 88 | 89 | sub1 90 | } 91 | } 92 | 93 | impl SchedulerPeriodic for CurrentThreadScheduler 94 | { 95 | fn schedule_periodic(&self, period: Duration, act: impl Act>> + 'static) -> Unsub<'static, NO> where Self: Sized 96 | { 97 | let (sub1, sub2) = Unsub::::new().clones(); 98 | let act = Rc::new(move || { 99 | act.call(&sub2); 100 | }); 101 | 102 | self.queue.borrow_mut().push(ActItem{ 103 | due: Instant::now() + period, 104 | period: Some(period), 105 | unsub: sub1.clone(), 106 | act 107 | }); 108 | 109 | if !self.running.get() { 110 | self.running.replace(true); 111 | self.run(); 112 | self.running.replace(false); 113 | } 114 | 115 | sub1 116 | } 117 | } 118 | 119 | impl PartialEq for ActItem 120 | { 121 | fn eq(&self, other: &ActItem) -> bool { self.due == other.due } 122 | } 123 | 124 | impl Eq for ActItem {} 125 | 126 | impl PartialOrd for ActItem 127 | { 128 | fn partial_cmp(&self, other: &ActItem) -> Option<::std::cmp::Ordering> { Some(other.due.cmp(&self.due)) } 129 | } 130 | 131 | impl Ord for ActItem 132 | { 133 | fn cmp(&self, other: &Self) -> ::std::cmp::Ordering { other.due.cmp(&self.due) } 134 | } 135 | 136 | #[cfg(test)] 137 | mod test 138 | { 139 | use crate::*; 140 | use crate::util::clones::*; 141 | 142 | use std::time::Duration; 143 | use std::cell::Cell; 144 | use std::rc::Rc; 145 | use std::sync::Arc; 146 | use std::cell::RefCell; 147 | 148 | #[test] 149 | fn smoke() 150 | { 151 | let (n, n1) = Rc::new(Cell::new(0)).clones(); 152 | let s = CurrentThreadScheduler::new(); 153 | 154 | s.schedule(Some(Duration::from_millis(100)), move || { 155 | n.replace(n.get() + 1); 156 | Unsub::done() 157 | }); 158 | 159 | assert_eq!(n1.get(), 1); 160 | } 161 | 162 | #[test] 163 | fn recurse() 164 | { 165 | let (n, n2) = Rc::new(RefCell::new(String::new())).clones(); 166 | let (s, s1, s2) = Arc::new(CurrentThreadScheduler::new()).clones(); 167 | 168 | s.schedule(Some(Duration::from_millis(1)), move || { 169 | let (n, n1) = n.clones(); 170 | n.borrow_mut().push_str("a"); 171 | 172 | s1.schedule(Some(Duration::from_millis(3)), move || { 173 | n.borrow_mut().push_str("b"); 174 | Unsub::done() 175 | } ); 176 | 177 | s2.schedule(Some(Duration::from_millis(2)), move || { 178 | n1.borrow_mut().push_str("c"); 179 | Unsub::done() 180 | } ); 181 | 182 | Unsub::done() 183 | }); 184 | 185 | assert_eq!(n2.borrow().as_str(), "acb"); 186 | } 187 | 188 | #[test] 189 | fn periododic() 190 | { 191 | let (n, n1) = Rc::new(Cell::new(0)).clones(); 192 | let s = Arc::new(CurrentThreadScheduler::new()); 193 | 194 | s.schedule_periodic(Duration::from_millis(10), move |unsub: &Unsub| { 195 | if n.replace(n.get() + 1) == 9 { 196 | unsub.unsub(); 197 | } 198 | }); 199 | 200 | assert_eq!(n1.get(), 10); 201 | } 202 | } -------------------------------------------------------------------------------- /src/scheduler/event_loop_scheduler.rs: -------------------------------------------------------------------------------- 1 | use std::cell::UnsafeCell; 2 | use std::collections::BinaryHeap; 3 | use std::mem::forget; 4 | use std::sync::{Condvar, Mutex, Arc, atomic::*}; 5 | use std::time::{Duration, Instant}; 6 | use crate::*; 7 | use crate::util::clones::*; 8 | 9 | pub struct EventLoopScheduler 10 | { 11 | state: Arc 12 | } 13 | 14 | struct Inner 15 | { 16 | queue: Mutex, 17 | 18 | has_thread: AtomicBool, 19 | disposed: AtomicBool, 20 | exit_if_empty: bool, 21 | 22 | noti: Condvar, 23 | fac: Arc 24 | } 25 | 26 | struct ActQueue 27 | { 28 | timers: BinaryHeap, 29 | ready: Vec, 30 | 31 | tmp_for_remove: Option> 32 | } 33 | 34 | type ArcActFn = Arc; 35 | 36 | struct ActItem 37 | { 38 | due: Instant, 39 | period: Option, 40 | unsub: Unsub<'static, YES>, 41 | act: ArcActFn 42 | } 43 | 44 | impl Scheduler for Inner 45 | { 46 | fn schedule(&self, due: Option, act: impl ActOnce> + 'static) -> Unsub<'static, YES> where Self: Sized 47 | { 48 | if self.disposed.load(Ordering::Acquire) { return Unsub::done(); } 49 | 50 | let (sub, sub1) = Unsub::new().clones(); 51 | let act = unsafe{ AnySendSync::new(UnsafeCell::new(Some(act))) }; 52 | self.schedule_internal(due.unwrap_or(Duration::new(0,0)), None, Arc::new(move || 53 | unsafe{ &mut *act.get()}.take().map_or((), |a| { sub1.add_each(a.call_once(())); }) 54 | ), sub) 55 | } 56 | } 57 | 58 | impl SchedulerPeriodic for Inner 59 | { 60 | fn schedule_periodic(&self, period: Duration, act: impl Act>> + 'static) -> Unsub<'static, YES> where Self: Sized 61 | { 62 | if self.disposed.load(Ordering::Acquire) { return Unsub::done(); } 63 | 64 | let (sub, sub1) = Unsub::new().clones(); 65 | let act = unsafe{ AnySendSync::new(UnsafeCell::new(Some(act))) }; 66 | self.schedule_internal(period, Some(period), Arc::new(move || 67 | unsafe{ &*act.get()}.as_ref().map_or((), |a| a.call(&sub1)) 68 | ), sub) 69 | } 70 | } 71 | 72 | impl Inner 73 | { 74 | fn run(state: Arc) 75 | { 76 | let mut ready: Vec = Vec::new(); 77 | let mut re_schedules: Vec = Vec::new(); 78 | let mut queue = state.queue.lock().unwrap(); 79 | 80 | while ! state.disposed.load(Ordering::Relaxed) { 81 | 82 | if ready.len() == 0 && queue.ready.len() == 0 && queue.timers.len() == 0 { 83 | if state.exit_if_empty { 84 | state.has_thread.store(false, Ordering::Relaxed); 85 | break; 86 | } 87 | queue = state.noti.wait(queue).unwrap(); 88 | } 89 | 90 | ready.extend(queue.ready.drain(..)); 91 | let now = Instant::now(); 92 | while queue.timers.peek().filter(|item| item.due <= now).is_some() { 93 | ready.push(queue.timers.pop().unwrap()); 94 | } 95 | 96 | if ready.len() == 0 { 97 | if let Some(next_tick) = queue.timers.peek().map(|item| item.due) { 98 | queue = state.noti.wait_timeout(queue, next_tick - now).unwrap().0; 99 | } 100 | continue; 101 | } 102 | 103 | drop(queue); 104 | for mut act in ready.drain(..).filter(|a| !a.unsub.is_done()) { 105 | act.act.call(()); 106 | if act.unsub.is_done() { continue; } 107 | 108 | if let Some(period) = act.period { 109 | act.due += period; 110 | re_schedules.push(act); 111 | } 112 | } 113 | 114 | queue = state.queue.lock().unwrap(); 115 | let now = Instant::now(); 116 | for a in re_schedules.drain(..) { 117 | if a.due <= now || a.unsub.is_done() { 118 | ready.push(a); 119 | } else { 120 | queue.timers.push(a); 121 | } 122 | } 123 | } 124 | 125 | } 126 | 127 | fn ensure_thread(&self) 128 | { 129 | if ! self.has_thread.swap(true, Ordering::Release) { 130 | let selv = self.get_arc_self(); 131 | self.fac.start_dyn(box move || Self::run(selv)); 132 | } 133 | } 134 | 135 | fn remove(&self, act: &ArcActFn) 136 | { 137 | //since BinaryHeap has no `remove()`, we use a ~O(n) way to remove the target item 138 | let mut queue = self.queue.lock().unwrap(); 139 | let mut tmp = queue.tmp_for_remove.take().unwrap(); 140 | 141 | tmp.append(&mut queue.timers); 142 | for a in tmp.drain() { 143 | if ! Arc::ptr_eq(act, &a.act) { 144 | queue.timers.push(a); 145 | } 146 | } 147 | queue.tmp_for_remove.replace(tmp); 148 | } 149 | 150 | fn get_arc_self(&self) -> Arc 151 | { 152 | let (arc, ret) = unsafe{ Arc::from_raw(self) }.clones(); 153 | forget(arc); 154 | ret 155 | } 156 | 157 | fn schedule_internal(&self, due: Duration, period: Option, act: ArcActFn, sub: Unsub<'static, YES>) -> Unsub<'static, YES> 158 | { 159 | let mut queues = self.queue.lock().unwrap(); 160 | let item = ActItem{ due: Instant::now() + due, act: act.clone(), period, unsub: sub.clone()}; 161 | if due == Duration::new(0, 0) { 162 | queues.ready.push(item); 163 | } else { 164 | queues.timers.push(item); 165 | } 166 | 167 | let selv = Arc::downgrade(&self.get_arc_self()); 168 | sub.add(Unsub::::with(move || selv.upgrade().map_or((), |arc| arc.remove(&act) ))); 169 | 170 | self.noti.notify_one(); 171 | self.ensure_thread(); 172 | 173 | sub 174 | } 175 | } 176 | 177 | impl Scheduler for EventLoopScheduler 178 | { 179 | fn schedule(&self, due: Option, act: impl ActOnce> + 'static) -> Unsub<'static, YES> where Self: Sized 180 | { 181 | self.state.schedule(due, act) 182 | } 183 | } 184 | 185 | impl SchedulerPeriodic for EventLoopScheduler 186 | { 187 | fn schedule_periodic(&self, period: Duration, act: impl Act>> + 'static) -> Unsub<'static, YES> where Self: Sized 188 | { 189 | self.state.schedule_periodic(period, act) 190 | } 191 | } 192 | 193 | impl Drop for EventLoopScheduler 194 | { 195 | fn drop(&mut self) 196 | { 197 | self.state.disposed.store(true, Ordering::Release); 198 | self.state.noti.notify_one(); 199 | } 200 | } 201 | 202 | impl EventLoopScheduler 203 | { 204 | pub fn new(fac: Arc, exit_if_empty: bool) -> EventLoopScheduler 205 | { 206 | let state = Arc::new(Inner { 207 | queue: Mutex::new(ActQueue{ timers: BinaryHeap::new(), tmp_for_remove: Some(BinaryHeap::new()), ready: Vec::new() }), 208 | has_thread: AtomicBool::new(false), 209 | disposed: AtomicBool::new(false), 210 | exit_if_empty, 211 | noti: Condvar::new(), 212 | fac 213 | }); 214 | 215 | EventLoopScheduler{ state } 216 | } 217 | } 218 | 219 | impl PartialEq for ActItem 220 | { 221 | fn eq(&self, other: &ActItem) -> bool { self.due == other.due } 222 | } 223 | 224 | impl Eq for ActItem {} 225 | 226 | impl PartialOrd for ActItem 227 | { 228 | fn partial_cmp(&self, other: &ActItem) -> Option<::std::cmp::Ordering> { Some(other.due.cmp(&self.due)) } 229 | } 230 | 231 | impl Ord for ActItem 232 | { 233 | fn cmp(&self, other: &Self) -> ::std::cmp::Ordering { other.due.cmp(&self.due) } 234 | } 235 | 236 | #[cfg(test)] 237 | mod test 238 | { 239 | use crate::*; 240 | use ::std::time::Duration; 241 | use std::sync::Arc; 242 | 243 | #[test] 244 | fn smoke() 245 | { 246 | let sch = EventLoopScheduler::new(Arc::new(DefaultThreadFac), true); 247 | 248 | let sub = sch.schedule_periodic(Duration::from_millis(33), |_:&Unsub<'static, YES>| println!("shit")); 249 | ::std::thread::spawn(move ||{ 250 | ::std::thread::sleep(Duration::from_millis(700)); 251 | sub.unsub(); 252 | }); 253 | 254 | 255 | sch.schedule(None, || { 256 | println!("ok? a"); 257 | Unsub::done() 258 | }); 259 | sch.schedule(None, || { 260 | println!("ok? b"); 261 | Unsub::done() 262 | }); 263 | 264 | sch.schedule(None, || { 265 | println!("ok? c"); 266 | Unsub::done() 267 | }); 268 | 269 | sch.schedule(Some(::std::time::Duration::from_millis(4)), || { 270 | println!("later...4"); 271 | Unsub::done() 272 | }); 273 | 274 | 275 | sch.schedule(Some(::std::time::Duration::from_millis(3)), || { 276 | println!("later...3"); 277 | ::std::thread::sleep(Duration::from_millis(200)); 278 | Unsub::done() 279 | }); 280 | sch.schedule(Some(::std::time::Duration::from_millis(2)), || { 281 | println!("later... 2"); 282 | ::std::thread::sleep(Duration::from_millis(200)); 283 | 284 | Unsub::done() 285 | }); 286 | sch.schedule(Some(::std::time::Duration::from_millis(1)), || { 287 | println!("later... 1"); 288 | ::std::thread::sleep(Duration::from_millis(200)); 289 | 290 | Unsub::done() 291 | }); 292 | 293 | ::std::thread::sleep(Duration::from_millis(2000)); 294 | } 295 | } -------------------------------------------------------------------------------- /src/scheduler/mod.rs: -------------------------------------------------------------------------------- 1 | use std::boxed::FnBox; 2 | use crate::*; 3 | 4 | pub trait Scheduler 5 | { 6 | fn schedule(&self, due: Option<::std::time::Duration>, act: impl ActOnce> + 'static) -> Unsub<'static, SS> where Self: Sized; 7 | } 8 | 9 | pub trait SchedulerPeriodic : Scheduler 10 | { 11 | fn schedule_periodic(&self, period: ::std::time::Duration, act: impl Act>> + 'static) -> Unsub<'static, SS> where Self: Sized; 12 | } 13 | 14 | pub trait ThreadFactory 15 | { 16 | fn start(&self, main: impl FnOnce()+Send+Sync+'static) where Self: Sized{ self.start_dyn(box main) } 17 | fn start_dyn(&self, main: Box); 18 | } 19 | 20 | impl> Scheduler for Arc 21 | { 22 | #[inline(always)] 23 | fn schedule(&self, due: Option, act: impl ActOnce>+'static) -> Unsub<'static, SS> where Self: Sized { 24 | Arc::as_ref(self).schedule(due, act) 25 | } 26 | } 27 | 28 | impl> SchedulerPeriodic for Arc 29 | { 30 | #[inline(always)] 31 | fn schedule_periodic(&self, period: Duration, act: impl Act>>+'static) -> Unsub<'static, SS> { 32 | Arc::as_ref(self).schedule_periodic(period, act) 33 | } 34 | } 35 | 36 | pub struct DefaultThreadFac; 37 | impl ThreadFactory for DefaultThreadFac 38 | { 39 | fn start_dyn(&self, main: Box) 40 | { 41 | ::std::thread::spawn(move || main.call_box(())); 42 | } 43 | } 44 | 45 | pub use self::event_loop_scheduler::*; 46 | pub use self::new_thread_scheduler::*; 47 | pub use self::current_thread_scheduler::*; 48 | use std::sync::Arc; 49 | use std::time::Duration; 50 | 51 | mod event_loop_scheduler; 52 | mod new_thread_scheduler; 53 | mod current_thread_scheduler; 54 | -------------------------------------------------------------------------------- /src/scheduler/new_thread_scheduler.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | use std::time::Duration; 3 | use std::sync::Arc; 4 | 5 | pub struct NewThreadScheduler 6 | { 7 | ev: EventLoopScheduler 8 | } 9 | 10 | impl NewThreadScheduler 11 | { 12 | pub fn new(fac: Arc) -> NewThreadScheduler 13 | { 14 | NewThreadScheduler{ ev: EventLoopScheduler::new(fac, true) } 15 | } 16 | } 17 | 18 | impl Scheduler for NewThreadScheduler 19 | { 20 | fn schedule(&self, due: Option, act: impl ActOnce> + 'static) -> Unsub<'static, YES> where Self: Sized 21 | { 22 | self.ev.schedule(due, act) 23 | } 24 | } 25 | 26 | impl SchedulerPeriodic for NewThreadScheduler 27 | { 28 | fn schedule_periodic(&self, period: Duration, act: impl Act>> + 'static) -> Unsub<'static, YES> where Self: Sized 29 | { 30 | self.ev.schedule_periodic(period, act) 31 | } 32 | } -------------------------------------------------------------------------------- /src/subject/behavior_subject.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | use std::sync::Arc; 3 | 4 | pub struct BehaviorSubject<'o, SS:YesNo, V> 5 | { 6 | val: ReSpinMutex>, 7 | subj: Subject<'o, SS, V>, 8 | } 9 | 10 | unsafe impl<'o, V:Send+Sync+'o> Send for BehaviorSubject<'o, YES, V>{} 11 | unsafe impl<'o, V:Send+Sync+'o> Sync for BehaviorSubject<'o, YES, V>{} 12 | 13 | impl<'o, V:'o, SS:YesNo> BehaviorSubject<'o, SS, V> 14 | { 15 | #[inline(always)] 16 | pub fn new(value: V) -> BehaviorSubject<'o, SS, V> 17 | { 18 | BehaviorSubject{ val: ReSpinMutex::new(Some(value)), subj: Subject::new() } 19 | } 20 | 21 | pub fn value(&self, map: impl FnOnce(&Option) -> U) -> U 22 | { 23 | self.val.lock().map(map) 24 | } 25 | } 26 | 27 | impl<'o, V:'o, SS:YesNo> 28 | Observable<'o, SS, Ref> 29 | for BehaviorSubject<'o, SS, V> 30 | { 31 | fn subscribe(&self, next: impl ActNext<'o, SS, Ref>, ec: impl ActEc<'o, SS>) -> Unsub<'o, SS> where Self: Sized 32 | { 33 | let val = self.val.lock(); 34 | if val.map(|v:&_| v.is_some()) { 35 | let next = Arc::new(SSActNextWrap::new(next)); 36 | let sub = self.subj.subscribe( next.clone(), ec); 37 | sub.if_not_done(||{ 38 | if ! next.stopped() { 39 | val.map(|v: &Option| next.call(v.as_ref().unwrap())); 40 | } 41 | }); 42 | sub 43 | } else { 44 | self.subj.subscribe(next, ec) 45 | } 46 | } 47 | 48 | fn subscribe_dyn(&self, next: Box>>, ec: Box>) -> Unsub<'o, SS> 49 | { self.subscribe(next, ec) } 50 | } 51 | 52 | 53 | impl<'o, V:'o, SS:YesNo> BehaviorSubject<'o, SS, V> 54 | { 55 | pub fn next(&self, v:V) 56 | { 57 | let cell = self.val.lock(); 58 | cell.map(|val: &Option| { 59 | if val.is_some() { 60 | let _drop = cell.replace(Some(v)); 61 | cell.map(|val: &Option| self.subj.next_ref(val.as_ref().unwrap())); 62 | } 63 | }) 64 | } 65 | 66 | pub fn error(&self, e:RxError) 67 | { 68 | let cell = self.val.lock(); 69 | cell.map(|val: &Option| { 70 | if val.is_some() { 71 | let _drop = cell.replace(None); 72 | self.subj.error(e); 73 | } 74 | }); 75 | } 76 | 77 | pub fn complete(&self) 78 | { 79 | let cell = self.val.lock(); 80 | cell.map(|val: &Option| { 81 | if val.is_some() { 82 | let _drop = cell.replace(None); 83 | self.subj.complete(); 84 | } 85 | }); 86 | 87 | } 88 | } 89 | 90 | 91 | #[cfg(test)] 92 | mod test 93 | { 94 | 95 | use std::cell::Cell; 96 | use crate::*; 97 | use std::rc::Rc; 98 | use crate::util::clones::Clones; 99 | 100 | #[test] 101 | fn shoudl_emit_on_sub() 102 | { 103 | let n = Cell::new(0); 104 | let x = Cell::new(0); 105 | 106 | let s = BehaviorSubject::::new(123); 107 | 108 | s.subscribe(|v:&_| { n.replace(*v); }, ()); 109 | assert_eq!(n.get(), 123); 110 | 111 | s.next(456); 112 | assert_eq!(n.get(), 456); 113 | 114 | s.next(789); 115 | 116 | s.subscribe(|v:&_| { x.replace(*v); }, ()); 117 | assert_eq!(x.get(), 789); 118 | assert_eq!(n.get(), 789); 119 | } 120 | 121 | #[test] 122 | fn recurse() 123 | { 124 | let (n, n1) = Rc::new(Cell::new(0)).clones(); 125 | 126 | let s = Rc::new(BehaviorSubject::::new(1)); 127 | s.clone().subscribe(move |v: &i32| { 128 | if *v == 1 { 129 | s.next(2); 130 | let n = n.clone(); 131 | s.subscribe(move |v:&_| { n.replace(n.get() + v); }, ()); 132 | } 133 | n.replace(n.get() + v); 134 | }, ()); 135 | 136 | assert_eq!(n1.get(), 1+2+2); 137 | } 138 | 139 | 140 | } -------------------------------------------------------------------------------- /src/subject/mod.rs: -------------------------------------------------------------------------------- 1 | mod subject; 2 | mod behavior_subject; 3 | 4 | pub use self::subject::*; 5 | pub use self::behavior_subject::*; -------------------------------------------------------------------------------- /src/subject/subject.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | use std::sync::*; 3 | use std::cell::UnsafeCell; 4 | use self::SubjectState::*; 5 | use std::sync::Arc; 6 | 7 | enum SubjectState<'o, SS:YesNo, V> 8 | { 9 | Next(Vec<(Arc>>, UnsafeCell>>>, Unsub<'o, SS>)>), 10 | Error(RxError), 11 | Complete, 12 | Drop 13 | } 14 | 15 | struct Wrap<'o, SS:YesNo, V> 16 | { 17 | lock: ReSpinLock, 18 | state: RecurCell>> 19 | } 20 | 21 | unsafe impl <'o, V:Send+Sync+'o> Send for Wrap<'o, YES, V> {} 22 | unsafe impl <'o, V:Send+Sync+'o> Sync for Wrap<'o, YES, V> {} 23 | 24 | pub struct Subject<'o, SS:YesNo, V> 25 | { 26 | state: Arc>, 27 | } 28 | unsafe impl<'o, V:Send+Sync+'o> Send for Subject<'o, YES, V> {} 29 | unsafe impl<'o, V:Send+Sync+'o> Sync for Subject<'o, YES, V> {} 30 | 31 | impl<'o, V, SS:YesNo> Subject<'o, SS, V> 32 | { 33 | pub fn new() -> Subject<'o, SS, V> 34 | { 35 | Subject{ state: Arc::new(Wrap{lock: ReSpinLock::new(), state: RecurCell::new(UnsafeCell::new(Next(Vec::new()))) }) } 36 | } 37 | 38 | pub fn new_dyn() -> Box 39 | { 40 | box Subject::new() 41 | } 42 | 43 | #[inline(never)] 44 | fn unsub(state: &Weak>, observer: &Weak>>) 45 | { 46 | if let Some(state) = state.upgrade() { 47 | if let Some(observer) = observer.upgrade() { 48 | let Wrap{lock, state} = state.as_ref(); 49 | let recur = lock.enter(); 50 | 51 | state.map(|s: &UnsafeCell<_>|{ 52 | if let Next(obs) = unsafe{ &mut *s.get() } { 53 | if recur == 0 { 54 | let _to_drop = obs.iter().position(|(n,_,_)| Arc::ptr_eq(n, &observer)).map(|i| obs.remove(i)) 55 | .expect("the observer is expected to be in the vec"); 56 | lock.exit(); 57 | } else { 58 | let mut vec = Vec::with_capacity(obs.len() - 1 ); 59 | vec.extend(obs.iter() 60 | .filter(|(n,_,_)| ! Arc::ptr_eq(n, &observer)) 61 | .map(|(n, ec, sub)| (n.clone(), UnsafeCell::new(unsafe{ &mut *ec.get() }.take()), sub.clone() )) 62 | ); 63 | let _to_drop = state.replace(UnsafeCell::new(SubjectState::Next(vec))); 64 | lock.exit(); 65 | } 66 | } else { lock.exit(); } 67 | }); 68 | } 69 | } 70 | } 71 | } 72 | 73 | 74 | impl<'s, 'o, V, SS:YesNo> ::std::ops::Drop for Subject<'o,SS,V> 75 | { 76 | fn drop(&mut self) 77 | { 78 | let Wrap{lock, state} = self.state.as_ref(); 79 | let _ = lock.enter(); 80 | 81 | state.map(|s: &UnsafeCell<_>| { 82 | let _to_drop; 83 | if let Next(vec) = unsafe{ &mut *s.get() } { 84 | _to_drop = state.replace(UnsafeCell::new(Drop)); 85 | for (_, _, sub) in vec { sub.unsub(); } 86 | } 87 | lock.exit(); 88 | }); 89 | } 90 | } 91 | 92 | impl<'o, V:'o, SS:YesNo> 93 | Observable<'o, SS, Ref> 94 | for Subject<'o, SS, V> 95 | { 96 | fn subscribe(&self, next: impl ActNext<'o, SS, Ref>, ec: impl ActEc<'o, SS>) -> Unsub<'o, SS> where Self: Sized 97 | { 98 | let Wrap{lock, state} = self.state.as_ref(); 99 | let recur = lock.enter(); 100 | 101 | state.map(|s: &UnsafeCell<_>|{ 102 | match unsafe { &mut *s.get() } { 103 | Next(obs) => { 104 | let next : Arc>> = Arc::new(next); 105 | let ec = Box::new(ec); 106 | let weak_state = unsafe{ AnySendSync::new(Arc::downgrade(&self.state)) }; 107 | let weak_next = unsafe{ AnySendSync::new(Arc::downgrade(&next)) }; 108 | 109 | let sub = Unsub::with(forward_act_once((SSWrap::new(weak_state), SSWrap::new(weak_next)), |(weak_state, weak_next), ()| { 110 | Self::unsub(&*weak_state, &*weak_next); 111 | })); 112 | if recur == 0 { 113 | obs.push((next, UnsafeCell::new(Some(ec)), sub.clone())); 114 | } else { 115 | let mut vec = Vec::with_capacity(obs.len() + 1); 116 | vec.extend( obs.iter().map(|(n, ec, sub)| (n.clone(), UnsafeCell::new(unsafe{ &mut *ec.get() }.take()), sub.clone()))); 117 | vec.push((next, UnsafeCell::new(Some(ec)), sub.clone())); 118 | 119 | state.replace(UnsafeCell::new(Next(vec))); 120 | } 121 | lock.exit(); 122 | return sub; 123 | }, 124 | Error(e) => ec.call_once(Some(e.clone())), 125 | Complete => ec.call_once(None), 126 | Drop => {} 127 | } 128 | 129 | lock.exit(); 130 | return Unsub::done() 131 | }) 132 | } 133 | 134 | fn subscribe_dyn(&self, next: Box>>, ec: Box>) -> Unsub<'o, SS> 135 | { 136 | self.subscribe(next, ec) 137 | } 138 | } 139 | 140 | impl<'o, V:'o+'o, SS:YesNo> Subject<'o, SS, V> 141 | { 142 | pub fn next(&self, v: V) 143 | { 144 | self.next_ref(&v); 145 | } 146 | 147 | pub fn ec(&self, e: Option) 148 | { 149 | if e.is_some() { 150 | self.error(e.unwrap()); 151 | } else { 152 | self.complete(); 153 | } 154 | } 155 | 156 | pub fn next_ref(&self, v: &V) 157 | { 158 | let Wrap{lock, state} = self.state.as_ref(); 159 | lock.enter(); 160 | 161 | state.map(|s: &UnsafeCell<_>|{ 162 | if let Next(vec) = unsafe { & *s.get() } { 163 | for (n,_,sub) in vec { 164 | if ! sub.is_done() { n.call(v,); } 165 | } 166 | } 167 | lock.exit(); 168 | }); 169 | } 170 | 171 | pub fn error(&self, e: RxError) 172 | { 173 | let e = e.set_handled(); 174 | let Wrap{lock, state} = self.state.as_ref(); 175 | lock.enter(); 176 | 177 | state.map(|s:&UnsafeCell<_>|{ 178 | if let Next(vec) = unsafe { &*s.get() } { 179 | let _to_drop = state.replace(UnsafeCell::new(Error(e.clone()))); 180 | 181 | for (_,ec,sub) in vec.iter() { 182 | if sub.is_done() { continue; } 183 | sub.unsub(); 184 | unsafe{ &mut *ec.get()}.take().map(|ec| ec.call_box(Some(e.clone()))); 185 | } 186 | } 187 | lock.exit(); 188 | }); 189 | } 190 | 191 | pub fn complete(&self) 192 | { 193 | let Wrap{lock, state} = self.state.as_ref(); 194 | 195 | lock.enter(); 196 | 197 | state.map(|s:&UnsafeCell<_>|{ 198 | 199 | if let Next(vec) = unsafe { &*s.get() } { 200 | let _to_drop = state.replace(UnsafeCell::new(Complete)); 201 | 202 | for (_, ec, sub) in vec.iter() { 203 | if sub.is_done() { continue; } 204 | sub.unsub(); 205 | unsafe{ &mut *ec.get() }.take().map(|ec| ec.call_box(None)); 206 | } 207 | } 208 | 209 | lock.exit(); 210 | }); 211 | } 212 | } 213 | 214 | #[cfg(test)] 215 | mod tests 216 | { 217 | //use test::Bencher; 218 | use crate::*; 219 | use crate::util::clones::*; 220 | 221 | use std::cell::Cell; 222 | use std::rc::Rc; 223 | use std::sync::Arc; 224 | use std::sync::atomic::*; 225 | 226 | #[test] 227 | fn smoke() 228 | { 229 | let n = Arc::new(AtomicI32::new(0)); 230 | let s = Arc::new(Subject::::new()); 231 | 232 | let nn = n.clone(); 233 | let ss = s.clone(); 234 | s.subscribe(move |v:&_| { nn.store(*v, Ordering::SeqCst); }, ()); 235 | 236 | ::std::thread::spawn(move ||{ 237 | ss.next(123); 238 | }).join().ok(); 239 | assert_eq!(n.load(Ordering::SeqCst), 123); 240 | 241 | s.next(1); 242 | assert_eq!(n.load(Ordering::SeqCst), 1); 243 | 244 | s.next(2); 245 | assert_eq!(n.load(Ordering::SeqCst), 2); 246 | 247 | //expects: `temp` does not live long enough 248 | // let s = Subject::::new(); 249 | // let temp = Cell::new(0); 250 | // s.sub(|v:&_| { temp.replace(*v); }, ()); 251 | 252 | 253 | 254 | s.complete(); 255 | 256 | let n = Cell::new(0); 257 | let ss = Subject::::new_dyn(); 258 | ss.subscribe_dyn(box |v:&_| { n.replace(*v); }, box()); 259 | } 260 | 261 | #[test] 262 | fn next_after_complete() 263 | { 264 | let s = Subject::::new(); 265 | s.subscribe(|_:&_| assert!(false, "shouldn't call"), ()); 266 | 267 | s.complete(); 268 | s.next(1); 269 | } 270 | 271 | #[test] 272 | fn unsub() 273 | { 274 | let s = Subject::::new(); 275 | let unsub = s.subscribe(|_: &_| assert!(false, "shouldn't call"), ()); 276 | unsub(); 277 | 278 | s.next(1); 279 | } 280 | 281 | #[test] 282 | fn unsub_in_next() 283 | { 284 | let (sub, sub2) = Unsub::new().clones(); 285 | let s = Subject::::new(); 286 | s.subscribe(move |_: &_| sub.unsub(), ()); 287 | sub2.add(s.subscribe(move |_: &_| assert!(false, "should not happen"), ())); 288 | 289 | s.next(1); 290 | } 291 | 292 | #[test] 293 | fn should_complete_only_once() 294 | { 295 | // let n = Arc::new(AtomicI32::new(0)); 296 | // let s = Arc::new(Subject::::new()); 297 | // 298 | // let nn = n.clone(); 299 | // s.sub(((), (), move |()|{ nn.fetch_add(1, Ordering::SeqCst); })); 300 | // 301 | // let mut threads = vec![]; 302 | // for i in 0..8 { 303 | // let ss = s.clone(); 304 | // threads.push(::std::thread::spawn(move ||{ 305 | // 306 | // for j in 0..10 { 307 | // ss.complete(); 308 | // } 309 | // 310 | // })); 311 | // } 312 | // 313 | // for t in threads { t.join(); } 314 | // 315 | // assert_eq!(n.load(Ordering::SeqCst), 1); 316 | } 317 | 318 | #[test] 319 | fn drop_should_unsub() 320 | { 321 | let n = Rc::new(Cell::new(0)); 322 | let s = Subject::::new(); 323 | 324 | for _ in 0..10{ 325 | let nn = n.clone(); 326 | s.subscribe(|_:&_|{}, ()).add(Unsub::::with(move || { nn.replace(nn.get() + 1); })); 327 | } 328 | 329 | //s.complete(); 330 | drop(s); 331 | 332 | assert_eq!(n.get(), 10); 333 | } 334 | 335 | #[test] 336 | fn as_observer() 337 | { 338 | let src = Of::value(123); 339 | 340 | let n = std::cell::Cell::new(0); 341 | let s = Subject::::new(); 342 | 343 | s.subscribe(|v:&_| { n.replace(*v); }, ()); 344 | 345 | src.subscribe(|v:&_| s.next(*v), |e| { s.ec(e) } ); 346 | 347 | assert_eq!(n.get(), 123); 348 | } 349 | 350 | } -------------------------------------------------------------------------------- /src/sync/act.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | use std::sync::Arc; 3 | 4 | pub unsafe trait Act 5 | { 6 | fn call(&self, v: A::V) -> R; 7 | } 8 | 9 | pub unsafe trait ActOnce 10 | { 11 | fn call_once(self, e: A::V) -> R; 12 | } 13 | 14 | pub unsafe trait ActBox 15 | { 16 | fn call_box(self: Box, e: A::V) -> R; 17 | } 18 | 19 | pub fn act_sendsync(act: impl Act) -> impl Act + Ssmark 20 | { 21 | struct X(A); 22 | unsafe impl Ssmark for X{} 23 | unsafe impl> Act for X 24 | { 25 | #[inline(always)] 26 | fn call(&self, v: ::V) -> R { self.0.call(v) } 27 | } 28 | 29 | X(act) 30 | } 31 | 32 | 33 | unsafe impl<'a, V, R, F: Fn(V) -> R+'a> 34 | Act, R> 35 | for F 36 | { 37 | #[inline(always)] fn call(&self, v: V) -> R { self(v) } 38 | } 39 | 40 | unsafe impl<'a, V, R, F: Fn(V)->R+Send+Sync+'a> 41 | Act, R> 42 | for F 43 | { 44 | #[inline(always)] fn call(&self, v: V) -> R { self(v) } 45 | } 46 | 47 | unsafe impl<'a, V, R, F: Fn(&V) -> R+'a> 48 | Act, R> 49 | for F 50 | { 51 | #[inline(always)] fn call(&self, v: *const V) -> R { self(unsafe{ &*v }) } 52 | } 53 | 54 | unsafe impl<'a, V, R, F: Fn(&V)->R+Send+Sync+'a> 55 | Act, R> 56 | for F 57 | { 58 | #[inline(always)] fn call(&self, v: *const V) -> R { self(unsafe{ &*v }) } 59 | } 60 | 61 | unsafe impl <'a, SS:YesNo, BY: RefOrVal, R> 62 | Act 63 | for Box+'a> 64 | { 65 | #[inline(always)] fn call(&self, v: BY::V) -> R { Box::as_ref(self).call(v) } 66 | } 67 | 68 | 69 | 70 | 71 | unsafe impl<'a, V, R, F: FnOnce(V) -> R+'a> 72 | ActOnce, R> 73 | for F 74 | { 75 | #[inline(always)] fn call_once(self, v: V) -> R { self(v) } 76 | } 77 | 78 | unsafe impl<'a, V, R, F: FnOnce(V)->R+Send+Sync+'a> 79 | ActOnce, R> 80 | for F 81 | { 82 | #[inline(always)] fn call_once(self, v: V) -> R { self(v) } 83 | } 84 | 85 | unsafe impl<'a, V, R, F: FnOnce(&V) -> R+'a> 86 | ActOnce, R> 87 | for F 88 | { 89 | #[inline(always)] fn call_once(self, v: *const V) -> R { self(unsafe{ &*v }) } 90 | } 91 | 92 | unsafe impl<'a, V, R, F: FnOnce(&V)->R+Send+Sync+'a> 93 | ActOnce, R> 94 | for F 95 | { 96 | #[inline(always)] fn call_once(self, v: *const V) -> R { self(unsafe{ &*v }) } 97 | } 98 | 99 | unsafe impl<'a, R, F: FnOnce()->R+Send+Sync+'a> 100 | ActOnce 101 | for F 102 | { 103 | #[inline(always)] fn call_once(self, _v: ()) -> R { self() } 104 | } 105 | 106 | unsafe impl<'a, R, F: FnOnce()->R+'a> 107 | ActOnce 108 | for F 109 | { 110 | #[inline(always)] fn call_once(self, _v: ()) -> R { self() } 111 | } 112 | 113 | 114 | 115 | unsafe impl<'a, SS:YesNo, A: RefOrVal, R, F: ActOnce> 116 | ActBox 117 | for F 118 | { 119 | #[inline(always)] fn call_box(self: Box, v: A::V) -> R { self.call_once(v) } 120 | } 121 | 122 | unsafe impl <'a, SS:YesNo, BY: RefOrVal, R> 123 | ActOnce 124 | for Box+'a> 125 | { 126 | #[inline(always)] fn call_once(self, v: BY::V) -> R { self.call_box(v) } 127 | } 128 | 129 | 130 | unsafe impl> 131 | Act 132 | for Arc 133 | { 134 | #[inline(always)] 135 | fn call(&self, v: ::V) -> R { Arc::as_ref(self).call(v) } 136 | } 137 | 138 | 139 | unsafe impl 140 | Act 141 | for () 142 | { 143 | #[inline(always)] fn call(&self, _: A::V) { } 144 | } 145 | 146 | unsafe impl 147 | ActOnce 148 | for () 149 | { 150 | #[inline(always)] fn call_once(self, _: A::V) { } 151 | } 152 | 153 | 154 | pub fn forward_act_once<'o, SS:YesNo, Caps: Ssmark+'o, BY: RefOrVal> 155 | (caps: Caps, f: fn(Caps, BY)) 156 | -> SsForward 157 | { 158 | SsForward::new((caps, f)) 159 | } 160 | 161 | unsafe impl<'o, SS:YesNo, Caps: Ssmark+'o, BY: RefOrVal> 162 | ActOnce 163 | for SsForward 164 | { 165 | #[inline(always)] 166 | fn call_once(self, v: BY::V) 167 | { 168 | let (caps, f) = self.captures; 169 | f(caps, unsafe{ BY::from_v(v) }) 170 | } 171 | } 172 | 173 | 174 | 175 | //pub struct WrapAct<'o, SS: YesNo, By: RefOrVal, A, R> 176 | //{ 177 | // act: A, 178 | // PhantomData: PhantomData<&'o (SS, By, R)> 179 | //} 180 | // 181 | //unsafe impl<'o, By: RefOrVal, A: Send+'o, R> Send for WrapAct<'o, YES, By, A, R> {} 182 | //unsafe impl<'o, By: RefOrVal, A: Sync+'o, R> Sync for WrapAct<'o, YES, By, A, R> {} 183 | // 184 | //impl<'o, SS:YesNo, A: Fn(By)->R+'o, By: RefOrVal, R> 185 | //WrapAct<'o, SS, By, A, R> 186 | //{ 187 | // #[inline(always)] 188 | // pub unsafe fn new(act: A) -> WrapAct<'o, SS, By, A, R> 189 | // { 190 | // WrapAct { act, PhantomData } 191 | // } 192 | //} 193 | // 194 | //unsafe impl<'o, SS:YesNo, A: Fn(By)->R+'o, By: RefOrVal, R> 195 | //Act 196 | //for WrapAct<'o, SS, By, A, R> 197 | //{ 198 | // #[inline(always)] 199 | // fn call(&self, v: By::V) -> R 200 | // { 201 | // (self.act)(unsafe { By::from_v(v) }) 202 | // } 203 | //} 204 | 205 | -------------------------------------------------------------------------------- /src/sync/any_send_sync.rs: -------------------------------------------------------------------------------- 1 | use std::ops::Deref; 2 | 3 | pub struct AnySendSync{ t: T } 4 | unsafe impl Send for AnySendSync{} 5 | unsafe impl Sync for AnySendSync{} 6 | 7 | impl AnySendSync 8 | { 9 | #[inline(always)] pub unsafe fn new(t: T) -> AnySendSync { AnySendSync{ t } } 10 | #[inline(always)] pub fn into_inner(self) -> T { self.t } 11 | } 12 | 13 | impl Deref for AnySendSync 14 | { 15 | type Target = T; 16 | #[inline(always)] fn deref(&self) -> &T { &self.t } 17 | } -------------------------------------------------------------------------------- /src/sync/mod.rs: -------------------------------------------------------------------------------- 1 | mod re_spin_lock; 2 | mod any_send_sync; 3 | mod ss_mark; 4 | mod yesno; 5 | mod act; 6 | mod recur_cell; 7 | mod re_spin_mutex; 8 | 9 | pub use self::re_spin_lock::*; 10 | pub use self::ss_mark::*; 11 | pub use self::yesno::*; 12 | pub use self::any_send_sync::*; 13 | pub use self::act::*; 14 | pub use self::recur_cell::*; 15 | pub use self::re_spin_mutex::*; -------------------------------------------------------------------------------- /src/sync/re_spin_lock.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | use std::sync::atomic::*; 3 | use std::cell::UnsafeCell; 4 | use std::marker::PhantomData; 5 | 6 | /// Recursive SpinLock 7 | pub struct ReSpinLock 8 | { 9 | recur: UnsafeCell, 10 | held: AtomicUsize, 11 | owner: AtomicUsize, 12 | 13 | //recur_nss: UnsafeCell, 14 | 15 | PhantomData: PhantomData 16 | 17 | } 18 | 19 | unsafe impl Send for ReSpinLock{} 20 | unsafe impl Sync for ReSpinLock{} 21 | 22 | impl ReSpinLock 23 | { 24 | pub fn new() -> ReSpinLock 25 | { 26 | ReSpinLock{ 27 | recur: UnsafeCell::new(0), owner: AtomicUsize::new(0), held: AtomicUsize::new(0), 28 | //recur_nss: UnsafeCell::new(0), 29 | PhantomData 30 | } 31 | } 32 | 33 | #[inline(always)] 34 | pub fn enter(&self) -> usize 35 | { 36 | if SS::VALUE { 37 | let tid = Self::tid(); 38 | loop { 39 | if self.held.swap(1, Ordering::Acquire) == 0 { 40 | debug_assert_eq!( unsafe{ *self.recur.get() }, 0); 41 | self.owner.store(tid, Ordering::Relaxed); 42 | break; 43 | } else if self.owner.load(Ordering::Relaxed) == tid { 44 | debug_assert!(unsafe { *self.recur.get() } > 0); 45 | break; 46 | } 47 | } 48 | unsafe { 49 | let r = *self.recur.get(); 50 | *self.recur.get() += 1; 51 | return r; 52 | } 53 | } else { 54 | unsafe { 55 | let r = *self.recur.get(); 56 | *self.recur.get() += 1; 57 | r 58 | } 59 | } 60 | } 61 | 62 | #[inline(always)] 63 | pub fn exit(&self) 64 | { 65 | unsafe { *self.recur.get() -= 1; } 66 | 67 | if SS::VALUE { 68 | debug_assert_eq!(self.held.load(Ordering::SeqCst), 1); 69 | debug_assert_eq!(self.owner.load(Ordering::SeqCst), Self::tid()); 70 | 71 | 72 | if unsafe { *self.recur.get() } == 0 { 73 | self.owner.store(0, Ordering::Relaxed); 74 | self.held.store(0, Ordering::Release); 75 | } 76 | } 77 | } 78 | 79 | pub fn recur(&self) -> usize 80 | { 81 | unsafe { *self.recur.get() } 82 | } 83 | 84 | #[inline(always)] 85 | fn tid() -> usize 86 | { 87 | //from: https://github.com/Amanieu/parking_lot/blob/master/src/remutex.rs 88 | 89 | // The address of a thread-local variable is guaranteed to be unique to the 90 | // current thread, and is also guaranteed to be recur_nssn-zero. 91 | thread_local!(static KEY: u8 = unsafe { ::std::mem::uninitialized() }); 92 | KEY.with(|x| x as *const _ as usize) 93 | } 94 | } 95 | 96 | 97 | 98 | #[cfg(test)] 99 | mod test 100 | { 101 | #[test] 102 | fn recur() 103 | { 104 | let r = crate::sync::ReSpinLock::::new(); 105 | assert_eq!(r.enter(), 0); 106 | a(&r); 107 | r.exit(); 108 | 109 | assert_eq!(r.enter(), 0); 110 | r.exit(); 111 | 112 | 113 | fn a(l: &crate::sync::ReSpinLock) 114 | { 115 | assert_eq!(l.enter(), 1); 116 | 117 | b(l); 118 | 119 | l.exit(); 120 | } 121 | 122 | fn b(l: &crate::sync::ReSpinLock) 123 | { 124 | assert_eq!(l.enter(), 2); 125 | l.exit(); 126 | } 127 | } 128 | } -------------------------------------------------------------------------------- /src/sync/re_spin_mutex.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | use std::ops::Deref; 3 | 4 | pub struct ReSpinMutex 5 | { 6 | lock: ReSpinLock, 7 | value: RecurCell, 8 | } 9 | 10 | pub struct Guard<'a, SS:YesNo, V> 11 | { 12 | value: &'a RecurCell, 13 | lock: &'a ReSpinLock 14 | } 15 | 16 | impl<'a, SS:YesNo, V> Drop for Guard<'a, SS, V> 17 | { 18 | fn drop(&mut self) 19 | { 20 | self.lock.exit(); 21 | } 22 | } 23 | 24 | impl<'a, SS:YesNo, V> Deref for Guard<'a, SS, V> 25 | { 26 | type Target = RecurCell; 27 | fn deref(&self) -> &Self::Target { self.value } 28 | } 29 | 30 | impl ReSpinMutex 31 | { 32 | pub fn new(value: V) -> Self 33 | { 34 | ReSpinMutex { lock: ReSpinLock::new(), value: RecurCell::new(value) } 35 | } 36 | 37 | pub fn lock(&self) -> Guard 38 | { 39 | self.lock.enter(); 40 | Guard{ value: &self.value, lock: &self.lock } 41 | } 42 | } -------------------------------------------------------------------------------- /src/sync/recur_cell.rs: -------------------------------------------------------------------------------- 1 | use std::cell::UnsafeCell; 2 | use std::cell::Cell; 3 | use std::ptr; 4 | 5 | pub struct RecurCell 6 | { 7 | val: UnsafeCell>, 8 | cur: Cell<*const Option>, 9 | } 10 | 11 | impl RecurCell 12 | { 13 | pub fn new(val: V) -> Self 14 | { 15 | RecurCell { val: UnsafeCell::new(Some(val)), cur: Cell::new(ptr::null()) } 16 | } 17 | 18 | pub fn map(&self, f: impl FnOnce(&V) -> U) -> U 19 | { 20 | let val = unsafe{ &mut *self.val.get() }.take(); 21 | let u = if val.is_some() { 22 | assert_eq!(self.cur.get(), ptr::null()); 23 | self.cur.replace(&val); 24 | f(val.as_ref().unwrap()) 25 | } else { 26 | assert_ne!(self.cur.get(), ptr::null()); 27 | f(unsafe{ &*self.cur.get() }.as_ref().unwrap()) 28 | }; 29 | 30 | if self.cur.get() == &val { 31 | self.cur.replace(ptr::null()); 32 | assert!(unsafe{ &*self.val.get() }.is_none()); 33 | *unsafe{ &mut *self.val.get() } = val; 34 | } 35 | 36 | u 37 | } 38 | 39 | pub fn replace(&self, val: V) -> Option 40 | { 41 | self.cur.replace(ptr::null()); 42 | unsafe{ &mut *self.val.get() }.replace(val) 43 | } 44 | } -------------------------------------------------------------------------------- /src/sync/ss_mark.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | use std::ops::Deref; 3 | use std::marker::PhantomData; 4 | 5 | /// Send+Sync Mark 6 | pub unsafe trait Ssmark : Sized { } 7 | 8 | unsafe impl Ssmark for () {} 9 | unsafe impl > Ssmark for (A,) {} 10 | unsafe impl , B: Ssmark> Ssmark for (A, B) {} 11 | unsafe impl , B: Ssmark, C: Ssmark> Ssmark for (A, B, C) {} 12 | unsafe impl , B: Ssmark, C: Ssmark, D: Ssmark> Ssmark for (A, B, C, D) {} 13 | unsafe impl , B: Ssmark, C: Ssmark, D: Ssmark, E: Ssmark> Ssmark for (A, B, C, D, E) {} 14 | unsafe impl , B: Ssmark, C: Ssmark, D: Ssmark, E: Ssmark, F: Ssmark> Ssmark for (A, B, C, D, E, F) {} 15 | unsafe impl , B: Ssmark, C: Ssmark, D: Ssmark, E: Ssmark, F: Ssmark, G: Ssmark> Ssmark for (A, B, C, D, E, F, F, G) {} 16 | 17 | unsafe impl Ssmark for fn(A, B, C) -> R {} 18 | unsafe impl Ssmark for fn(A, B) -> R {} 19 | unsafe impl Ssmark for fn(&A, &B) -> R {} 20 | unsafe impl Ssmark for fn(&A, B) -> R {} 21 | unsafe impl Ssmark for fn(&A, &B, C) -> R {} 22 | 23 | pub struct SSWrap(V); 24 | unsafe impl Ssmark for SSWrap {} 25 | impl SSWrap 26 | { 27 | pub fn new(v: V) -> Self { SSWrap(v) } 28 | pub fn into_inner(self) -> V { self.0 } 29 | } 30 | impl Deref for SSWrap 31 | { 32 | type Target = V; 33 | fn deref(&self) -> &V { &self.0 } 34 | } 35 | 36 | pub struct SsForward> 37 | { 38 | pub captures: Caps, 39 | PhantomData: PhantomData 40 | } 41 | 42 | impl> SsForward 43 | { 44 | pub fn new(value: Caps) -> Self 45 | { 46 | SsForward { captures: value, PhantomData } 47 | } 48 | 49 | pub fn into_inner(self) -> Caps { self.captures } 50 | } 51 | 52 | unsafe impl> 53 | Ssmark 54 | for SsForward {} 55 | 56 | impl> 57 | Deref 58 | for SsForward 59 | { 60 | type Target = Caps; 61 | fn deref(&self) -> &Caps { &self.captures } 62 | } -------------------------------------------------------------------------------- /src/sync/yesno.rs: -------------------------------------------------------------------------------- 1 | 2 | pub trait YesNo : Send+Sync+Clone+ 'static 3 | { 4 | const SELF: Self; 5 | const VALUE: bool; 6 | } 7 | #[derive(PartialEq, Copy, Clone)] 8 | pub struct YES; 9 | #[derive(PartialEq, Copy, Clone)] 10 | pub struct NO; 11 | 12 | impl YesNo for YES 13 | { 14 | const SELF: Self = YES; 15 | const VALUE: bool = true; 16 | } 17 | impl YesNo for NO 18 | { 19 | const SELF: Self = NO; 20 | const VALUE: bool = false; 21 | } 22 | 23 | pub unsafe auto trait No {} 24 | 25 | impl !No for YES {} -------------------------------------------------------------------------------- /src/unsub.rs: -------------------------------------------------------------------------------- 1 | use crate::*; 2 | use std::cell::UnsafeCell; 3 | use std::sync::{Arc, Once, ONCE_INIT}; 4 | use std::sync::atomic::{AtomicBool, Ordering}; 5 | 6 | struct State<'a, SS:YesNo> 7 | { 8 | lock: ReSpinLock, 9 | done: AtomicBool, 10 | cb: UnsafeCell+'a>>>, 11 | cbs: UnsafeCell>>, 12 | } 13 | 14 | impl<'a, SS:YesNo> Drop for State<'a, SS> 15 | { 16 | fn drop(&mut self) { self.unsub_then(||{}); } 17 | } 18 | 19 | pub struct Unsub<'a, SS:YesNo> 20 | { 21 | state: Arc> 22 | } 23 | 24 | unsafe impl Send for Unsub<'static, YES> {} 25 | unsafe impl Sync for Unsub<'static, YES> {} 26 | 27 | unsafe impl<'a, SS:YesNo> Ssmark for Unsub<'a, SS> {} 28 | 29 | impl<'a, SS:YesNo> State<'a, SS> 30 | { 31 | #[inline(always)] 32 | fn is_done(&self) -> bool 33 | { 34 | self.done.load(Ordering::Relaxed) 35 | } 36 | 37 | fn unsub_then(&self, f: impl FnOnce()) 38 | { 39 | self.lock.enter(); 40 | if ! self.done.swap(true, Ordering::Release) { 41 | 42 | unsafe{ 43 | if let Some(cb) = (&mut *self.cb.get()).take() { 44 | cb.call_box(()); 45 | } 46 | for cb in (&mut *self.cbs.get()).drain(..) { 47 | cb.unsub(); 48 | } 49 | (&mut *self.cbs.get()).shrink_to_fit(); 50 | } 51 | self.lock.exit(); 52 | 53 | f(); 54 | return; 55 | } 56 | 57 | self.lock.exit(); 58 | } 59 | 60 | pub fn if_not_done(&self, then: impl FnOnce()) 61 | { 62 | if self.is_done() { return; } 63 | 64 | self.lock.enter(); 65 | 66 | if ! self.is_done() { 67 | then(); 68 | } 69 | 70 | self.lock.exit(); 71 | } 72 | 73 | #[inline(never)] 74 | fn add_internal(&self, cb: Unsub<'a, SS>) 75 | { 76 | if self.is_done() || cb.is_done() { 77 | cb.unsub(); 78 | return; 79 | } 80 | 81 | self.lock.enter(); 82 | unsafe { (&mut * self.cbs.get()).push(cb); } 83 | self.lock.exit(); 84 | } 85 | } 86 | 87 | impl<'a, SS:YesNo> Clone for Unsub<'a, SS> 88 | { 89 | fn clone(&self) -> Unsub<'a, SS> 90 | { 91 | Unsub { state: self.state.clone() } 92 | } 93 | } 94 | 95 | impl<'a, SS:YesNo> Unsub<'a, SS> 96 | { 97 | 98 | pub fn new() -> Unsub<'a, SS> 99 | { 100 | Unsub { state: Arc::new(State { lock: ReSpinLock::new(), done: AtomicBool::new(false), cb: UnsafeCell::new(None), cbs: UnsafeCell::new(Vec::new()) }) } 101 | } 102 | 103 | #[inline(never)] 104 | pub fn done() -> Unsub<'a, SS> 105 | { 106 | unsafe { 107 | static mut VAL: *const () = ::std::ptr::null(); 108 | static INIT: Once = ONCE_INIT; 109 | INIT.call_once(|| VAL = ::std::mem::transmute(Arc::into_raw(Arc::>::new(State { lock: ReSpinLock::new(), done: AtomicBool::new(true), cb: UnsafeCell::new(None), cbs: UnsafeCell::new(Vec::new()) })))); 110 | let arc = Arc::>::from_raw(::std::mem::transmute(VAL)); 111 | let sub = Unsub { state: arc.clone() }; 112 | ::std::mem::forget(arc); 113 | return sub; 114 | } 115 | } 116 | 117 | #[inline(always)] 118 | pub fn is_done(&self) -> bool { self.state.is_done() } 119 | 120 | pub fn unsub(&self) 121 | { 122 | self.state.unsub_then(||{}); 123 | } 124 | 125 | pub fn unsub_then(&self, f: impl FnOnce()) 126 | { 127 | self.state.unsub_then(f); 128 | } 129 | 130 | pub fn if_not_done(&self, then: impl FnOnce()) 131 | { 132 | self.state.if_not_done(then); 133 | } 134 | 135 | pub fn add(&self, cb: Unsub<'a, SS>) -> &Self 136 | { 137 | self.state.add_internal(cb); 138 | self 139 | } 140 | 141 | pub fn added(self, cb: Unsub<'a, SS>) -> Self 142 | { 143 | self.add(cb); 144 | self 145 | } 146 | 147 | pub fn add_each(&self, b: Unsub<'a, SS>) -> &Self 148 | { 149 | self.add(b.added(self.clone())) 150 | } 151 | 152 | pub fn added_each(self, b: Unsub<'a, SS>) -> Self 153 | { 154 | self.add_each(b); 155 | self 156 | } 157 | } 158 | 159 | impl<'a, SS:YesNo> Unsub<'a, SS> 160 | { 161 | pub fn with(cb: impl ActOnce+'a) -> Unsub<'a, SS> 162 | { 163 | Unsub { state: Arc::new(State { lock: ReSpinLock::new(), done: AtomicBool::new(false), cb:UnsafeCell::new(Some(box cb)), cbs: UnsafeCell::new(Vec::new()) }) } 164 | } 165 | } 166 | 167 | //impl Unsub<'static, YES> 168 | //{ 169 | // pub fn with(cb: impl FnOnce()+Send+Sync+'static) -> Unsub<'static, YES> 170 | // { 171 | // Unsub { state: Arc::new(State { lock: ReSpinLock::new(), done: AtomicBool::new(false), cb:UnsafeCell::new(Some(box cb)), cbs: UnsafeCell::new(Vec::new()) }) } 172 | // } 173 | //} 174 | 175 | impl<'o, SS: YesNo> FnOnce<()> for Unsub<'o, SS> 176 | { 177 | type Output = (); 178 | extern "rust-call" fn call_once(self, _: ()) 179 | { 180 | self.unsub(); 181 | } 182 | } 183 | 184 | #[cfg(test)] 185 | mod test 186 | { 187 | use crate::*; 188 | use std::cell::Cell; 189 | use std::sync::Arc; 190 | 191 | #[test] 192 | fn drop_should_unsub() 193 | { 194 | let n = Cell::new(0); 195 | let a = Unsub::::with(|| { n.replace(1); }); 196 | 197 | drop(a); 198 | 199 | assert_eq!(n.get(), 1); 200 | } 201 | 202 | #[test] 203 | fn scope() 204 | { 205 | let a = Unsub::::new(); 206 | let r = Arc::new(123); 207 | { 208 | //let n = Cell::new(123); 209 | //a.add(Unsub::::with(|| println!("n={}", n.get()))); 210 | let _ = Arc::downgrade(&r); 211 | 212 | //let mksub = || Unsub::::with(|| weak.upgrade()); 213 | //a.add(mksub()); 214 | //a.add(Unsub::::with(|| weak.upgrade())); 215 | 216 | //let x = weak.upgrade(); 217 | 218 | 219 | } 220 | 221 | a.unsub(); 222 | } 223 | 224 | } -------------------------------------------------------------------------------- /src/util/clones.rs: -------------------------------------------------------------------------------- 1 | 2 | pub trait Clones : Clone 3 | { 4 | fn clones(self) -> R; 5 | } 6 | 7 | impl Clones for T 8 | { 9 | fn clones(self) -> T 10 | { 11 | self 12 | } 13 | } 14 | 15 | impl Clones<(T, T)> for T 16 | { 17 | fn clones(self) -> (T, T) 18 | { 19 | (self.clone(), self) 20 | } 21 | } 22 | 23 | impl Clones<(T, T, T)> for T 24 | { 25 | fn clones(self) -> (T, T, T) 26 | { 27 | (self.clone(), self.clone(), self) 28 | } 29 | } 30 | 31 | impl Clones<(T, T, T, T)> for T 32 | { 33 | fn clones(self) -> (T, T, T, T) 34 | { 35 | (self.clone(), self.clone(), self.clone(), self) 36 | } 37 | } 38 | 39 | impl Clones<(T, T, T, T, T)> for T 40 | { 41 | fn clones(self) -> (T, T, T, T, T) 42 | { 43 | (self.clone(), self.clone(), self.clone(), self.clone(), self) 44 | } 45 | } 46 | 47 | impl Clones<(T, T, T, T, T, T)> for T 48 | { 49 | fn clones(self) -> (T, T, T, T, T, T) 50 | { 51 | (self.clone(), self.clone(), self.clone(), self.clone(), self.clone(), self) 52 | } 53 | } 54 | 55 | impl Clones<(T, T, T, T, T, T, T)> for T 56 | { 57 | fn clones(self) -> (T, T, T, T, T, T, T) 58 | { 59 | (self.clone(), self.clone(), self.clone(), self.clone(), self.clone(), self.clone(), self) 60 | } 61 | } 62 | 63 | pub trait RcExt 64 | { 65 | type Weak; 66 | fn weak(&self) -> Self::Weak; 67 | } 68 | 69 | impl RcExt for ::std::rc::Rc 70 | { 71 | type Weak = ::std::rc::Weak; 72 | fn weak(&self) -> Self::Weak 73 | { 74 | ::std::rc::Rc::downgrade(self) 75 | } 76 | } 77 | 78 | impl RcExt for ::std::sync::Arc 79 | { 80 | type Weak = ::std::sync::Weak; 81 | fn weak(&self) -> Self::Weak 82 | { 83 | ::std::sync::Arc::downgrade(self) 84 | } 85 | } 86 | 87 | pub fn weak(rc: &R) -> R::Weak 88 | { 89 | rc.weak() 90 | } 91 | 92 | 93 | #[cfg(test)] 94 | mod test 95 | { 96 | use std::rc::Rc; 97 | use super::*; 98 | 99 | #[test] 100 | fn compiles() 101 | { 102 | let x = 1; 103 | let (_,b) = x.clones(); 104 | let (c,_,_) = x.clones(); 105 | 106 | let rc = Rc::new(0); 107 | 108 | let _ = hello((|_,_,_| ||{ 109 | println!("ok?"); 110 | })(rc.weak(),b,c)); 111 | 112 | fn hello(f: impl FnOnce()){ f() } 113 | } 114 | } -------------------------------------------------------------------------------- /src/util/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod clones; --------------------------------------------------------------------------------