Skip to main content

dope_core/io/
pipe.rs

1use std::cell::Cell;
2use std::io;
3use std::marker::PhantomData;
4use std::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, OwnedFd, RawFd};
5
6use crate::driver::Driver;
7use crate::platform::raw::abi::PlatformAbi;
8
9pub struct Pipe {
10    read: OwnedFd,
11    write: OwnedFd,
12    _exclusive: PhantomData<Cell<()>>,
13}
14
15impl Pipe {
16    pub fn new() -> io::Result<Self> {
17        let fds = Driver::open_pipe()?;
18        Ok(Self::from_fds(fds[0], fds[1]))
19    }
20
21    pub fn write_end(&self) -> BorrowedFd<'_> {
22        self.write.as_fd()
23    }
24
25    pub fn try_clone(&self) -> io::Result<Self> {
26        Ok(Self {
27            read: self.read.try_clone()?,
28            write: self.write.try_clone()?,
29            _exclusive: PhantomData,
30        })
31    }
32
33    pub fn from_fds(read: RawFd, write: RawFd) -> Self {
34        unsafe {
35            Self {
36                read: OwnedFd::from_raw_fd(read),
37                write: OwnedFd::from_raw_fd(write),
38                _exclusive: PhantomData,
39            }
40        }
41    }
42
43    pub fn read_end(&self) -> BorrowedFd<'_> {
44        self.read.as_fd()
45    }
46
47    pub fn notify(&self) -> io::Result<()> {
48        let byte = 1u8;
49        loop {
50            let written =
51                unsafe { libc::write(self.write.as_raw_fd(), (&byte as *const u8).cast(), 1) };
52            if written == 1 {
53                return Ok(());
54            }
55            let error = io::Error::last_os_error();
56            match error.kind() {
57                io::ErrorKind::Interrupted => continue,
58                io::ErrorKind::WouldBlock => return Ok(()),
59                _ => return Err(error),
60            }
61        }
62    }
63}