C ++中是否有可等待的队列?

Is there a awaitable queue in c++?

我在我的代码库中大量使用 ppltasks.h 中的 concurrency::task

我想找到一个可等待的队列,我可以在其中执行“co_await my_queue.pop()”。有人实施过吗?

详情: 我有一个将元素推送到队列的生产者线程,另一个接收者线程将在元素到达队列时等待并唤醒。此接收线程可能 wait/wake 同时处理其他任务(使用 pplpp::when_any)。

我不想要一个带有接口的队列,在该接口中我必须轮询 try_pop 方法,因为它很慢,而且我不想要 blocking_pop 方法,因为这意味着我可以'同时处理其他准备好的任务。

这基本上是您的 standard thread-safe queue implementation,但您必须使用 future 来协调不同的线程,而不是 condition_variable。然后,您可以 co_awaitpop 编辑的未来 return 上做好准备。

队列的实现将需要保留与未完成的 pop 调用相对应的承诺列表。如果 poping 时队列仍然满,您可以 return 立即准备好未来。您可以使用普通的旧 std::mutex 来同步对底层数据结构的并发访问。

我不知道有任何实现已经做到了这一点,但应该不会太难实现。请注意,虽然管理所有期货会引入一些额外的开销,因此您的队列可能会比经典的基于 condition_variable 的方法效率稍低。

发表了评论,但我还是把它写成答案,因为它很长,我需要格式化。

基本上你有两个选择:

无锁队列,最流行的是这个:

https://github.com/cameron314/concurrentqueue

他们确实有 try_pop,因为它使用原子指针和任何原子方法(例如 std::atomic_compare_exchange_weak)有时会 "fail" 和 return false,所以您被迫对它们进行自旋锁定。

您可能会在 "pop" 中找到将其抽象化的队列,它只调用 "try_pop" 直到它工作,但这在后台是相同的开销。

基于锁的队列:

这些你自己做起来更容易,没有第三方库,只需将你需要的每个方法包装在锁中,如果你想 'peek' 经常查看使用 shared_locks,否则只需 std::lock_guard 就足以保护所有包装器。然而,这就是您所说的 'blocking' 队列,因为在访问期间,无论是读取还是写入,整个队列都将被锁定。

这两个实现没有线程安全的替代方案。如果您在大量使用下需要一个非常大的队列(例如,数百 GB 内存的对象),您可以考虑编写一些自定义混合数据结构,但对于大多数用例,moodycamel 的队列将绰绰有余。