tempest_rt/fs/
close_file.rs1use std::{
4 io,
5 marker::PhantomData,
6 mem::replace,
7 pin::Pin,
8 task::{Context, Poll},
9};
10
11use tempest_io::{Io, OpHandle};
12
13use crate::context::{current_io, get_op_handle};
14
15enum CloseFileState<I: Io> {
16 NeedsSubmit { fd: I::Fd, handle: Option<OpHandle> },
17 InFlight { handle: OpHandle },
18 Done,
19}
20
21#[must_use = "futures do nothing unless awaited"]
23pub struct CloseFile<I: Io> {
24 state: CloseFileState<I>,
25 _marker: PhantomData<fn() -> I>,
27}
28
29pub fn close_file<I: Io>(fd: I::Fd) -> CloseFile<I> {
31 CloseFile {
32 state: CloseFileState::NeedsSubmit { fd, handle: None },
33 _marker: PhantomData,
34 }
35}
36
37impl<I: Io> Unpin for CloseFile<I> {}
39
40impl<I: Io> Future for CloseFile<I> {
41 type Output = io::Result<()>;
42
43 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
44 let this = self.get_mut();
45
46 match replace(&mut this.state, CloseFileState::Done) {
47 CloseFileState::NeedsSubmit { fd, handle } => {
48 let handle = handle.unwrap_or_else(|| unsafe { get_op_handle(cx) });
49
50 let io = unsafe { current_io::<I>() };
52 match io.close(fd, handle) {
53 Ok(()) => {
54 this.state = CloseFileState::InFlight { handle };
55 Poll::Pending
56 }
57 Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
58 this.state = CloseFileState::NeedsSubmit {
60 fd,
61 handle: Some(handle),
62 };
63 cx.waker().wake_by_ref();
64 Poll::Pending
65 }
66 Err(e) => Poll::Ready(Err(e)),
67 }
68 }
69 CloseFileState::InFlight { handle } => {
70 let io = unsafe { current_io::<I>() };
72 match io.get_cqe(handle).transpose()? {
73 Some(_) => Poll::Ready(Ok(())),
74 None => {
75 this.state = CloseFileState::InFlight { handle };
76 Poll::Pending
77 }
78 }
79 }
80 CloseFileState::Done => panic!("polled after completion"),
81 }
82 }
83}