Search code examples
c++multithreadingc++11atomic

C++11: does atomic::compare_exchange_weak support none-primitive types?


I've got the following code:

#include<atomic>
#include<iostream>
using namespace std;

struct Big{
    int i;
    int j;
    int k[100];
};
int main(){
    atomic<int> i;
    cout<<i.load()<<endl;
    i.store(20);
    cout<<i.load()<<endl;
    i.exchange(30);
    cout<<i.load()<<endl;

    atomic<Big> ab,expect,value;
    ab.compare_exchange_weak(expect,value,memory_order_release,memory_order_relaxed);//error
    return 0;
}

Well, atomic works well, but I wish to see if none-lock function of compare_exchange_weak could work for complex data structures. Compiled with --std=c++11 it gives me:

error: no matching member function for call to 'compare_exchange_weak'
    ab.compare_exchange_weak(expect,value,memory_order_release,memory_order_relaxed);
    ~~~^~~~~~~~~~~~~~~~~~~~~
candidate function not viable: no known conversion from 'atomic<Big>' to 'Big &' for 1st argument
    bool compare_exchange_weak(_Tp& __e, _Tp __d,

So my question:

  1. Does std::atomic::compare_exchange_weak work with complex structures?

  2. If intel cpu hardware CMPEXG only works within 64 bit length cache line, does structures larger than 8 bytes work with CMPEXG? Is it still atomic operation?

  3. How to fix my program?

Thanks.


Solution

  • Does std::atomic::compare_exchange_weak work with complex structures?

    Yes, but there are conditions that include trivially copyable and trivially constructible.

    If intel cpu hardware CMPEXG only works within 64 bit length cache line, does structures larger than 8 bytes work with CMPEXG?

    No. It doesn't work that way. If you create crazily big structures like the one you have there, your code will not be "lockfree". Your compiler will issue bus-locks to ensure thread-safety, which is why you should never, ever do what you're doing up there with big data strucutres. You'll slow down your program by hundreds of times, if not more. Consider atomically exchanging pointers.

    Is it still atomic operation?

    No, it uses locks. You can test this with std::atomic::is_lock_free()

    How to fix my program?

    There you go:

    #include <atomic>
    #include <iostream>
    
    using namespace std;
    
    struct Big {
      int i;
      int j;
      int k[100];
    };
    
    int main() {
      Big value, expect;
      atomic<Big> ab;
      ab.compare_exchange_weak(expect, value);
      return 0;
    }