Lock-free swap of two unique_ptr

后端 未结 3 1014
梦毁少年i
梦毁少年i 2021-01-30 16:20

Swapping two unique_ptrs is not guaranteed to be threadsafe.

std::unique_ptr a, b;
std::swap(a, b); // not threadsafe

Sin

3条回答
  •  隐瞒了意图╮
    2021-01-30 17:06

    Lock-free swapping of two pointers

    It seems there is no general lock-free solution for this problem. To do this, you need a possibility to atomically write new values into two non-continous memory locations. This is called DCAS, but it is not available in Intel processors.

    Lock-free transfer of ownership

    This one is possible, as it is only needed to atomically save new value into global and receive its old value. My first idea was to use CAS operation. Take a look at the following code to get an idea:

    std::atomic global;
    
    void f() {
       T* local = new T;
       T* temp = nullptr;
       do {
           temp = global;                                                   // 1
       } while(!std::atomic_compare_exchange_weak(&global, &temp, local));  // 2
    
       delete temp;
    }
    

    Steps

    1. Remember current global pointer in temp
    2. Save local to global if global is still equal to temp (it wasn't changed by other thread). Try again if this is not true.

    Actually, CAS is overkill there, as we do not do anything special with old global value before it is changed. So, we just can use atomic exchange operation:

    std::atomic global;
    
    void f() {
       T* local = new T;
       T* temp = std::atomic_exchange(&global, local);
       delete temp;
    }
    

    See Jonathan's answer for even more short and elegant solution.

    Anyway, you will have to write your own smart pointer. You can't use this trick with standard unique_ptr.

提交回复
热议问题