Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A safer way to get interact with other threads would be very nice #246

Open
mullr opened this issue Feb 6, 2022 · 1 comment
Open

A safer way to get interact with other threads would be very nice #246

mullr opened this issue Feb 6, 2022 · 1 comment

Comments

@mullr
Copy link

mullr commented Feb 6, 2022

My program has a worker thread that the UI needs to interact with. I'm presently using queued_callback to do this, which in itself is fine. But in order to actually affect any UI changes in its callback, you need to do some acrobatics that feel very unsettling to a Rust developer.

This is the pattern I arrived at, and the only thing I could get to work:

fn do_stuff_in_a_qobj(&mut self) {
   let self_ptr = QPointer::from(self as &Self);
   self.worker_thread_sender
        .send(WorkerThreadRequest::DoWork(Box::new(queued_callback(
            move |result: ResultOfWork| {
                self_ptr.as_pinned().borrow_mut().map(|self_| {
                    let mut self_mut = self_.borrow_mut();
                    self_mut.deal_with_result_of_work(result);
                });
            },
        ))))
        .unwrap();
}

This is very hairy, and I'm not even certain it's correct. (If self_ptr wasn't pinned before, does that mean it could be moved before the callback triggers?) If this is indeed the intended pattern, it would be great to facilitate it, perhaps via a version that does the capturing for you, something like this:

trait CallbackHelper {
    fn capturing_queued_callback<T: Send>(
        &mut self,
        func: fn(&mut Self, T),
    ) -> Box<dyn Fn(T) + Send + Sync>;
}

impl<Q: QObject> CallbackHelper for Q {
    fn capturing_queued_callback<T: Send>(
        &mut self,
        func: fn(&mut Self, T),
    ) -> Box<dyn Fn(T) + Send + Sync> {
        // Rust does not believe I should be able to implement this
    }
}
@mullr mullr changed the title A safer-feeling way to get interact with other threads would be very nice A safer way to get interact with other threads would be very nice Feb 7, 2022
@mullr
Copy link
Author

mullr commented Feb 8, 2022

I understand now that 'self' is in fact pinned, as long as it has previously been handed over to qmetaobject-rs. I think a more idiomatic way to deal with this in client code would be to require do_stuff_in_a_qobj to take a Pin<Box<Self>> or similar as its self type (I /think/ you can do that now).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant