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}