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