#future #scope #async #run-time #spawning #spawn #non-static

futures-scopes

运行时无关、可嵌套的非静态 futures 的作用域

7 个版本

0.2.0 2023 年 10 月 6 日
0.1.7 2023 年 9 月 9 日
0.1.5 2022 年 9 月 20 日

#429异步

Download history 25/week @ 2024-04-15 24/week @ 2024-04-22 14/week @ 2024-04-29 22/week @ 2024-05-06 29/week @ 2024-05-13 80/week @ 2024-05-20 23/week @ 2024-05-27 154/week @ 2024-06-03 411/week @ 2024-06-10 93/week @ 2024-06-17 33/week @ 2024-06-24 172/week @ 2024-07-01 10/week @ 2024-07-08 13/week @ 2024-07-15 44/week @ 2024-07-22 37/week @ 2024-07-29

每月 104 次下载

MIT 许可证

55KB
868 代码行

Build Creates.io Docs

futures-scopes

是 futures-rs 的扩展,提供作用域。作用域可以用来生成可以引用作用域创建之前创建的栈变量的非静态 futures。作用域会将这些 futures 转发到多个底层生成器之一。这允许将多个生成器组合成一个。当作用域被丢弃时,该生成器下的所有 futures 将立即被丢弃。

由于作用域本身就是一个 Spawn,它可以在其中生成进一步嵌套的作用域。

示例

// An async example function that has access to some kind of spawner
async fn example(spawn: &(impl Spawn + Clone + Send + 'static)) {
    let counter = AtomicUsize::new(0);

    // Create a scope.
    // Futures spawned on `scope` can reference everything before new_relay_scope!()
    let scope = new_relay_scope!();

    // We spawn the new scope on the given spawn.
    // This could be a ThreadPool, for example.
    // It is also possible to spawn on multiple Spawns to share the work between them
    //
    // The scope will spawn a single future to the given Spawn.
    // This future will self-replicate to fill the Spawn, but not overwhelm it either.
    spawn.spawn_scope(scope);

    // Create a new Spawner that spawns futures on the scope.
    // `spawner` is Spawn+Clone+Send+'static,
    // so another nested scope can be spawned inside our scope
    // with `spawner.spawn_scope(another_nested_scope)`.
    let spawner = scope.spawner();

    for i in 1..=100 {
        // Tell rust not to move the counter into the async fn
        let counter = &counter;
        let fut = async move {
            for _ in 0..100 {
                // `counter` is not moved into the future but referenced
                // `i`, however, was moved(copied) into the future
                counter.fetch_add(i, Relaxed);
            }
        };

        // spawn the future on the scope
        spawner.spawn_scoped(fut).unwrap();
    }

    // Wait until all futures have been finished.
    // This does not block the thread, but returns a future that we can await!
    scope.until_empty().await;

    // Counter: 505000
    println!("Counter: {}", counter.load(SeqCst));

    // The scope is dropped here.
    // If we wouldn't have waited for all futures to be processed,
    // the drop would stop the execution of all scope-futures and drop them.
    // The drop blocks the current thread only minimally
    // until all currently running futures are have left their poll method
    // and all futures are destroyed.
}

fn main() {
    // Run `example` with a ThreadPool.
    let pool = ThreadPool::new().unwrap();
    block_on(example(&pool));
}

依赖

~1–7MB
~42K SLoC