MySQL 26.7.0
Source Code Documentation
thread_pool_impl.hpp
Go to the documentation of this file.
1// Copyright (c) 2026, Oracle and/or its affiliates.
2//
3// This program is free software; you can redistribute it and/or modify
4// it under the terms of the GNU General Public License, version 2.0,
5// as published by the Free Software Foundation.
6//
7// This program is designed to work with certain software (including
8// but not limited to OpenSSL) that is licensed under separate terms,
9// as designated in a particular file or component or in included license
10// documentation. The authors of MySQL hereby grant you an additional
11// permission to link the program and your derivative works with the
12// separately licensed software that they have either included with
13// the program or referenced in the documentation.
14//
15// This program is distributed in the hope that it will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License, version 2.0, for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with this program; if not, write to the Free Software
22// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
23
27
28namespace mysql::scheduler {
29
30template <class T, std::size_t t_queue_size>
32 unsigned int instance_id,
33 Thread_pool_psi psi_params)
34 : m_workers(Thread_allocator(psi_params.memory_resource)),
35 m_tasks(psi_params.memory_resource),
36 m_workers_num(thread_num),
37 m_instance_id(instance_id),
38 m_psi(psi_params) {
39 m_workers.reserve(thread_num);
40 for (unsigned int i = 0; i < m_workers_num; ++i) {
41 m_end_execution.emplace(std::piecewise_construct, std::forward_as_tuple(i),
42 std::forward_as_tuple(false));
43 }
44}
45
46template <class T, std::size_t t_queue_size>
48 if (m_initialized) return false;
49
50 for (auto &[_, end_execution] : m_end_execution) {
51 end_execution.store(false);
52 }
53 for (unsigned int i = 0; i < m_workers_num; i++) {
54 try {
55 auto worker = MDEF_CREATE_THREAD(m_psi.key_thread_worker,
56 &Thread_pool::run_worker, this, i);
57 if (has_creation_error(worker)) {
58 deinit();
59 return true;
60 }
61 m_workers.push_back(std::move(worker));
62 } catch (const std::system_error &) {
63 deinit();
64 return true;
65 }
66 }
67 m_initialized = true;
68 return false;
69}
70
71template <class T, std::size_t t_queue_size>
73 end_execution();
74 for (auto &worker : m_workers) {
75 if (worker.joinable()) {
76 worker.join();
77 }
78 }
79 m_workers.clear();
80 m_initialized = false;
81}
82
83template <class T, std::size_t t_queue_size>
85 m_tasks.enqueue(std::move(task));
86}
87
88template <class T, std::size_t t_queue_size>
90 return m_tasks.print_queue_state();
91}
92
93template <class T, std::size_t t_queue_size>
95 return m_tasks.size();
96}
97
98template <class T, std::size_t t_queue_size>
100 [[maybe_unused]] unsigned int thread_id) {
101 auto &stat_monitor = Statistics_monitor::get(m_instance_id);
102 stat_monitor.get_stat(Statistics_map::thp_thread_internal_id)
104 auto &task_time_stat =
105 stat_monitor.get_stat(Statistics_map::thp_task_exec_time);
106 auto &worker_time_stat =
107 stat_monitor.get_stat(Statistics_map::thp_worker_exec_time);
108 worker_time_stat.start_time(thread_id);
109
110 concurrency::set_stage(m_psi.key_stage_waiting);
111
112 while (true) {
113 auto stop_waiting = [this, &thread_id]() -> bool {
114 return m_end_execution[thread_id].load();
115 };
116 auto [task, valid] = m_tasks.dequeue(stop_waiting);
117 if (!valid) {
118 break;
119 }
120 concurrency::set_stage(m_psi.key_stage_executing);
121 task_time_stat.start_time(thread_id);
122 task(thread_id);
123 task_time_stat.stop_time(thread_id);
124 concurrency::set_stage(m_psi.key_stage_waiting);
125 }
126 worker_time_stat.stop_time(thread_id);
127 concurrency::set_stage(m_psi.key_stage_stopped);
128}
129
130template <class T, std::size_t t_queue_size>
132 deinit();
133}
134
135template <class T, std::size_t t_queue_size>
137 for (unsigned int i = 0; i < m_workers_num; i++) {
138 m_end_execution[i].store(true);
139 }
140 m_tasks.notify_all();
141}
142
143template <class T, std::size_t t_queue_size>
145 return m_workers.size();
146}
147
148template <class T, std::size_t t_queue_size>
150#ifdef STANDALONE_LIBS_MYSQL
151 (void)thread;
152 return false;
153#else
154 return thread.creation_error_code() != 0;
155#endif
156}
157
158} // namespace mysql::scheduler
static mysql_service_status_t deinit()
Component deinitialization.
Definition: audit_api_message_emit.cc:575
Allocator using a Memory_resource to do the allocation.
Definition: allocator.h:52
Wrapper to mysql thread, which matches interface of std::thread.
Definition: thread_srv.h:46
int creation_error_code() const
Returns the thread creation error code.
Definition: thread_srv.h:76
static constexpr auto thp_thread_internal_id
Definition: statistics_map.h:49
static constexpr auto thp_worker_exec_time
Definition: statistics_map.h:47
static constexpr auto thp_task_exec_time
Definition: statistics_map.h:46
static Statistics_instance_monitor & get(std::size_t instance_id)
Definition: statistics_monitor.cpp:35
void end_execution()
Notifies all threads to end execution in a gracious way.
Definition: thread_pool_impl.hpp:136
bool init()
Initializes the thread pool by starting worker threads.
Definition: thread_pool_impl.hpp:47
void deinit()
Deinitializes the thread pool and joins all worker threads.
Definition: thread_pool_impl.hpp:72
unsigned int m_workers_num
The number of threads in the thread pool.
Definition: thread_pool.h:125
void run_worker(unsigned int thread_id)
Function executed by each thread.
Definition: thread_pool_impl.hpp:99
std::vector< Thread, Thread_allocator > m_workers
Thread container.
Definition: thread_pool.h:118
Thread_pool(unsigned int thread_num=std::thread::hardware_concurrency(), unsigned int instance_id=0, Thread_pool_psi psi_params={})
Constructs a thread pool.
Definition: thread_pool_impl.hpp:31
std::size_t size() const
Obtains worker pool size.
Definition: thread_pool_impl.hpp:144
std::size_t queue_size() const
Get an estimation of number of elements in the worker queue.
Definition: thread_pool_impl.hpp:94
std::unordered_map< unsigned int, std::atomic< bool > > m_end_execution
Variable indicating the end of execution, allows threads to stop in a gracious way.
Definition: thread_pool.h:121
virtual ~Thread_pool()
Destructor.
Definition: thread_pool_impl.hpp:131
std::packaged_task< T(unsigned int)> Task_type
Runnable task type, future is obtained by the caller.
Definition: thread_pool.h:53
std::string print_queue_state() const
Prints worker queue state, debug function.
Definition: thread_pool_impl.hpp:89
void enqueue(Task_type &&task)
Enqueues task for execution.
Definition: thread_pool_impl.hpp:84
static bool has_creation_error(const Thread &thread)
Checks whether worker thread construction failed.
Definition: thread_pool_impl.hpp:149
static my_thread_id thread_id
Definition: my_thr_init.cc:60
void set_stage(auto key)
Definition: stage.h:41
unsigned long long fetch_thread_mysql_id(std::size_t my_internal_id)
Fetches internal id, PSI id in case linked with mysqld, or internal thread id.
Definition: thread_srv.h:91
Definition: base_dependency_tracker.h:41
Thread_pool instrumentation parameters, packed into this structure to simplify construction of a Thre...
Definition: thread_pool_psi.h:38
#define MDEF_CREATE_THREAD(thread_key, callable,...)
Definition: thread_srv.h:103
#define _(str)
Definition: win_i18n.h:33