Fix thread executor not executing closure when called from non-loop thread

This commit is contained in:
Osspial
2018-11-18 18:51:24 -05:00
parent 5a3a5e2293
commit 2c18b804df

View File

@@ -140,8 +140,6 @@ impl<T> ThreadMsgTargetSubclassInput<T> {
} }
pub struct EventLoop<T: 'static> { pub struct EventLoop<T: 'static> {
// Id of the background thread from the Win32 API.
thread_msg_target: HWND,
thread_msg_sender: Sender<T>, thread_msg_sender: Sender<T>,
window_target: RootELW<T> window_target: RootELW<T>
} }
@@ -149,6 +147,7 @@ pub struct EventLoop<T: 'static> {
pub struct EventLoopWindowTarget<T> { pub struct EventLoopWindowTarget<T> {
thread_id: DWORD, thread_id: DWORD,
trigger_newevents_on_redraw: Arc<AtomicBool>, trigger_newevents_on_redraw: Arc<AtomicBool>,
thread_msg_target: HWND,
pub(crate) runner_shared: EventLoopRunnerShared<T>, pub(crate) runner_shared: EventLoopRunnerShared<T>,
} }
@@ -172,11 +171,12 @@ impl<T: 'static> EventLoop<T> {
let (thread_msg_target, thread_msg_sender) = thread_event_target_window(runner_shared.clone()); let (thread_msg_target, thread_msg_sender) = thread_event_target_window(runner_shared.clone());
EventLoop { EventLoop {
thread_msg_target, thread_msg_sender, thread_msg_sender,
window_target: RootELW { window_target: RootELW {
p: EventLoopWindowTarget { p: EventLoopWindowTarget {
thread_id, thread_id,
trigger_newevents_on_redraw: Arc::new(AtomicBool::new(true)), trigger_newevents_on_redraw: Arc::new(AtomicBool::new(true)),
thread_msg_target,
runner_shared runner_shared
}, },
_marker: PhantomData _marker: PhantomData
@@ -261,7 +261,7 @@ impl<T: 'static> EventLoop<T> {
pub fn create_proxy(&self) -> EventLoopProxy<T> { pub fn create_proxy(&self) -> EventLoopProxy<T> {
EventLoopProxy { EventLoopProxy {
target_window: self.thread_msg_target, target_window: self.window_target.p.thread_msg_target,
event_send: self.thread_msg_sender.clone() event_send: self.thread_msg_sender.clone()
} }
} }
@@ -272,7 +272,8 @@ impl<T> EventLoopWindowTarget<T> {
pub(crate) fn create_thread_executor(&self) -> EventLoopThreadExecutor { pub(crate) fn create_thread_executor(&self) -> EventLoopThreadExecutor {
EventLoopThreadExecutor { EventLoopThreadExecutor {
thread_id: self.thread_id, 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
} }
} }
} }
@@ -327,7 +328,7 @@ impl<T> EventLoopRunner<T> {
control_flow: ControlFlow::default(), control_flow: ControlFlow::default(),
runner_state: RunnerState::New, runner_state: RunnerState::New,
in_modal_loop: false, 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::< event_handler: mem::transmute::<
Box<FnMut(Event<T>, &mut ControlFlow)>, Box<FnMut(Event<T>, &mut ControlFlow)>,
Box<FnMut(Event<T>, &mut ControlFlow)> Box<FnMut(Event<T>, &mut ControlFlow)>
@@ -558,16 +559,20 @@ fn dur2timeout(dur: Duration) -> DWORD {
impl<T> Drop for EventLoop<T> { impl<T> Drop for EventLoop<T> {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
winuser::DestroyWindow(self.thread_msg_target); winuser::DestroyWindow(self.window_target.p.thread_msg_target);
} }
} }
} }
pub(crate) struct EventLoopThreadExecutor { pub(crate) struct EventLoopThreadExecutor {
thread_id: DWORD, 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 { impl EventLoopThreadExecutor {
/// Check to see if we're in the parent event loop's thread. /// Check to see if we're in the parent event loop's thread.
pub(super) fn in_event_loop_thread(&self) -> bool { pub(super) fn in_event_loop_thread(&self) -> bool {
@@ -605,11 +610,11 @@ impl EventLoopThreadExecutor {
let raw = Box::into_raw(boxed2); let raw = Box::into_raw(boxed2);
let res = winuser::PostThreadMessageA(self.thread_id, *EXEC_MSG_ID, let res = winuser::PostMessageW(
raw as *mut () as usize as WPARAM, 0); self.target_window, *EXEC_MSG_ID,
// PostThreadMessage can only fail if the thread ID is invalid (which shouldn't happen raw as *mut () as usize as WPARAM, 0
// as the events loop is still alive) or if the queue is full. );
assert!(res != 0, "PostThreadMessage failed ; is the messages queue full?"); assert!(res != 0, "PostMessage failed ; is the messages queue full?");
} }
} }
} }