这个问题的目的是为了了解Rust中Futures应该如何工作。我没有一个具体不起作用的代码片段,而是对于如何编写Futures以满足其约定存在问题。
假设你正在编写一个Future。poll()的约定允许调用者每次传入一个不同的Waker,而Future只会调用最新的那个。
假设这个Future隐藏了后台由工作线程完成的实际工作。如果工作线程在创建Future时所传递的工作尚未完成,那么Future应该返回Pending并且克隆和存储Waker。然后,Future在一段时间内什么都不做,并且是工作线程调用Waker。这将导致再次对Future进行轮询。
假设当Future再次被轮询时,它判断工作线程到目前为止所做的还不够,所以它再次返回Pending,并且在这第二次调用中也克隆和存储新的Waker。
由于实际调用唤醒器的是工作线程,因此poll()实现必须在后台线程中更新唤醒器。然而,我不清楚poll()实现如何以无竞争的方式进行更新——但现在问题变得棘手了,因为细节取决于poll()合同中的细节,我认为这些细节甚至没有被准确地指定。
可能发生的一件事是,在poll()运行时,就在它想要将新的唤醒器交给后台工作者之前,工作者决定该调用唤醒器。现在它调用旧的唤醒器,即使poll()已经收到了新的唤醒器,这可能违反合同(我认为这并没有指定)。因此,人们可能认为,在poll()完成之前,工作者可以调用旧的唤醒器,但这仅在工作者允许在poll()运行时调用任一唤醒器时才有效,这也没有提到,并且只需要在poll()返回后调用新的唤醒器。
最后,即使这个假设依赖于另一个未指定的事情:在多线程上下文中,“在 poll() 返回之后”的确切含义,通常必须诉诸于特别定义的术语,例如 happens-after,以定义一个事件发生在另一个事件之后。
考虑到所有这些,poll() 实现如何履行其仅调用最新的 Waker 的契约?是否有一份文件详细说明了似乎缺失于 poll() 文档中的所有细节?
poll
函数中,将互斥锁作为第一操作进行锁定。 - PitaJ