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::backend::PlatformAbi;
7use crate::driver::Driver;
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_fd(&self) -> RawFd {
22        self.write.as_raw_fd()
23    }
24
25    pub fn write_end(&self) -> BorrowedFd<'_> {
26        self.write.as_fd()
27    }
28
29    pub fn try_clone(&self) -> io::Result<Self> {
30        Ok(Self {
31            read: self.read.try_clone()?,
32            write: self.write.try_clone()?,
33            _exclusive: PhantomData,
34        })
35    }
36
37    pub fn from_fds(read: RawFd, write: RawFd) -> Self {
38        unsafe {
39            Self {
40                read: OwnedFd::from_raw_fd(read),
41                write: OwnedFd::from_raw_fd(write),
42                _exclusive: PhantomData,
43            }
44        }
45    }
46
47    pub fn read_fd(&self) -> RawFd {
48        self.read.as_raw_fd()
49    }
50
51    pub fn read_end(&self) -> BorrowedFd<'_> {
52        self.read.as_fd()
53    }
54
55    pub fn notify(&self) -> io::Result<()> {
56        let byte = 1u8;
57        loop {
58            let written =
59                unsafe { libc::write(self.write.as_raw_fd(), (&byte as *const u8).cast(), 1) };
60            if written == 1 {
61                return Ok(());
62            }
63            let error = io::Error::last_os_error();
64            match error.kind() {
65                io::ErrorKind::Interrupted => continue,
66                io::ErrorKind::WouldBlock => return Ok(()),
67                _ => return Err(error),
68            }
69        }
70    }
71}