Want an efficient way to swap two pointers in C++

后端 未结 1 477
旧巷少年郎
旧巷少年郎 2021-01-21 09:28

I have two pointers which point to a big graph object in a multi-threading C++ app. I try to swap them every 5 minutes. Which way is safe and has the best performance? Is C++11

相关标签:
1条回答
  • 2021-01-21 10:09

    Does the swap need to be atomic? i.e. do you need to guarantee that another thread cannot observe them both having the same value while swapping?

    If you don't need to guarantee the swap is atomic then just use two std::atomic<T*> objects and swap them using a temporary:

    T* tmp = p1;
    p1 = p2.load();
    p2 = tmp;
    

    If you need the swap to be atomic then to do it in standard C++ you will need to store them both in the same structure, so it can be updated in a single step e.g.

    struct TwoPointers { T* p1; T* p2; }
    std::atomic<TwoPointers> p;
    

    then you can swap them like so:

    auto old = p.load();
    p = { old.p2, old.p1 };
    

    This uses double-word atomic operations, which might be implemented with a mutex behind the scenes, so the simple assignment via a temporary is likely to perform better, but I doubt it will make any difference once every five minutes.

    Both versions above assume only one thread will try to swap them at any time, because although loading the old value is done atomically, and writing the new value is done atomically, there is a window between those two steps during which another thread could change the pointer values. If that's a problem use a std::atomic<TwoPointers> like this instead:

    auto old = p.load();
    while (!p.compare_exchange_strong(old, { old.p2, old.p1 }))
    { };
    

    Using compare_exchange_strong in a loop is slightly slower than a single atomic store, but again you won't notice the difference if it only happens once every five minutes.

    This TwoPointers solutions also mean the two pointers share a cache-line, but if they are read-only apart from the swap every five minutes then that's not a problem.

    0 讨论(0)
提交回复
热议问题