Skip to content

Commit f971d9f

Browse files
committed
ThreadPool: Fix check-then-act race condition
1 parent 8bab650 commit f971d9f

9 files changed

Lines changed: 26 additions & 26 deletions

File tree

modules/Chrono/Chronometer.mpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export namespace CppUtils::Chrono
3232
str += " " + std::to_string(microsec.count()) + "us";
3333
if (ns.count() > 0)
3434
str += " " + std::to_string(ns.count()) + "ns";
35-
return !str.empty() ? str.substr(1) : "0ns";
35+
return not std::empty(str) ? str.substr(1) : "0ns";
3636
}
3737

3838
template<Clock Clock = std::chrono::high_resolution_clock>

modules/Container/Sequence.mpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ export namespace CppUtils::Container::Sequence
1616
[[nodiscard]] inline auto getDifferences(std::span<const T> list0, std::span<const T> list1) -> std::vector<Difference>
1717
{
1818
auto differences = std::vector<Difference>{};
19-
differences.reserve(std::max(list0.size(), list1.size()));
19+
differences.reserve(std::max(std::size(list0), std::size(list1)));
2020
auto i = 0uz, j = 0uz, diffLength = 0uz;
21-
while (i < list0.size() and j < list1.size())
21+
while (i < std::size(list0) and j < std::size(list1))
2222
{
2323
const auto& lhs = list0[i];
2424
const auto& rhs = list1[j];
@@ -52,10 +52,10 @@ export namespace CppUtils::Container::Sequence
5252
++i;
5353
++j;
5454
}
55-
auto offsetList0 = list0.size() - i;
55+
auto offsetList0 = std::size(list0) - i;
5656
while (offsetList0--)
5757
differences.emplace_back(Difference::Removed);
58-
auto offsetList1 = list1.size() - j;
58+
auto offsetList1 = std::size(list1) - j;
5959
while (offsetList1--)
6060
differences.emplace_back(Difference::Added);
6161
return differences;

modules/Network/Client.mpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export namespace CppUtils::Network
2525

2626
inline auto connect(std::string_view ip, std::uint16_t port) const -> void
2727
{
28-
auto address = makeAddress(ip.empty() ? "127.0.0.1" : ip, port);
28+
auto address = makeAddress(std::empty(ip) ? "127.0.0.1" : ip, port);
2929
if (address.length == 0)
3030
throw std::runtime_error{"CppUtils::Network::Client::connect: Invalid address length"};
3131
#if defined(OS_WINDOWS)

modules/Network/Socket.mpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ export namespace CppUtils::Network
305305
ipv4->sin_family = AF_INET;
306306
ipv4->sin_port = Math::toBigEndian(port);
307307

308-
if (ip.empty())
308+
if (std::empty(ip))
309309
ipv4->sin_addr.s_addr = INADDR_ANY;
310310
else if (::inet_pton(AF_INET, std::data(ip), std::addressof(ipv4->sin_addr)) <= 0)
311311
throw std::invalid_argument{"CppUtils::Network::Socket::makeAddress: Invalid IPv4 address"};
@@ -318,7 +318,7 @@ export namespace CppUtils::Network
318318
ipv6->sin6_family = AF_INET6;
319319
ipv6->sin6_port = Math::toBigEndian(port);
320320

321-
if (ip.empty())
321+
if (std::empty(ip))
322322
ipv6->sin6_addr = in6addr_any;
323323
else if (::inet_pton(AF_INET6, std::data(ip), std::addressof(ipv6->sin6_addr)) <= 0)
324324
throw std::invalid_argument{"CppUtils::Network::Socket::makeAddress: Invalid IPv6 address"};

modules/String/Hash.mpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export namespace CppUtils::String
2929
inline constexpr Hasher(const CharT (&cString)[N]):
3030
hash{CppUtils::String::hash(cString)}
3131
{
32-
std::copy(cString, cString + N, name.begin());
32+
std::copy(cString, cString + N, std::begin(name));
3333
}
3434

3535
[[nodiscard]] inline constexpr operator Hash() const noexcept

modules/String/Utility.mpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,14 @@ export namespace CppUtils::String
7878
[[nodiscard]] inline auto concatenateStringsWithSeparator(const std::vector<std::string>& strings, std::string_view separator) -> std::string
7979
{
8080
return std::accumulate(std::cbegin(strings), std::cend(strings), std::string{}, [separator](const std::string& lhs, const std::string& rhs) {
81-
return lhs.empty() ? rhs : (lhs + std::data(separator) + rhs);
81+
return std::empty(lhs) ? rhs : (lhs + std::data(separator) + rhs);
8282
});
8383
}
8484

8585
[[nodiscard]] inline auto concatenateStringsWithSeparator(const std::vector<std::string_view>& strings, std::string_view separator) -> std::string
8686
{
8787
return std::accumulate(std::cbegin(strings), std::cend(strings), std::string{}, [separator](std::string_view lhs, std::string_view rhs) {
88-
return lhs.empty() ? std::string{rhs} : (std::string{lhs} + std::string{separator} + std::string{rhs});
88+
return std::empty(lhs) ? std::string{rhs} : (std::string{lhs} + std::string{separator} + std::string{rhs});
8989
});
9090
}
9191
}

modules/Thread/ThreadLoop.mpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,6 @@ export namespace CppUtils::Thread
109109

110110
inline auto isStopRequested() const -> bool
111111
{
112-
auto lockGuard = std::unique_lock{m_mutex};
113-
if (not m_thread.joinable())
114-
return false;
115112
return m_thread.get_stop_token().stop_requested();
116113
}
117114

@@ -127,14 +124,17 @@ export namespace CppUtils::Thread
127124
{
128125
try
129126
{
130-
auto lockGuard = std::unique_lock{m_mutex};
131-
if (not m_thread.joinable() or m_thread.get_stop_token().stop_requested())
132-
return;
133-
m_thread.request_stop();
134-
if (m_interruptFunction)
127+
auto interruptFunction = std::function<void()>{};
128+
{
129+
auto lockGuard = std::unique_lock{m_mutex};
130+
if (not m_thread.joinable() or m_thread.get_stop_token().stop_requested())
131+
return;
132+
m_thread.request_stop();
133+
interruptFunction = m_interruptFunction;
134+
}
135+
136+
if (interruptFunction)
135137
{
136-
auto interruptFunction = m_interruptFunction;
137-
lockGuard.unlock();
138138
try
139139
{
140140
interruptFunction();
@@ -143,7 +143,6 @@ export namespace CppUtils::Thread
143143
{
144144
Logger::print<"error">("ThreadLoop: interruptFunction threw during stop");
145145
}
146-
lockGuard.lock();
147146
}
148147
if (m_thread.joinable())
149148
m_thread.join();

modules/Thread/ThreadPool.mpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,16 +107,17 @@ export namespace CppUtils::Thread
107107

108108
task = std::move(tasksQueueAccessor->front());
109109
tasksQueueAccessor->pop();
110+
m_activeWorkers.fetch_add(1, std::memory_order_relaxed);
110111
}
111112

112-
m_activeWorkers.fetch_add(1, std::memory_order_relaxed);
113113
task();
114114
m_activeWorkers.fetch_sub(1, std::memory_order_relaxed);
115115

116-
if (m_activeWorkers.load(std::memory_order_relaxed) == 0 and isTasksQueueEmpty())
116+
if (m_activeWorkers.load(std::memory_order_relaxed) == 0)
117117
{
118118
auto lockGuard = std::lock_guard{m_waitingMutex};
119-
m_waitUntilFinishedCondition.notify_all();
119+
if (isTasksQueueEmpty())
120+
m_waitUntilFinishedCondition.notify_all();
120121
}
121122
}
122123

tests/Container/Sequence.mpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace
88
[[nodiscard]] auto generateDifferenceVector(std::string_view string) -> std::vector<CppUtils::Container::Sequence::Difference>
99
{
1010
auto result = std::vector<CppUtils::Container::Sequence::Difference>{};
11-
result.reserve(string.size());
11+
result.reserve(std::size(string));
1212
for (const auto c : string)
1313
{
1414
switch (c)

0 commit comments

Comments
 (0)