3个不稳定版本

0.2.0 2024年5月10日
0.1.1 2024年5月10日
0.1.0 2024年5月9日

#243 in 异步


asyncs 中使用

Apache-2.0

150KB
4K SLoC

async-select

crates.io github-ci docs.rs Apache-2.0

select! 同时复用异步 futures。

动机

最初,我为 支持多个异步运行时,但不仅限于 tokio 打开了 zookeeper-client-rust 的问题。我发现,社区中确实存在其他项目来帮助运行时无关的库。虽然我不敢说其中大部分如果不是全部都很糟糕 -:),但我也不认为它们很优雅。在创建了 spawns 之后,我发现实际上对于使用运行时无关库的库作者来说,从 tokio 运行时迁移过来非常容易,比如通过 async-ioasync-netfuturesfutures-rustlsfutures-lite 等库的帮助。但是树中仍然存在 tokio 依赖,一个是 select!,我想试一试。

特性

use core::future::ready;

use async_select::select;

#[derive(Default)]
struct FieldStruct {
    _a: TupleStruct,
    _b: i32,
    _c: i32,
}

#[derive(Default)]
struct TupleStruct((), (), ());

// pattern according to syn::Pat
//
// failure will cause compilation error.
async fn patterns() {
    select! {
        default => {},
        complete => {},

        // Const(PatConst)
        //
        // unstable: #![feature(inline_const_pat)] https://github.com/rust-lang/rust/issues/76001
        // const { 5 } = ready(5) => {},

        // Ident(PatIdent)
        mut _v = ready(()) => {},
        ref _v = ready(()) => {},
        ref mut _v = ready(()) => {},
        ref mut _x@FieldStruct{ _b, ..} = ready(FieldStruct::default()) => {},
        ref mut _x@FieldStruct{ mut _b, ..} = ready(FieldStruct::default()) => {},
        mut _x@FieldStruct{ mut _b, ..} = ready(FieldStruct::default()) => {},


        // Lit(PatLit)
        5 = ready(5) => {},

        // Macro(PatMacro)

        // Or(PatOr)
        5 | 6 = ready(5) => {},

        // Paren(PatParen)
        (5 | 6) = ready(5) => {},

        // Path(PatPath)
        ::core::option::Option::None = ready(Some(5)) => {},
        ::core::option::Option::Some(ref _i) = ready(Some(5)) => {},

        // Range(PatRange)
        1..=2 = ready(5) => {},

        // Reference(PatReference)
        //
        // This is not supported as we are pattern against value.
        // &_v = ready(5) => {}
        // &mut _v = ready(5) => {}

        // Rest(PatRest)
        (ref _i, mut _v, ..) = ready((1, 2, 3, 4)) => {},

        // Slice(PatSlice)
        //
        // Pattern against value but not reference.

        // Struct(PatStruct)
        FieldStruct { ref mut _a, ref _b, .. } = ready(FieldStruct::default()) => {},

        // Tuple(PatTuple)
        (1, 2) = ready((1, 2)) => {},

        // TupleStruct(PatTupleStruct)
        TupleStruct(_a, _b, ..) = ready(TupleStruct::default()) => {},
        TupleStruct(ref mut _a, ref _b, ..) = ready(TupleStruct::default()) => {},

        // Type(PatType)
        // Is this only used in variable definition ?

        // Verbatim(TokenStream)
        //
        // Tokens in pattern position not interpreted by Syn.

        // Wild(PatWild)
        _ = ready(()) => {}
    }
}
  • crossbeam-channel:这是我学习真正宏的地方。
  • stuck::select:这是 async-select::select! 推导出来的。
  • futures::select:这是 defaultcomplete 推导出来的。
  • tokio:tokio 本身就很好。但它显然对运行时无关库不够友好。你根本无法判断它哪部分是运行时无关的。所以如果你甚至想实现运行时无关,最好完全避免它。
  • 《Rust宏简明书》:嗯,这本书。

无运行时依赖