Skip to content

Commit

Permalink
Fix thread executor not executing closure when called from non-loop t…
Browse files Browse the repository at this point in the history
…hread
  • Loading branch information
Osspial committed Nov 18, 2018
1 parent 5a3a5e2 commit 2c18b80
Showing 1 changed file with 18 additions and 13 deletions.
31 changes: 18 additions & 13 deletions src/platform_impl/windows/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,15 +140,14 @@ impl<T> ThreadMsgTargetSubclassInput<T> {
}

pub struct EventLoop<T: 'static> {
// Id of the background thread from the Win32 API.
thread_msg_target: HWND,
thread_msg_sender: Sender<T>,
window_target: RootELW<T>
}

pub struct EventLoopWindowTarget<T> {
thread_id: DWORD,
trigger_newevents_on_redraw: Arc<AtomicBool>,
thread_msg_target: HWND,
pub(crate) runner_shared: EventLoopRunnerShared<T>,
}

Expand All @@ -172,11 +171,12 @@ impl<T: 'static> EventLoop<T> {
let (thread_msg_target, thread_msg_sender) = thread_event_target_window(runner_shared.clone());

EventLoop {
thread_msg_target, thread_msg_sender,
thread_msg_sender,
window_target: RootELW {
p: EventLoopWindowTarget {
thread_id,
trigger_newevents_on_redraw: Arc::new(AtomicBool::new(true)),
thread_msg_target,
runner_shared
},
_marker: PhantomData
Expand Down Expand Up @@ -261,7 +261,7 @@ impl<T: 'static> EventLoop<T> {

pub fn create_proxy(&self) -> EventLoopProxy<T> {
EventLoopProxy {
target_window: self.thread_msg_target,
target_window: self.window_target.p.thread_msg_target,
event_send: self.thread_msg_sender.clone()
}
}
Expand All @@ -272,7 +272,8 @@ impl<T> EventLoopWindowTarget<T> {
pub(crate) fn create_thread_executor(&self) -> EventLoopThreadExecutor {
EventLoopThreadExecutor {
thread_id: self.thread_id,
trigger_newevents_on_redraw: self.trigger_newevents_on_redraw.clone()
trigger_newevents_on_redraw: self.trigger_newevents_on_redraw.clone(),
target_window: self.thread_msg_target
}
}
}
Expand Down Expand Up @@ -327,7 +328,7 @@ impl<T> EventLoopRunner<T> {
control_flow: ControlFlow::default(),
runner_state: RunnerState::New,
in_modal_loop: false,
modal_redraw_window: event_loop.thread_msg_target,
modal_redraw_window: event_loop.window_target.p.thread_msg_target,
event_handler: mem::transmute::<
Box<FnMut(Event<T>, &mut ControlFlow)>,
Box<FnMut(Event<T>, &mut ControlFlow)>
Expand Down Expand Up @@ -558,16 +559,20 @@ fn dur2timeout(dur: Duration) -> DWORD {
impl<T> Drop for EventLoop<T> {
fn drop(&mut self) {
unsafe {
winuser::DestroyWindow(self.thread_msg_target);
winuser::DestroyWindow(self.window_target.p.thread_msg_target);
}
}
}

pub(crate) struct EventLoopThreadExecutor {
thread_id: DWORD,
trigger_newevents_on_redraw: Arc<AtomicBool>
trigger_newevents_on_redraw: Arc<AtomicBool>,
target_window: HWND
}

unsafe impl Send for EventLoopThreadExecutor {}
unsafe impl Sync for EventLoopThreadExecutor {}

impl EventLoopThreadExecutor {
/// Check to see if we're in the parent event loop's thread.
pub(super) fn in_event_loop_thread(&self) -> bool {
Expand Down Expand Up @@ -605,11 +610,11 @@ impl EventLoopThreadExecutor {

let raw = Box::into_raw(boxed2);

let res = winuser::PostThreadMessageA(self.thread_id, *EXEC_MSG_ID,
raw as *mut () as usize as WPARAM, 0);
// PostThreadMessage can only fail if the thread ID is invalid (which shouldn't happen
// as the events loop is still alive) or if the queue is full.
assert!(res != 0, "PostThreadMessage failed ; is the messages queue full?");
let res = winuser::PostMessageW(
self.target_window, *EXEC_MSG_ID,
raw as *mut () as usize as WPARAM, 0
);
assert!(res != 0, "PostMessage failed ; is the messages queue full?");
}
}
}
Expand Down

0 comments on commit 2c18b80

Please sign in to comment.