Skip to content

Commit bac74c2

Browse files
author
Stjepan Glavina
authored
Reduce dependency on futures crate (#140)
* Add future::poll_fn * Replace all uses of poll_fn with the new one * Remove some uses of futures * Simplify ReadDir and DirEntry * Remove some use of futures from File * Use futures subcrates * Fix imports in docs * Remove futures-util dependency * Remove futures-executor-preview * Refactor * Require more features in the futures-preview crate
1 parent 75a4ba8 commit bac74c2

35 files changed

+454
-363
lines changed

Cargo.toml

+8-5
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ unstable = []
2727
async-task = "1.0.0"
2828
cfg-if = "0.1.9"
2929
crossbeam-channel = "0.3.9"
30+
futures-channel-preview = "0.3.0-alpha.18"
31+
futures-core-preview = "0.3.0-alpha.18"
32+
futures-io-preview = "0.3.0-alpha.18"
3033
futures-timer = "0.3.0"
3134
lazy_static = "1.3.0"
3235
log = { version = "0.4.8", features = ["kv_unstable"] }
@@ -37,11 +40,11 @@ num_cpus = "1.10.0"
3740
pin-utils = "0.1.0-alpha.4"
3841
slab = "0.4.2"
3942

40-
[dependencies.futures-preview]
41-
version = "0.3.0-alpha.18"
42-
features = ["async-await", "nightly"]
43-
4443
[dev-dependencies]
4544
femme = "1.1.0"
46-
tempdir = "0.3.7"
4745
surf = "1.0.1"
46+
tempdir = "0.3.7"
47+
48+
[dev-dependencies.futures-preview]
49+
version = "0.3.0-alpha.18"
50+
features = ["std", "nightly", "async-await"]

docs/src/tutorial/connecting_readers_and_writers.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ The order of events "Bob sends message to Alice" and "Alice joins" is determined
2020
# task,
2121
# };
2222
# use futures::channel::mpsc;
23-
# use futures::SinkExt;
23+
# use futures::sink::SinkExt;
2424
# use std::sync::Arc;
2525
#
2626
# type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;

docs/src/tutorial/sending_messages.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ if Alice and Charley send two messages to Bob at the same time, Bob will see the
2020
# prelude::Stream,
2121
# };
2222
use futures::channel::mpsc; // 1
23-
use futures::SinkExt;
23+
use futures::sink::SinkExt;
2424
use std::sync::Arc;
2525
2626
# type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;

src/fs/dir_entry.rs

+12-93
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
use std::ffi::OsString;
22
use std::fs;
33
use std::path::PathBuf;
4-
use std::pin::Pin;
5-
use std::sync::Mutex;
4+
use std::sync::Arc;
65

76
use cfg_if::cfg_if;
8-
use futures::future::{self, FutureExt, TryFutureExt};
97

10-
use crate::future::Future;
118
use crate::io;
12-
use crate::task::{blocking, Poll};
9+
use crate::task::blocking;
1310

1411
/// An entry inside a directory.
1512
///
@@ -21,44 +18,25 @@ use crate::task::{blocking, Poll};
2118
/// [`std::fs::DirEntry`]: https://doc.rust-lang.org/std/fs/struct.DirEntry.html
2219
#[derive(Debug)]
2320
pub struct DirEntry {
24-
/// The state of the entry.
25-
state: Mutex<State>,
26-
27-
/// The full path to the entry.
28-
path: PathBuf,
21+
/// The inner synchronous `DirEntry`.
22+
inner: Arc<fs::DirEntry>,
2923

3024
#[cfg(unix)]
3125
ino: u64,
32-
33-
/// The bare name of the entry without the leading path.
34-
file_name: OsString,
35-
}
36-
37-
/// The state of an asynchronous `DirEntry`.
38-
///
39-
/// The `DirEntry` can be either idle or busy performing an asynchronous operation.
40-
#[derive(Debug)]
41-
enum State {
42-
Idle(Option<fs::DirEntry>),
43-
Busy(blocking::JoinHandle<State>),
4426
}
4527

4628
impl DirEntry {
4729
/// Creates an asynchronous `DirEntry` from a synchronous handle.
4830
pub(crate) fn new(inner: fs::DirEntry) -> DirEntry {
4931
#[cfg(unix)]
5032
let dir_entry = DirEntry {
51-
path: inner.path(),
52-
file_name: inner.file_name(),
5333
ino: inner.ino(),
54-
state: Mutex::new(State::Idle(Some(inner))),
34+
inner: Arc::new(inner),
5535
};
5636

5737
#[cfg(windows)]
5838
let dir_entry = DirEntry {
59-
path: inner.path(),
60-
file_name: inner.file_name(),
61-
state: Mutex::new(State::Idle(Some(inner))),
39+
inner: Arc::new(inner),
6240
};
6341

6442
dir_entry
@@ -89,7 +67,7 @@ impl DirEntry {
8967
/// # Ok(()) }) }
9068
/// ```
9169
pub fn path(&self) -> PathBuf {
92-
self.path.clone()
70+
self.inner.path()
9371
}
9472

9573
/// Returns the metadata for this entry.
@@ -114,35 +92,8 @@ impl DirEntry {
11492
/// # Ok(()) }) }
11593
/// ```
11694
pub async fn metadata(&self) -> io::Result<fs::Metadata> {
117-
future::poll_fn(|cx| {
118-
let state = &mut *self.state.lock().unwrap();
119-
120-
loop {
121-
match state {
122-
State::Idle(opt) => match opt.take() {
123-
None => return Poll::Ready(None),
124-
Some(inner) => {
125-
let (s, r) = futures::channel::oneshot::channel();
126-
127-
// Start the operation asynchronously.
128-
*state = State::Busy(blocking::spawn(async move {
129-
let res = inner.metadata();
130-
let _ = s.send(res);
131-
State::Idle(Some(inner))
132-
}));
133-
134-
return Poll::Ready(Some(r));
135-
}
136-
},
137-
// Poll the asynchronous operation the file is currently blocked on.
138-
State::Busy(task) => *state = futures::ready!(Pin::new(task).poll(cx)),
139-
}
140-
}
141-
})
142-
.map(|opt| opt.ok_or_else(|| io_error("invalid state")))
143-
.await?
144-
.map_err(|_| io_error("blocking task failed"))
145-
.await?
95+
let inner = self.inner.clone();
96+
blocking::spawn(async move { inner.metadata() }).await
14697
}
14798

14899
/// Returns the file type for this entry.
@@ -167,35 +118,8 @@ impl DirEntry {
167118
/// # Ok(()) }) }
168119
/// ```
169120
pub async fn file_type(&self) -> io::Result<fs::FileType> {
170-
future::poll_fn(|cx| {
171-
let state = &mut *self.state.lock().unwrap();
172-
173-
loop {
174-
match state {
175-
State::Idle(opt) => match opt.take() {
176-
None => return Poll::Ready(None),
177-
Some(inner) => {
178-
let (s, r) = futures::channel::oneshot::channel();
179-
180-
// Start the operation asynchronously.
181-
*state = State::Busy(blocking::spawn(async move {
182-
let res = inner.file_type();
183-
let _ = s.send(res);
184-
State::Idle(Some(inner))
185-
}));
186-
187-
return Poll::Ready(Some(r));
188-
}
189-
},
190-
// Poll the asynchronous operation the file is currently blocked on.
191-
State::Busy(task) => *state = futures::ready!(Pin::new(task).poll(cx)),
192-
}
193-
}
194-
})
195-
.map(|opt| opt.ok_or_else(|| io_error("invalid state")))
196-
.await?
197-
.map_err(|_| io_error("blocking task failed"))
198-
.await?
121+
let inner = self.inner.clone();
122+
blocking::spawn(async move { inner.file_type() }).await
199123
}
200124

201125
/// Returns the bare name of this entry without the leading path.
@@ -218,15 +142,10 @@ impl DirEntry {
218142
/// # Ok(()) }) }
219143
/// ```
220144
pub fn file_name(&self) -> OsString {
221-
self.file_name.clone()
145+
self.inner.file_name()
222146
}
223147
}
224148

225-
/// Creates a custom `io::Error` with an arbitrary error type.
226-
fn io_error(err: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> io::Error {
227-
io::Error::new(io::ErrorKind::Other, err)
228-
}
229-
230149
cfg_if! {
231150
if #[cfg(feature = "docs")] {
232151
use crate::os::unix::fs::DirEntryExt;

0 commit comments

Comments
 (0)