Coverage Report

Created: 2025-05-07 06:59

/rust/registry/src/index.crates.io-6f17d22bba15001f/mio-1.0.3/src/io_source.rs
Line
Count
Source (jump to first uncovered line)
1
use std::ops::{Deref, DerefMut};
2
#[cfg(any(unix, target_os = "wasi"))]
3
use std::os::fd::AsRawFd;
4
// TODO: once <https://github.com/rust-lang/rust/issues/126198> is fixed this
5
// can use `std::os::fd` and be merged with the above.
6
#[cfg(target_os = "hermit")]
7
use std::os::hermit::io::AsRawFd;
8
#[cfg(windows)]
9
use std::os::windows::io::AsRawSocket;
10
#[cfg(debug_assertions)]
11
use std::sync::atomic::{AtomicUsize, Ordering};
12
use std::{fmt, io};
13
14
use crate::sys::IoSourceState;
15
use crate::{event, Interest, Registry, Token};
16
17
/// Adapter for a [`RawFd`] or [`RawSocket`] providing an [`event::Source`]
18
/// implementation.
19
///
20
/// `IoSource` enables registering any FD or socket wrapper with [`Poll`].
21
///
22
/// While only implementations for TCP, UDP, and UDS (Unix only) are provided,
23
/// Mio supports registering any FD or socket that can be registered with the
24
/// underlying OS selector. `IoSource` provides the necessary bridge.
25
///
26
/// [`RawFd`]: std::os::fd::RawFd
27
/// [`RawSocket`]: std::os::windows::io::RawSocket
28
///
29
/// # Notes
30
///
31
/// To handle the registrations and events properly **all** I/O operations (such
32
/// as `read`, `write`, etc.) must go through the [`do_io`] method to ensure the
33
/// internal state is updated accordingly.
34
///
35
/// [`Poll`]: crate::Poll
36
/// [`do_io`]: IoSource::do_io
37
pub struct IoSource<T> {
38
    state: IoSourceState,
39
    inner: T,
40
    #[cfg(debug_assertions)]
41
    selector_id: SelectorId,
42
}
43
44
impl<T> IoSource<T> {
45
    /// Create a new `IoSource`.
46
0
    pub fn new(io: T) -> IoSource<T> {
47
0
        IoSource {
48
0
            state: IoSourceState::new(),
49
0
            inner: io,
50
0
            #[cfg(debug_assertions)]
51
0
            selector_id: SelectorId::new(),
52
0
        }
53
0
    }
Unexecuted instantiation: <mio::io_source::IoSource<std::fs::File>>::new
Unexecuted instantiation: <mio::io_source::IoSource<std::net::tcp::TcpListener>>::new
Unexecuted instantiation: <mio::io_source::IoSource<std::net::tcp::TcpStream>>::new
Unexecuted instantiation: <mio::io_source::IoSource<std::net::udp::UdpSocket>>::new
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::stream::UnixStream>>::new
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::datagram::UnixDatagram>>::new
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::listener::UnixListener>>::new
54
55
    /// Execute an I/O operations ensuring that the socket receives more events
56
    /// if it hits a [`WouldBlock`] error.
57
    ///
58
    /// # Notes
59
    ///
60
    /// This method is required to be called for **all** I/O operations to
61
    /// ensure the user will receive events once the socket is ready again after
62
    /// returning a [`WouldBlock`] error.
63
    ///
64
    /// [`WouldBlock`]: io::ErrorKind::WouldBlock
65
0
    pub fn do_io<F, R>(&self, f: F) -> io::Result<R>
66
0
    where
67
0
        F: FnOnce(&T) -> io::Result<R>,
68
0
    {
69
0
        self.state.do_io(f, &self.inner)
70
0
    }
Unexecuted instantiation: <mio::io_source::IoSource<std::net::udp::UdpSocket>>::do_io::<<mio::net::udp::UdpSocket>::try_io<<tokio::net::udp::UdpSocket>::peek_sender_inner::{closure#0}, core::net::socket_addr::SocketAddr>::{closure#0}, core::net::socket_addr::SocketAddr>
Unexecuted instantiation: <mio::io_source::IoSource<std::fs::File>>::do_io::<<mio::sys::unix::pipe::Sender as std::io::Write>::write_vectored::{closure#0}, usize>
Unexecuted instantiation: <mio::io_source::IoSource<std::fs::File>>::do_io::<<mio::sys::unix::pipe::Sender as std::io::Write>::flush::{closure#0}, ()>
Unexecuted instantiation: <mio::io_source::IoSource<std::fs::File>>::do_io::<<mio::sys::unix::pipe::Sender as std::io::Write>::write::{closure#0}, usize>
Unexecuted instantiation: <mio::io_source::IoSource<std::fs::File>>::do_io::<<&mio::sys::unix::pipe::Sender as std::io::Write>::write_vectored::{closure#0}, usize>
Unexecuted instantiation: <mio::io_source::IoSource<std::fs::File>>::do_io::<<&mio::sys::unix::pipe::Sender as std::io::Write>::flush::{closure#0}, ()>
Unexecuted instantiation: <mio::io_source::IoSource<std::fs::File>>::do_io::<<&mio::sys::unix::pipe::Sender as std::io::Write>::write::{closure#0}, usize>
Unexecuted instantiation: <mio::io_source::IoSource<std::fs::File>>::do_io::<<mio::sys::unix::pipe::Receiver as std::io::Read>::read_vectored::{closure#0}, usize>
Unexecuted instantiation: <mio::io_source::IoSource<std::fs::File>>::do_io::<<mio::sys::unix::pipe::Receiver as std::io::Read>::read::{closure#0}, usize>
Unexecuted instantiation: <mio::io_source::IoSource<std::fs::File>>::do_io::<<&mio::sys::unix::pipe::Receiver as std::io::Read>::read_vectored::{closure#0}, usize>
Unexecuted instantiation: <mio::io_source::IoSource<std::fs::File>>::do_io::<<&mio::sys::unix::pipe::Receiver as std::io::Read>::read::{closure#0}, usize>
Unexecuted instantiation: <mio::io_source::IoSource<std::net::tcp::TcpListener>>::do_io::<<mio::net::tcp::listener::TcpListener>::accept::{closure#0}, (mio::net::tcp::stream::TcpStream, core::net::socket_addr::SocketAddr)>
Unexecuted instantiation: <mio::io_source::IoSource<std::net::tcp::TcpStream>>::do_io::<<&mio::net::tcp::stream::TcpStream as std::io::Read>::read_vectored::{closure#0}, usize>
Unexecuted instantiation: <mio::io_source::IoSource<std::net::tcp::TcpStream>>::do_io::<<&mio::net::tcp::stream::TcpStream as std::io::Read>::read::{closure#0}, usize>
Unexecuted instantiation: <mio::io_source::IoSource<std::net::tcp::TcpStream>>::do_io::<<mio::net::tcp::stream::TcpStream as std::io::Write>::write_vectored::{closure#0}, usize>
Unexecuted instantiation: <mio::io_source::IoSource<std::net::tcp::TcpStream>>::do_io::<<mio::net::tcp::stream::TcpStream as std::io::Write>::flush::{closure#0}, ()>
Unexecuted instantiation: <mio::io_source::IoSource<std::net::tcp::TcpStream>>::do_io::<<mio::net::tcp::stream::TcpStream as std::io::Write>::write::{closure#0}, usize>
Unexecuted instantiation: <mio::io_source::IoSource<std::net::tcp::TcpStream>>::do_io::<<&mio::net::tcp::stream::TcpStream as std::io::Write>::write_vectored::{closure#0}, usize>
Unexecuted instantiation: <mio::io_source::IoSource<std::net::tcp::TcpStream>>::do_io::<<&mio::net::tcp::stream::TcpStream as std::io::Write>::flush::{closure#0}, ()>
Unexecuted instantiation: <mio::io_source::IoSource<std::net::tcp::TcpStream>>::do_io::<<&mio::net::tcp::stream::TcpStream as std::io::Write>::write::{closure#0}, usize>
Unexecuted instantiation: <mio::io_source::IoSource<std::net::tcp::TcpStream>>::do_io::<<mio::net::tcp::stream::TcpStream as std::io::Read>::read_vectored::{closure#0}, usize>
Unexecuted instantiation: <mio::io_source::IoSource<std::net::tcp::TcpStream>>::do_io::<<mio::net::tcp::stream::TcpStream as std::io::Read>::read::{closure#0}, usize>
Unexecuted instantiation: <mio::io_source::IoSource<std::net::udp::UdpSocket>>::do_io::<<mio::net::udp::UdpSocket>::peek::{closure#0}, usize>
Unexecuted instantiation: <mio::io_source::IoSource<std::net::udp::UdpSocket>>::do_io::<<mio::net::udp::UdpSocket>::recv::{closure#0}, usize>
Unexecuted instantiation: <mio::io_source::IoSource<std::net::udp::UdpSocket>>::do_io::<<mio::net::udp::UdpSocket>::send::{closure#0}, usize>
Unexecuted instantiation: <mio::io_source::IoSource<std::net::udp::UdpSocket>>::do_io::<<mio::net::udp::UdpSocket>::send_to::{closure#0}, usize>
Unexecuted instantiation: <mio::io_source::IoSource<std::net::udp::UdpSocket>>::do_io::<<mio::net::udp::UdpSocket>::peek_from::{closure#0}, (usize, core::net::socket_addr::SocketAddr)>
Unexecuted instantiation: <mio::io_source::IoSource<std::net::udp::UdpSocket>>::do_io::<<mio::net::udp::UdpSocket>::recv_from::{closure#0}, (usize, core::net::socket_addr::SocketAddr)>
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::stream::UnixStream>>::do_io::<<&mio::net::uds::stream::UnixStream as std::io::Read>::read_vectored::{closure#0}, usize>
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::stream::UnixStream>>::do_io::<<&mio::net::uds::stream::UnixStream as std::io::Read>::read::{closure#0}, usize>
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::stream::UnixStream>>::do_io::<<mio::net::uds::stream::UnixStream as std::io::Write>::write_vectored::{closure#0}, usize>
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::stream::UnixStream>>::do_io::<<mio::net::uds::stream::UnixStream as std::io::Write>::flush::{closure#0}, ()>
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::stream::UnixStream>>::do_io::<<mio::net::uds::stream::UnixStream as std::io::Write>::write::{closure#0}, usize>
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::stream::UnixStream>>::do_io::<<&mio::net::uds::stream::UnixStream as std::io::Write>::write_vectored::{closure#0}, usize>
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::stream::UnixStream>>::do_io::<<&mio::net::uds::stream::UnixStream as std::io::Write>::flush::{closure#0}, ()>
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::stream::UnixStream>>::do_io::<<&mio::net::uds::stream::UnixStream as std::io::Write>::write::{closure#0}, usize>
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::stream::UnixStream>>::do_io::<<mio::net::uds::stream::UnixStream as std::io::Read>::read_vectored::{closure#0}, usize>
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::stream::UnixStream>>::do_io::<<mio::net::uds::stream::UnixStream as std::io::Read>::read::{closure#0}, usize>
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::datagram::UnixDatagram>>::do_io::<<mio::net::uds::datagram::UnixDatagram>::recv::{closure#0}, usize>
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::datagram::UnixDatagram>>::do_io::<<mio::net::uds::datagram::UnixDatagram>::send::{closure#0}, usize>
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::datagram::UnixDatagram>>::do_io::<<mio::net::uds::datagram::UnixDatagram>::recv_from::{closure#0}, (usize, std::os::unix::net::addr::SocketAddr)>
71
72
    /// Returns the I/O source, dropping the state.
73
    ///
74
    /// # Notes
75
    ///
76
    /// To ensure no more events are to be received for this I/O source first
77
    /// [`deregister`] it.
78
    ///
79
    /// [`deregister`]: Registry::deregister
80
0
    pub fn into_inner(self) -> T {
81
0
        self.inner
82
0
    }
Unexecuted instantiation: <mio::io_source::IoSource<std::fs::File>>::into_inner
Unexecuted instantiation: <mio::io_source::IoSource<std::net::tcp::TcpListener>>::into_inner
Unexecuted instantiation: <mio::io_source::IoSource<std::net::tcp::TcpStream>>::into_inner
Unexecuted instantiation: <mio::io_source::IoSource<std::net::udp::UdpSocket>>::into_inner
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::stream::UnixStream>>::into_inner
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::datagram::UnixDatagram>>::into_inner
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::listener::UnixListener>>::into_inner
83
}
84
85
/// Be careful when using this method. All I/O operations that may block must go
86
/// through the [`do_io`] method.
87
///
88
/// [`do_io`]: IoSource::do_io
89
impl<T> Deref for IoSource<T> {
90
    type Target = T;
91
92
0
    fn deref(&self) -> &Self::Target {
93
0
        &self.inner
94
0
    }
Unexecuted instantiation: <mio::io_source::IoSource<std::fs::File> as core::ops::deref::Deref>::deref
Unexecuted instantiation: <mio::io_source::IoSource<std::net::tcp::TcpListener> as core::ops::deref::Deref>::deref
Unexecuted instantiation: <mio::io_source::IoSource<std::net::tcp::TcpStream> as core::ops::deref::Deref>::deref
Unexecuted instantiation: <mio::io_source::IoSource<std::net::udp::UdpSocket> as core::ops::deref::Deref>::deref
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::stream::UnixStream> as core::ops::deref::Deref>::deref
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::datagram::UnixDatagram> as core::ops::deref::Deref>::deref
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::listener::UnixListener> as core::ops::deref::Deref>::deref
95
}
96
97
/// Be careful when using this method. All I/O operations that may block must go
98
/// through the [`do_io`] method.
99
///
100
/// [`do_io`]: IoSource::do_io
101
impl<T> DerefMut for IoSource<T> {
102
0
    fn deref_mut(&mut self) -> &mut Self::Target {
103
0
        &mut self.inner
104
0
    }
105
}
106
107
#[cfg(any(unix, target_os = "hermit"))]
108
impl<T> event::Source for IoSource<T>
109
where
110
    T: AsRawFd,
111
{
112
0
    fn register(
113
0
        &mut self,
114
0
        registry: &Registry,
115
0
        token: Token,
116
0
        interests: Interest,
117
0
    ) -> io::Result<()> {
118
0
        #[cfg(debug_assertions)]
119
0
        self.selector_id.associate(registry)?;
120
0
        self.state
121
0
            .register(registry, token, interests, self.inner.as_raw_fd())
122
0
    }
Unexecuted instantiation: <mio::io_source::IoSource<std::fs::File> as mio::event::source::Source>::register
Unexecuted instantiation: <mio::io_source::IoSource<std::net::tcp::TcpListener> as mio::event::source::Source>::register
Unexecuted instantiation: <mio::io_source::IoSource<std::net::tcp::TcpStream> as mio::event::source::Source>::register
Unexecuted instantiation: <mio::io_source::IoSource<std::net::udp::UdpSocket> as mio::event::source::Source>::register
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::stream::UnixStream> as mio::event::source::Source>::register
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::datagram::UnixDatagram> as mio::event::source::Source>::register
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::listener::UnixListener> as mio::event::source::Source>::register
123
124
0
    fn reregister(
125
0
        &mut self,
126
0
        registry: &Registry,
127
0
        token: Token,
128
0
        interests: Interest,
129
0
    ) -> io::Result<()> {
130
0
        #[cfg(debug_assertions)]
131
0
        self.selector_id.check_association(registry)?;
132
0
        self.state
133
0
            .reregister(registry, token, interests, self.inner.as_raw_fd())
134
0
    }
Unexecuted instantiation: <mio::io_source::IoSource<std::fs::File> as mio::event::source::Source>::reregister
Unexecuted instantiation: <mio::io_source::IoSource<std::net::tcp::TcpListener> as mio::event::source::Source>::reregister
Unexecuted instantiation: <mio::io_source::IoSource<std::net::tcp::TcpStream> as mio::event::source::Source>::reregister
Unexecuted instantiation: <mio::io_source::IoSource<std::net::udp::UdpSocket> as mio::event::source::Source>::reregister
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::stream::UnixStream> as mio::event::source::Source>::reregister
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::datagram::UnixDatagram> as mio::event::source::Source>::reregister
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::listener::UnixListener> as mio::event::source::Source>::reregister
135
136
0
    fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
137
0
        #[cfg(debug_assertions)]
138
0
        self.selector_id.remove_association(registry)?;
139
0
        self.state.deregister(registry, self.inner.as_raw_fd())
140
0
    }
Unexecuted instantiation: <mio::io_source::IoSource<std::fs::File> as mio::event::source::Source>::deregister
Unexecuted instantiation: <mio::io_source::IoSource<std::net::tcp::TcpListener> as mio::event::source::Source>::deregister
Unexecuted instantiation: <mio::io_source::IoSource<std::net::tcp::TcpStream> as mio::event::source::Source>::deregister
Unexecuted instantiation: <mio::io_source::IoSource<std::net::udp::UdpSocket> as mio::event::source::Source>::deregister
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::stream::UnixStream> as mio::event::source::Source>::deregister
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::datagram::UnixDatagram> as mio::event::source::Source>::deregister
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::listener::UnixListener> as mio::event::source::Source>::deregister
141
}
142
143
#[cfg(windows)]
144
impl<T> event::Source for IoSource<T>
145
where
146
    T: AsRawSocket,
147
{
148
    fn register(
149
        &mut self,
150
        registry: &Registry,
151
        token: Token,
152
        interests: Interest,
153
    ) -> io::Result<()> {
154
        #[cfg(debug_assertions)]
155
        self.selector_id.associate(registry)?;
156
        self.state
157
            .register(registry, token, interests, self.inner.as_raw_socket())
158
    }
159
160
    fn reregister(
161
        &mut self,
162
        registry: &Registry,
163
        token: Token,
164
        interests: Interest,
165
    ) -> io::Result<()> {
166
        #[cfg(debug_assertions)]
167
        self.selector_id.check_association(registry)?;
168
        self.state.reregister(registry, token, interests)
169
    }
170
171
    fn deregister(&mut self, _registry: &Registry) -> io::Result<()> {
172
        #[cfg(debug_assertions)]
173
        self.selector_id.remove_association(_registry)?;
174
        self.state.deregister()
175
    }
176
}
177
178
#[cfg(target_os = "wasi")]
179
impl<T> event::Source for IoSource<T>
180
where
181
    T: AsRawFd,
182
{
183
    fn register(
184
        &mut self,
185
        registry: &Registry,
186
        token: Token,
187
        interests: Interest,
188
    ) -> io::Result<()> {
189
        #[cfg(debug_assertions)]
190
        self.selector_id.associate(registry)?;
191
        registry
192
            .selector()
193
            .register(self.inner.as_raw_fd() as _, token, interests)
194
    }
195
196
    fn reregister(
197
        &mut self,
198
        registry: &Registry,
199
        token: Token,
200
        interests: Interest,
201
    ) -> io::Result<()> {
202
        #[cfg(debug_assertions)]
203
        self.selector_id.check_association(registry)?;
204
        registry
205
            .selector()
206
            .reregister(self.inner.as_raw_fd() as _, token, interests)
207
    }
208
209
    fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
210
        #[cfg(debug_assertions)]
211
        self.selector_id.remove_association(registry)?;
212
        registry.selector().deregister(self.inner.as_raw_fd() as _)
213
    }
214
}
215
216
impl<T> fmt::Debug for IoSource<T>
217
where
218
    T: fmt::Debug,
219
{
220
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
221
0
        self.inner.fmt(f)
222
0
    }
Unexecuted instantiation: <mio::io_source::IoSource<std::net::tcp::TcpListener> as core::fmt::Debug>::fmt
Unexecuted instantiation: <mio::io_source::IoSource<std::net::tcp::TcpStream> as core::fmt::Debug>::fmt
Unexecuted instantiation: <mio::io_source::IoSource<std::net::udp::UdpSocket> as core::fmt::Debug>::fmt
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::stream::UnixStream> as core::fmt::Debug>::fmt
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::datagram::UnixDatagram> as core::fmt::Debug>::fmt
Unexecuted instantiation: <mio::io_source::IoSource<std::os::unix::net::listener::UnixListener> as core::fmt::Debug>::fmt
223
}
224
225
/// Used to associate an `IoSource` with a `sys::Selector`.
226
#[cfg(debug_assertions)]
227
#[derive(Debug)]
228
struct SelectorId {
229
    id: AtomicUsize,
230
}
231
232
#[cfg(debug_assertions)]
233
impl SelectorId {
234
    /// Value of `id` if `SelectorId` is not associated with any
235
    /// `sys::Selector`. Valid selector ids start at 1.
236
    const UNASSOCIATED: usize = 0;
237
238
    /// Create a new `SelectorId`.
239
    const fn new() -> SelectorId {
240
        SelectorId {
241
            id: AtomicUsize::new(Self::UNASSOCIATED),
242
        }
243
    }
244
245
    /// Associate an I/O source with `registry`, returning an error if its
246
    /// already registered.
247
    fn associate(&self, registry: &Registry) -> io::Result<()> {
248
        let registry_id = registry.selector().id();
249
        let previous_id = self.id.swap(registry_id, Ordering::AcqRel);
250
251
        if previous_id == Self::UNASSOCIATED {
252
            Ok(())
253
        } else {
254
            Err(io::Error::new(
255
                io::ErrorKind::AlreadyExists,
256
                "I/O source already registered with a `Registry`",
257
            ))
258
        }
259
    }
260
261
    /// Check the association of an I/O source with `registry`, returning an
262
    /// error if its registered with a different `Registry` or not registered at
263
    /// all.
264
    fn check_association(&self, registry: &Registry) -> io::Result<()> {
265
        let registry_id = registry.selector().id();
266
        let id = self.id.load(Ordering::Acquire);
267
268
        if id == registry_id {
269
            Ok(())
270
        } else if id == Self::UNASSOCIATED {
271
            Err(io::Error::new(
272
                io::ErrorKind::NotFound,
273
                "I/O source not registered with `Registry`",
274
            ))
275
        } else {
276
            Err(io::Error::new(
277
                io::ErrorKind::AlreadyExists,
278
                "I/O source already registered with a different `Registry`",
279
            ))
280
        }
281
    }
282
283
    /// Remove a previously made association from `registry`, returns an error
284
    /// if it was not previously associated with `registry`.
285
    fn remove_association(&self, registry: &Registry) -> io::Result<()> {
286
        let registry_id = registry.selector().id();
287
        let previous_id = self.id.swap(Self::UNASSOCIATED, Ordering::AcqRel);
288
289
        if previous_id == registry_id {
290
            Ok(())
291
        } else {
292
            Err(io::Error::new(
293
                io::ErrorKind::NotFound,
294
                "I/O source not registered with `Registry`",
295
            ))
296
        }
297
    }
298
}
299
300
#[cfg(debug_assertions)]
301
impl Clone for SelectorId {
302
    fn clone(&self) -> SelectorId {
303
        SelectorId {
304
            id: AtomicUsize::new(self.id.load(Ordering::Acquire)),
305
        }
306
    }
307
}