15
15
//! This implementation is also used as the fallback implementation of an event
16
16
//! loop if no other one is provided (and M:N scheduling is desired).
17
17
18
+ use alloc:: arc:: Arc ;
19
+ use std:: sync:: atomics;
18
20
use std:: mem;
19
21
use std:: rt:: rtio:: { EventLoop , IoFactory , RemoteCallback } ;
20
22
use std:: rt:: rtio:: { PausableIdleCallback , Callback } ;
@@ -27,10 +29,11 @@ pub fn event_loop() -> Box<EventLoop:Send> {
27
29
28
30
struct BasicLoop {
29
31
work : Vec < proc ( ) : Send > , // pending work
30
- idle : Option < * mut BasicPausable > , // only one is allowed
31
32
remotes : Vec < ( uint , Box < Callback : Send > ) > ,
32
33
next_remote : uint ,
33
34
messages : Exclusive < Vec < Message > > ,
35
+ idle : Option < Box < Callback : Send > > ,
36
+ idle_active : Option < Arc < atomics:: AtomicBool > > ,
34
37
}
35
38
36
39
enum Message { RunRemote ( uint ) , RemoveRemote ( uint ) }
@@ -40,6 +43,7 @@ impl BasicLoop {
40
43
BasicLoop {
41
44
work : vec ! [ ] ,
42
45
idle : None ,
46
+ idle_active : None ,
43
47
next_remote : 0 ,
44
48
remotes : vec ! [ ] ,
45
49
messages : Exclusive :: new ( vec ! [ ] ) ,
@@ -92,20 +96,18 @@ impl BasicLoop {
92
96
93
97
/// Run the idle callback if one is registered
94
98
fn idle ( & mut self ) {
95
- unsafe {
96
- match self . idle {
97
- Some ( idle) => {
98
- if ( * idle) . active {
99
- ( * idle) . work . call ( ) ;
100
- }
99
+ match self . idle {
100
+ Some ( ref mut idle) => {
101
+ if self . idle_active . get_ref ( ) . load ( atomics:: SeqCst ) {
102
+ idle. call ( ) ;
101
103
}
102
- None => { }
103
104
}
105
+ None => { }
104
106
}
105
107
}
106
108
107
109
fn has_idle ( & self ) -> bool {
108
- unsafe { self . idle . is_some ( ) && ( * * self . idle . get_ref ( ) ) . active }
110
+ self . idle . is_some ( ) && self . idle_active . get_ref ( ) . load ( atomics :: SeqCst )
109
111
}
110
112
}
111
113
@@ -141,13 +143,11 @@ impl EventLoop for BasicLoop {
141
143
// FIXME: Seems like a really weird requirement to have an event loop provide.
142
144
fn pausable_idle_callback ( & mut self , cb : Box < Callback : Send > )
143
145
-> Box < PausableIdleCallback : Send > {
144
- let callback = box BasicPausable :: new ( self , cb) ;
145
146
rtassert ! ( self . idle. is_none( ) ) ;
146
- unsafe {
147
- let cb_ptr: & * mut BasicPausable = mem:: transmute ( & callback) ;
148
- self . idle = Some ( * cb_ptr) ;
149
- }
150
- callback as Box < PausableIdleCallback : Send >
147
+ self . idle = Some ( cb) ;
148
+ let a = Arc :: new ( atomics:: AtomicBool :: new ( true ) ) ;
149
+ self . idle_active = Some ( a. clone ( ) ) ;
150
+ box BasicPausable { active : a } as Box < PausableIdleCallback : Send >
151
151
}
152
152
153
153
fn remote_callback ( & mut self , f : Box < Callback : Send > )
@@ -196,35 +196,21 @@ impl Drop for BasicRemote {
196
196
}
197
197
198
198
struct BasicPausable {
199
- eloop : * mut BasicLoop ,
200
- work : Box < Callback : Send > ,
201
- active : bool ,
202
- }
203
-
204
- impl BasicPausable {
205
- fn new ( eloop : & mut BasicLoop , cb : Box < Callback : Send > ) -> BasicPausable {
206
- BasicPausable {
207
- active : false ,
208
- work : cb,
209
- eloop : eloop,
210
- }
211
- }
199
+ active : Arc < atomics:: AtomicBool > ,
212
200
}
213
201
214
202
impl PausableIdleCallback for BasicPausable {
215
203
fn pause ( & mut self ) {
216
- self . active = false ;
204
+ self . active . store ( false , atomics :: SeqCst ) ;
217
205
}
218
206
fn resume ( & mut self ) {
219
- self . active = true ;
207
+ self . active . store ( true , atomics :: SeqCst ) ;
220
208
}
221
209
}
222
210
223
211
impl Drop for BasicPausable {
224
212
fn drop ( & mut self ) {
225
- unsafe {
226
- ( * self . eloop ) . idle = None ;
227
- }
213
+ self . active . store ( false , atomics:: SeqCst ) ;
228
214
}
229
215
}
230
216
0 commit comments