Rust 的变更

通过挂起 get 机制使用 API 时,必须格外小心 以免丢失对待处理 FIDL 请求的引用。某些 Future Abortablefuchsia_async::TimeoutExt会丢弃待定的未来 这会导致对 FIDL 请求的引用也被删除。因为 挂起获取通常由协议服务器以有状态的方式实现, 在上一个 Future 上,调用挂起的 get 方法可能无效 相同的 Proxy 已被丢弃。

为了避免在使用此类组合器时 Proxy 失效,一种很好的模式是 使用以下代码将挂起的 get 调用封装在 streamHangingGetStream:

// When you don't need to write down the type of the result, you can use a
// fn item, which has zero size and is statically dispatched when called.
let watch_foo_stream = HangingGetStream::new(proxy, FooWatcherProxy::watch_foo);
// Also you can use a capturing closure in that case.
let watch_bar_stream = HangingGetStream::new(proxy, |p| p.watch_bar(some_captured_var));

// If you do want to write down the type (for example when embedding this in
// another Future), you can achieve so by storing a fn pointer. A fn pointer
// can be obtained through coercion from a non-capturing closure or a fn item.
// That said, if you use a capturing closure, there is no way to name the type.
let watch_baz_stream: HangingGetStream<BazProxy, Baz> = HangingGetStream::new_with_fn_ptr(proxy, |p| p.watch_baz());

另一种替代方案是使用以下模式创建流。

fn hanging_get_stream(proxy: &FooProxy) -> impl futures::Stream<Item=Result<FooResult, fidl::Error>> + '_ {
    futures::stream::try_unfold(proxy, |proxy| {
       proxy.watch_foo().map_ok(move |watch_result| Some((watch_result, proxy)))
    })
}

丢弃 Stream::next Future 始终是安全的,因为它不会导致 底层 FIDL 请求将被丢弃。如果流本身在等待 则系统将忽略该响应。如果 FIDL 服务器不允许 多个挂起的 getter 文件。