kilasuelika
kilasuelika

Reputation: 305

Can we use c++20's atomic_ref to concurrently accessing user type member function?

Consider this problem: I have an atomic_ref of a user type. I want to concurrently accessing its member functions. See code below:

struct A{
    int counter=0;
    
    int add(){
        ++counter;
        return counter;
    };
};

int main() { 
    A a;
    std::atomic_ref<A> ra{a};
    std::vector<std::thread> v;
    for(int i=0;i<1000;++i){
        v.emplace_back([&ra]{ra.load().add();});
    };
    for(auto & t: v){t.join();};
    std::cout<<a.counter<<std::endl;
 };

Final output is 0 because load() returns a copy. Is there any other way to reach the correct result by atomic_ref?

And I also want to ask that, if we have an atomic_ref<T*>, can we use load() to accessing member functions, e.g. ra.load()->add(). Is it safe? Code will become like this:

struct A{
    int counter=0;
    
    int add(){
        ++counter;
        return counter;
    };
};

int main() { 
    A* a=new A;
    std::atomic_ref<A*> ra{a};
    std::vector<std::thread> v;
    for(int i=0;i<1000;++i){
        v.emplace_back([&ra]{ra.load()->add();}); //Accessing member functions.
    };
    for(auto & t: v){t.join();};
    std::cout<<a->counter<<std::endl;
 };

In my test, it's indeed 1000 which is correct.

Upvotes: 0

Views: 361

Answers (1)

Nicol Bolas
Nicol Bolas

Reputation: 473212

Atomics are not magical. They only affect the loading and accessing of the reference itself, not of anything accessed though the reference.

Upvotes: 2

Related Questions