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::{AsFd, 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    /// * `S` should be an owned fd.
29    pub unsafe fn new_unchecked(source: S) -> Self {
30        Self {
31            source: unsafe { SharedFd::new_unchecked(source) },
32        }
33    }
34
35    /// Create [`Attacher`] without trying to attach the source.
36    ///
37    /// # Safety
38    ///
39    /// See [`Attacher::new_unchecked`].
40    pub unsafe fn from_shared_fd_unchecked(source: SharedFd<S>) -> Self {
41        Self { source }
42    }
43}
44
45impl<S: AsFd> Attacher<S> {
46    /// Create [`Attacher`]. It tries to attach the source, and will return
47    /// [`Err`] if it fails.
48    ///
49    /// ## Platform specific
50    /// * IOCP: a handle could not be attached more than once. If you want to
51    ///   clone the handle, create the [`Attacher`] before cloning.
52    pub fn new(source: S) -> io::Result<Self> {
53        Runtime::with_current(|r| r.attach(source.as_fd().as_raw_fd()))?;
54        Ok(unsafe { Self::new_unchecked(source) })
55    }
56}
57
58impl<S> IntoInner for Attacher<S> {
59    type Inner = SharedFd<S>;
60
61    fn into_inner(self) -> Self::Inner {
62        self.source
63    }
64}
65
66impl<S> Clone for Attacher<S> {
67    fn clone(&self) -> Self {
68        Self {
69            source: self.source.clone(),
70        }
71    }
72}
73
74#[cfg(windows)]
75impl<S: FromRawHandle> FromRawHandle for Attacher<S> {
76    unsafe fn from_raw_handle(handle: RawHandle) -> Self {
77        unsafe { Self::new_unchecked(S::from_raw_handle(handle)) }
78    }
79}
80
81#[cfg(windows)]
82impl<S: FromRawSocket> FromRawSocket for Attacher<S> {
83    unsafe fn from_raw_socket(sock: RawSocket) -> Self {
84        unsafe { Self::new_unchecked(S::from_raw_socket(sock)) }
85    }
86}
87
88#[cfg(unix)]
89impl<S: FromRawFd> FromRawFd for Attacher<S> {
90    unsafe fn from_raw_fd(fd: RawFd) -> Self {
91        unsafe { Self::new_unchecked(S::from_raw_fd(fd)) }
92    }
93}
94
95impl<S> Deref for Attacher<S> {
96    type Target = S;
97
98    fn deref(&self) -> &Self::Target {
99        self.source.deref()
100    }
101}
102
103impl<S> ToSharedFd<S> for Attacher<S> {
104    fn to_shared_fd(&self) -> SharedFd<S> {
105        self.source.to_shared_fd()
106    }
107}