From 404db1bc94ef7e327bb4e5fa118a6db18202e2f5 Mon Sep 17 00:00:00 2001 From: Perelyn Date: Fri, 9 Jan 2026 18:48:42 +0100 Subject: [PATCH] Move the ref counts out --- quinn/src/connection.rs | 22 +++++++++++++--------- quinn/src/endpoint.rs | 34 +++++++++++++++++++--------------- 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/quinn/src/connection.rs b/quinn/src/connection.rs index 13b3671d2..14ca68957 100644 --- a/quinn/src/connection.rs +++ b/quinn/src/connection.rs @@ -5,7 +5,10 @@ use std::{ io, net::{IpAddr, SocketAddr}, pin::Pin, - sync::Arc, + sync::{ + Arc, + atomic::{AtomicUsize, Ordering}, + }, task::{Context, Poll, Waker, ready}, }; @@ -917,17 +920,19 @@ impl ConnectionRef { impl Clone for ConnectionRef { fn clone(&self) -> Self { - self.state.lock("clone").ref_count += 1; + self.shared.ref_count.fetch_add(1, Ordering::Relaxed); Self(self.0.clone()) } } impl Drop for ConnectionRef { fn drop(&mut self) { - let conn = &mut *self.state.lock("drop"); - if let Some(x) = conn.ref_count.checked_sub(1) { - conn.ref_count = x; - if x == 0 && !conn.inner.is_closed() { + let ref_count = self.shared.ref_count.fetch_sub(1, Ordering::Relaxed); + + if ref_count == 0 { + let conn = &mut *self.state.lock("drop"); + + if !conn.inner.is_closed() { // If the driver is alive, it's just it and us, so we'd better shut it down. If it's // not, we can't do any harm. If there were any streams being opened, then either // the connection will be closed for an unrelated reason or a fresh reference will @@ -962,6 +967,8 @@ pub(crate) struct Shared { datagram_received: Notify, datagrams_unblocked: Notify, closed: Notify, + /// Number of live handles that can used to initiate or handle I/O; excludes the driver + ref_count: AtomicUsize, } pub(crate) struct State { @@ -981,8 +988,6 @@ pub(crate) struct State { pub(crate) stopped: FxHashMap>, /// Always set to Some before the connection becomes drained pub(crate) error: Option, - /// Number of live handles that can be used to initiate or handle I/O; excludes the driver - ref_count: usize, sender: Pin>, runtime: Arc, send_buffer: Vec, @@ -1018,7 +1023,6 @@ impl State { blocked_readers: FxHashMap::default(), stopped: FxHashMap::default(), error: None, - ref_count: 0, sender, runtime, send_buffer: Vec::new(), diff --git a/quinn/src/endpoint.rs b/quinn/src/endpoint.rs index 56915e444..b35f8c0d1 100644 --- a/quinn/src/endpoint.rs +++ b/quinn/src/endpoint.rs @@ -7,7 +7,10 @@ use std::{ net::{SocketAddr, SocketAddrV6}, pin::Pin, str, - sync::{Arc, Mutex}, + sync::{ + Arc, Mutex, + atomic::{AtomicUsize, Ordering}, + }, task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, }; @@ -390,7 +393,9 @@ impl Future for EndpointDriver { self.0.shared.incoming.notify_waiters(); } - if endpoint.ref_count == 0 && endpoint.recv_state.connections.is_empty() { + if self.0.shared.ref_count.load(Ordering::Relaxed) == 0 + && endpoint.recv_state.connections.is_empty() + { Poll::Ready(Ok(())) } else { drop(endpoint); @@ -488,8 +493,6 @@ pub(crate) struct State { driver: Option, ipv6: bool, events: mpsc::UnboundedReceiver<(ConnectionHandle, EndpointEvent)>, - /// Number of live handles that can be used to initiate or handle I/O; excludes the driver - ref_count: usize, driver_lost: bool, runtime: Arc, stats: EndpointStats, @@ -500,6 +503,8 @@ pub(crate) struct State { pub(crate) struct Shared { incoming: Notify, idle: Notify, + /// Number of live handles that can be used to initiate or handle I/O; excludes the driver + ref_count: AtomicUsize, } impl State { @@ -736,6 +741,7 @@ impl EndpointRef { shared: Shared { incoming: Notify::new(), idle: Notify::new(), + ref_count: AtomicUsize::new(0), }, state: Mutex::new(State { socket, @@ -745,7 +751,6 @@ impl EndpointRef { ipv6, events, driver: None, - ref_count: 0, driver_lost: false, recv_state, runtime, @@ -758,22 +763,21 @@ impl EndpointRef { impl Clone for EndpointRef { fn clone(&self) -> Self { - self.0.state.lock().unwrap().ref_count += 1; + self.0.shared.ref_count.fetch_add(1, Ordering::Relaxed); Self(self.0.clone()) } } impl Drop for EndpointRef { fn drop(&mut self) { - let endpoint = &mut *self.0.state.lock().unwrap(); - if let Some(x) = endpoint.ref_count.checked_sub(1) { - endpoint.ref_count = x; - if x == 0 { - // If the driver is about to be on its own, ensure it can shut down if the last - // connection is gone. - if let Some(task) = endpoint.driver.take() { - task.wake(); - } + let ref_count = self.shared.ref_count.fetch_sub(1, Ordering::Relaxed); + + if ref_count == 0 { + let endpoint = &mut *self.0.state.lock().unwrap(); + // If the driver is about to be on its own, ensure it can shut down if the last + // connection is gone. + if let Some(task) = endpoint.driver.take() { + task.wake(); } } }