在 C++ 中将(预定义的)原子值添加到向量

Posted

技术标签:

【中文标题】在 C++ 中将(预定义的)原子值添加到向量【英文标题】:Add (predefined) atomic values to vector in C++ 【发布时间】:2020-01-25 22:03:43 【问题描述】:

我在 C++ 中使用多线程时遇到了一个问题。

我有一个类(称为 class_a_example),它在带有公共和受保护访问修饰符的头文件中定义。 class_a_example 取决于几个变量/结构。

在'protected'中我定义了 m_accessed 成员 - 向量由原子组成,当创建类的元素时,它还依赖于 m_accessed,这需要在 m_accessed 中有预定义的值。就像这样:

// class_a_example_header.h

class class_a_example 
protected:
    std::vector<std::atomic<uint32_t>> m_accessed;
    std::vector<uint32_t> m_vars;
    std::mutex m_mtx;
    // some other structures

public:
    // some methods
    inline class_a_example(/*params*/, size_t c_count, /*params*/) : m_vars(c_count, 0), m_accessed(c_count, std::atomic<uint32_t>(0))
    
        /* some actions */
    
;

class_a_example_header.cpp 的一种方法中 class_a_example 我需要与 m_accessed 交互(需要更改原子值):

// class_a_example_header.cpp

int32_t class_a_example::change_values(uint32_t thread_index)

    /* some actions */
    m_accessed[thread_index]++;
    /* some actions */

但是当我编译我的程序时,我收到了一个错误(特别是在 m_accessed(c_count, std::atomic(0))):

inline class_a_example(/*params*/, size_t c_count, /*params*/) : m_vars(c_count, 0), m_accessed(c_count, std::atomic<uint32_t>(0))

错误是:

class_a_example.cpp:114:57:   required from here
/opt/rh/devtoolset-8/root/usr/include/c++/8/ext/new_allocator.h:136:4: error: use of deleted function ‘std::atomic<unsigned int>::atomic(const std::atomic<unsigned int>&)’
   ::new((void *)__p) _Up(std::forward<_Args>(__args)...); 

之后我重写了 class_a_example.hclass_a_example.cpp

// class_a_example_header.h

class class_a_example 
protected:
    std::vector<std::atomic<uint32_t>> m_accessed;
    // ...

public:
    inline class_a_example(/*params*/, size_t c_count, /*params*/) : m_vars(c_count, 0), m_accessed()
    
        // ...
    
    // ...
;



// class_a_example_header.cpp

int32_t class_a_example::change_values(uint32_t thread_index)

    /* some actions */
    if (m_accessed.size() < m_vars.size())
        m_accessed.emplace_back(std::atomic<uint32_t>(0));

    m_accessed[thread_index]++;
    /* some actions */

但一般的错误是一样的,只是从这里开始:m_accessed.emplace_back(std::atomic&lt;uint32_t&gt;(0));

有什么方法(最好是简单的)来创建预定义的原子向量或为其添加值?

【问题讨论】:

m_accessed 变量似乎存在初始化问题。请查看:***.com/questions/29332897/… @Pankaj 谢谢,我试试这个变种 您的问题缺少minimal reproducible example。作为这里的新用户,也可以使用tour 并阅读How to Ask。也就是说,将互斥锁与原子混合可能是一个坏主意。你有什么具体原因吗? @UlrichEckhardt 我需要使用不在互斥锁下的原子,它们就像标志,报告何时需要打开互斥锁 【参考方案1】:

std::atomic 没有复制构造函数。

使用

m_accessed.emplace_back();
m_accessed.back().store(0);

代替

m_accessed.emplace_back(std::atomic<uint32_t>(0));

【讨论】:

我试过你的变种,但不幸的是它和我得到的错误一样 虽然解释是正确的,但您的代码犯了这个错误。现在由您来提取和创建minimal reproducible example,以便我们为这次讨论找到一个共同的基础。 @UlrichEckhardt 我已经尝试过这段代码,但它并没有解决错误。我自己找到了解决方案,如果您有兴趣 - 您可以在下面查看***.com/a/59946282/12782346【参考方案2】:

我找到了一个解决方案,可以用我想要使用的值来定义原子向量。问题解决了

// class_a_example_header.h

class class_a_example 
protected:
    std::vector<std::atomic<uint32_t>> m_accessed;
    // some other structures

public:
    // some methods
    inline class_a_example(/*params*/, size_t c_count, /*params*/) : m_vars(c_count, 0), m_accessed(c_count)
    
        for (auto it = m_accessed.begin(); it != m_accessed.end(); it++)
            std::atomic_init(&*it, 0u) //instead of 0u specify value you want to be in atomic
    
;

在此操作之后,原子向量将成功创建并使用您想要的值进行定义。

【讨论】:

以上是关于在 C++ 中将(预定义的)原子值添加到向量的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C++ 中将一个对象从一个向量复制到另一个向量?

在 C++ 中将类实例添加到对象层次结构时出现问题

C++ - 在自定义数据类型向量中按值匹配和替换元素

如何在 C++ 中将两个向量复制到另一个向量

在 C++ 中将派生类类型的向量链接到父类类型的向量

在 C++ 中将数据值添加到数组的末尾