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
- `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

View file

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

View file

@ -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<Message> {
id: WindowId,
sender: mpsc::SyncSender<WindowMessage<Message>>,
sender: Weak<mpsc::SyncSender<WindowMessage<Message>>>,
}
impl<Message> Window<Message> {
@ -44,7 +44,10 @@ impl<Message> Window<Message> {
///
/// 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<T> = (Arc<mpsc::SyncSender<T>>, mpsc::Receiver<T>);
type SyncChannel<T> = (mpsc::SyncSender<T>, mpsc::Receiver<T>);
/// A window that is running in its own thread.
@ -250,7 +255,7 @@ where
{
window: Arc<winit::window::Window>,
next_redraw_target: Option<RedrawTarget>,
messages: SyncChannel<WindowMessage<AppMessage::Window>>,
messages: SyncArcChannel<WindowMessage<AppMessage::Window>>,
responses: SyncChannel<AppMessage::Response>,
app: App<AppMessage>,
inner_size: PhysicalSize<u32>,
@ -281,7 +286,7 @@ where
pub fn handle(&self) -> Window<AppMessage::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<WindowMessage<AppMessage::Window>>,
sender: Arc<mpsc::SyncSender<WindowMessage<AppMessage::Window>>>,
) -> Result<Option<Arc<winit::window::Window>>, OsError> {
let (open_sender, open_receiver) = mpsc::sync_channel(1);
if self