Window no longer keeps msg channel allocated

This commit is contained in:
Jonathan Johnson 2023-12-22 08:24:12 -08:00
parent 8ca300682c
commit 1ff4b7b2a6
No known key found for this signature in database
GPG key ID: A66D6A34D6620579
4 changed files with 21 additions and 13 deletions

View file

@ -20,6 +20,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed ### Fixed
- `App` now implements `Application`. - `App` now implements `Application`.
- `Window` is now fully weak. Previously the channel for messages would still
remain allocated while instances of `Window` existed. Now, the messages
channel is freed as soon as the window is closed.
### Added ### Added

View file

@ -228,7 +228,7 @@ where
fn open( fn open(
&self, &self,
window: WindowAttributes, window: WindowAttributes,
sender: mpsc::SyncSender<WindowMessage<AppMessage::Window>>, sender: Arc<mpsc::SyncSender<WindowMessage<AppMessage::Window>>>,
) -> Result<Option<Arc<winit::window::Window>>, OsError> { ) -> Result<Option<Arc<winit::window::Window>>, OsError> {
self.running self.running
.windows .windows
@ -264,7 +264,7 @@ where
fn open( fn open(
&self, &self,
attrs: WindowAttributes, attrs: WindowAttributes,
sender: mpsc::SyncSender<WindowMessage<AppMessage::Window>>, sender: Arc<mpsc::SyncSender<WindowMessage<AppMessage::Window>>>,
) -> Result<Option<Arc<winit::window::Window>>, OsError> { ) -> Result<Option<Arc<winit::window::Window>>, OsError> {
let (open_sender, open_receiver) = mpsc::sync_channel(1); let (open_sender, open_receiver) = mpsc::sync_channel(1);
if self if self
@ -317,7 +317,7 @@ impl<Message> Windows<Message> {
&self, &self,
target: &EventLoopWindowTarget<EventLoopMessage<AppMessage>>, target: &EventLoopWindowTarget<EventLoopMessage<AppMessage>>,
attrs: WindowAttributes, attrs: WindowAttributes,
sender: mpsc::SyncSender<WindowMessage<Message>>, sender: Arc<mpsc::SyncSender<WindowMessage<Message>>>,
) -> Result<Arc<winit::window::Window>, OsError> ) -> Result<Arc<winit::window::Window>, OsError>
where where
AppMessage: crate::Message<Window = Message>, AppMessage: crate::Message<Window = Message>,
@ -407,5 +407,5 @@ impl<Message> Windows<Message> {
struct OpenWindow<User> { struct OpenWindow<User> {
winit: Arc<winit::window::Window>, winit: Arc<winit::window::Window>,
sender: mpsc::SyncSender<WindowMessage<User>>, sender: Arc<mpsc::SyncSender<WindowMessage<User>>>,
} }

View file

@ -20,7 +20,7 @@ where
fn open( fn open(
&self, &self,
window: WindowAttributes, window: WindowAttributes,
sender: mpsc::SyncSender<WindowMessage<AppMessage::Window>>, sender: Arc<mpsc::SyncSender<WindowMessage<AppMessage::Window>>>,
) -> Result<Option<Arc<winit::window::Window>>, OsError>; ) -> Result<Option<Arc<winit::window::Window>>, OsError>;
} }
@ -30,7 +30,7 @@ where
{ {
OpenWindow { OpenWindow {
attrs: WindowAttributes, attrs: WindowAttributes,
sender: mpsc::SyncSender<WindowMessage<AppMessage::Window>>, sender: Arc<mpsc::SyncSender<WindowMessage<AppMessage::Window>>>,
open_sender: mpsc::SyncSender<Result<Arc<winit::window::Window>, OsError>>, open_sender: mpsc::SyncSender<Result<Arc<winit::window::Window>, OsError>>,
}, },
CloseWindow(WindowId), CloseWindow(WindowId),

View file

@ -2,7 +2,7 @@ use std::collections::HashSet;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::panic::AssertUnwindSafe; use std::panic::AssertUnwindSafe;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::{mpsc, Arc}; use std::sync::{mpsc, Arc, Weak};
use std::thread; use std::thread;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
@ -24,7 +24,7 @@ use crate::{
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Window<Message> { pub struct Window<Message> {
id: WindowId, id: WindowId,
sender: mpsc::SyncSender<WindowMessage<Message>>, sender: Weak<mpsc::SyncSender<WindowMessage<Message>>>,
} }
impl<Message> Window<Message> { impl<Message> Window<Message> {
@ -44,7 +44,10 @@ impl<Message> Window<Message> {
/// ///
/// If the window is already closed, this function returns `Err(message)`. /// If the window is already closed, this function returns `Err(message)`.
pub fn send(&self, message: Message) -> Result<(), Message> { pub fn send(&self, message: Message) -> Result<(), Message> {
match self.sender.send(WindowMessage::User(message)) { let Some(sender) = self.sender.upgrade() else {
return Err(message);
};
match sender.send(WindowMessage::User(message)) {
Ok(()) => Ok(()), Ok(()) => Ok(()),
Err(mpsc::SendError(WindowMessage::User(message))) => Err(message), Err(mpsc::SendError(WindowMessage::User(message))) => Err(message),
_ => unreachable!("same input as output"), _ => unreachable!("same input as output"),
@ -205,6 +208,7 @@ where
// a fixed-size channel and be cautious to not block the main event loop // a fixed-size channel and be cautious to not block the main event loop
// by always using try_send. // by always using try_send.
let (sender, receiver) = mpsc::sync_channel(65536); let (sender, receiver) = mpsc::sync_channel(65536);
let sender = Arc::new(sender);
let Some(winit) = self let Some(winit) = self
.owner .owner
.as_application() .as_application()
@ -214,7 +218,7 @@ where
}; };
let window = Window { let window = Window {
id: winit.id(), id: winit.id(),
sender: sender.clone(), sender: Arc::downgrade(&sender),
}; };
let running_window = RunningWindow { let running_window = RunningWindow {
messages: (sender, receiver), messages: (sender, receiver),
@ -241,6 +245,7 @@ where
} }
} }
type SyncArcChannel<T> = (Arc<mpsc::SyncSender<T>>, mpsc::Receiver<T>);
type SyncChannel<T> = (mpsc::SyncSender<T>, mpsc::Receiver<T>); type SyncChannel<T> = (mpsc::SyncSender<T>, mpsc::Receiver<T>);
/// A window that is running in its own thread. /// A window that is running in its own thread.
@ -250,7 +255,7 @@ where
{ {
window: Arc<winit::window::Window>, window: Arc<winit::window::Window>,
next_redraw_target: Option<RedrawTarget>, next_redraw_target: Option<RedrawTarget>,
messages: SyncChannel<WindowMessage<AppMessage::Window>>, messages: SyncArcChannel<WindowMessage<AppMessage::Window>>,
responses: SyncChannel<AppMessage::Response>, responses: SyncChannel<AppMessage::Response>,
app: App<AppMessage>, app: App<AppMessage>,
inner_size: PhysicalSize<u32>, inner_size: PhysicalSize<u32>,
@ -281,7 +286,7 @@ where
pub fn handle(&self) -> Window<AppMessage::Window> { pub fn handle(&self) -> Window<AppMessage::Window> {
Window { Window {
id: self.window.id(), id: self.window.id(),
sender: self.messages.0.clone(), sender: Arc::downgrade(&self.messages.0),
} }
} }
@ -701,7 +706,7 @@ where
fn open( fn open(
&self, &self,
attrs: WindowAttributes, attrs: WindowAttributes,
sender: mpsc::SyncSender<WindowMessage<AppMessage::Window>>, sender: Arc<mpsc::SyncSender<WindowMessage<AppMessage::Window>>>,
) -> Result<Option<Arc<winit::window::Window>>, OsError> { ) -> Result<Option<Arc<winit::window::Window>>, OsError> {
let (open_sender, open_receiver) = mpsc::sync_channel(1); let (open_sender, open_receiver) = mpsc::sync_channel(1);
if self if self