From 611b4e11a7ebe69ae1a0f3d1bccc5286e33274f5 Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Thu, 26 Sep 2019 18:26:24 -0400 Subject: [PATCH] Make Barrier::wait future Send (#1611) It wasn't before. Now it is. And that is better. --- tokio-sync/src/barrier.rs | 34 +++++++++++++++++++--------------- tokio-sync/tests/barrier.rs | 7 +++++++ 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/tokio-sync/src/barrier.rs b/tokio-sync/src/barrier.rs index f71b4de9b..6a409e26f 100644 --- a/tokio-sync/src/barrier.rs +++ b/tokio-sync/src/barrier.rs @@ -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(); diff --git a/tokio-sync/tests/barrier.rs b/tokio-sync/tests/barrier.rs index b3c40e8ff..d50522242 100644 --- a/tokio-sync/tests/barrier.rs +++ b/tokio-sync/tests/barrier.rs @@ -4,6 +4,13 @@ use tokio_sync::Barrier; use tokio_test::task::spawn; use tokio_test::{assert_pending, assert_ready}; +struct IsSend(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);