notgull/async-winit

Further Limitations with mutable access

Closed this issue ยท 3 comments

Playing around with the lib, I unfortunately found the following limitation ๐Ÿ˜ข

 // create some wgpu_context bundling stuff for the gfx pipeline
// ...

            let resized = async {
                window
                    .resized()
                    .wait_many()
                    .for_each(|size| {
                        wgpu_context.resize(size);
                    })
                    .await;
                true
            };

            let redraw = async {
                window
                    .redraw_requested()
                    .wait_many()
                    .for_each(|_| {
                        wgpu_context.render().expect("Everything is fine .. ๐Ÿ”ฅ");
                    })
                    .await;
                true
            };
// ...

This example code doesn't compile since both the resize and render actions need mutable access to the wgp_contexts fields. The code is running without bundling everything into the struct but it limirs the ability to abstract all the low level details away. If there is a way to get the code above running I would be very happy but I see no easy way of doing that. If you also don't have an idea how to run that code, we could maybe mention that in the "Cons" part of the README. There is no free lunch after all ๐Ÿ˜ข ๐Ÿฅ– โŒ

You can put wgpu_context into a RefCell that's shared between the two futures. This allows you to get around the borrow checker limitations in this case. In addition, since it's just incrementing and decrementing a number it should be practically free. I suppose that something like this could be mentioned in the Cons section.

Yeah I was thinking about this aswell. But can we really make sure that the two futures are not borrowing the wgpu_context at the same time? For single threaded async runtimes that would probably be the case but if we go multi threaded then I'm not really sure. I should probably just try that out ๐Ÿค” Thanks for the hint!

Edit: Ah, Arc<RwLock<..>> might be used then, right? I need to continue experimenting with this! Anyways: It's a lot of fun even though I used a lot of crying emojis here!

Yeah I was thinking about this aswell. But can we really make sure that the two futures are not borrowing the wgpu_context at the same time?

For RefCell, as long as you don't hold the Ref/RefMut across an .await point, you should be fine. Futures can't be interrupted arbitrarily like they can be in other languages, so you can guarantee

For single threaded async runtimes that would probably be the case but if we go multi threaded then I'm not really sure. I should probably just try that out

Generally, for GUI programs there's a lot less to be gained from multithreading than, say, a network program. Many of the drawing primitives are locked to the EventLoop thread anyways.

Edit: Ah, Arc<RwLock<..>> might be used then, right? I need to continue experimenting with this! Anyways: It's a lot of fun even though I used a lot of crying emojis here!

This would work, but keep in mind that RwLock has slightly more overhead compared to RefCell.