Legends-of-Azeroth-Pandaria-5.4.8
229 строк · 5.7 Кб
1/*
2* This file is part of the Pandaria 5.4.8 Project. See THANKS 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
20TaskScheduler& TaskScheduler::ClearValidator()
21{
22_predicate = EmptyValidator;
23return *this;
24}
25
26TaskScheduler& TaskScheduler::Update(success_t const& callback)
27{
28_now = clock_t::now();
29Dispatch(callback);
30return *this;
31}
32
33TaskScheduler& TaskScheduler::Update(size_t const milliseconds, success_t const& callback)
34{
35return Update(std::chrono::milliseconds(milliseconds), callback);
36}
37
38TaskScheduler& TaskScheduler::Async(std::function<void()> const& callable)
39{
40_asyncHolder.push(callable);
41return *this;
42}
43
44TaskScheduler& TaskScheduler::CancelAll()
45{
46/// Clear the task holder
47_task_holder.Clear();
48_asyncHolder = AsyncHolder();
49return *this;
50}
51
52TaskScheduler& TaskScheduler::CancelGroup(group_t const group)
53{
54_task_holder.RemoveIf([group](TaskContainer const& task) -> bool
55{
56return task->IsInGroup(group);
57});
58return *this;
59}
60
61TaskScheduler& TaskScheduler::CancelGroupsOf(std::vector<group_t> const& groups)
62{
63std::for_each(groups.begin(), groups.end(),
64std::bind(&TaskScheduler::CancelGroup, this, std::placeholders::_1));
65
66return *this;
67}
68
69TaskScheduler& TaskScheduler::InsertTask(TaskContainer task)
70{
71_task_holder.Push(std::move(task));
72return *this;
73}
74
75void TaskScheduler::Dispatch(success_t const& callback)
76{
77// If the validation failed abort the dispatching here.
78if (!_predicate())
79return;
80
81// Process all asyncs
82while (!_asyncHolder.empty())
83{
84_asyncHolder.front()();
85_asyncHolder.pop();
86
87// If the validation failed abort the dispatching here.
88if (!_predicate())
89return;
90}
91
92while (!_task_holder.IsEmpty())
93{
94if (_task_holder.First()->_end > _now)
95break;
96
97// Perfect forward the context to the handler
98// Use weak references to catch destruction before callbacks.
99TaskContext context(_task_holder.Pop(), std::weak_ptr<TaskScheduler>(self_reference));
100
101// Invoke the context
102context.Invoke();
103
104// If the validation failed abort the dispatching here.
105if (!_predicate())
106return;
107}
108
109// On finish call the final callback
110callback();
111}
112
113void TaskScheduler::TaskQueue::Push(TaskContainer&& task)
114{
115container.insert(task);
116}
117
118auto TaskScheduler::TaskQueue::Pop() -> TaskContainer
119{
120TaskContainer result = *container.begin();
121container.erase(container.begin());
122return result;
123}
124
125auto TaskScheduler::TaskQueue::First() const -> TaskContainer const&
126{
127return *container.begin();
128}
129
130void TaskScheduler::TaskQueue::Clear()
131{
132container.clear();
133}
134
135void TaskScheduler::TaskQueue::RemoveIf(std::function<bool(TaskContainer const&)> const& filter)
136{
137for (auto itr = container.begin(); itr != container.end();)
138if (filter(*itr))
139itr = container.erase(itr);
140else
141++itr;
142}
143
144void TaskScheduler::TaskQueue::ModifyIf(std::function<bool(TaskContainer const&)> const& filter)
145{
146std::vector<TaskContainer> cache;
147for (auto itr = container.begin(); itr != container.end();)
148if (filter(*itr))
149{
150cache.push_back(*itr);
151itr = container.erase(itr);
152}
153else
154++itr;
155
156container.insert(cache.begin(), cache.end());
157}
158
159bool TaskScheduler::TaskQueue::IsEmpty() const
160{
161return container.empty();
162}
163
164TaskContext& TaskContext::Dispatch(std::function<TaskScheduler&(TaskScheduler&)> const& apply)
165{
166if (auto const owner = _owner.lock())
167apply(*owner);
168
169return *this;
170}
171
172bool TaskContext::IsExpired() const
173{
174return _owner.expired();
175}
176
177bool TaskContext::IsInGroup(TaskScheduler::group_t const group) const
178{
179return _task->IsInGroup(group);
180}
181
182TaskContext& TaskContext::SetGroup(TaskScheduler::group_t const group)
183{
184_task->_group = group;
185return *this;
186}
187
188TaskContext& TaskContext::ClearGroup()
189{
190_task->_group = std::numeric_limits<uint32>::max();
191return *this;
192}
193
194TaskScheduler::repeated_t TaskContext::GetRepeatCounter() const
195{
196return _task->_repeated;
197}
198
199TaskContext& TaskContext::Async(std::function<void()> const& callable)
200{
201return Dispatch(std::bind(&TaskScheduler::Async, std::placeholders::_1, callable));
202}
203
204TaskContext& TaskContext::CancelAll()
205{
206return Dispatch(std::mem_fn(&TaskScheduler::CancelAll));
207}
208
209TaskContext& TaskContext::CancelGroup(TaskScheduler::group_t const group)
210{
211return Dispatch(std::bind(&TaskScheduler::CancelGroup, std::placeholders::_1, group));
212}
213
214TaskContext& TaskContext::CancelGroupsOf(std::vector<TaskScheduler::group_t> const& groups)
215{
216return Dispatch(std::bind(&TaskScheduler::CancelGroupsOf, std::placeholders::_1, std::cref(groups)));
217}
218
219void TaskContext::AssertOnConsumed() const
220{
221// This was adapted to TC to prevent static analysis tools from complaining.
222// If you encounter this assertion check if you repeat a TaskContext more then 1 time!
223ASSERT(!(*_consumed) && "Bad task logic, task context was consumed already!");
224}
225
226void TaskContext::Invoke()
227{
228_task->_task(*this);
229}
230