beginning of the scheduler
This commit is contained in:
parent
f1a2006b4b
commit
26114aad5f
@ -38,6 +38,7 @@ Server::Server():
|
|||||||
router(std::make_shared<Router>()),
|
router(std::make_shared<Router>()),
|
||||||
pool(DB::Pool::create()),
|
pool(DB::Pool::create()),
|
||||||
taskManager(std::make_shared<TM::Manager>()),
|
taskManager(std::make_shared<TM::Manager>()),
|
||||||
|
scheduler(std::make_shared<TM::Scheduler>(taskManager)),
|
||||||
sessions()
|
sessions()
|
||||||
{
|
{
|
||||||
std::cout << "Startig pica..." << std::endl;
|
std::cout << "Startig pica..." << std::endl;
|
||||||
@ -65,6 +66,28 @@ void Server::run(int socketDescriptor) {
|
|||||||
router->addRoute(std::make_unique<Handler::Login>(shared_from_this()));
|
router->addRoute(std::make_unique<Handler::Login>(shared_from_this()));
|
||||||
|
|
||||||
taskManager->start();
|
taskManager->start();
|
||||||
|
scheduler->start();
|
||||||
|
|
||||||
|
scheduler->schedule([]() {
|
||||||
|
std::cout << "5000" << std::endl;
|
||||||
|
}, TM::Scheduler::Delay(5000));
|
||||||
|
scheduler->schedule([]() {
|
||||||
|
std::cout << "2000" << std::endl;
|
||||||
|
}, TM::Scheduler::Delay(2000));
|
||||||
|
scheduler->schedule([]() {
|
||||||
|
std::cout << "6000" << std::endl;
|
||||||
|
}, TM::Scheduler::Delay(6000));
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||||
|
|
||||||
|
scheduler->schedule([]() {
|
||||||
|
std::cout << "2000 + 500" << std::endl;
|
||||||
|
}, TM::Scheduler::Delay(2000));
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
|
|
||||||
|
scheduler->schedule([]() {
|
||||||
|
std::cout << "1000 + 600" << std::endl;
|
||||||
|
}, TM::Scheduler::Delay(1000));
|
||||||
|
|
||||||
while (!terminating) {
|
while (!terminating) {
|
||||||
std::unique_ptr<Request> request = std::make_unique<Request>();
|
std::unique_ptr<Request> request = std::make_unique<Request>();
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "utils/helpers.h"
|
#include "utils/helpers.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "taskmanager/manager.h"
|
#include "taskmanager/manager.h"
|
||||||
|
#include "taskmanager/scheduler.h"
|
||||||
|
|
||||||
class Server : public std::enable_shared_from_this<Server> {
|
class Server : public std::enable_shared_from_this<Server> {
|
||||||
public:
|
public:
|
||||||
@ -52,5 +53,6 @@ private:
|
|||||||
std::shared_ptr<Router> router;
|
std::shared_ptr<Router> router;
|
||||||
std::shared_ptr<DB::Pool> pool;
|
std::shared_ptr<DB::Pool> pool;
|
||||||
std::shared_ptr<TM::Manager> taskManager;
|
std::shared_ptr<TM::Manager> taskManager;
|
||||||
|
std::shared_ptr<TM::Scheduler> scheduler;
|
||||||
Sessions sessions;
|
Sessions sessions;
|
||||||
};
|
};
|
||||||
|
@ -5,12 +5,14 @@ set(HEADERS
|
|||||||
manager.h
|
manager.h
|
||||||
job.h
|
job.h
|
||||||
route.h
|
route.h
|
||||||
|
scheduler.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
manager.cpp
|
manager.cpp
|
||||||
job.cpp
|
job.cpp
|
||||||
route.cpp
|
route.cpp
|
||||||
|
scheduler.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_sources(${PROJECT_NAME} PRIVATE ${SOURCES})
|
target_sources(${PROJECT_NAME} PRIVATE ${SOURCES})
|
||||||
|
75
taskmanager/scheduler.cpp
Normal file
75
taskmanager/scheduler.cpp
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
//SPDX-FileCopyrightText: 2023 Yury Gubich <blue@macaw.me>
|
||||||
|
//SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#include "scheduler.h"
|
||||||
|
|
||||||
|
TM::Scheduler::Scheduler (std::weak_ptr<Manager> manager):
|
||||||
|
manager(manager),
|
||||||
|
queue(),
|
||||||
|
mutex(),
|
||||||
|
cond(),
|
||||||
|
thread(nullptr),
|
||||||
|
running(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
TM::Scheduler::~Scheduler () {
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TM::Scheduler::start () {
|
||||||
|
std::unique_lock lock(mutex);
|
||||||
|
if (running)
|
||||||
|
return;
|
||||||
|
|
||||||
|
running = true;
|
||||||
|
thread = std::make_unique<std::thread>(&Scheduler::loop, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TM::Scheduler::stop () {
|
||||||
|
std::unique_lock lock(mutex);
|
||||||
|
if (!running)
|
||||||
|
return;
|
||||||
|
|
||||||
|
running = false;
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
cond.notify_all();
|
||||||
|
thread->join();
|
||||||
|
|
||||||
|
lock.lock();
|
||||||
|
thread.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TM::Scheduler::loop () {
|
||||||
|
while (running) {
|
||||||
|
std::unique_lock<std::mutex> lock(mutex);
|
||||||
|
if (queue.empty()) {
|
||||||
|
cond.wait(lock);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Time currentTime = std::chrono::steady_clock::now();
|
||||||
|
while (!queue.empty()) {
|
||||||
|
Time nextScheduledTime = queue.top().first;
|
||||||
|
if (nextScheduledTime > currentTime) {
|
||||||
|
cond.wait_until(lock, nextScheduledTime);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Task task = queue.top().second;
|
||||||
|
queue.pop();
|
||||||
|
lock.unlock();
|
||||||
|
task();
|
||||||
|
lock.lock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TM::Scheduler::schedule (Task task, Delay delay) {
|
||||||
|
std::unique_lock lock(mutex);
|
||||||
|
Time time = std::chrono::steady_clock::now() + delay;
|
||||||
|
queue.emplace(time, task);
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
cond.notify_one();
|
||||||
|
}
|
48
taskmanager/scheduler.h
Normal file
48
taskmanager/scheduler.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
//SPDX-FileCopyrightText: 2023 Yury Gubich <blue@macaw.me>
|
||||||
|
//SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <thread>
|
||||||
|
#include <queue>
|
||||||
|
#include <chrono>
|
||||||
|
#include <functional>
|
||||||
|
#include <mutex>
|
||||||
|
#include <condition_variable>
|
||||||
|
|
||||||
|
#include "manager.h"
|
||||||
|
#include "utils/helpers.h"
|
||||||
|
|
||||||
|
namespace TM {
|
||||||
|
class Scheduler {
|
||||||
|
public:
|
||||||
|
using Delay = std::chrono::milliseconds;
|
||||||
|
using Task = std::function<void()>;
|
||||||
|
|
||||||
|
Scheduler (std::weak_ptr<Manager> manager);
|
||||||
|
~Scheduler ();
|
||||||
|
|
||||||
|
void start();
|
||||||
|
void stop();
|
||||||
|
void schedule(Task task, Delay delay);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void loop();
|
||||||
|
|
||||||
|
private:
|
||||||
|
using Time = std::chrono::time_point<std::chrono::steady_clock>;
|
||||||
|
using Record = std::pair<Time, Task>;
|
||||||
|
|
||||||
|
std::weak_ptr<Manager> manager;
|
||||||
|
std::priority_queue<
|
||||||
|
Record,
|
||||||
|
std::vector<Record>,
|
||||||
|
FirstGreater<Record>
|
||||||
|
> queue;
|
||||||
|
std::mutex mutex;
|
||||||
|
std::condition_variable cond;
|
||||||
|
std::unique_ptr<std::thread> thread;
|
||||||
|
bool running;
|
||||||
|
};
|
||||||
|
}
|
@ -15,3 +15,10 @@ void ltrim(std::string& string);
|
|||||||
void rtrim(std::string& string);
|
void rtrim(std::string& string);
|
||||||
void trim(std::string& string);
|
void trim(std::string& string);
|
||||||
std::string extract(std::string& string, std::string::size_type begin, std::string::size_type end);
|
std::string extract(std::string& string, std::string::size_type begin, std::string::size_type end);
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct FirstGreater {
|
||||||
|
bool operator () (T left, T right) {
|
||||||
|
return std::get<0>(left) > std::get<0>(right);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user