Verified Commit b2a960b4 authored by Andrei Pavel's avatar Andrei Pavel 🐧
Browse files

[#237] add scoped_lock

parent 6233400b
......@@ -26,6 +26,7 @@ libkea_util_la_SOURCES += pointer_util.h
libkea_util_la_SOURCES += range_utilities.h
libkea_util_la_SOURCES += readwrite_mutex.h
libkea_util_la_SOURCES += reconnect_ctl.h reconnect_ctl.cc
libkea_util_la_SOURCES += scoped_lock.h
libkea_util_la_SOURCES += staged_value.h
libkea_util_la_SOURCES += state_model.cc state_model.h
libkea_util_la_SOURCES += stopwatch.cc stopwatch.h
......@@ -76,6 +77,7 @@ libkea_util_include_HEADERS = \
range_utilities.h \
readwrite_mutex.h \
reconnect_ctl.h \
scoped_lock.h \
staged_value.h \
state_model.h \
stopwatch.h \
......
// Copyright (C) 2022 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#ifndef ISC_SCOPED_LOCK_H
#define ISC_SCOPED_LOCK_H 1
#include <vector>
namespace isc {
namespace util {
/// @brief A toned down version of C++17's std::scoped_lock. Can hold multiple mutexes.
///
/// @tparam mutex_t the mutex type
template <typename mutex_t>
struct scoped_lock {
/// @brief Lock the mutex. Keep track of it so that it can be unlocked later.
///
/// @param mutex the mutex being locked
void lock(mutex_t& mutex) {
mutex.lock();
mutexes_.push_back(&mutex);
}
/// @brief Unlock the mutex.
~scoped_lock() {
for (mutex_t* m : mutexes_) {
m->unlock();
}
}
private:
/// @brief the container that keeps locked mutexes for the whole lifetime of the scoped_lock
std::vector<mutex_t*> mutexes_;
};
} // namespace util
} // namespace isc
#endif // ISC_SCOPED_LOCK_H
......@@ -45,6 +45,7 @@ run_unittests_SOURCES += memory_segment_common_unittest.cc
run_unittests_SOURCES += multi_threading_mgr_unittest.cc
run_unittests_SOURCES += optional_unittest.cc
run_unittests_SOURCES += pid_file_unittest.cc
run_unittests_SOURCES += scoped_lock_unittest.cc
run_unittests_SOURCES += staged_value_unittest.cc
run_unittests_SOURCES += state_model_unittest.cc
run_unittests_SOURCES += strutil_unittest.cc
......
// Copyright (C) 2022 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h>
#include <util/scoped_lock.h>
#include <mutex>
#include <gtest/gtest.h>
namespace {
// Check that scoped_lock can take multiple mutexes and that locking and unlocking works properly.
TEST(ScopedLockTest, lock_unlock) {
std::mutex m;
std::mutex m2;
// Lockable.
EXPECT_TRUE(m.try_lock());
m.unlock();
EXPECT_TRUE(m2.try_lock());
m2.unlock();
{
isc::util::scoped_lock<std::mutex> lock;
lock.lock(m);
// Only m2 should be lockable.
EXPECT_FALSE(m.try_lock());
EXPECT_TRUE(m2.try_lock());
m2.unlock();
// Try to trick it with a scoped add() that should have no effect.
{
lock.lock(m2);
}
// Not lockable.
EXPECT_FALSE(m.try_lock());
EXPECT_FALSE(m2.try_lock());
}
// Lockable.
EXPECT_TRUE(m.try_lock());
m.unlock();
EXPECT_TRUE(m2.try_lock());
m2.unlock();
}
} // namespace
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment