mirror of
https://github.com/fafhrd91/actix-net
synced 2025-01-19 00:31:50 +01:00
Add Arbiter::local_join associated function
Arbiter::local_join function can be used to await for futures spawned on current arbiter. Signed-off-by: Jonathas-Conceicao <jadoliveira@inf.ufpel.edu.br>
This commit is contained in:
parent
e3b6a33b97
commit
f1685d8253
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
- Expose `System::is_set` to check if current system is running
|
- Expose `System::is_set` to check if current system is running
|
||||||
|
|
||||||
|
- Add `Arbiter::local_join` associated function to get be able to `await` for spawned futures
|
||||||
|
|
||||||
## [1.0.0] - 2019-12-11
|
## [1.0.0] - 2019-12-11
|
||||||
|
|
||||||
* Update dependencies
|
* Update dependencies
|
||||||
|
@ -15,10 +15,13 @@ use crate::system::System;
|
|||||||
|
|
||||||
use copyless::BoxHelper;
|
use copyless::BoxHelper;
|
||||||
|
|
||||||
|
pub use tokio::task::JoinHandle;
|
||||||
|
|
||||||
thread_local!(
|
thread_local!(
|
||||||
static ADDR: RefCell<Option<Arbiter>> = RefCell::new(None);
|
static ADDR: RefCell<Option<Arbiter>> = RefCell::new(None);
|
||||||
static RUNNING: Cell<bool> = Cell::new(false);
|
static RUNNING: Cell<bool> = Cell::new(false);
|
||||||
static Q: RefCell<Vec<Pin<Box<dyn Future<Output = ()>>>>> = RefCell::new(Vec::new());
|
static Q: RefCell<Vec<Pin<Box<dyn Future<Output = ()>>>>> = RefCell::new(Vec::new());
|
||||||
|
static PENDING: RefCell<Vec<JoinHandle<()>>> = RefCell::new(Vec::new());
|
||||||
static STORAGE: RefCell<HashMap<TypeId, Box<dyn Any>>> = RefCell::new(HashMap::new());
|
static STORAGE: RefCell<HashMap<TypeId, Box<dyn Any>>> = RefCell::new(HashMap::new());
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -170,7 +173,9 @@ impl Arbiter {
|
|||||||
RUNNING.with(move |cell| {
|
RUNNING.with(move |cell| {
|
||||||
if cell.get() {
|
if cell.get() {
|
||||||
// Spawn the future on running executor
|
// Spawn the future on running executor
|
||||||
tokio::task::spawn_local(future);
|
PENDING.with(move |cell| {
|
||||||
|
cell.borrow_mut().push(tokio::task::spawn_local(future));
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
// Box the future and push it to the queue, this results in double boxing
|
// Box the future and push it to the queue, this results in double boxing
|
||||||
// because the executor boxes the future again, but works for now
|
// because the executor boxes the future again, but works for now
|
||||||
@ -294,6 +299,15 @@ impl Arbiter {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a future that will be completed once all currently spawned futures
|
||||||
|
/// have completed.
|
||||||
|
pub fn local_join() -> impl Future<Output = ()> {
|
||||||
|
PENDING.with(move |cell| {
|
||||||
|
let current = cell.replace(Vec::new());
|
||||||
|
future::join_all(current).map(|_| ())
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ArbiterController {
|
struct ArbiterController {
|
||||||
@ -329,7 +343,9 @@ impl Future for ArbiterController {
|
|||||||
return Poll::Ready(());
|
return Poll::Ready(());
|
||||||
}
|
}
|
||||||
ArbiterCommand::Execute(fut) => {
|
ArbiterCommand::Execute(fut) => {
|
||||||
tokio::task::spawn_local(fut);
|
PENDING.with(move |cell| {
|
||||||
|
cell.borrow_mut().push(tokio::task::spawn_local(fut));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
ArbiterCommand::ExecuteFn(f) => {
|
ArbiterCommand::ExecuteFn(f) => {
|
||||||
f.call_box();
|
f.call_box();
|
||||||
|
@ -61,3 +61,40 @@ fn join_another_arbiter() {
|
|||||||
"Premature stop of arbiter should conclude regardless of it's current state"
|
"Premature stop of arbiter should conclude regardless of it's current state"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn join_current_arbiter() {
|
||||||
|
let time = Duration::from_secs(2);
|
||||||
|
|
||||||
|
let instant = Instant::now();
|
||||||
|
actix_rt::System::new("test_join_current_arbiter").block_on(async move {
|
||||||
|
actix_rt::spawn(async move {
|
||||||
|
tokio::time::delay_for(time).await;
|
||||||
|
actix_rt::Arbiter::current().stop();
|
||||||
|
});
|
||||||
|
actix_rt::Arbiter::local_join().await;
|
||||||
|
});
|
||||||
|
assert!(
|
||||||
|
instant.elapsed() >= time,
|
||||||
|
"Join on current arbiter should wait for all spawned futures"
|
||||||
|
);
|
||||||
|
|
||||||
|
let large_timer = Duration::from_secs(20);
|
||||||
|
let instant = Instant::now();
|
||||||
|
actix_rt::System::new("test_join_current_arbiter").block_on(async move {
|
||||||
|
actix_rt::spawn(async move {
|
||||||
|
tokio::time::delay_for(time).await;
|
||||||
|
actix_rt::Arbiter::current().stop();
|
||||||
|
});
|
||||||
|
let f = actix_rt::Arbiter::local_join();
|
||||||
|
actix_rt::spawn(async move {
|
||||||
|
tokio::time::delay_for(large_timer).await;
|
||||||
|
actix_rt::Arbiter::current().stop();
|
||||||
|
});
|
||||||
|
f.await;
|
||||||
|
});
|
||||||
|
assert!(
|
||||||
|
instant.elapsed() < large_timer,
|
||||||
|
"local_join should await only for the already spawned futures"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user