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}