Move the ref counts out

This commit is contained in:
Perelyn
2026-01-09 18:48:42 +01:00
committed by Benjamin Saunders
parent 26a776626e
commit 404db1bc94
2 changed files with 32 additions and 24 deletions
+13 -9
View File
@@ -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<StreamId, Arc<Notify>>,
/// Always set to Some before the connection becomes drained
pub(crate) error: Option<ConnectionError>,
/// Number of live handles that can be used to initiate or handle I/O; excludes the driver
ref_count: usize,
sender: Pin<Box<dyn UdpSender>>,
runtime: Arc<dyn Runtime>,
send_buffer: Vec<u8>,
@@ -1018,7 +1023,6 @@ impl State {
blocked_readers: FxHashMap::default(),
stopped: FxHashMap::default(),
error: None,
ref_count: 0,
sender,
runtime,
send_buffer: Vec::new(),
+19 -15
View File
@@ -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<Waker>,
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<dyn Runtime>,
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();
}
}
}