lundi 27 septembre 2021

vector of atomics in c++: msvc vs gcc

I developed some code on Linux which uses a std::vector of std::atomic variables - one for each thread that I use, which might be set to a different number for some different computation. In simple form it looked something like:

Edit: also including a reset function:

class threadsafe_vals{
    std::vector<std::atomic<int> > vals;
public:
    threadsafe_vals(int _n){
        vals = std::vector<std::atomic<int> >(_n);
        for (auto &x:vals){
            x=0;
        }
    }
    void reset(int _i){
        vals =std::vector<std::atomic<int> >(n);
        for (auto &x:vals){
            x=0;
        }
    }
    int get(int _i){ return vals[_i];}
    void set(int _i,in _val){ vals[_i] = _val;}
};

I know that std::atomics have no copy constructor so I made sure I never used anything like erase push_back etc. etc., but simply treated the vector as a fixed array until I reset the whole thing. And whenever I reset the vector I always did so using the line vals = std::vector<std::atomic<int> >(n) such that the use of the copy constructor was avoided, and instead the existing atomics destructed and then simply initialised (I think). The code was not required to be threadsafe during the reset(int n) operation.

Anyway, for both Linux using gcc and Mac using Clang, this all worked.

I then however, tried to port my code to Windows under MSVC, and it won't compile.

I now get the compiler error

std::atomic<int>::atomic(const std::atomic<int> &): attempting to reference a deleted function

in file xmemory().

It looks like it is complaining that it is having to use the copy-constructor for the atomics I am using.

Now: gcc and clang were both smart enough to figure out I didn't actually use the copy constructor and compiled my code, so I'm assuming that this is a Microsoft c++ implementation thing.

But then the questions remains:

  1. Why does MSVC think I'm invoking the copy constructor here?

  2. More crucially, how I can I get the desired effect whereby I can have a vector of atomics without invoking the copy constructor according to MSVC (or any other method), similar to my original code, in a portable way?

I've tried searching for some similar questions, but the answers seem all over the place with some stating that vectors of atomics simply aren't possible. But this is false, at least according to the gcc and clang interpretations of the c++ standard.

Aucun commentaire:

Enregistrer un commentaire