-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Remove Clone bound on Application::Message #155
Conversation
Although we can remove it in Why do you want to send GPU resources through a However, I'd advise you against using a |
I have a Command that triggers a compute shader, and a message that returns the results. Commands have a bound of static on their futures, which means the futures need to take ownership of their parameters -- so the future needs ownership over the compute resources. That means either box or arc. Arc is problematic though, because my command needs mutable access to its GPU resources. So a mutex would be required if I used arc. So the simplest thing to do is box. When starting the computation, I move the box into the future, and when the computation, it moves the box back via the message. The nice thing about this design is that it also prevents multiple commands from accessing the compute resources at once, at compile time. Because you have to move the box containing the resources into the command, there's no possibility of reusing it to issue another command later which will wait on a mutex. |
How does a Why do you need to share a From what I gathered, I feel like you are trying to own state that shouldn't be yours. In other words, I think you should design your renderer as a separate runtime and then have a communication layer between it and your GUI. One way to achieve this is by making your renderer live in a |
In any case, this PR doesn't really remove the bounds found in the widgets themselves, just the If the |
I gave it some more thought, and I think your changes are worth merging. Although I would tackle your particular use case differently, I think non-cloneable messages can be useful for other scenarios. For instance, you can achieve what you want and still be able to use widgets that need a #[derive(Debug)]
enum Message {
Interaction(Interaction),
RenderingFinished(RenderState),
}
#[derive(Debug, Clone, Copy)]
enum Interaction {
ButtonPressed,
// ... Other interactions you may be interested in!
} Notice that Additionally, I have removed the impl Application for Example {
// ...
fn view(&mut self) -> Element<Message> {
let content: Element<Interaction> =
Button::new(&mut self.increment_button, Text::new("Press me!"))
.on_press(Interaction::ButtonPressed)
.into();
content.map(Message::Interaction)
}
} Thank you for helping me notice this approach! I didn't think it was possible. About the time travelling debugger, I imagine we could implement it with a trait extension. We can ask for Finally, I have removed |
The ultimate goal is to show a fractal render in-progress. I have a fractal that takes 100k iterations to complete. I'd like to make a system where you can request that it run N iterations and then return incremental progress back to the UI. So the design is, there's a Command to run N iterations, and when it's done it sends a message back that it's done. The message handler will spawn 2 commands when this happens. The first command converts the fractal data into an Image handle for rendering, and the second command is to continue computations. Finally, when the fractal is completely done, it either just drops the GPU state right there, or stores it on the GUI object. I want to try the former first. So I don't want to recreate the render state every time because I imagine the steps will be quite short (N might be 1 to 10).
I had never heard of subscriptions before. I'm willing to try this out! |
Thanks for the details! Sounds really cool. If you end up open-sourcing it, I'd love to try it out! I think event subscriptions are the best way to do what you want. They are basically the Event subscriptions were merged recently in #122. Feel free to ask any questions in the Zulip server. |
impl<Message> Clone for Bus<Message> { | ||
fn clone(&self) -> Self { | ||
Self { | ||
publish: Rc::clone(&self.publish), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like you discovered the same thing I did, where #[derive(Clone)] seemsto generate a wonky implementation of clone here, which only kicks in if Message is Clone -- even though all the fields are trivially cloneable unconditionally. And the solution isto just manually implement an unconditional clone.
I'll be honest, your last example there is over my head. I'm not super clear on the difference between interactions, elements, messages, and One concern is, how discoverable do you think it is to have to put element interactions inside an inner message? I can imagine the following sequence:
I suppose it's fine if they do - something like this would probably be a pretty advanced usage. It it's worth thinking about. |
Ah, I see my confusion. I thought How many people will discover that you can do something like |
@ejmahler The Elm Architecture composes quite nicely. The whole idea is that your
The |
Yeah, I agree that the idea of nesting messages should feel pretty natural. I developed something for this a while ago and I reached for nesting messages almost immediately. This looks good then. |
The |
I'm currently writing an application where I want to create a message that should not be cloned.
It's a
Box<RenderState>
whereRenderState
contains a bunch of wgpu handles to GPU resources. I could wrap it inArc<Mutex<>>
and pass it through a message that way, but being able to pass it as a box achieves the same thing more clearly.I can't do this in master, because the Message associated type has a bound on Clone. But it turns out that nothing actually takes advantage of this bound, and IMO it's logical that the system should only ever be moving messages, not cloning them.
This change will put a greater restriction on how Message is used, but it's a restriction that the system appears to be currently handling fine.