I need help with thread sync and borrowing

I'm working with Win32 and initializing a new thread with a message queue. I will be using the new window created in the thread outside the thread boundaries for sending windows messages. There must be a better way of doing this, right?

Here's the code I'm stuck with:

impl<T> ThreadedView<T> {
    fn new(inner: T) -> Self {
        
        // Static number to increase when creating new threads
        static THREAD_NUMBER : Mutex<u64> = Mutex::new(0);
        let mut thread_num = THREAD_NUMBER.lock().unwrap();
        
        // Create a barrier to synchronize the new thread with this thread.
        let init_barrier = Arc::new(RwLock::new(Barrier::new(2)));
        let barrier_ptr = init_barrier.clone();
        
        // Create an uninitialized window handle to initialize in the thread.
        let window_handle = Arc::new(Mutex::new(MaybeUninit::<WindowHandle>::uninit()));
        let window_handle_ptr = window_handle.clone();

        // Create the thread.
        let thread_handle = Builder::new()
            .name((format!("View Thread #{}", *thread_num)))
            .spawn(|| -> windows_result::Result<()> {
                let instance = HINSTANCE::from(unsafe { GetModuleHandleW(None) }?);

                // Initialize the handle in the thread.
                
                let mut handle = window_handle_ptr.lock().unwrap();
                handle.write(WindowHandle::from(unsafe { CreateWindowExW(
                    WINDOW_EX_STYLE::default(),
                    w!("window"),
                    w!("window"),
                    WINDOW_STYLE::default(),
                    CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
                    None, None, Some(instance), None
                )}?));
                
                drop(handle);
                drop(window_handle_ptr);
                
                // Trigger the barrier.
                
                let barrier = barrier_ptr.read().unwrap();

                barrier.wait();
                
                drop(barrier);
                drop(barrier_ptr);
                
                // Continue processing.

                message_loop();
                
                Ok(())
        }).ok();

        // Increase thread number after creation.
        
        *thread_num += 1;

        // Wait until the barrier triggers.
        
        init_barrier.read().unwrap().wait();

        // I just gave up here, this doesn't work.
        
        let window_result = window_handle.lock().unwrap();
        let new_handle = unsafe { window_result.assume_init() };
        ThreadedView { window_handle, thread_handle, inner }
    }
}

fn message_loop() {
    let mut win_msg = MSG { ..Default::default() };

    while win_msg.message != WM_QUIT {
        flush_messages(&mut win_msg);
    }
}

I have difficulty understanding the problem. are you trying to send a window handle to another thread?

if that's what you mean, you can just send it through a channel, it may seem overkill, but it's the simplest way to send data between threads.

note, you must use a Send wrapper for the handle, since the raw handle is an alias of *mut *c_void, which doesn't implement Send.

let (tx, rx) = channel();
thread_spawn(move || {
    // assume `WindowHandle` is `Send`
    let handle = WindowHandle::from_raw(unsafe { CreateWindowEx(...) });
    tx.send(handle).unwrap();
    // thread continues
    //...
});
let handle = rx.recv().unwrap();

This should more or less achieve what I'm trying to do at the moment. I got caught up in using sync primitives and overlooked channel functionality.