1use std::cell::RefCell;
4use std::fmt;
5use std::mem;
6use std::panic;
7use std::rc::Rc;
8use std::sync::Arc;
9use std::thread;
10
11use crate::coroutine_impl::{spawn, Coroutine};
12use crate::join::JoinHandle;
13use crossbeam::atomic::AtomicCell;
14
15pub unsafe fn spawn_unsafe<'a, F>(f: F) -> JoinHandle<()>
17 where
18 F: FnOnce() + Send + 'a,
19{
20 let closure: Box<dyn FnOnce() + 'a> = Box::new(f);
21 let closure: Box<dyn FnOnce() + Send> = mem::transmute(closure);
22 spawn(move || closure())
23}
24
25pub struct Scope<'a> {
26 dtors: RefCell<Option<DtorChain<'a>>>,
27}
28
29struct DtorChain<'a> {
30 dtor: Box<dyn FnOnce() + 'a>,
31 next: Option<Box<DtorChain<'a>>>,
32}
33
34enum JoinState {
35 Running(JoinHandle<()>),
36 Joined,
37}
38
39impl JoinState {
40 fn join(&mut self) {
41 let mut state = JoinState::Joined;
42 mem::swap(self, &mut state);
43 if let JoinState::Running(handle) = state {
44 let res = handle.join();
45
46 if !thread::panicking() {
48 res.unwrap_or_else(|e| panic::resume_unwind(e));
49 }
50 }
51 }
52}
53
54pub struct ScopedJoinHandle<T> {
56 inner: Rc<RefCell<JoinState>>,
57 packet: Arc<AtomicCell<Option<T>>>,
58 co: Coroutine,
59}
60
61pub fn scope<'a, F, R>(f: F) -> R
66 where
67 F: FnOnce(&Scope<'a>) -> R,
68{
69 let mut scope = Scope {
70 dtors: RefCell::new(None),
71 };
72 let ret = f(&scope);
73 scope.drop_all();
74 ret
75}
76
77impl<'a> fmt::Debug for Scope<'a> {
78 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
79 write!(f, "Scope {{ ... }}")
80 }
81}
82
83impl<T> fmt::Debug for ScopedJoinHandle<T> {
84 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
85 write!(f, "ScopedJoinHandle {{ ... }}")
86 }
87}
88
89impl<'a> Scope<'a> {
90 fn drop_all(&mut self) {
96 loop {
97 let dtor = {
100 let mut dtors = self.dtors.borrow_mut();
101 if let Some(mut node) = dtors.take() {
102 *dtors = node.next.take().map(|b| *b);
103 node.dtor
104 } else {
105 return;
106 }
107 };
108 dtor();
109 }
110 }
111
112 pub fn defer<F>(&self, f: F)
117 where
118 F: FnOnce() + 'a,
119 {
120 let mut dtors = self.dtors.borrow_mut();
121 *dtors = Some(DtorChain {
122 dtor: Box::new(f),
123 next: dtors.take().map(Box::new),
124 });
125 }
126
127 fn spawn_impl<F, T>(&self, f: F) -> ScopedJoinHandle<T>
135 where
136 F: FnOnce() -> T + Send + 'a,
137 T: Send + 'a,
138 {
139 let their_packet = Arc::new(AtomicCell::new(None));
140 let my_packet = their_packet.clone();
141
142 let join_handle = unsafe {
143 spawn_unsafe(move || {
144 their_packet.swap(Some(f()));
145 })
146 };
147
148 let co = join_handle.coroutine().clone();
149 let deferred_handle = Rc::new(RefCell::new(JoinState::Running(join_handle)));
150 let my_handle = deferred_handle.clone();
151
152 self.defer(move || {
153 let mut state = deferred_handle.borrow_mut();
154 state.join();
155 });
156
157 ScopedJoinHandle {
158 inner: my_handle,
159 packet: my_packet,
160 co,
161 }
162 }
163
164 pub unsafe fn spawn<F, T>(&self, f: F) -> ScopedJoinHandle<T>
172 where
173 F: FnOnce() -> T + Send + 'a,
174 T: Send + 'a,
175 {
176 self.spawn_impl(f)
177 }
178}
179
180impl<T> ScopedJoinHandle<T> {
181 pub fn join(self) -> T {
183 self.inner.borrow_mut().join();
184 self.packet.take().unwrap()
185 }
186
187 pub fn coroutine(&self) -> &Coroutine {
189 &self.co
190 }
191}
192
193impl<'a> Drop for Scope<'a> {
194 fn drop(&mut self) {
195 self.drop_all()
196 }
197}