TrinityCore
Loading...
Searching...
No Matches
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
26
28{
29 _now = clock_t::now();
30 Dispatch(callback);
31 return *this;
32}
33
34TaskScheduler& TaskScheduler::Update(size_t const milliseconds, success_t const& callback)
35{
36 return Update(std::chrono::milliseconds(milliseconds), callback);
37}
38
39TaskScheduler& TaskScheduler::Async(std::function<void()> const& callable)
40{
41 _asyncHolder.push(callable);
42 return *this;
43}
44
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 std::for_each(groups.begin(), groups.end(),
65 std::bind(&TaskScheduler::CancelGroup, this, std::placeholders::_1));
66
67 return *this;
68}
69
71{
72 _task_holder.Push(std::move(task));
73 return *this;
74}
75
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 callback();
112}
113
115{
116 container.insert(task);
117}
118
120{
121 TaskContainer result = *container.begin();
122 container.erase(container.begin());
123 return result;
124}
125
127{
128 return *container.begin();
129}
130
132{
133 container.clear();
134}
135
136void TaskScheduler::TaskQueue::RemoveIf(std::function<bool(TaskContainer const&)> const& filter)
137{
138 for (auto itr = container.begin(); itr != container.end();)
139 if (filter(*itr))
140 itr = container.erase(itr);
141 else
142 ++itr;
143}
144
145void TaskScheduler::TaskQueue::ModifyIf(std::function<bool(TaskContainer const&)> const& filter)
146{
147 std::vector<TaskContainer> cache;
148 for (auto itr = container.begin(); itr != container.end();)
149 if (filter(*itr))
150 {
151 cache.push_back(*itr);
152 itr = container.erase(itr);
153 }
154 else
155 ++itr;
156
157 container.insert(cache.begin(), cache.end());
158}
159
161{
162 return container.empty();
163}
164
166{
167 if (auto const owner = _owner.lock())
168 apply(*owner);
169
170 return *this;
171}
172
174{
175 return _owner.expired();
176}
177
179{
180 return _task->IsInGroup(group);
181}
182
184{
185 _task->_group = group;
186 return *this;
187}
188
190{
191 _task->_group = std::nullopt;
192 return *this;
193}
194
196{
197 return _task->_repeated;
198}
199
200TaskContext& TaskContext::Async(std::function<void()> const& callable)
201{
202 return Dispatch(std::bind(&TaskScheduler::Async, std::placeholders::_1, callable));
203}
204
209
211{
212 return Dispatch(std::bind(&TaskScheduler::CancelGroup, std::placeholders::_1, group));
213}
214
215TaskContext& TaskContext::CancelGroupsOf(std::vector<TaskScheduler::group_t> const& groups)
216{
217 return Dispatch(std::bind(&TaskScheduler::CancelGroupsOf, std::placeholders::_1, std::cref(groups)));
218}
219
221{
222 // This was adapted to TC to prevent static analysis tools from complaining.
223 // If you encounter this assertion check if you repeat a TaskContext more then 1 time!
224 ASSERT(!(*_consumed) && "Bad task logic, task context was consumed already!");
225}
226
228{
229 _task->_task(*this);
230}
#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 & CancelAll()
std::shared_ptr< Task > TaskContainer
TaskScheduler & Async(std::function< void()> const &callable)
TaskScheduler & CancelGroupsOf(std::vector< group_t > const &groups)
void Dispatch(success_t const &callback)
Dispatch remaining tasks.
TaskScheduler & Update(success_t const &callback=EmptyCallback)
std::function< void()> success_t
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 & CancelGroup(group_t const group)
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
static bool EmptyValidator()
TaskQueue _task_holder
The Task Queue which contains all task objects.