compio_runtime/
attacher.rs

1#[cfg(unix)]
2use std::os::fd::{FromRawFd, RawFd};
3#[cfg(windows)]
4use std::os::windows::io::{FromRawHandle, FromRawSocket, RawHandle, RawSocket};
5use std::{io, ops::Deref};
6
7use compio_buf::IntoInner;
8use compio_driver::{AsRawFd, SharedFd, ToSharedFd};
9
10use crate::Runtime;
11
12/// Attach a handle to the driver of current thread.
13///
14/// A handle can and only can attach once to one driver. The attacher will try
15/// to attach the handle.
16#[derive(Debug)]
17pub struct Attacher<S> {
18    source: SharedFd<S>,
19}
20
21impl<S> Attacher<S> {
22    /// Create [`Attacher`] without trying to attach the source.
23    ///
24    /// # Safety
25    ///
26    /// The user should ensure that the source is attached to the current
27    /// driver.
28    pub unsafe fn new_unchecked(source: S) -> Self {
29        Self {
30            source: SharedFd::new(source),
31        }
32    }
33
34    /// Create [`Attacher`] without trying to attach the source.
35    ///
36    /// # Safety
37    ///
38    /// See [`Attacher::new_unchecked`].
39    pub unsafe fn from_shared_fd_unchecked(source: SharedFd<S>) -> Self {
40        Self { source }
41    }
42}
43
44impl<S: AsRawFd> Attacher<S> {
45    /// Create [`Attacher`]. It tries to attach the source, and will return
46    /// [`Err`] if it fails.
47    ///
48    /// ## Platform specific
49    /// * IOCP: a handle could not be attached more than once. If you want to
50    ///   clone the handle, create the [`Attacher`] before cloning.
51    pub fn new(source: S) -> io::Result<Self> {
52        Runtime::with_current(|r| r.attach(source.as_raw_fd()))?;
53        Ok(unsafe { Self::new_unchecked(source) })
54    }
55}
56
57impl<S> IntoInner for Attacher<S> {
58    type Inner = SharedFd<S>;
59
60    fn into_inner(self) -> Self::Inner {
61        self.source
62    }
63}
64
65impl<S> Clone for Attacher<S> {
66    fn clone(&self) -> Self {
67        Self {
68            source: self.source.clone(),
69        }
70    }
71}
72
73#[cfg(windows)]
74impl<S: FromRawHandle> FromRawHandle for Attacher<S> {
75    unsafe fn from_raw_handle(handle: RawHandle) -> Self {
76        Self::new_unchecked(S::from_raw_handle(handle))
77    }
78}
79
80#[cfg(windows)]
81impl<S: FromRawSocket> FromRawSocket for Attacher<S> {
82    unsafe fn from_raw_socket(sock: RawSocket) -> Self {
83        Self::new_unchecked(S::from_raw_socket(sock))
84    }
85}
86
87#[cfg(unix)]
88impl<S: FromRawFd> FromRawFd for Attacher<S> {
89    unsafe fn from_raw_fd(fd: RawFd) -> Self {
90        Self::new_unchecked(S::from_raw_fd(fd))
91    }
92}
93
94impl<S> Deref for Attacher<S> {
95    type Target = S;
96
97    fn deref(&self) -> &Self::Target {
98        self.source.deref()
99    }
100}
101
102impl<S> ToSharedFd<S> for Attacher<S> {
103    fn to_shared_fd(&self) -> SharedFd<S> {
104        self.source.to_shared_fd()
105    }
106}