TrinityCore
TaskScheduler.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "TaskScheduler.h"
19#include "Errors.h"
20
22{
24 return *this;
25}
26
27TaskScheduler& TaskScheduler::Update(success_t const& callback/* = nullptr*/)
28{
29 _now = clock_t::now();
30 Dispatch(callback);
31 return *this;
32}
33
34TaskScheduler& TaskScheduler::Update(size_t milliseconds, success_t const& callback/* = nullptr*/)
35{
36 return Update(std::chrono::milliseconds(milliseconds), callback);
37}
38
39TaskScheduler& TaskScheduler::Async(std::function<void()> callable)
40{
41 _asyncHolder.emplace(std::move(callable));
42 return *this;
43}
44
46{
50 return *this;
51}
52
54{
55 _task_holder.RemoveIf([group](TaskContainer const& task) -> bool
56 {
57 return task->IsInGroup(group);
58 });
59 return *this;
60}
61
62TaskScheduler& TaskScheduler::CancelGroupsOf(std::vector<group_t> const& groups)
63{
64 for (group_t group : groups)
65 CancelGroup(group);
66
67 return *this;
68}
69
71{
72 _task_holder.Push(std::move(task));
73 return *this;
74}
75
76void TaskScheduler::Dispatch(success_t const& callback/* = nullptr*/)
77{
78 // If the validation failed abort the dispatching here.
79 if (!_predicate())
80 return;
81
82 // Process all asyncs
83 while (!_asyncHolder.empty())
84 {
85 _asyncHolder.front()();
86 _asyncHolder.pop();
87
88 // If the validation failed abort the dispatching here.
89 if (!_predicate())
90 return;
91 }
92
93 while (!_task_holder.IsEmpty())
94 {
95 if (_task_holder.First()->_end > _now)
96 break;
97
98 // Perfect forward the context to the handler
99 // Use weak references to catch destruction before callbacks.
100 TaskContext context(_task_holder.Pop(), std::weak_ptr<TaskScheduler>(self_reference));
101
102 // Invoke the context
103 context.Invoke();
104
105 // If the validation failed abort the dispatching here.
106 if (!_predicate())
107 return;
108 }
109
110 // On finish call the final callback
111 if (callback)
112 callback();
113}
114
116{
117 container.emplace(std::move(task));
118}
119
121{
122 TaskContainer result = *container.begin();
123 container.erase(container.begin());
124 return result;
125}
126
128{
129 return *container.begin();
130}
131
133{
134 container.clear();
135}
136
137void TaskScheduler::TaskQueue::RemoveIf(std::function<bool(TaskContainer const&)> const& filter)
138{
139 for (auto itr = container.begin(); itr != container.end();)
140 if (filter(*itr))
141 itr = container.erase(itr);
142 else
143 ++itr;
144}
145
146void TaskScheduler::TaskQueue::ModifyIf(std::function<bool(TaskContainer const&)> const& filter)
147{
148 std::vector<TaskContainer> cache;
149 for (auto itr = container.begin(); itr != container.end();)
150 if (filter(*itr))
151 {
152 cache.push_back(*itr);
153 itr = container.erase(itr);
154 }
155 else
156 ++itr;
157
158 container.insert(cache.begin(), cache.end());
159}
160
162{
163 return container.empty();
164}
165
167{
168 if (std::shared_ptr<TaskScheduler> owner = _owner.lock())
169 apply(*owner);
170
171 return *this;
172}
173
175{
176 return _owner.expired();
177}
178
180{
181 return _task->IsInGroup(group);
182}
183
185{
186 _task->_group = group;
187 return *this;
188}
189
191{
192 _task->_group = std::nullopt;
193 return *this;
194}
195
197{
198 return _task->_repeated;
199}
200
201TaskContext& TaskContext::Async(std::function<void()> const& callable)
202{
203 return Dispatch([&](TaskScheduler& scheduler) -> TaskScheduler&
204 {
205 return scheduler.Async(callable);
206 });
207}
208
210{
212}
213
215{
216 return Dispatch([=](TaskScheduler& scheduler) -> TaskScheduler&
217 {
218 return scheduler.CancelGroup(group);
219 });
220}
221
222TaskContext& TaskContext::CancelGroupsOf(std::vector<TaskScheduler::group_t> const& groups)
223{
224 return Dispatch([&](TaskScheduler& scheduler) -> TaskScheduler&
225 {
226 return scheduler.CancelGroupsOf(groups);
227 });
228}
229
231{
232 // This was adapted to TC to prevent static analysis tools from complaining.
233 // If you encounter this assertion check if you repeat a TaskContext more then 1 time!
234 ASSERT(!(*_consumed) && "Bad task logic, task context was consumed already!");
235}
236
238{
239 _task->_task(*this);
240}
#define ASSERT
Definition: Errors.h:68
void AssertOnConsumed() const
Asserts if the task was consumed already.
void Invoke()
Invokes the associated hook of the task.
TaskContext & Dispatch(std::function< TaskScheduler &(TaskScheduler &)> const &apply)
Dispatches an action safe on the TaskScheduler.
TaskContext & CancelAll()
Cancels all tasks from within the context.
TaskContext & SetGroup(TaskScheduler::group_t const group)
Sets the event in the given group.
TaskContext & Async(std::function< void()> const &callable)
TaskContext & CancelGroup(TaskScheduler::group_t const group)
Cancel all tasks of a single group from within the context.
TaskScheduler::repeated_t GetRepeatCounter() const
Returns the repeat counter which increases every time the task is repeated.
TaskContext & CancelGroupsOf(std::vector< TaskScheduler::group_t > const &groups)
TaskContext & ClearGroup()
Removes the group from the event.
bool IsInGroup(TaskScheduler::group_t const group) const
Returns true if the event is in the given group.
bool IsExpired() const
Returns true if the owner was deallocated and this context has expired.
void ModifyIf(std::function< bool(TaskContainer const &)> const &filter)
TaskContainer Pop()
Pops the task out of the container.
void RemoveIf(std::function< bool(TaskContainer const &)> const &filter)
TaskContainer const & First() const
std::multiset< TaskContainer, Compare > container
void Push(TaskContainer &&task)
TaskScheduler & CancelGroup(group_t group)
TaskScheduler & CancelAll()
std::shared_ptr< Task > TaskContainer
TaskScheduler & CancelGroupsOf(std::vector< group_t > const &groups)
void Dispatch(success_t const &callback)
Dispatch remaining tasks.
std::function< void()> success_t
Definition: TaskScheduler.h:65
std::shared_ptr< TaskScheduler > self_reference
Contains a self reference to track if this object was deleted or not.
AsyncHolder _asyncHolder
predicate_t _predicate
TaskScheduler & InsertTask(TaskContainer task)
Insert a new task to the enqueued tasks.
TaskScheduler & ClearValidator()
Clears the validator which is asked if tasks are allowed to be executed.
timepoint_t _now
The current time point (now)
std::queue< std::function< void()> > AsyncHolder
TaskScheduler & Async(std::function< void()> callable)
TaskScheduler & Update(success_t const &callback=nullptr)
static bool EmptyValidator()
TaskQueue _task_holder
The Task Queue which contains all task objects.
uint32 repeated_t
Definition: TaskScheduler.h:59
void apply(T *val)
Definition: ByteConverter.h:41