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:
@@ -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,
|
||||
|
@@ -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.
|
||||
|
||||
|
@@ -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:
|
||||
|
Reference in New Issue
Block a user