MySQL 26.7.0
Source Code Documentation
scheduler_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
24#include <chrono>
25#include <iostream>
26#include <memory>
27#include <type_traits>
28
29#include <string>
30
33
34namespace mysql::scheduler {
35
36namespace detail {
37
38template <class F, class Tid, class Tuple, std::size_t... I>
39constexpr decltype(auto) apply_with_thread_id_impl(F &&f, Tid &&tid, Tuple &&t,
40 std::index_sequence<I...>) {
41 return std::invoke(std::forward<F>(f), std::forward<Tid>(tid),
42 std::get<I>(std::forward<Tuple>(t))...);
43}
44
45template <class F, class Tid, class Tuple, std::size_t... I>
46constexpr decltype(auto) apply_with_thread_id(F &&f, Tid &&tid, Tuple &&t) {
48 std::forward<F>(f), std::forward<Tid>(tid), std::forward<Tuple>(t),
49 std::make_index_sequence<std::tuple_size_v<std::decay_t<Tuple>>>{});
50}
51
52} // namespace detail
53
54template <typename FType, typename... Args>
56 Args &&...args) {
59 this->synchronize_partial();
60 }
61 auto task_delay = schedule->get_task_delay();
62 while (true) {
63 if (m_scheduler_clock->add_time(schedule->get_id(), task_delay)) {
64 break; // ok
65 }
67 this->synchronize_partial();
68 }
69
71
72 using Decayed_FType = std::decay_t<FType>;
73 auto task_shared = std::make_shared<Decayed_FType>(std::forward<FType>(task));
74
75 constexpr bool may_error_out = requires(Decayed_FType & t) { t.is_error(); };
76
77 std::tuple<Args...> tuple_args =
78 std::forward_as_tuple(std::forward<Args>(args)...);
79
80 auto repeatable_lambda = [this, schedule, task_shared,
81 tuple_args = std::move(tuple_args)](
82 unsigned int thread_id) mutable -> bool {
83 auto &time_exec_stat =
85 time_exec_stat.start_time(thread_id);
86 detail::apply_with_thread_id(*task_shared, thread_id, tuple_args);
87 time_exec_stat.stop_time(thread_id);
88 bool is_error = false;
89 if constexpr (may_error_out) {
90 is_error = task_shared->is_error();
91 }
92 return is_error;
93 };
94
95 auto repeatable_task = std::make_shared<Repeatable_task_state>(
96 m_scheduled_tasks_cnt, std::move(repeatable_lambda));
97
98 auto exec_task = [this, schedule, task_delay, repeatable_task](
99 unsigned int thread_id) mutable -> Task_result {
100 auto is_error = repeatable_task->execute(thread_id);
101 return this->callback(schedule, task_delay, is_error, repeatable_task,
102 thread_id);
103 };
104
105 Scheduled_task scheduled(schedule->get_id(), std::move(exec_task),
106 repeatable_task, schedule, schedule->get_phase_id());
107 if (!schedule->is_finished()) {
108 scheduled.set_enqueued_by_scheduler();
109 }
110 if (!enqueue_helper(std::move(scheduled))) {
111 return false;
112 }
113 return true;
114}
115
116template <typename Repeatable_task_type>
119 std::shared_ptr<Repeatable_task_type> repeatable_task,
120 unsigned int current_thread_id, unsigned int phase_id) {
121 auto &phase_clock = schedule->get_phase_clock(phase_id);
122 auto &phase_queue = get_phase_queue(phase_clock);
123 // auto & phase_mt = get_phase_queue_lock(phase_clock);
124 auto phase_delay = schedule->get_phase_delay(phase_id);
125 [[maybe_unused]] auto subscribed =
126 phase_clock->add_time(schedule->get_id(), phase_delay);
127 assert(subscribed);
128 bool self_enqueue = (current_thread_id == Constants::scheduler_thread_id);
129
130 auto phase_task = [this, schedule, task_delay, repeatable_task,
131 phase_id](unsigned int thread_id) mutable -> Task_result {
132 bool is_error = repeatable_task->execute(thread_id);
133 auto result = this->callback_phase(schedule, is_error, phase_id);
135 is_error = true;
136 }
137 // hack for start-to-start is to call () twice, first call is
138 // an after start callback
139 if (schedule->get_phase_clock(phase_id)->get_type() ==
142 is_error = repeatable_task->execute(thread_id);
143 }
144 return this->callback(schedule, task_delay, is_error, repeatable_task,
145 thread_id);
146 };
147
148 Scheduled_task scheduled(schedule->get_id(), std::move(phase_task),
149 repeatable_task, schedule, phase_id);
150 {
151 if (!self_enqueue) {
153 if (is_error() || m_stop_now) {
155 return false;
156 }
157 }
158 phase_queue.push(std::move(scheduled));
159 if (!self_enqueue) {
161 }
162 }
164 return true;
165}
166
167template <typename Repeatable_task_type>
170 bool task_error, std::shared_ptr<Repeatable_task_type> repeatable_task,
171 unsigned int current_thread_id) {
172 if (task_error) {
173 handle_error();
175 }
176 if (schedule->next()) {
177 if (!schedule->is_enqueued_by_scheduler()) {
178 [[maybe_unused]] auto enqueued =
179 enqueue_phase(schedule, task_delay, repeatable_task,
180 current_thread_id, schedule->get_phase_id());
181 if (!enqueued) {
183 }
184 }
185 schedule->set_phase_ready();
188 }
189 auto id = schedule->get_id();
190 auto unblocked_tasks = m_dependencies->mark_dependency_met(id, true);
191 for (auto &entry_id : unblocked_tasks) {
192 m_notified_tasks.push(entry_id.get());
193 }
194 bool time_advanced = m_scheduler_clock->tick(id, task_delay);
195 if (time_advanced || !unblocked_tasks.empty()) {
197 }
198 // At this point, we are not using internal data structures anymore, we
199 // can notify scheduler that we are done with this task
201}
202
203template <typename FType, typename... Args>
204bool Scheduler::enqueue(Task_schedule_ptr schedule, FType &&task,
205 Args &&...args) {
206 const auto &task_id = schedule->get_id();
207 [[maybe_unused]] bool activated = m_dependencies->activate_task(task_id);
208 assert(activated);
209 bool is_ok = enqueue_internal(schedule, std::forward<FType>(task),
210 std::forward<Args>(args)...);
211 return is_ok;
212}
213
214template <typename FType, typename... Args>
215bool Scheduler::enqueue_after(const Task_id &predecessor,
216 Task_schedule_ptr schedule, FType &&task,
217 Args &&...args) {
218 const auto &task_id = schedule->get_id();
219 [[maybe_unused]] bool activated = m_dependencies->activate_task(task_id);
220 assert(activated);
221 [[maybe_unused]] auto dep_registered = add_dependency(predecessor, task_id);
222 assert(dep_registered);
223 bool is_ok = enqueue_internal(schedule, std::forward<FType>(task),
224 std::forward<Args>(args)...);
225 return is_ok;
226}
227
228} // namespace mysql::scheduler
void unlock()
Unblocks access to a critical section for other threads.
Definition: mutex_wrapper.cpp:38
void lock() noexcept
Acquire a lock, blocks access to a critical section until "unlock" is called.
Definition: mutex_wrapper.cpp:32
Represents task that is scheduled in the priority queue.
Definition: scheduled_task.h:87
void set_enqueued_by_scheduler()
Sets the repeatable task and marks as enqueued by scheduler.
Definition: scheduled_task.h:120
uint64_t Time_point_t
Definition: scheduler_clock.h:54
Scheduler_clock_ptr m_scheduler_clock
Scheduler clock.
Definition: scheduler.h:354
Task_result callback(Task_schedule_ptr schedule, Scheduler_clock::Time_point_t task_delay, bool task_error, std::shared_ptr< Repeatable_task_type > repeatable_task, unsigned int current_thread_id)
Function used to notify that task ended its execution.
Definition: scheduler_impl.hpp:168
void notify_scheduler()
Function used to notify scheduler thread by the other thread (enqueueing thread / worker poll thread)
Definition: scheduler.cpp:382
container::Integrals_lockfree_queue< uint64_t > m_notified_tasks
Lock-free queue of task IDs that are ready for execution.
Definition: scheduler.h:336
Dependency_tracker_ptr m_dependencies
Task dependencies, used mainly to implement dependencies between events in one transaction or between...
Definition: scheduler.h:371
bool is_error() const
Internal function to check on whether error has been set.
Definition: scheduler.cpp:252
std::atomic< std::size_t > m_scheduled_tasks_cnt
The number of scheduled tasks.
Definition: scheduler.h:351
bool enqueue_helper(Scheduled_task &&task)
Enqueue helper.
Definition: scheduler.cpp:310
Task_result callback_phase(Task_schedule_ptr schedule, bool task_error, unsigned int phase_id)
Function used to notify that task phase ended its execution.
Definition: scheduler.cpp:390
bool add_dependency(const Task_id &predecessor, const Task_id &successor)
add_dependency
Definition: scheduler.cpp:86
Statistics_instance_monitor_ref m_stat_monitor
Statistics monitoring object for the current instance.
Definition: scheduler.h:381
std::atomic< std::size_t > m_allowed_task_count
Maximum allowed number of tasks active in the scheduler.
Definition: scheduler.h:384
void synchronize_partial(bool print_checkpoint=false)
Waits for percent of tasks to finish.
Definition: scheduler.cpp:376
std::atomic< bool > m_stop_now
Variable that instructs scheduler to withdraw all work and stop.
Definition: scheduler.h:348
bool enqueue_internal(Task_schedule_ptr schedule, FType &&task, Args &&...args)
Enqueues a task identified by the task_id.
Definition: scheduler_impl.hpp:55
bool enqueue_phase(Task_schedule_ptr schedule, Scheduler_clock::Time_point_t task_delay, std::shared_ptr< Repeatable_task_type > repeatable_task, unsigned int current_thread_id, unsigned int phase_id)
Function that enqueues next task phase.
Definition: scheduler_impl.hpp:117
Mutex_type m_mutex_phases
This mutex protect access to phase.
Definition: scheduler.h:316
bool enqueue(Task_schedule_ptr schedule, FType &&task, Args &&...args)
Enqueues a task.
Definition: scheduler_impl.hpp:204
Scheduler_psi m_psi
PSI parameters.
Definition: scheduler.h:393
void handle_error()
Worker error handling function.
Definition: scheduler.cpp:276
bool enqueue_after(const Task_id &predecessor, Task_schedule_ptr schedule, FType &&task, Args &&...args)
Enqueues a task that should execute after a predecessor task finishes.
Definition: scheduler_impl.hpp:215
Task_queue_type & get_phase_queue(Scheduler_clock_ptr phase_clock)
Definition: scheduler.cpp:281
static constexpr auto sched_task_exec_time
Definition: statistics_map.h:48
Represents the identifier of a task ingested by the scheduler,.
Definition: task_id.h:41
#define F
Definition: jit_executor_value.cc:374
static my_thread_id thread_id
Definition: my_thr_init.cc:60
Definition: packet_based_table_with_cursor.h:36
void set_stage(auto key)
Definition: stage.h:41
constexpr decltype(auto) apply_with_thread_id_impl(F &&f, Tid &&tid, Tuple &&t, std::index_sequence< I... >)
Definition: scheduler_impl.hpp:39
constexpr decltype(auto) apply_with_thread_id(F &&f, Tid &&tid, Tuple &&t)
Definition: scheduler_impl.hpp:46
Definition: base_dependency_tracker.h:41
Task_result
Acceptable task state after its execution.
Definition: task_result.h:32
@ fatal_error
Fatal error which we cannot recover and need to stop.
@ success
Task executed successfully.
std::shared_ptr< Task_schedule > Task_schedule_ptr
Definition: task_schedule.h:41
static constexpr unsigned int scheduler_thread_id
Scheduler thread id constant, used by the scheduler thread (max)
Definition: constants.h:40
concurrency::Stage_key key_stage_wait_clock_queue
stage: waiting for clock (cannot handle more dependencies)
Definition: scheduler_psi.h:66
concurrency::Stage_key key_reached_max_task_limit
stage: synchronizing scheduler - reached max task limit
Definition: scheduler_psi.h:68
Definition: result.h:30