1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use std::cell::RefCell;
use std::mem;
use std::rc::Rc;
use std::sync::atomic::Ordering;
use std::sync::Arc;
use std::thread;
use {spawn_unsafe, FnBox};
use sync::AtomicOption;
pub struct Scope<'a> {
dtors: RefCell<Option<DtorChain<'a>>>
}
struct DtorChain<'a> {
dtor: Box<FnBox + 'a>,
next: Option<Box<DtorChain<'a>>>
}
enum JoinState {
Running(thread::JoinHandle<()>),
Joined,
}
impl JoinState {
fn join(&mut self) {
let mut state = JoinState::Joined;
mem::swap(self, &mut state);
if let JoinState::Running(handle) = state {
let res = handle.join();
if !thread::panicking() { res.unwrap(); }
}
}
}
pub struct ScopedJoinHandle<T> {
inner: Rc<RefCell<JoinState>>,
packet: Arc<AtomicOption<T>>,
thread: thread::Thread,
}
pub fn scope<'a, F, R>(f: F) -> R where F: FnOnce(&Scope<'a>) -> R {
let mut scope = Scope { dtors: RefCell::new(None) };
let ret = f(&scope);
scope.drop_all();
ret
}
impl<'a> Scope<'a> {
fn drop_all(&mut self) {
loop {
let dtor = {
let mut dtors = self.dtors.borrow_mut();
if let Some(mut node) = dtors.take() {
*dtors = node.next.take().map(|b| *b);
node.dtor
} else {
return
}
};
dtor.call_box()
}
}
pub fn defer<F>(&self, f: F) where F: FnOnce() + 'a {
let mut dtors = self.dtors.borrow_mut();
*dtors = Some(DtorChain {
dtor: Box::new(f),
next: dtors.take().map(Box::new)
});
}
pub fn spawn<F, T>(&self, f: F) -> ScopedJoinHandle<T> where
F: FnOnce() -> T + Send + 'a, T: Send + 'a
{
let their_packet = Arc::new(AtomicOption::new());
let my_packet = their_packet.clone();
let join_handle = unsafe {
spawn_unsafe(move || {
their_packet.swap(f(), Ordering::Relaxed);
})
};
let thread = join_handle.thread().clone();
let deferred_handle = Rc::new(RefCell::new(JoinState::Running(join_handle)));
let my_handle = deferred_handle.clone();
self.defer(move || {
let mut state = deferred_handle.borrow_mut();
state.join();
});
ScopedJoinHandle {
inner: my_handle,
packet: my_packet,
thread: thread,
}
}
}
impl<T> ScopedJoinHandle<T> {
pub fn join(self) -> T {
self.inner.borrow_mut().join();
self.packet.take(Ordering::Relaxed).unwrap()
}
pub fn thread(&self) -> &thread::Thread {
&self.thread
}
}
impl<'a> Drop for Scope<'a> {
fn drop(&mut self) {
self.drop_all()
}
}