Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 5f4aa9f

Browse files
committedDec 21, 2018
Protect against reentrancy (messily)
1 parent b75073a commit 5f4aa9f

File tree

1 file changed

+49
-14
lines changed

1 file changed

+49
-14
lines changed
 

‎src/platform_impl/macos/app_state.rs

+49-14
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,13 @@ where
8282
#[derive(Default)]
8383
struct Handler {
8484
ready: AtomicBool,
85+
in_callback: AtomicBool,
8586
control_flow: Mutex<ControlFlow>,
8687
control_flow_prev: Mutex<ControlFlow>,
8788
start_time: Mutex<Option<Instant>>,
8889
callback: Mutex<Option<Box<dyn EventHandler>>>,
8990
pending_events: Mutex<VecDeque<Event<Never>>>,
91+
deferred_events: Mutex<VecDeque<Event<Never>>>,
9092
pending_redraw: Mutex<Vec<WindowId>>,
9193
waker: Mutex<EventLoopWaker>,
9294
}
@@ -99,6 +101,10 @@ impl Handler {
99101
self.pending_events.lock().unwrap()
100102
}
101103

104+
fn deferred<'a>(&'a self) -> MutexGuard<'a, VecDeque<Event<Never>>> {
105+
self.deferred_events.lock().unwrap()
106+
}
107+
102108
fn redraw<'a>(&'a self) -> MutexGuard<'a, Vec<WindowId>> {
103109
self.pending_redraw.lock().unwrap()
104110
}
@@ -143,10 +149,22 @@ impl Handler {
143149
mem::replace(&mut *self.events(), Default::default())
144150
}
145151

152+
fn take_deferred(&self) -> VecDeque<Event<Never>> {
153+
mem::replace(&mut *self.deferred(), Default::default())
154+
}
155+
146156
fn should_redraw(&self) -> Vec<WindowId> {
147157
mem::replace(&mut *self.redraw(), Default::default())
148158
}
149159

160+
fn get_in_callback(&self) -> bool {
161+
self.in_callback.load(Ordering::Acquire)
162+
}
163+
164+
fn set_in_callback(&self, in_callback: bool) {
165+
self.in_callback.store(in_callback, Ordering::Release);
166+
}
167+
150168
fn handle_nonuser_event(&self, event: Event<Never>) {
151169
if let Some(ref mut callback) = *self.callback.lock().unwrap() {
152170
callback.handle_nonuser_event(
@@ -181,13 +199,17 @@ impl AppState {
181199
}
182200

183201
pub fn exit() {
202+
HANDLER.set_in_callback(true);
184203
HANDLER.handle_nonuser_event(Event::LoopDestroyed);
204+
HANDLER.set_in_callback(false);
185205
}
186206

187207
pub fn launched() {
188208
HANDLER.set_ready();
189209
HANDLER.waker().start();
210+
HANDLER.set_in_callback(true);
190211
HANDLER.handle_nonuser_event(Event::NewEvents(StartCause::Init));
212+
HANDLER.set_in_callback(false);
191213
}
192214

193215
pub fn wakeup() {
@@ -214,7 +236,9 @@ impl AppState {
214236
},
215237
ControlFlow::Exit => StartCause::Poll,//panic!("unexpected `ControlFlow::Exit`"),
216238
};
239+
HANDLER.set_in_callback(true);
217240
HANDLER.handle_nonuser_event(Event::NewEvents(cause));
241+
HANDLER.set_in_callback(false);
218242
}
219243

220244
// This is called from multiple threads at present
@@ -227,38 +251,49 @@ impl AppState {
227251

228252
pub fn queue_event(event: Event<Never>) {
229253
if !unsafe { msg_send![class!(NSThread), isMainThread] } {
230-
panic!("uh-oh");
254+
panic!("Event queued from different thread: {:#?}", event);
231255
}
232256
HANDLER.events().push_back(event);
233257
}
234258

235259
pub fn queue_events(mut events: VecDeque<Event<Never>>) {
236260
if !unsafe { msg_send![class!(NSThread), isMainThread] } {
237-
panic!("uh-ohs");
261+
panic!("Events queued from different thread: {:#?}", events);
238262
}
239263
HANDLER.events().append(&mut events);
240264
}
241265

242266
pub fn send_event_immediately(event: Event<Never>) {
243267
if !unsafe { msg_send![class!(NSThread), isMainThread] } {
244-
panic!("uh-oh");
268+
panic!("Event sent from different thread: {:#?}", event);
269+
}
270+
HANDLER.deferred().push_back(event);
271+
if !HANDLER.get_in_callback() {
272+
HANDLER.set_in_callback(true);
273+
for event in HANDLER.take_deferred() {
274+
HANDLER.handle_nonuser_event(event);
275+
}
276+
HANDLER.set_in_callback(false);
245277
}
246-
HANDLER.handle_nonuser_event(event);
247278
}
248279

249280
pub fn cleared() {
250281
if !HANDLER.is_ready() { return }
251-
HANDLER.handle_user_events();
252-
for event in HANDLER.take_events() {
253-
HANDLER.handle_nonuser_event(event);
254-
}
255-
for window_id in HANDLER.should_redraw() {
256-
HANDLER.handle_nonuser_event(Event::WindowEvent {
257-
window_id,
258-
event: WindowEvent::RedrawRequested,
259-
});
282+
if !HANDLER.get_in_callback() {
283+
HANDLER.set_in_callback(true);
284+
HANDLER.handle_user_events();
285+
for event in HANDLER.take_events() {
286+
HANDLER.handle_nonuser_event(event);
287+
}
288+
for window_id in HANDLER.should_redraw() {
289+
HANDLER.handle_nonuser_event(Event::WindowEvent {
290+
window_id,
291+
event: WindowEvent::RedrawRequested,
292+
});
293+
}
294+
HANDLER.handle_nonuser_event(Event::EventsCleared);
295+
HANDLER.set_in_callback(false);
260296
}
261-
HANDLER.handle_nonuser_event(Event::EventsCleared);
262297
if HANDLER.should_exit() {
263298
let _: () = unsafe { msg_send![NSApp(), stop:nil] };
264299
return

0 commit comments

Comments
 (0)
Please sign in to comment.