Skip to content

Commit

Permalink
feat: add TickSyncTaskPool
Browse files Browse the repository at this point in the history
  • Loading branch information
OEOTYAN committed Nov 24, 2023
1 parent 936fc71 commit c24be30
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 22 deletions.
1 change: 0 additions & 1 deletion src/ll/api/chrono/GameChrono.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#include "ll/api/service/GlobalService.h"

#include "mc/server/ServerLevel.h"
#include "mc/world/level/Level.h"
#include "mc/world/level/Tick.h"

namespace ll::chrono::game_chrono {
Expand Down
21 changes: 13 additions & 8 deletions src/ll/api/chrono/TickSyncSleep.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,23 @@
#include "ll/api/memory/Hook.h"
#include "mc/server/ServerLevel.h"

namespace ll::chrono {
namespace detail {
std::mutex listMutex;
namespace ll::chrono::detail {
std::mutex listMutex;
std::atomic_size_t tickListSize{};
std::atomic_bool hooked{};
std::vector<std::variant<
std::reference_wrapper<TickSyncSleep<game_chrono::ServerClock>>,
std::reference_wrapper<TickSyncSleep<game_chrono::GameTimeClock>>>>
tickList;
} // namespace detail
LL_AUTO_TYPED_INSTANCE_HOOK(
TickSyncSleepInterrruptHook,
HookPriority::Normal,
ServerLevel,
&ServerLevel::_subTick,
void
) {
origin();
using namespace detail;
if (!tickList.empty()) {
if (tickListSize > 0) {
std::lock_guard lock(listMutex);
for (auto& e : tickList) {
std::visit(
Expand All @@ -45,7 +44,13 @@ LL_AUTO_TYPED_INSTANCE_HOOK(
e
);
}
} else {
unhook();
hooked = false;
}
origin();
}

} // namespace ll::chrono
void notify() {
if (!hooked) TickSyncSleepInterrruptHook::hook();
}
} // namespace ll::chrono::detail
9 changes: 7 additions & 2 deletions src/ll/api/chrono/TickSyncSleep.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ template <class Clock>
class TickSyncSleep;
namespace detail {
LLETAPI std::mutex listMutex;
LLETAPI std::vector<std::variant<
LLETAPI std::atomic_size_t tickListSize;
LLETAPI std::vector<std::variant<
std::reference_wrapper<TickSyncSleep<game_chrono::ServerClock>>,
std::reference_wrapper<TickSyncSleep<game_chrono::GameTimeClock>>>>
tickList;
tickList;
LLAPI void notify();
}; // namespace detail

template <class Clock>
Expand Down Expand Up @@ -48,6 +50,8 @@ class TickSyncSleep {
std::lock_guard lock(listMutex);
id = tickList.size();
tickList.emplace_back(std::ref(*this));
++tickListSize;
notify();
}

~TickSyncSleep() {
Expand All @@ -56,6 +60,7 @@ class TickSyncSleep {
state = State::None;
std::swap(tickList[id], tickList.back());
tickList.pop_back();
--tickListSize;
}

void sleepFor(Clock::duration duration) {
Expand Down
21 changes: 13 additions & 8 deletions src/ll/api/schedule/Scheduler.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "ll/api/schedule/Task.h"
#include "ll/api/thread/InterruptableSleep.h"
#include "ll/api/thread/ThreadPool.h"
#include "ll/api/thread/TickSyncTaskPool.h"

namespace ll::schedule {

Expand All @@ -26,15 +27,17 @@ struct SleeperType<ll::chrono::GameTimeClock> {
using Type = ll::chrono::TickSyncSleep<ll::chrono::GameTimeClock>;
};

template <class Clock, class Sleeper = SleeperType<Clock>::Type, class Pool = ll::thread::ThreadPool>
template <class Clock, class Pool = ll::thread::ThreadPool, class Sleeper = SleeperType<Clock>::Type>
class Scheduler;

using GameTickScheduler = Scheduler<ll::chrono::ServerClock>;
using GameTimeScheduler = Scheduler<ll::chrono::GameTimeClock>;

using SystemTimeScheduler = Scheduler<std::chrono::system_clock>;

template <class Clock, class Sleeper, class Pool>
using GameSyncTickScheduler = Scheduler<ll::chrono::ServerClock, ll::thread::TickSyncTaskPool>;
using GameSyncTimeScheduler = Scheduler<ll::chrono::GameTimeClock, ll::thread::TickSyncTaskPool>;

template <class Clock, class Pool, class Sleeper>
class Scheduler {
private:
using TimePoint = typename Clock::time_point;
Expand All @@ -46,7 +49,8 @@ class Scheduler {
std::atomic<bool> done;
std::mutex mutex;
Sleeper sleeper;
Pool threads;
Pool workers;
std::thread manager;

std::weak_ptr<Task<Clock>> addTask(TaskPtr t) {
std::weak_ptr<Task<Clock>> res = t;
Expand Down Expand Up @@ -80,7 +84,7 @@ class Scheduler {
continue;
}
if (task->interval) {
threads.addTask([this, task] {
workers.addTask([this, task] {
try {
task->f();
} catch (...) {
Expand All @@ -89,7 +93,7 @@ class Scheduler {
addTask(task);
});
} else {
threads.addTask([task] {
workers.addTask([task] {
try {
task->f();
} catch (...) {
Expand All @@ -116,8 +120,8 @@ class Scheduler {
Scheduler& operator=(Scheduler const&) = delete;
Scheduler& operator=(Scheduler&&) noexcept = delete;

explicit Scheduler(int maxThreads = 1) : done(false), threads(std::max<int>(1, maxThreads) + 1) {
threads.addTask([this] {
explicit Scheduler(int maxThreads = 1) : done(false), workers(std::max<int>(1, maxThreads)) {
manager = std::thread([this] {
while (!done) {
if (tasks.empty()) {
sleeper.sleep();
Expand All @@ -132,6 +136,7 @@ class Scheduler {
~Scheduler() {
done = true;
sleeper.interrupt();
manager.join();
}

template <template <class> class T, class... Args>
Expand Down
28 changes: 28 additions & 0 deletions src/ll/api/thread/TickSyncTaskPool.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include "ll/api/thread/TickSyncTaskPool.h"
#include "ll/api/memory/Hook.h"

#include "mc/server/ServerLevel.h"
#include "mc/world/level/Tick.h"

namespace ll::thread {
std::vector<std::function<void()>> TickSyncTaskPool::tasks;
std::atomic_bool TickSyncTaskPool::hasTask;
std::mutex TickSyncTaskPool::mutex;

LL_TYPED_INSTANCE_HOOK(TickSyncTaskPoolWorker, HookPriority::Normal, ServerLevel, &ServerLevel::_subTick, void) {
origin();
if (TickSyncTaskPool::hasTask) {
std::lock_guard lock{TickSyncTaskPool::mutex};
for (auto& task : TickSyncTaskPool::tasks) {
task();
}
TickSyncTaskPool::tasks.clear();
TickSyncTaskPool::hasTask = false;
}
}

void TickSyncTaskPool::notify() {
static memory::HookAutoRegister<TickSyncTaskPoolWorker> reg{};
hasTask = true;
}
} // namespace ll::thread
47 changes: 47 additions & 0 deletions src/ll/api/thread/TickSyncTaskPool.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#pragma once

#include <functional>
#include <future>
#include <memory>
#include <mutex>
#include <queue>
#include <stdexcept>
#include <thread>
#include <vector>

#include "ll/api/base/Macro.h"
#include "ll/api/base/StdInt.h"

namespace ll::thread {
struct TickSyncTaskPoolWorker;
class TickSyncTaskPool {
friend TickSyncTaskPoolWorker;

private:
LLAPI static std::vector<std::function<void()>> tasks;
LLAPI static std::atomic_bool hasTask;
LLAPI static std::mutex mutex;

LLAPI static void notify();

public:
explicit TickSyncTaskPool(size_t) {}
~TickSyncTaskPool() = default;

template <class F, class... Args>
decltype(auto) addTask(F&& f, Args&&... args) {

auto task = std::move(std::make_shared<std::packaged_task<std::invoke_result_t<F, Args...>()>>(
[f = std::forward<F>(f), args...] { return f(args...); }
));
auto res = task->get_future();
{
std::lock_guard lock{mutex};
tasks.emplace_back([task] { (*task)(); });
}
notify();

return res;
}
};
} // namespace ll::thread
6 changes: 3 additions & 3 deletions src/ll/test/ScheduleTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ using namespace ll::chrono_literals;

ll::Logger schedulelogger("Schedule");

SystemTimeScheduler s;
GameTickScheduler s2;
GameTimeScheduler s3;
SystemTimeScheduler s;
GameSyncTickScheduler s2;
GameTimeScheduler s3;

#include "mc/network/packet/TextPacket.h"

Expand Down

0 comments on commit c24be30

Please sign in to comment.