【问题标题】:Out-parameters and move semantics输出参数和移动语义
【发布时间】: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


【解决方案1】:
#include <boost/optional.hpp>
#include <string>

template<class T>
struct atomic_queue
{
    using value_type = T;

    auto pop() -> boost::optional<T>
    {
        boost::optional<T> result;

        /*
         * insert atomic ops here, optionally filling result
         */

        return result;
    };

    auto push(T&& arg) -> bool
    {

        /*
         * insert atomic ops here, optionally stealing arg
         */

        return true;
    };

    static auto make_empty_result() {
        return boost::optional<T>();
    }

};

struct difficult {
    difficult(std::string);
    difficult() = delete;
    difficult(difficult const&) = delete;
    difficult& operator=(difficult const&) = delete;
    difficult(difficult &&) = default;
    difficult& operator=(difficult &&) = default;
};

extern void spin();

int main()
{
    atomic_queue<difficult> q;

    auto d = difficult("arg");
    while(not q.push(std::move(d)))
        spin();

    auto popped = q.make_empty_result();
    while(not (popped = q.pop()))
        spin();

    auto& val = popped.get();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-18
    • 1970-01-01
    • 1970-01-01
    • 2015-10-13
    • 2016-02-04
    • 2020-08-20
    • 2012-01-01
    • 1970-01-01
    相关资源
    最近更新 更多