Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Right now you use
std::sync::Mutex
inStdin
which can block an entire reactor.async-std/src/io/stdin.rs
Line 32 in c6e4c65
The solution for this flaw is to use
futures::lock::Mutex
.Solution №1
pub struct Stdin(futures::lock::Mutex<Inner>);
is not enough becausefutures::lock::Mutex::lock
returnsfutures::lock::MutexLockFuture<'a>
which depends on&self
, andblocking::spawn
expectsFuture
to be'static,
. Which is sad =(In the first commit I implemented it as
pub struct Stdin(Arc<futures::lock::Mutex<io::Stdin>>);
which allows to.clone()
the data and makesblocking::spawn
happy. However the lock is acquired insideblocking::spawn
which is not cool, because we need to spawn a thread (potentially) to try to lock the mutex. And I could not reuse buffers fromstdin.rs/Inner
(line
,buf
), so I had to allocate the buffers every time you make a call to Stdin::read_line or Stdin::poll_read.Solution №2
pub struct Stdin(Mutex<Arc<StdMutex<Inner>>>);
is what we want. It uses 2 mutexes:The first mutex is a futures-aware mutex. It will lock the data without blocking an entire reactor.
Arc is a solution to make blocking::spawn happy.
StdMutex is a solution to sync the
Inner
data, because we need to callblocking::spawn
and after that get the data to the parent "thread" to write it intobuf: &mut String
(in case of read_line).Does it look like a working solution?
BTW I reduced the state machine and the code is much easier to read.