diff --git a/base_cpp/include/embb/base/internal/mutex-inl.h b/base_cpp/include/embb/base/internal/mutex-inl.h index 0d9b336..86f66ac 100644 --- a/base_cpp/include/embb/base/internal/mutex-inl.h +++ b/base_cpp/include/embb/base/internal/mutex-inl.h @@ -28,6 +28,7 @@ #define EMBB_BASE_INTERNAL_MUTEX_INL_H_ #include +#include namespace embb { namespace base { @@ -95,8 +96,8 @@ void UniqueLock::Unlock() { template void UniqueLock::Swap(UniqueLock& other) { - locked_ = other.locked_; - mutex_ = other.Release(); + std::swap(mutex_, other.mutex_); + std::swap(locked_, other.locked_); } template diff --git a/base_cpp/include/embb/base/mutex.h b/base_cpp/include/embb/base/mutex.h index 0b8c7e3..5844ac3 100644 --- a/base_cpp/include/embb/base/mutex.h +++ b/base_cpp/include/embb/base/mutex.h @@ -439,11 +439,11 @@ class UniqueLock { void Unlock(); /** - * Transfers ownership of a mutex to this lock. + * Exchanges ownership of the wrapped mutexes with another lock. */ void Swap( UniqueLock& other - /**< [IN/OUT] Lock from which ownership shall be transferred */ + /**< [IN/OUT] The lock to exchange ownership with */ ); /** diff --git a/base_cpp/test/mutex_test.cc b/base_cpp/test/mutex_test.cc index 17e5c9e..7364670 100644 --- a/base_cpp/test/mutex_test.cc +++ b/base_cpp/test/mutex_test.cc @@ -191,13 +191,29 @@ void MutexTest::TestUniqueLock() { } { // Test lock swapping - UniqueLock<> lock1; - UniqueLock<> lock2(mutex_); - PT_EXPECT_EQ(lock1.OwnsLock(), false); - PT_EXPECT_EQ(lock2.OwnsLock(), true); - lock1.Swap(lock2); + // Create a second mutex to swap with + Mutex another_mutex; + UniqueLock<> lock1(another_mutex); PT_EXPECT_EQ(lock1.OwnsLock(), true); - PT_EXPECT_EQ(lock2.OwnsLock(), false); + + { + UniqueLock<> lock2(mutex_); + PT_EXPECT_EQ(lock2.OwnsLock(), true); + + lock1.Swap(lock2); + PT_EXPECT_EQ(lock1.OwnsLock(), true); + PT_EXPECT_EQ(lock2.OwnsLock(), true); + } + + // At this point, lock2 was destroyed and "another_mutex" must be unlocked + UniqueLock<> lock3(another_mutex, embb::base::try_lock); + PT_EXPECT_EQ(lock3.OwnsLock(), true); + + // But lock1 must still be locking "mutex_" + PT_EXPECT_EQ(lock1.OwnsLock(), true); + + lock1.Release()->Unlock(); + PT_EXPECT_EQ(lock1.OwnsLock(), false); } }