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 intemp
- Save
local
toglobal
ifglobal
is still equal totemp
(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
.