Skip to content

Commit 7792563

Browse files
committed
mt_queue: added underLock function
1 parent 6d559dc commit 7792563

File tree

2 files changed

+45
-3
lines changed

2 files changed

+45
-3
lines changed

include/mt_queue/include/ut/mt_queue/mt_queue.hpp

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#ifndef UT_MT_QUEUE_HPP
22
#define UT_MT_QUEUE_HPP
33

4+
#include <type_traits>
45
#if __cplusplus < 202'002L
56
# error this file has to be compiled with at least C++20
67
#endif
@@ -174,18 +175,40 @@ class MtQueue {
174175
std::lock_guard<std::mutex> g {m_mu};
175176
return m_q.empty();
176177
}
178+
179+
/**
180+
* Access internal queue under a mutex lock.
181+
*
182+
* Allows performing multiple operations on a queue atomically
183+
*/
184+
template<typename Fn>
185+
auto underLock(Fn &&fn) {
186+
std::lock_guard<std::mutex> g {m_mu};
187+
return fn(m_q);
188+
}
189+
190+
/**
191+
* Access internal queue under a mutex lock.
192+
*
193+
* Allows performing multiple operations on a queue atomically
194+
*/
195+
template<typename Fn>
196+
auto underLock(Fn &&fn) const {
197+
std::lock_guard<std::mutex> g {m_mu};
198+
return fn(m_q);
199+
}
177200
private:
178201
mutable std::mutex m_mu;
179202
mutable std::condition_variable m_cv;
180203
Q m_q;
181204
static constexpr bool has_top = requires {
182-
{ m_q.top() } -> std::same_as<T const &>;
205+
{m_q.top()}->std::same_as<T const &>;
183206
};
184207
static constexpr bool has_front = requires {
185-
{ m_q.front() } -> std::same_as<T const &>;
208+
{m_q.front()}->std::same_as<T const &>;
186209
}
187210
|| requires {
188-
{ m_q.front() } -> std::same_as<T &>;
211+
{m_q.front()}->std::same_as<T &>;
189212
};
190213
static constexpr bool has_push = requires(T t) {
191214
m_q.push(t);

tests/mt_queue.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
// NOLINTBEGIN(readability-magic-numbers,google-build-using-namespace)
22
#include <ut/mt_queue/mt_queue.hpp>
3+
#include <ut/overload/overload.hpp>
34

45
#include <barrier>
56
#include <chrono>
67
#include <numeric>
78
#include <thread>
9+
#include <utility>
810
namespace chr = std::chrono;
911
using namespace std::chrono_literals;
1012

@@ -69,6 +71,23 @@ TEMPLATE_TEST_CASE("Single threaded", "[mt_queue]", std::queue<int>, std::deque<
6971
REQUIRE(p.has_value());
7072
REQUIRE(*p == 7);
7173
}
74+
75+
SECTION("underLock") {
76+
q.underLock([](auto &inner) {
77+
ut::Overload {
78+
[&](std::queue<int> &inner_q) { inner_q.push(10); },
79+
[&](std::deque<int> &inner_q) { inner_q.push_back(10); },
80+
[&](std::priority_queue<int> &inner_q) { inner_q.push(10); },
81+
}(inner);
82+
auto back = ut::Overload {
83+
[&](std::queue<int> &inner_q) { return inner_q.back(); },
84+
[&](std::deque<int> &inner_q) { return inner_q.back(); },
85+
[&](std::priority_queue<int> &inner_q) { return inner_q.top(); },
86+
}(inner);
87+
REQUIRE(back == 10);
88+
});
89+
std::as_const(q).underLock([](auto &inner) { REQUIRE(!inner.empty()); });
90+
}
7291
}
7392

7493
TEMPLATE_TEST_CASE("Multi-threaded", "[mt_queue]", std::queue<int>, std::deque<int>, std::priority_queue<int>) {

0 commit comments

Comments
 (0)