TeaSpeakLibrary/src/EventLoop.h

90 lines
3.2 KiB
C
Raw Normal View History

2019-06-26 22:11:22 +02:00
#pragma once
#include <mutex>
#include <memory>
#include <vector>
#include <string>
#include <thread>
#include <condition_variable>
namespace ts {
2020-01-24 02:49:59 +01:00
namespace event {
class EventExecutor;
2019-06-26 22:11:22 +02:00
2020-01-24 02:49:59 +01:00
class EventEntry {
friend class EventExecutor;
public:
virtual void event_execute(const std::chrono::system_clock::time_point& /* scheduled timestamp */) = 0;
2019-06-26 22:11:22 +02:00
2020-01-24 02:49:59 +01:00
private:
void* _event_ptr = nullptr;
};
2019-06-26 22:11:22 +02:00
2020-01-24 02:49:59 +01:00
template <typename class_t>
class ProxiedEventEntry : public event::EventEntry {
public:
using callback_t = void(class_t::*)(const std::chrono::system_clock::time_point &);
2020-02-15 14:01:07 +01:00
using static_callback_t = void(*)(class_t *, const std::chrono::system_clock::time_point &);
2019-06-26 22:11:22 +02:00
2020-01-24 02:49:59 +01:00
ProxiedEventEntry(const std::shared_ptr<class_t>& _instance, callback_t callback) : instance(_instance), callback(callback) { }
2019-06-26 22:11:22 +02:00
2020-01-24 02:49:59 +01:00
std::weak_ptr<class_t> instance;
callback_t callback;
2019-06-26 22:11:22 +02:00
2020-01-24 02:49:59 +01:00
void event_execute(const std::chrono::system_clock::time_point &point) override {
auto _instance = this->instance.lock();
if(!_instance)
return;
2019-06-26 22:11:22 +02:00
2020-02-15 14:01:07 +01:00
auto callback_ptr = (void**) &this->callback;
(*(static_callback_t*) callback_ptr)(&*_instance, point);
2020-01-24 02:49:59 +01:00
}
};
2019-06-26 22:11:22 +02:00
2020-01-24 02:49:59 +01:00
class EventExecutor {
public:
explicit EventExecutor(const std::string& /* thread prefix */);
virtual ~EventExecutor();
2019-06-26 22:11:22 +02:00
2020-01-24 02:49:59 +01:00
bool initialize(int /* num threads */);
bool schedule(const std::shared_ptr<EventEntry>& /* entry */);
bool cancel(const std::shared_ptr<EventEntry>& /* entry */); /* Note: Will not cancel already running executes */
void shutdown();
2019-06-26 22:11:22 +02:00
2020-01-24 02:49:59 +01:00
inline const std::string& thread_prefix() const { return this->_thread_prefix; }
2019-06-26 22:11:22 +02:00
2020-01-24 02:49:59 +01:00
void threads(int /* num threads */);
inline int threads() const { return this->target_threads; }
private:
struct LinkedEntry {
LinkedEntry* previous;
LinkedEntry* next;
2019-06-26 22:11:22 +02:00
2020-01-24 02:49:59 +01:00
std::chrono::system_clock::time_point scheduled;
std::weak_ptr<EventEntry> entry;
};
2019-06-26 22:11:22 +02:00
2020-01-24 02:49:59 +01:00
static void _executor(EventExecutor*);
void _spawn_executor(std::unique_lock<std::mutex>&);
void _shutdown(std::unique_lock<std::mutex>&);
void _reset_events(std::unique_lock<std::mutex>&);
2019-06-26 22:11:22 +02:00
#ifndef WIN32
2020-01-24 02:49:59 +01:00
void _reassign_thread_names(std::unique_lock<std::mutex>&);
2019-06-26 22:11:22 +02:00
#endif
2020-01-24 02:49:59 +01:00
bool should_shutdown = true;
bool should_adjust = false; /* thread adjustments */
int target_threads = 0;
2019-06-26 22:11:22 +02:00
2020-01-24 02:49:59 +01:00
std::vector<std::thread> _threads;
std::mutex lock;
std::condition_variable condition;
2019-06-26 22:11:22 +02:00
2020-01-24 02:49:59 +01:00
LinkedEntry* head = nullptr;
LinkedEntry* tail = nullptr;
2019-06-26 22:11:22 +02:00
2020-01-24 02:49:59 +01:00
std::string _thread_prefix;
};
}
2019-06-26 22:11:22 +02:00
}