这个问题的目的是了解期货在铁 rust 公司应该如何运作.我没有一段特定的代码不起作用,而是在理解必须如何编写期货以履行合同方面存在问题.

假设你在写《future 》.Poll()的约定允许调用者每次传递一个不同的Waker,而Future应该只调用最近的一个.

假设Future隐藏了由辅助线程在后台完成的实际工作.如果工作者还没有完成在创建Future时传递给它的工作,则Future应该返回挂起并克隆和存储Waker.然后,Future会在一段时间内不做任何事情,而必须调用Waker的是工作线程.这将导致future 再次被调查.

假设当再次轮询Future时,它确定工作线程到目前为止所做的工作还不够,因此它再次返回Pending,并克隆并存储它在第二次调用中获得的新Waker.

由于实际调用Waker的是工作线程,因此poll()实现必须在后台线程中更新Waker.然而,我并不清楚poll()实现如何在没有竞争条件的情况下做到这一点--但现在它变得棘手起来,因为细节在很大程度上依赖于poll()合同中的细节,我认为这个细节甚至没有具体指定.

一种可能发生的情况是,当poll()正在运行时,就在它想要将新的Waker交给后台Worker之前,Worker决定是时候调用Waker了.它现在调用oldWaker,尽管poll()已经收到了一个新的Waker,这可能会也可能不会违反合同(我认为这没有指定).因此,有人可能认为Worker可能会调用旧的Waker,直到Poll()完成,但只有当Worker被允许在Poll()运行时调用either Waker时才起作用,同样没有提到这一点,并且只需要在Poll()返回后调用新的Waker.

最后,即使这个假设也依赖于另一件未指定的事情:在多线程上下文中"After Poll()已返回"的确切含义,它通常必须求助于专门定义的术语,如发生之后,才能定义一件事接着一件事发生.

考虑到所有这些,poll()实现如何履行其合同,只调用最新的Waker呢?是否有一个文档指定了Poll()文档中似乎缺失的所有细节?

推荐答案

关于以无竞争的方式更新唤醒程序,我的建议是使用futures::task::AtomicWaker,它可以自动存储和唤醒唤醒程序.

需要注意的是,被唤醒并不意味着对future 有更多的工作要做,并且允许偶尔唤醒被唤醒的人(例如,如果一个不同的future 已经准备好前进).

考虑到这一点,让我们考虑一个简单的future ,它具有一个AtomicWaker和一个在future 和工作线程之间共享的"要完成的工作"标志.如果在轮询时未设置"要完成的工作"标志,则future 将简单地返回Poll::Pending.

对于正确性,我们只需要两件事:

  1. 工作线程在唤醒唤醒程序之前必须设置"Work to Do Do"标志.
  2. future 必须注册一个新的唤醒程序,然后才能判断"要完成的工作"标志.

这意味着,无论Worker和poll方法执行操作的顺序是什么,行为都是正确的:

  1. 如果没有调用poll方法,则工作进程将设置标志并唤醒唤醒进程,这将轮询future ,从而看到有工作要完成.

  2. 如果调用poll方法,并且在注册新的唤醒程序之前唤醒唤醒程序,那么future 将看到有工作要做,并且唤醒程序可以被忽略.(这可能会导致不必要地唤醒旧的人,但这没什么.)

  3. 如果调用poll方法,并且在注册新的唤醒程序之后唤醒唤醒程序,则future 可能会看到也可能不会看到有工作要做.如果是,那么唤醒者可以被忽略,就像在#2中一样;如果不是,那么唤醒者将确保像在#1中一样再次轮询future .

在这三种情况下,当工作线程将future 标记为可以做更多工作并唤醒唤醒程序时,将轮询future ,直到它完成更多工作,即使这可能需要轮询不止一次.

Rust相关问答推荐

在‘await’点上使用‘std::同步::Mutex’是否总是会导致僵局?

基于对vec值的引用从该值中删除该值

go 掉包装 struct 中的泛型

Rust中的相互递归特性与默认实现

在Rust中,在实现特征`Display`时,如何获取调用方指定的格式?

如何正确地将App handler传递给Tauri中的其他模块?

如何用Axum/Tower压缩Html内容?

程序在频道RX上挂起

将Vec<;U8&>转换为Vec<;{Float}&>

是否提供Bundle 在可执行文件中的warp中的静态文件?

为什么我需要 to_string 函数的参考?

如何迭代存储在 struct 中的字符串向量而不移动它们?

OpenGL 如何同时渲染无纹理的四边形和有纹理的四边形

仅当函数写为闭包时才会出现生命周期错误

仅在运行测试时生成调试输出

`use std::error::Error` 声明中断编译

我如何将特征作为 struct 的拥有字段?

有没有办法阻止 rust-analyzer 使非活动代码变暗?

为什么-x试图解析为文字并在声明性宏中失败?

为什么 u64::trailing_zeros() 在无分支工作时生成分支程序集?