From 1ff4b7b2a6f93e2c719787c76e585e6c2ecf290c Mon Sep 17 00:00:00 2001 From: Jonathan Johnson Date: Fri, 22 Dec 2023 08:24:12 -0800 Subject: [PATCH] Window no longer keeps msg channel allocated --- CHANGELOG.md | 3 +++ src/lib.rs | 8 ++++---- src/private.rs | 4 ++-- src/window.rs | 19 ++++++++++++------- 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 161c3da..794b04d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - `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 diff --git a/src/lib.rs b/src/lib.rs index 746ed6b..165c9ce 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -228,7 +228,7 @@ where fn open( &self, window: WindowAttributes, - sender: mpsc::SyncSender>, + sender: Arc>>, ) -> Result>, OsError> { self.running .windows @@ -264,7 +264,7 @@ where fn open( &self, attrs: WindowAttributes, - sender: mpsc::SyncSender>, + sender: Arc>>, ) -> Result>, OsError> { let (open_sender, open_receiver) = mpsc::sync_channel(1); if self @@ -317,7 +317,7 @@ impl Windows { &self, target: &EventLoopWindowTarget>, attrs: WindowAttributes, - sender: mpsc::SyncSender>, + sender: Arc>>, ) -> Result, OsError> where AppMessage: crate::Message, @@ -407,5 +407,5 @@ impl Windows { struct OpenWindow { winit: Arc, - sender: mpsc::SyncSender>, + sender: Arc>>, } diff --git a/src/private.rs b/src/private.rs index 9742845..c636438 100644 --- a/src/private.rs +++ b/src/private.rs @@ -20,7 +20,7 @@ where fn open( &self, window: WindowAttributes, - sender: mpsc::SyncSender>, + sender: Arc>>, ) -> Result>, OsError>; } @@ -30,7 +30,7 @@ where { OpenWindow { attrs: WindowAttributes, - sender: mpsc::SyncSender>, + sender: Arc>>, open_sender: mpsc::SyncSender, OsError>>, }, CloseWindow(WindowId), diff --git a/src/window.rs b/src/window.rs index 65f218f..ffd8f70 100644 --- a/src/window.rs +++ b/src/window.rs @@ -2,7 +2,7 @@ use std::collections::HashSet; use std::ops::{Deref, DerefMut}; use std::panic::AssertUnwindSafe; use std::path::PathBuf; -use std::sync::{mpsc, Arc}; +use std::sync::{mpsc, Arc, Weak}; use std::thread; use std::time::{Duration, Instant}; @@ -24,7 +24,7 @@ use crate::{ #[derive(Debug, Clone)] pub struct Window { id: WindowId, - sender: mpsc::SyncSender>, + sender: Weak>>, } impl Window { @@ -44,7 +44,10 @@ impl Window { /// /// If the window is already closed, this function returns `Err(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(()), Err(mpsc::SendError(WindowMessage::User(message))) => Err(message), _ => unreachable!("same input as output"), @@ -205,6 +208,7 @@ where // a fixed-size channel and be cautious to not block the main event loop // by always using try_send. let (sender, receiver) = mpsc::sync_channel(65536); + let sender = Arc::new(sender); let Some(winit) = self .owner .as_application() @@ -214,7 +218,7 @@ where }; let window = Window { id: winit.id(), - sender: sender.clone(), + sender: Arc::downgrade(&sender), }; let running_window = RunningWindow { messages: (sender, receiver), @@ -241,6 +245,7 @@ where } } +type SyncArcChannel = (Arc>, mpsc::Receiver); type SyncChannel = (mpsc::SyncSender, mpsc::Receiver); /// A window that is running in its own thread. @@ -250,7 +255,7 @@ where { window: Arc, next_redraw_target: Option, - messages: SyncChannel>, + messages: SyncArcChannel>, responses: SyncChannel, app: App, inner_size: PhysicalSize, @@ -281,7 +286,7 @@ where pub fn handle(&self) -> Window { Window { id: self.window.id(), - sender: self.messages.0.clone(), + sender: Arc::downgrade(&self.messages.0), } } @@ -701,7 +706,7 @@ where fn open( &self, attrs: WindowAttributes, - sender: mpsc::SyncSender>, + sender: Arc>>, ) -> Result>, OsError> { let (open_sender, open_receiver) = mpsc::sync_channel(1); if self