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}