Make Barrier::wait future Send (#1611)

It wasn't before. Now it is. And that is better.
This commit is contained in:
Jon Gjengset 2019-09-26 18:26:24 -04:00 committed by GitHub
parent 159abb375f
commit 611b4e11a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 26 additions and 15 deletions

View File

@ -83,22 +83,26 @@ impl Barrier {
// deadlock even if another future is concurrently holding the lock.
// It is _desireable_ to do so as synchronous Mutexes are, at least in theory, faster than
// the asynchronous counter-parts, so we should use them where possible [citation needed].
let mut state = self.state.lock().unwrap();
let generation = state.generation;
state.arrived += 1;
if state.arrived == self.n {
// we are the leader for this generation
// wake everyone, increment the generation, and return
state
.waker
.broadcast(state.generation)
.expect("there is at least one receiver");
state.arrived = 0;
state.generation += 1;
return BarrierWaitResult(true);
}
// NOTE: the extra scope here is so that the compiler doesn't think `state` is held across
// a yield point, and thus marks the returned future as !Send.
let generation = {
let mut state = self.state.lock().unwrap();
let generation = state.generation;
state.arrived += 1;
if state.arrived == self.n {
// we are the leader for this generation
// wake everyone, increment the generation, and return
state
.waker
.broadcast(state.generation)
.expect("there is at least one receiver");
state.arrived = 0;
state.generation += 1;
return BarrierWaitResult(true);
}
drop(state);
generation
};
// we're going to have to wait for the last of the generation to arrive
let mut wait = self.wait.clone();

View File

@ -4,6 +4,13 @@ use tokio_sync::Barrier;
use tokio_test::task::spawn;
use tokio_test::{assert_pending, assert_ready};
struct IsSend<T: Send>(T);
#[test]
fn barrier_future_is_send() {
let b = Barrier::new(0);
IsSend(b.wait());
}
#[test]
fn zero_does_not_block() {
let b = Barrier::new(0);