Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Core/QuestTracker): implement quest tracker manager #4112 #25

Open
wants to merge 30 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
0e89e09
feat(Core/QuestTracker): implement queue quest tracker
Winfidonarleyan Dec 30, 2020
f27b448
Split updates and fix memleak
Winfidonarleyan Jan 4, 2021
72f5877
CharacterDatabaseStatements enum
Winfidonarleyan Jan 7, 2021
eba4dd9
to 30s
Winfidonarleyan Jan 8, 2021
f00f0a5
1 trans for updates
Winfidonarleyan Jan 8, 2021
5c8ddce
fix builld
Winfidonarleyan Jan 8, 2021
a0124f2
fix lambda
Winfidonarleyan Jan 8, 2021
f3c4e08
Merge branch 'master' into quest-tracker-queue
Viste Jan 8, 2021
a6474dd
Merge branch 'master' into quest-tracker-queue
Kitzunu Jan 9, 2021
bee2e42
Merge remote-tracking branch 'off/master' into quest-tracker-queue
Winfidonarleyan Jan 20, 2021
d0e1d8c
Whitespace cleanup
Winfidonarleyan Jan 20, 2021
570ccac
Delete transactions
Winfidonarleyan Jan 20, 2021
e19f28c
Add info
Winfidonarleyan Jan 20, 2021
3863d07
Merge branch 'master' into quest-tracker-queue
Kitzunu Jan 27, 2021
3cd8810
Merge branch 'master' into quest-tracker-queue
Winfidonarleyan Jan 27, 2021
e3e5bdd
Merge branch 'master' into quest-tracker-queue
Winfidonarleyan Jan 28, 2021
2e2e874
Merge branch 'master' into quest-tracker-queue
Winfidonarleyan Jan 29, 2021
2ec6dc4
rework
Winfidonarleyan Jan 29, 2021
6f6cbda
to ac
Winfidonarleyan Jan 29, 2021
1e23325
disable default
Winfidonarleyan Jan 29, 2021
4fe27c4
copyright
Winfidonarleyan Jan 29, 2021
4d76ed6
+
Winfidonarleyan Jan 29, 2021
023831f
to int
Winfidonarleyan Jan 29, 2021
81f4fc9
Merge remote-tracking branch 'off/master' into quest-tracker-queue
Winfidonarleyan Feb 22, 2021
dd5d5da
Improve
Winfidonarleyan Feb 22, 2021
9ca6100
Merge branch 'master' into quest-tracker-queue
Winfidonarleyan Feb 23, 2021
badadb5
Merge branch 'master' into quest-tracker-queue
Winfidonarleyan Feb 28, 2021
1ecf4ce
includes
Winfidonarleyan Feb 28, 2021
49bda9d
Merge remote-tracking branch 'off/master' into quest-tracker-queue
Winfidonarleyan Feb 28, 2021
a2a45b2
new config api
Winfidonarleyan Feb 28, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
218 changes: 218 additions & 0 deletions src/common/Utilities/TaskScheduler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
* Copyright (C) 2008+ TrinityCore <http://www.trinitycore.org/>
*/

#include "TaskScheduler.h"
#include "Errors.h"

TaskScheduler& TaskScheduler::ClearValidator()
{
_predicate = EmptyValidator;
return *this;
}

TaskScheduler& TaskScheduler::Update(success_t const& callback)
{
_now = clock_t::now();
Dispatch(callback);
return *this;
}

TaskScheduler& TaskScheduler::Update(size_t const milliseconds, success_t const& callback)
{
return Update(std::chrono::milliseconds(milliseconds), callback);
}

TaskScheduler& TaskScheduler::Async(std::function<void()> const& callable)
{
_asyncHolder.push(callable);
return *this;
}

TaskScheduler& TaskScheduler::CancelAll()
{
/// Clear the task holder
_task_holder.Clear();
_asyncHolder = AsyncHolder();
return *this;
}

TaskScheduler& TaskScheduler::CancelGroup(group_t const group)
{
_task_holder.RemoveIf([group](TaskContainer const & task) -> bool
{
return task->IsInGroup(group);
});
return *this;
}

TaskScheduler& TaskScheduler::CancelGroupsOf(std::vector<group_t> const& groups)
{
std::for_each(groups.begin(), groups.end(),
std::bind(&TaskScheduler::CancelGroup, this, std::placeholders::_1));

return *this;
}

TaskScheduler& TaskScheduler::InsertTask(TaskContainer task)
{
_task_holder.Push(std::move(task));
return *this;
}

void TaskScheduler::Dispatch(success_t const& callback)
{
// If the validation failed abort the dispatching here.
if (!_predicate())
return;

// Process all asyncs
while (!_asyncHolder.empty())
{
_asyncHolder.front()();
_asyncHolder.pop();

// If the validation failed abort the dispatching here.
if (!_predicate())
return;
}

while (!_task_holder.IsEmpty())
{
if (_task_holder.First()->_end > _now)
break;

// Perfect forward the context to the handler
// Use weak references to catch destruction before callbacks.
TaskContext context(_task_holder.Pop(), std::weak_ptr<TaskScheduler>(self_reference));

// Invoke the context
context.Invoke();

// If the validation failed abort the dispatching here.
if (!_predicate())
return;
}

// On finish call the final callback
callback();
}

void TaskScheduler::TaskQueue::Push(TaskContainer&& task)
{
container.insert(task);
}

auto TaskScheduler::TaskQueue::Pop() -> TaskContainer
{
TaskContainer result = *container.begin();
container.erase(container.begin());
return result;
}

auto TaskScheduler::TaskQueue::First() const -> TaskContainer const&
{
return *container.begin();
}

void TaskScheduler::TaskQueue::Clear()
{
container.clear();
}

void TaskScheduler::TaskQueue::RemoveIf(std::function<bool(TaskContainer const&)> const& filter)
{
for (auto itr = container.begin(); itr != container.end();)
if (filter(*itr))
itr = container.erase(itr);
else
++itr;
}

void TaskScheduler::TaskQueue::ModifyIf(std::function<bool(TaskContainer const&)> const& filter)
{
std::vector<TaskContainer> cache;
for (auto itr = container.begin(); itr != container.end();)
if (filter(*itr))
{
cache.push_back(*itr);
itr = container.erase(itr);
}
else
++itr;

container.insert(cache.begin(), cache.end());
}

bool TaskScheduler::TaskQueue::IsEmpty() const
{
return container.empty();
}

TaskContext& TaskContext::Dispatch(std::function<TaskScheduler&(TaskScheduler&)> const& apply)
{
if (auto const owner = _owner.lock())
apply(*owner);

return *this;
}

bool TaskContext::IsExpired() const
{
return _owner.expired();
}

bool TaskContext::IsInGroup(TaskScheduler::group_t const group) const
{
return _task->IsInGroup(group);
}

TaskContext& TaskContext::SetGroup(TaskScheduler::group_t const group)
{
_task->_group = group;
return *this;
}

TaskContext& TaskContext::ClearGroup()
{
_task->_group = std::nullopt;
return *this;
}

TaskScheduler::repeated_t TaskContext::GetRepeatCounter() const
{
return _task->_repeated;
}

TaskContext& TaskContext::Async(std::function<void()> const& callable)
{
return Dispatch(std::bind(&TaskScheduler::Async, std::placeholders::_1, callable));
}

TaskContext& TaskContext::CancelAll()
{
return Dispatch(std::mem_fn(&TaskScheduler::CancelAll));
}

TaskContext& TaskContext::CancelGroup(TaskScheduler::group_t const group)
{
return Dispatch(std::bind(&TaskScheduler::CancelGroup, std::placeholders::_1, group));
}

TaskContext& TaskContext::CancelGroupsOf(std::vector<TaskScheduler::group_t> const& groups)
{
return Dispatch(std::bind(&TaskScheduler::CancelGroupsOf, std::placeholders::_1, std::cref(groups)));
}

void TaskContext::AssertOnConsumed() const
{
// This was adapted to TC to prevent static analysis tools from complaining.
// If you encounter this assertion check if you repeat a TaskContext more then 1 time!
ASSERT(!(*_consumed) && "Bad task logic, task context was consumed already!");
}

void TaskContext::Invoke()
{
_task->_task(*this);
}
Loading