1//! @file thread.cpp
2//! @author ryftchen
3//! @brief The definitions (thread) in the utility module.
4//! @version 0.1.0
5//! @copyright Copyright (c) 2022-2025 ryftchen. All rights reserved.
6
7#include "thread.hpp"
8
9#include <algorithm>
10
11namespace utility::thread
12{
13//! @brief Function version number.
14//! @return version number (major.minor.patch)
15const char* version() noexcept
16{
17 static const char* const ver = "0.1.0";
18 return ver;
19}
20
21Thread::Thread(const std::size_t capacity)
22{
23 thdColl.reserve(n: capacity);
24 std::generate_n(first: std::back_inserter(x&: thdColl), n: capacity, gen: [this]() { return std::thread{[this]() { workLoop(); }}; });
25}
26
27void Thread::workLoop()
28{
29 std::string thdName{};
30 std::packaged_task<void()> thdTask{};
31 for (constexpr std::uint8_t nameLen = 15;;)
32 {
33 if (std::unique_lock<std::mutex> lock(mtx); true)
34 {
35 cond.wait(lock&: lock, p: [this]() { return releaseReady.load() || !taskQueue.empty(); });
36 if (releaseReady.load() && taskQueue.empty())
37 {
38 return;
39 }
40
41 std::tie(args&: thdName, args&: thdTask) = std::move(taskQueue.front());
42 taskQueue.pop();
43 if (taskQueue.empty())
44 {
45 lock.unlock();
46 producer.notify_one();
47 }
48 }
49
50 if (!thdName.empty())
51 {
52 if (thdName.size() > nameLen)
53 {
54 thdName.resize(n: nameLen);
55 }
56 ::pthread_setname_np(target_thread: ::pthread_self(), name: thdName.c_str());
57 }
58 if (thdTask.valid())
59 {
60 thdTask();
61 }
62 }
63}
64
65Thread::~Thread()
66{
67 if (std::unique_lock<std::mutex> lock(mtx); true)
68 {
69 producer.wait(lock&: lock, p: [this]() { return taskQueue.empty(); });
70 releaseReady.store(i: true);
71 }
72
73 cond.notify_all();
74 std::for_each(
75 first: thdColl.begin(),
76 last: thdColl.end(),
77 f: [](auto& thd)
78 {
79 if (thd.joinable())
80 {
81 thd.join();
82 }
83 });
84}
85} // namespace utility::thread
86