MultiThreadingMgr::instance().exitCriticalSection();
}
+MultiThreadingLock::MultiThreadingLock(std::mutex& mutex) {
+ if (MultiThreadingMgr::instance().getMode()) {
+ lock_ = std::unique_lock<std::mutex>(mutex);
+ }
+}
+
void
CSCallbackSetList::addCallbackSet(const std::string& name,
const CSCallbackSet::Callback& check_cb,
///
/// This singleton class holds the multi-threading mode.
///
-/// The standard way to use it is:
+/// See the @ref MultiThreadingLock class for a standard way of protecting code
+/// with a mutex. Or if you want to make it look like you're writing more code:
/// @code
/// if (MultiThreadingMgr::instance().getMode()) {
/// multi-threaded code
CSCallbackSetList cs_callbacks_;
};
+/// @brief RAII lock object to protect the code in the same scope with a mutex
+struct MultiThreadingLock {
+ /// @brief Constructor locks the mutex if multi-threading is enabled.
+ ///
+ /// The lock is automatically unlocked in the default destructor.
+ ///
+ /// @param mutex the mutex to be locked
+ MultiThreadingLock(std::mutex& mutex);
+
+private:
+ /// @brief object keeping the mutex locked for its entire lifetime
+ std::unique_lock<std::mutex> lock_;
+};
+
/// @note: everything here MUST be used ONLY from the main thread.
/// When called from a thread of the pool it can deadlock.
MultiThreadingMgr::instance().apply(false, 0, 0);
}
+/// @brief Checks that the lock works only when multi-threading is enabled and
+/// only during its lifetime.
+TEST(MultiThreadingLockTest, scope) {
+ // Check that the mutex is unlocked by default at first.
+ std::mutex mutex;
+ ASSERT_TRUE(mutex.try_lock());
+ mutex.unlock();
+
+ EXPECT_NO_THROW(MultiThreadingMgr::instance().setMode(false));
+
+ // Check that the lock does not locks the mutex if multi-threading is disabled.
+ {
+ MultiThreadingLock lock(mutex);
+ ASSERT_TRUE(mutex.try_lock());
+ mutex.unlock();
+ }
+
+ // Check that the mutex is still unlocked when the lock goes out of scope.
+ ASSERT_TRUE(mutex.try_lock());
+ mutex.unlock();
+
+ EXPECT_NO_THROW(MultiThreadingMgr::instance().setMode(true));
+
+ // Check that the lock actively locks the mutex if multi-threading is enabled.
+ {
+ MultiThreadingLock lock(mutex);
+ ASSERT_FALSE(mutex.try_lock());
+ }
+
+ // Check that the mutex is unlocked when the lock goes out of scope.
+ ASSERT_TRUE(mutex.try_lock());
+ mutex.unlock();
+}
+
/// @brief Test fixture for exercised CriticalSection callbacks.
class CriticalSectionCallbackTest : public ::testing::Test {
public: