From 85b9b7222d4a949cd673bf4ecf9c7278b5613c88 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Fri, 13 Mar 2026 12:56:17 +0100 Subject: [PATCH] object_drop_queue: add new utility --- src/compositor.rs | 2 + src/state.rs | 4 ++ src/utils.rs | 1 + src/utils/object_drop_queue.rs | 84 ++++++++++++++++++++++++++++++++++ 4 files changed, 91 insertions(+) create mode 100644 src/utils/object_drop_queue.rs diff --git a/src/compositor.rs b/src/compositor.rs index 27a96be2..fa6777b5 100644 --- a/src/compositor.rs +++ b/src/compositor.rs @@ -72,6 +72,7 @@ use { fdcloser::FdCloser, nice::{did_elevate_scheduler, elevate_scheduler}, numcell::NumCell, + object_drop_queue::ObjectDropQueue, oserror::OsError, queue::AsyncQueue, rc_eq::RcEq, @@ -390,6 +391,7 @@ fn start_compositor2( supports_presentation_feedback: Default::default(), eventfd_cache, lazy_event_sources: Default::default(), + bo_drop_queue: Rc::new(ObjectDropQueue::new(&ring)), }); state.tracker.register(ClientId::from_raw(0)); create_dummy_output(&state); diff --git a/src/state.rs b/src/state.rs index 652f50a0..5788a95f 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,6 +1,7 @@ use { crate::{ acceptor::Acceptor, + allocator::BufferObject, async_engine::{AsyncEngine, SpawnedFuture}, backend::{ Backend, BackendConnectorState, BackendConnectorStateSerials, BackendDrmDevice, @@ -115,6 +116,7 @@ use { hash_map_ext::HashMapExt, linkedlist::LinkedList, numcell::NumCell, + object_drop_queue::ObjectDropQueue, queue::AsyncQueue, refcounted::RefCounted, run_toplevel::RunToplevel, @@ -292,6 +294,7 @@ pub struct State { pub supports_presentation_feedback: Cell, pub eventfd_cache: Rc, pub lazy_event_sources: Rc, + pub bo_drop_queue: Rc>>, } // impl Drop for State { @@ -1154,6 +1157,7 @@ impl State { self.wait_for_syncobj.clear(); self.xdg_surface_configure_events.clear(); self.lazy_event_sources.clear(); + self.bo_drop_queue.kill(); } pub fn remove_toplevel_id(&self, id: ToplevelIdentifier) { diff --git a/src/utils.rs b/src/utils.rs index 7c956c82..31cadb59 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -31,6 +31,7 @@ pub mod nice; pub mod nonblock; pub mod num_cpus; pub mod numcell; +pub mod object_drop_queue; pub mod on_change; pub mod on_drop_event; pub mod once; diff --git a/src/utils/object_drop_queue.rs b/src/utils/object_drop_queue.rs new file mode 100644 index 00000000..2ce1ea45 --- /dev/null +++ b/src/utils/object_drop_queue.rs @@ -0,0 +1,84 @@ +use { + crate::{ + io_uring::{IoUring, PendingPoll, PollCallback}, + utils::{errorfmt::ErrorFmt, oserror::OsError, stack::Stack}, + }, + std::{ + cell::{Cell, RefCell}, + rc::Rc, + }, + uapi::{OwnedFd, c::c_short}, +}; + +pub struct ObjectDropQueue { + ring: Rc, + killed: Cell, + pending: RefCell>>, + stack: Stack>>, +} + +struct Pollable { + queue: Rc>, + idx: usize, +} + +impl ObjectDropQueue { + pub fn new(ring: &Rc) -> Self { + Self { + ring: ring.clone(), + killed: Default::default(), + pending: Default::default(), + stack: Default::default(), + } + } + + #[expect(dead_code)] + pub fn push(self: &Rc, fd: &Rc, t: T) + where + T: 'static, + { + if self.killed.get() { + return; + } + let pending = &mut *self.pending.borrow_mut(); + let pollable = match self.stack.pop() { + Some(p) => p, + None => { + let pollable = Rc::new(Pollable { + queue: self.clone(), + idx: pending.len(), + }); + pending.push(None); + pollable + } + }; + let idx = pollable.idx; + match self.ring.readable_external(fd, pollable) { + Ok(p) => { + pending[idx] = Some((t, p)); + } + Err(e) => { + log::error!("Could not register object: {}", ErrorFmt(e)); + } + } + } + + pub fn kill(&self) { + self.killed.set(true); + self.pending.take(); + self.stack.take(); + } +} + +impl PollCallback for Pollable { + fn completed(self: Rc, res: Result) { + if let Err(e) = res { + log::error!("Could not wait for fd to become readable: {}", ErrorFmt(e)); + } + let q = &self.queue; + if !q.killed.get() { + q.pending.borrow_mut()[self.idx] = None; + q.stack.push(self.clone()); + } + } +}