我在代码库中大量使用concurrency::task
中的ppltasks.h
。
我想找到一个等待的队列,我可以在那里“co_await my_queue.pop()
”。有人实施了吗?
详细说明: 我有一个生产者线程将元素推送到队列,另一个接收器线程将等待并在元素到达队列时唤醒。此接收线程可能会等待/唤醒以同时处理其他任务(使用pplpp :: when_any)。
我不想要一个带有接口的队列,我必须轮询try_pop方法,因为它很慢,而且我不想要一个blocking_pop方法,因为这意味着我不能在此期间处理其他准备好的任务。
答案 0 :(得分:5)
这基本上是您的standard thread-safe queue implementation,但不是condition_variable
,而是使用future
来协调不同的主题。然后,您可以co_await
pop
返回由pop
准备的未来。
队列的实现需要保留与未完成的pop
调用相对应的承诺列表。如果std::mutex
时队列仍然已满,您可以立即返回准备好的未来。您可以使用普通的旧condition_variable
来同步对底层数据结构的并发访问。
我不知道已经执行过的任何实现,但它不应该太难实现。请注意,管理所有期货会带来一些额外的开销,因此您的队列可能会比基于Map
的经典方法效率略低。
答案 1 :(得分:1)
发表评论但我不妨将其写为答案,因为我需要格式化。
基本上你有两个选择:
无锁队列,其中最受欢迎的是:
https://github.com/cameron314/concurrentqueue
他们确实有try_pop,因为它使用原子指针,任何原子方法(例如std :: atomic_compare_exchange_weak)都可以并且将会失败"并且有时返回false,因此您被迫对它们进行自旋锁定。
您可能会在" pop"中找到抽象的队列。只是打电话" try_pop"直到它起作用,但背景中的开销相同。
基于锁定的队列:
这些更容易自己做,没有第三部分库,只需要在锁中包装你需要的每一种方法,如果你想偷看'经常考虑使用shared_locks,否则只需要std :: lock_guard就足以保护所有包装器。然而,这就是你可以称之为“阻止”的东西。队列,因为在访问期间,天气是读取或写入,整个队列将被锁定。
这两种实现没有线程安全的替代方案。如果你需要一个非常大的队列(例如数百GB的内存对象),你可以考虑编写一些自定义的混合数据结构,但对于大多数用例来说,moodycamel的队列将是绰绰有余的