0

I've faced a problem while working with multithreading in C++.

I have a class (call it class_a_example) which is defined in header file with public & protected access modifiers. class_a_example depends on several variables/structures.

In 'protected' I've defined m_accessed member - vector consists of atomics, and when an element of class is created, it also depends on m_accessed, which needs to have predefined values in m_accessed. Just like this:

// 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 */
    }
};

In class_a_example_header.cpp in one method of class_a_example I need to interact with m_accessed (need to change atomic values):

// class_a_example_header.cpp

int32_t class_a_example::change_values(uint32_t thread_index)
{
    /* some actions */
    m_accessed[thread_index]++;
    /* some actions */
}

But when I compile my program, I get an error required from (particularly in 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))

Error is:

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)...); }

After that I've rewritten class_a_example.h and class_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 */
}

But error in general is the same, only it starts from here: m_accessed.emplace_back(std::atomic<uint32_t>(0));

Is there any way (preferably simple) to create predefined atomic vector or add values to it?

kerzhy
  • 9
  • 3
  • 1
    it seems there is initialization problem with m_accessed variable. please check: https://stackoverflow.com/questions/29332897/error-c2280-attempting-to-reference-a-deleted-function-atomicint – Pankaj Jan 25 '20 at 22:31
  • @Pankaj thank you, I'll try this variant – kerzhy Jan 27 '20 at 09:36
  • Your question lacks a [mcve]. As a new user here, also take the [tour] and read [ask]. That said, mixing a mutex with atomics is probably a bad idea. Do you have a specific reason for that? – Ulrich Eckhardt Jan 27 '20 at 11:20
  • @UlrichEckhardt I need to use atomics not under mutex, they are like flags, which report when mutex needs to be turn on – kerzhy Jan 28 '20 at 09:49

2 Answers2

1

std::atomic hasn't copy constructor.

Use

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

Instead of

m_accessed.emplace_back(std::atomic<uint32_t>(0));
kusstas
  • 111
  • 3
  • I've tried your variant, but unfortunately it gets the same mistake as I got – kerzhy Jan 27 '20 at 09:27
  • The explanation is right though and your code makes that mistake. It's up to you to extract and create a [mcve] now, so that we get a common base for this discussion. – Ulrich Eckhardt Jan 28 '20 at 09:58
  • @UlrichEckhardt I've tried this code and it doesn't solve the mistake. I have found the solution myself, if you interested - you can check it below https://stackoverflow.com/a/59946282/12782346 – kerzhy Jan 28 '20 at 10:10
0

I've found a SOLUTION to define atomic vector with values I want to use. It has solved the problem

// 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
    }
};

After this actions atomic vector will be created successfully & defined with values you want.

kerzhy
  • 9
  • 3