1//! @file thread.hpp
2//! @author ryftchen
3//! @brief The declarations (thread) in the utility module.
4//! @version 0.1.0
5//! @copyright Copyright (c) 2022-2026 ryftchen. All rights reserved.
6
7#pragma once
8
9#include <functional>
10#include <future>
11#include <queue>
12
13//! @brief The utility module.
14namespace utility // NOLINT(modernize-concat-nested-namespaces)
15{
16//! @brief Thread-pool-related functions in the utility module.
17namespace thread
18{
19//! @brief Brief function description.
20//! @return function description (module_function)
21inline static const char* description() noexcept
22{
23 return "UTIL_THREAD";
24}
25extern const char* version() noexcept;
26
27//! @brief Thread pool.
28class Thread
29{
30public:
31 //! @brief Construct a new Thread object.
32 //! @param capacity - maximum number of threads
33 explicit Thread(const std::size_t capacity);
34 //! @brief Destroy the Thread object.
35 virtual ~Thread();
36 //! @brief Construct a new Thread object.
37 Thread(const Thread&) = delete;
38 //! @brief Construct a new Thread object.
39 Thread(Thread&&) = delete;
40 //! @brief The operator (=) overloading of Thread class.
41 //! @return reference of the Thread object
42 Thread& operator=(const Thread&) = delete;
43 //! @brief The operator (=) overloading of Thread class.
44 //! @return reference of the Thread object
45 Thread& operator=(Thread&&) = delete;
46
47 //! @brief Enqueue tasks that require multi-threading.
48 //! @tparam Func - type of callable function
49 //! @tparam Args - type of function arguments
50 //! @param name - thread name
51 //! @param func - callable function
52 //! @param args - function arguments
53 //! @return result of thread execution
54 template <typename Func, typename... Args>
55 decltype(auto) enqueue(const std::string_view name, Func&& func, Args&&... args);
56
57private:
58 //! @brief The container of target threads to join.
59 std::vector<std::thread> thdColl;
60 //! @brief The queue of tasks.
61 std::queue<std::pair<std::string, std::packaged_task<void()>>> taskQueue;
62 //! @brief Mutex for controlling queue.
63 mutable std::mutex mtx;
64 //! @brief The synchronization condition for queue. Use with mtx.
65 std::condition_variable cond;
66 //! @brief The synchronization condition for availability of resources.
67 std::condition_variable producer;
68 //! @brief Flag for ready release.
69 std::atomic_bool releaseReady{false};
70
71 //! @brief The work loop.
72 void workLoop();
73};
74
75template <typename Func, typename... Args>
76decltype(auto) Thread::enqueue(const std::string_view name, Func&& func, Args&&... args)
77{
78 std::packaged_task<std::invoke_result_t<Func, Args...>()> task(
79 std::bind(std::forward<Func>(func), std::forward<Args>(args)...));
80 auto taskFuture = task.get_future();
81
82 std::unique_lock<std::mutex> lock(mtx);
83 if (releaseReady.load())
84 {
85 throw std::logic_error{"The thread resource is coming to be released."};
86 }
87 taskQueue.emplace(std::make_pair(name, std::move(task)));
88 lock.unlock();
89 cond.notify_one();
90 return taskFuture;
91}
92} // namespace thread
93} // namespace utility
94