2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-30 13:37:55 +00:00

[#2448] add MultiThreadingLock

This commit is contained in:
Andrei Pavel
2022-06-28 17:46:00 +03:00
parent c7c136b4bf
commit 7c73b87afe
3 changed files with 56 additions and 1 deletions

View File

@@ -227,6 +227,12 @@ MultiThreadingCriticalSection::~MultiThreadingCriticalSection() {
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,

View File

@@ -108,7 +108,8 @@ private:
///
/// 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
@@ -325,6 +326,20 @@ private:
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.

View File

@@ -324,6 +324,40 @@ TEST(MultiThreadingMgrTest, criticalSection) {
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: