Lock-free swap of two unique_ptr<T>
atomic-swap, c++, c++11, lock-free, unique-ptr
Solution
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<T*> 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
- Remember current `global` pointer in `temp`
- 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<T*> 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`.
Problem
Swapping two `unique_ptr`s is not guaranteed to be threadsafe. ``` std::unique_ptr<T> a, b; std::swap(a, b); // not threadsafe ``` Since I need atomic pointer swaps and since I like the ownership handling of `unique_ptr`, is there a simple way to combine them both? Edit: If this is not possible, I am open for alternatives. I at least want to do something like this: ``` threadshared_unique_ptr<T> global; void f() { threadlocal_unique_ptr<T> local(new T(...)); local.swap_content(global); // atomically for global } ``` What is the idiomatic way of doing this in C++11?