使用具有等待取得的 API 時,必須小心謹慎
以避免遺失待處理 FIDL 要求的參照。未來期
我們結合了 Abortable
和
fuchsia_async::TimeoutExt
將會捨棄待處理的未來,
因此,系統會捨棄對 FIDL 要求的參照。由於
停止運作的作業通常是由通訊協定伺服器以有狀態的方式實作
若是呼叫 hanging get 方法,則會失效於
已捨棄相同的 Proxy
。
為避免在使用這類合併器時使 Proxy
失效,採用以下模式:
使用stream
HangingGetStream
:
// 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 伺服器不允許
讓多名等待人員同時等待。