Is it possible to safely move unique_ptr with c++11 atomic operations?
Currently I have a code like this
std::unique_ptr<SyncToken> DataManager::borrowSyncToken()
{
std::unique_lock<std::mutex> syncTokenLock(syncTokenMutex);
return std::move(syncToken);
}
I am wondering whether there is some more elegant way, like simply declaring:
std::atomic<std::unique_ptr<SyncToken>> syncToken;
and avoiding the need of mutex. Or possibly I don’t need to care about the lock here at all and std::move is already atomic?
After research I made so far it seems to me:
- the std::move itself is not atomic and needs to have some synchronization around otherwise 2 threads calling my method concurrently may end up with 2 copies of some undefined pointers.
- the std::atomic declaration compiles for me, but I don’t know how to initialize it and and make the move.
No, this is not possible.
The value
Twhich you pass tostd::atomicneeds to be trivially copyable, whichstd::unique_ptris not. Operations likestd::atomic::loadorstd::atomic::storetake T objects by value.Packing something in a
std::atomicalso doesn’t make operations from the value atomic.When using
std::unique_ptrin an atomic context, you have to think about the fact that you might have problems when it comes to managing resources. You never know how many threads still refer to your data, this problem can be solved with astd::shared_ptrwhich uses atomic reference counting. (You need to check whether it’s really atomic by using thestd::atomic_is_lock_freefunction. )One thing I was also stumbling upon when looking in your code is the intent of the
borrowSyncTokenfunction. It’s called borrow but you pass ownership of the token to the caller by moving out thestd::unique_ptr, how is the ownership passed back and what do other threads get when the DataManager currently doesn’t own the token?