aboutsummaryrefslogtreecommitdiff
path: root/src/common/Utilities/TaskScheduler.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/Utilities/TaskScheduler.h')
-rw-r--r--src/common/Utilities/TaskScheduler.h247
1 files changed, 137 insertions, 110 deletions
diff --git a/src/common/Utilities/TaskScheduler.h b/src/common/Utilities/TaskScheduler.h
index e76e6f1c45e..2ebd3e57b37 100644
--- a/src/common/Utilities/TaskScheduler.h
+++ b/src/common/Utilities/TaskScheduler.h
@@ -15,8 +15,8 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _TASK_SCHEDULER_H_
-#define _TASK_SCHEDULER_H_
+#ifndef TRINITYCORE_TASK_SCHEDULER_H
+#define TRINITYCORE_TASK_SCHEDULER_H
#include "Duration.h"
#include "Optional.h"
@@ -94,6 +94,8 @@ class TC_COMMON_API TaskScheduler
// Move Assign
Task& operator= (Task&& right) = delete;
+ ~Task() = default;
+
// Order tasks by its end
std::weak_ordering operator<=> (Task const& other) const
{
@@ -181,6 +183,8 @@ public:
TaskScheduler& operator= (TaskScheduler const&) = delete;
TaskScheduler& operator= (TaskScheduler&&) = delete;
+ ~TaskScheduler() = default;
+
/// Sets a validator which is asked if tasks are allowed to be executed.
template<typename P>
TaskScheduler& SetValidator(P&& predicate)
@@ -198,12 +202,12 @@ public:
/// Update the scheduler with a difftime in ms.
/// Calls the optional callback on successfully finish.
- TaskScheduler& Update(size_t const milliseconds, success_t const& callback = nullptr);
+ TaskScheduler& Update(size_t milliseconds, success_t const& callback = nullptr);
/// Update the scheduler with a difftime.
/// Calls the optional callback on successfully finish.
- template<class _Rep, class _Period>
- TaskScheduler& Update(std::chrono::duration<_Rep, _Period> difftime,
+ template<class Rep, class Period>
+ TaskScheduler& Update(std::chrono::duration<Rep, Period> difftime,
success_t const& callback = nullptr)
{
_now += difftime;
@@ -217,39 +221,39 @@ public:
/// Schedule an event with a fixed rate.
/// Never call this from within a task context! Use TaskContext::Schedule instead!
- template<class _Rep, class _Period>
- TaskScheduler& Schedule(std::chrono::duration<_Rep, _Period> time,
+ template<class Rep, class Period>
+ TaskScheduler& Schedule(std::chrono::duration<Rep, Period> time,
task_handler_t task)
{
- return ScheduleAt(_now, time, std::move(task));
+ return this->ScheduleAt(_now, time, std::move(task));
}
/// Schedule an event with a fixed rate.
/// Never call this from within a task context! Use TaskContext::Schedule instead!
- template<class _Rep, class _Period>
- TaskScheduler& Schedule(std::chrono::duration<_Rep, _Period> time,
+ template<class Rep, class Period>
+ TaskScheduler& Schedule(std::chrono::duration<Rep, Period> time,
group_t const group, task_handler_t task)
{
- return ScheduleAt(_now, time, group, std::move(task));
+ return this->ScheduleAt(_now, time, group, std::move(task));
}
/// Schedule an event with a randomized rate between min and max rate.
/// Never call this from within a task context! Use TaskContext::Schedule instead!
- template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
- TaskScheduler& Schedule(std::chrono::duration<_RepLeft, _PeriodLeft> min,
- std::chrono::duration<_RepRight, _PeriodRight> max, task_handler_t task)
+ template<class RepLeft, class PeriodLeft, class RepRight, class PeriodRight>
+ TaskScheduler& Schedule(std::chrono::duration<RepLeft, PeriodLeft> min,
+ std::chrono::duration<RepRight, PeriodRight> max, task_handler_t task)
{
- return Schedule(randtime(min, max), std::move(task));
+ return this->Schedule(::randtime(min, max), std::move(task));
}
/// Schedule an event with a fixed rate.
/// Never call this from within a task context! Use TaskContext::Schedule instead!
- template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
- TaskScheduler& Schedule(std::chrono::duration<_RepLeft, _PeriodLeft> min,
- std::chrono::duration<_RepRight, _PeriodRight> max, group_t const group,
+ template<class RepLeft, class PeriodLeft, class RepRight, class PeriodRight>
+ TaskScheduler& Schedule(std::chrono::duration<RepLeft, PeriodLeft> min,
+ std::chrono::duration<RepRight, PeriodRight> max, group_t const group,
task_handler_t task)
{
- return Schedule(randtime(min, max), group, std::move(task));
+ return this->Schedule(::randtime(min, max), group, std::move(task));
}
/// Cancels all tasks.
@@ -258,15 +262,15 @@ public:
/// Cancel all tasks of a single group.
/// Never call this from within a task context! Use TaskContext::CancelGroup instead!
- TaskScheduler& CancelGroup(group_t const group);
+ TaskScheduler& CancelGroup(group_t group);
/// Cancels all groups in the given std::vector.
/// Hint: Use std::initializer_list for this: "{1, 2, 3, 4}"
TaskScheduler& CancelGroupsOf(std::vector<group_t> const& groups);
/// Delays all tasks with the given duration.
- template<class _Rep, class _Period>
- TaskScheduler& DelayAll(std::chrono::duration<_Rep, _Period> duration)
+ template<class Rep, class Period>
+ TaskScheduler& DelayAll(std::chrono::duration<Rep, Period> duration)
{
_task_holder.ModifyIf([&duration](TaskContainer const& task) -> bool
{
@@ -277,16 +281,16 @@ public:
}
/// Delays all tasks with a random duration between min and max.
- template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
- TaskScheduler& DelayAll(std::chrono::duration<_RepLeft, _PeriodLeft> min,
- std::chrono::duration<_RepRight, _PeriodRight> max)
+ template<class RepLeft, class PeriodLeft, class RepRight, class PeriodRight>
+ TaskScheduler& DelayAll(std::chrono::duration<RepLeft, PeriodLeft> min,
+ std::chrono::duration<RepRight, PeriodRight> max)
{
- return DelayAll(randtime(min, max));
+ return this->DelayAll(::randtime(min, max));
}
/// Delays all tasks of a group with the given duration.
- template<class _Rep, class _Period>
- TaskScheduler& DelayGroup(group_t const group, std::chrono::duration<_Rep, _Period> duration)
+ template<class Rep, class Period>
+ TaskScheduler& DelayGroup(group_t const group, std::chrono::duration<Rep, Period> duration)
{
_task_holder.ModifyIf([&duration, group](TaskContainer const& task) -> bool
{
@@ -302,17 +306,17 @@ public:
}
/// Delays all tasks of a group with a random duration between min and max.
- template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ template<class RepLeft, class PeriodLeft, class RepRight, class PeriodRight>
TaskScheduler& DelayGroup(group_t const group,
- std::chrono::duration<_RepLeft, _PeriodLeft> min,
- std::chrono::duration<_RepRight, _PeriodRight> max)
+ std::chrono::duration<RepLeft, PeriodLeft> min,
+ std::chrono::duration<RepRight, PeriodRight> max)
{
- return DelayGroup(group, randtime(min, max));
+ return this->DelayGroup(group, ::randtime(min, max));
}
/// Reschedule all tasks with a given duration.
- template<class _Rep, class _Period>
- TaskScheduler& RescheduleAll(std::chrono::duration<_Rep, _Period> duration)
+ template<class Rep, class Period>
+ TaskScheduler& RescheduleAll(std::chrono::duration<Rep, Period> duration)
{
auto const end = _now + duration;
_task_holder.ModifyIf([end](TaskContainer const& task) -> bool
@@ -324,16 +328,16 @@ public:
}
/// Reschedule all tasks with a random duration between min and max.
- template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
- TaskScheduler& RescheduleAll(std::chrono::duration<_RepLeft, _PeriodLeft> min,
- std::chrono::duration<_RepRight, _PeriodRight> max)
+ template<class RepLeft, class PeriodLeft, class RepRight, class PeriodRight>
+ TaskScheduler& RescheduleAll(std::chrono::duration<RepLeft, PeriodLeft> min,
+ std::chrono::duration<RepRight, PeriodRight> max)
{
- return RescheduleAll(randtime(min, max));
+ return this->RescheduleAll(::randtime(min, max));
}
/// Reschedule all tasks of a group with the given duration.
- template<class _Rep, class _Period>
- TaskScheduler& RescheduleGroup(group_t const group, std::chrono::duration<_Rep, _Period> duration)
+ template<class Rep, class Period>
+ TaskScheduler& RescheduleGroup(group_t const group, std::chrono::duration<Rep, Period> duration)
{
auto const end = _now + duration;
_task_holder.ModifyIf([end, group](TaskContainer const& task) -> bool
@@ -350,33 +354,33 @@ public:
}
/// Reschedule all tasks of a group with a random duration between min and max.
- template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ template<class RepLeft, class PeriodLeft, class RepRight, class PeriodRight>
TaskScheduler& RescheduleGroup(group_t const group,
- std::chrono::duration<_RepLeft, _PeriodLeft> min,
- std::chrono::duration<_RepRight, _PeriodRight> max)
+ std::chrono::duration<RepLeft, PeriodLeft> min,
+ std::chrono::duration<RepRight, PeriodRight> max)
{
- return RescheduleGroup(group, randtime(min, max));
+ return this->RescheduleGroup(group, ::randtime(min, max));
}
private:
/// Insert a new task to the enqueued tasks.
TaskScheduler& InsertTask(TaskContainer task);
- template<class _Rep, class _Period>
+ template<class Rep, class Period>
TaskScheduler& ScheduleAt(timepoint_t end,
- std::chrono::duration<_Rep, _Period> time, task_handler_t task)
+ std::chrono::duration<Rep, Period> time, task_handler_t task)
{
return InsertTask(TaskContainer(new Task(end + time, time, std::move(task))));
}
/// Schedule an event with a fixed rate.
/// Never call this from within a task context! Use TaskContext::schedule instead!
- template<class _Rep, class _Period>
+ template<class Rep, class Period>
TaskScheduler& ScheduleAt(timepoint_t end,
- std::chrono::duration<_Rep, _Period> time,
+ std::chrono::duration<Rep, Period> time,
group_t const group, task_handler_t task)
{
- static repeated_t const DEFAULT_REPEATED = 0;
+ static constexpr repeated_t DEFAULT_REPEATED = 0;
return InsertTask(TaskContainer(new Task(end + time, time, group, DEFAULT_REPEATED, std::move(task))));
}
@@ -407,7 +411,7 @@ public:
// Construct from task and owner
explicit TaskContext(TaskScheduler::TaskContainer&& task, std::weak_ptr<TaskScheduler>&& owner)
- : _task(std::move(task)), _owner(owner), _consumed(std::make_shared<bool>(false)) { }
+ : _task(std::move(task)), _owner(std::move(owner)), _consumed(std::make_shared<bool>(false)) { }
// Copy construct
TaskContext(TaskContext const& right)
@@ -418,23 +422,31 @@ public:
: _task(std::move(right._task)), _owner(std::move(right._owner)), _consumed(std::move(right._consumed)) { }
// Copy assign
- TaskContext& operator= (TaskContext const& right)
+ TaskContext& operator=(TaskContext const& right)
{
- _task = right._task;
- _owner = right._owner;
- _consumed = right._consumed;
+ if (this != &right)
+ {
+ _task = right._task;
+ _owner = right._owner;
+ _consumed = right._consumed;
+ }
return *this;
}
// Move assign
- TaskContext& operator= (TaskContext&& right) noexcept
+ TaskContext& operator=(TaskContext&& right) noexcept
{
- _task = std::move(right._task);
- _owner = std::move(right._owner);
- _consumed = std::move(right._consumed);
+ if (this != &right)
+ {
+ _task = std::move(right._task);
+ _owner = std::move(right._owner);
+ _consumed = std::move(right._consumed);
+ }
return *this;
}
+ ~TaskContext() = default;
+
/// Returns true if the owner was deallocated and this context has expired.
bool IsExpired() const;
@@ -454,8 +466,8 @@ public:
/// std::chrono::seconds(5) for example.
/// This will consume the task context, its not possible to repeat the task again
/// from the same task context!
- template<class _Rep, class _Period>
- TaskContext& Repeat(std::chrono::duration<_Rep, _Period> duration)
+ template<class Rep, class Period>
+ TaskContext& Repeat(std::chrono::duration<Rep, Period> duration)
{
AssertOnConsumed();
@@ -464,7 +476,10 @@ public:
_task->_end += duration;
_task->_repeated += 1;
(*_consumed) = true;
- return Dispatch(std::bind(&TaskScheduler::InsertTask, std::placeholders::_1, _task));
+ return this->Dispatch([this](TaskScheduler& scheduler) -> TaskScheduler&
+ {
+ return scheduler.InsertTask(_task);
+ });
}
/// Repeats the event with the same duration.
@@ -479,11 +494,11 @@ public:
/// std::chrono::seconds(5) for example.
/// This will consume the task context, its not possible to repeat the task again
/// from the same task context!
- template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
- TaskContext& Repeat(std::chrono::duration<_RepLeft, _PeriodLeft> min,
- std::chrono::duration<_RepRight, _PeriodRight> max)
+ template<class RepLeft, class PeriodLeft, class RepRight, class PeriodRight>
+ TaskContext& Repeat(std::chrono::duration<RepLeft, PeriodLeft> min,
+ std::chrono::duration<RepRight, PeriodRight> max)
{
- return Repeat(randtime(min, max));
+ return this->Repeat(::randtime(min, max));
}
/// Schedule a callable function that is executed at the next update tick from within the context.
@@ -494,14 +509,14 @@ public:
/// Its possible that the new event is executed immediately!
/// Use TaskScheduler::Async to create a task
/// which will be called at the next update tick.
- template<class _Rep, class _Period>
- TaskContext& Schedule(std::chrono::duration<_Rep, _Period> time,
+ template<class Rep, class Period>
+ TaskContext& Schedule(std::chrono::duration<Rep, Period> time,
TaskScheduler::task_handler_t task)
{
auto const end = _task->_end;
- return Dispatch([end, time, task = std::move(task)](TaskScheduler& scheduler) -> TaskScheduler&
+ return this->Dispatch([end, time, task = std::move(task)](TaskScheduler& scheduler) -> TaskScheduler&
{
- return scheduler.ScheduleAt<_Rep, _Period>(end, time, std::move(task));
+ return scheduler.ScheduleAt<Rep, Period>(end, time, std::move(task));
});
}
@@ -509,14 +524,14 @@ public:
/// Its possible that the new event is executed immediately!
/// Use TaskScheduler::Async to create a task
/// which will be called at the next update tick.
- template<class _Rep, class _Period>
- TaskContext& Schedule(std::chrono::duration<_Rep, _Period> time,
+ template<class Rep, class Period>
+ TaskContext& Schedule(std::chrono::duration<Rep, Period> time,
TaskScheduler::group_t const group, TaskScheduler::task_handler_t task)
{
auto const end = _task->_end;
- return Dispatch([end, time, group, task = std::move(task)](TaskScheduler& scheduler) -> TaskScheduler&
+ return this->Dispatch([end, time, group, task = std::move(task)](TaskScheduler& scheduler) -> TaskScheduler&
{
- return scheduler.ScheduleAt<_Rep, _Period>(end, time, group, std::move(task));
+ return scheduler.ScheduleAt<Rep, Period>(end, time, group, std::move(task));
});
}
@@ -524,23 +539,23 @@ public:
/// Its possible that the new event is executed immediately!
/// Use TaskScheduler::Async to create a task
/// which will be called at the next update tick.
- template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
- TaskContext& Schedule(std::chrono::duration<_RepLeft, _PeriodLeft> min,
- std::chrono::duration<_RepRight, _PeriodRight> max, TaskScheduler::task_handler_t task)
+ template<class RepLeft, class PeriodLeft, class RepRight, class PeriodRight>
+ TaskContext& Schedule(std::chrono::duration<RepLeft, PeriodLeft> min,
+ std::chrono::duration<RepRight, PeriodRight> max, TaskScheduler::task_handler_t task)
{
- return Schedule(randtime(min, max), std::move(task));
+ return this->Schedule(::randtime(min, max), std::move(task));
}
/// Schedule an event with a randomized rate between min and max rate from within the context.
/// Its possible that the new event is executed immediately!
/// Use TaskScheduler::Async to create a task
/// which will be called at the next update tick.
- template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
- TaskContext& Schedule(std::chrono::duration<_RepLeft, _PeriodLeft> min,
- std::chrono::duration<_RepRight, _PeriodRight> max, TaskScheduler::group_t const group,
+ template<class RepLeft, class PeriodLeft, class RepRight, class PeriodRight>
+ TaskContext& Schedule(std::chrono::duration<RepLeft, PeriodLeft> min,
+ std::chrono::duration<RepRight, PeriodRight> max, TaskScheduler::group_t const group,
TaskScheduler::task_handler_t task)
{
- return Schedule(randtime(min, max), group, std::move(task));
+ return this->Schedule(::randtime(min, max), group, std::move(task));
}
/// Cancels all tasks from within the context.
@@ -554,65 +569,77 @@ public:
TaskContext& CancelGroupsOf(std::vector<TaskScheduler::group_t> const& groups);
/// Delays all tasks with the given duration from within the context.
- template<class _Rep, class _Period>
- TaskContext& DelayAll(std::chrono::duration<_Rep, _Period> duration)
+ template<class Rep, class Period>
+ TaskContext& DelayAll(std::chrono::duration<Rep, Period> duration)
{
- return Dispatch(std::bind(&TaskScheduler::DelayAll<_Rep, _Period>, std::placeholders::_1, duration));
+ return this->Dispatch([=](TaskScheduler& scheduler) -> TaskScheduler&
+ {
+ return scheduler.DelayAll(duration);
+ });
}
/// Delays all tasks with a random duration between min and max from within the context.
- template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
- TaskContext& DelayAll(std::chrono::duration<_RepLeft, _PeriodLeft> min,
- std::chrono::duration<_RepRight, _PeriodRight> max)
+ template<class RepLeft, class PeriodLeft, class RepRight, class PeriodRight>
+ TaskContext& DelayAll(std::chrono::duration<RepLeft, PeriodLeft> min,
+ std::chrono::duration<RepRight, PeriodRight> max)
{
- return DelayAll(randtime(min, max));
+ return this->DelayAll(::randtime(min, max));
}
/// Delays all tasks of a group with the given duration from within the context.
- template<class _Rep, class _Period>
- TaskContext& DelayGroup(TaskScheduler::group_t const group, std::chrono::duration<_Rep, _Period> duration)
+ template<class Rep, class Period>
+ TaskContext& DelayGroup(TaskScheduler::group_t const group, std::chrono::duration<Rep, Period> duration)
{
- return Dispatch(std::bind(&TaskScheduler::DelayGroup<_Rep, _Period>, std::placeholders::_1, group, duration));
+ return this->Dispatch([=](TaskScheduler& scheduler) -> TaskScheduler&
+ {
+ return scheduler.DelayGroup(group, duration);
+ });
}
/// Delays all tasks of a group with a random duration between min and max from within the context.
- template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ template<class RepLeft, class PeriodLeft, class RepRight, class PeriodRight>
TaskContext& DelayGroup(TaskScheduler::group_t const group,
- std::chrono::duration<_RepLeft, _PeriodLeft> min,
- std::chrono::duration<_RepRight, _PeriodRight> max)
+ std::chrono::duration<RepLeft, PeriodLeft> min,
+ std::chrono::duration<RepRight, PeriodRight> max)
{
- return DelayGroup(group, randtime(min, max));
+ return this->DelayGroup(group, ::randtime(min, max));
}
/// Reschedule all tasks with the given duration.
- template<class _Rep, class _Period>
- TaskContext& RescheduleAll(std::chrono::duration<_Rep, _Period> duration)
+ template<class Rep, class Period>
+ TaskContext& RescheduleAll(std::chrono::duration<Rep, Period> duration)
{
- return Dispatch(std::bind(&TaskScheduler::RescheduleAll, std::placeholders::_1, duration));
+ return this->Dispatch([=](TaskScheduler& scheduler) -> TaskScheduler&
+ {
+ return scheduler.RescheduleAll(duration);
+ });
}
/// Reschedule all tasks with a random duration between min and max.
- template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
- TaskContext& RescheduleAll(std::chrono::duration<_RepLeft, _PeriodLeft> min,
- std::chrono::duration<_RepRight, _PeriodRight> max)
+ template<class RepLeft, class PeriodLeft, class RepRight, class PeriodRight>
+ TaskContext& RescheduleAll(std::chrono::duration<RepLeft, PeriodLeft> min,
+ std::chrono::duration<RepRight, PeriodRight> max)
{
- return RescheduleAll(randtime(min, max));
+ return this->RescheduleAll(::randtime(min, max));
}
/// Reschedule all tasks of a group with the given duration.
- template<class _Rep, class _Period>
- TaskContext& RescheduleGroup(TaskScheduler::group_t const group, std::chrono::duration<_Rep, _Period> duration)
+ template<class Rep, class Period>
+ TaskContext& RescheduleGroup(TaskScheduler::group_t const group, std::chrono::duration<Rep, Period> duration)
{
- return Dispatch(std::bind(&TaskScheduler::RescheduleGroup<_Rep, _Period>, std::placeholders::_1, group, duration));
+ return this->Dispatch([=](TaskScheduler& scheduler) -> TaskScheduler&
+ {
+ return scheduler.RescheduleGroup(group, duration);
+ });
}
/// Reschedule all tasks of a group with a random duration between min and max.
- template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight>
+ template<class RepLeft, class PeriodLeft, class RepRight, class PeriodRight>
TaskContext& RescheduleGroup(TaskScheduler::group_t const group,
- std::chrono::duration<_RepLeft, _PeriodLeft> min,
- std::chrono::duration<_RepRight, _PeriodRight> max)
+ std::chrono::duration<RepLeft, PeriodLeft> min,
+ std::chrono::duration<RepRight, PeriodRight> max)
{
- return RescheduleGroup(group, randtime(min, max));
+ return this->RescheduleGroup(group, ::randtime(min, max));
}
private:
@@ -623,4 +650,4 @@ private:
void Invoke();
};
-#endif /// _TASK_SCHEDULER_H_
+#endif /// TRINITYCORE_TASK_SCHEDULER_H