Suppose we have a class with a std::mutex:
class Foo
{
std::mutex mutex_;
std::string str_;
// other members etc
public:
You can use std::lock() to acquire the locks in a non-deadlocking way.
If you want to use std::lock_guard, have them adopt the locks once taken:
std::lock(lhs.mutex_, rhs.mutex_);
std::lock_guard lock_a(lhs.mutex_, std::adopt_lock);
std::lock_guard lock_b(rhs.mutex_, std::adopt_lock);
//swap actions
swap(ls.str_, rhs.str_);
If you prefer std::unique_lock, then construct them without locking, then call std::lock() to lock them both (this also works with std::lock_guard):
std::unique_lock lock_a(lhs.mutex_, std::defer_lock);
std::unique_lock lock_b(rhs.mutex_, std::defer_lock);
std::lock(lock_a, lock_b);
//swap actions
swap(ls.str_, rhs.str_);
In both cases, you should first test for lhs and rhs being the same object, because using std::lock with one mutex twice is undefined behavior:
if (&lhs == &rhs)
return;