【发布时间】:2017-07-29 01:20:58
【问题描述】:
考虑一个无锁并发数据结构的情况,其中pop() 操作需要返回一个项目或false 如果硬币容器为空(而不是阻塞或抛出)。数据结构以用户类型T 为模板,它可能很大(但也可能是轻量级的,我希望在任何一种情况下都高效)。 T 至少必须是可移动的,但我不希望它必须是可复制的。
我在想函数签名将是bool DS<T>::pop(T &item),因此该项目被提取为输出参数而不是返回值(它用于指示成功或失败)。但是,我如何真正将其传递出去?假设有一个底层缓冲区。我会做item = std::move(_buff[_tail]) - 进入参考输出参数是否有意义?缺点是用户必须传入一个默认构造的 T,这有点违背有效的 RAII,因为如果函数失败,结果是一个实际上没有初始化其资源的对象。
另一种选择是返回std::pair<bool, T>,而不是使用输出参数,但对于return std::make_pair(false, T),再次需要一个默认构造的T,它在失败的情况下不保存任何资源。
第三种选择是将项目返回为std::unique_ptr<T>,但在T 是指针或其他轻量级类型的情况下,这会产生无用的开销。虽然我可以只将指针存储在数据结构中,而实际项目存储在外部,但这不仅会导致额外的取消引用和缓存未命中,而且还会删除直接存储在缓冲区中的项目添加的自然填充,并有助于最大限度地减少生产者和消费者线程访问相同的缓存行。
【问题讨论】:
-
这就是
boost::optional和很快std::optional的用途。 -
您可以使用
std::aligned_storage返回一个可能包含或不包含对象的存储。std::optional基本上就是这样
标签: c++ c++11 move-semantics rvalue-reference