mirror of
https://github.com/donnaskiez/ac.git
synced 2024-11-21 22:24:08 +01:00
refactor the timer class a lil bit
This commit is contained in:
parent
51faa685ba
commit
67fe04c2e2
6 changed files with 132 additions and 124 deletions
|
@ -15,8 +15,14 @@ void dispatcher::dispatcher::timer_test_callback() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispatcher::dispatcher::init_timer_callbacks() {
|
void dispatcher::dispatcher::init_timer_callbacks() {
|
||||||
|
std::optional<HANDLE> result = this->timers.insert_callback(
|
||||||
|
std::bind(&dispatcher::dispatcher::timer_test_callback, this), 5, 5);
|
||||||
|
this->timers.insert_callback(
|
||||||
|
std::bind(&dispatcher::dispatcher::timer_test_callback, this), 7, 7);
|
||||||
this->timers.insert_callback(
|
this->timers.insert_callback(
|
||||||
std::bind(&dispatcher::dispatcher::timer_test_callback, this), 10, 10);
|
std::bind(&dispatcher::dispatcher::timer_test_callback, this), 10, 10);
|
||||||
|
|
||||||
|
this->timers.remove_callback(result.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispatcher::dispatcher::run_timer_thread() {
|
void dispatcher::dispatcher::run_timer_thread() {
|
||||||
|
@ -32,10 +38,10 @@ void dispatcher::dispatcher::run() {
|
||||||
this->init_timer_callbacks();
|
this->init_timer_callbacks();
|
||||||
this->run_timer_thread();
|
this->run_timer_thread();
|
||||||
this->run_io_port_thread();
|
this->run_io_port_thread();
|
||||||
thread_pool.queue_job([this]() { k_interface.run_completion_port(); });
|
//thread_pool.queue_job([this]() { k_interface.run_completion_port(); });
|
||||||
while (true) {
|
while (true) {
|
||||||
this->issue_kernel_job();
|
//this->issue_kernel_job();
|
||||||
helper::sleep_thread(DISPATCH_LOOP_SLEEP_TIME);
|
//helper::sleep_thread(DISPATCH_LOOP_SLEEP_TIME);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,12 @@
|
||||||
#include "../common.h"
|
#include "../common.h"
|
||||||
#include "../helper.h"
|
#include "../helper.h"
|
||||||
|
|
||||||
dispatcher::timer::timer() { this->active_callbacks = 0; }
|
dispatcher::timer::timer() {
|
||||||
|
this->active_callbacks = 0;
|
||||||
|
for (auto &entry : handles) {
|
||||||
|
entry = INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dispatcher::timer::~timer() {}
|
dispatcher::timer::~timer() {}
|
||||||
|
|
||||||
|
@ -18,65 +23,94 @@ bool dispatcher::timer::set_timer_object(HANDLE handle, LARGE_INTEGER *due_time,
|
||||||
: false;
|
: false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dispatcher::timer::insert_callback(std::function<void()> routine,
|
dispatcher::timer::callback::callback(std::function<void()> routine,
|
||||||
int due_time_seconds,
|
int due_time_seconds,
|
||||||
int period_seconds) {
|
int period_seconds) {
|
||||||
|
this->callback_routine = routine;
|
||||||
|
this->due_time.QuadPart = helper::seconds_to_nanoseconds(due_time_seconds);
|
||||||
|
this->period = helper::seconds_to_milliseconds(period_seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<HANDLE>
|
||||||
|
dispatcher::timer::insert_callback(std::function<void()> routine,
|
||||||
|
int due_time_seconds, int period_seconds) {
|
||||||
std::lock_guard<std::mutex> lock(this->lock);
|
std::lock_guard<std::mutex> lock(this->lock);
|
||||||
std::optional<int> index = this->find_free_handle_index();
|
std::optional<HANDLE *> handle = this->find_free_handle();
|
||||||
if (!index.has_value()) {
|
if (!handle.has_value()) {
|
||||||
LOG_ERROR("No free event handles available. Unable to create timer.");
|
LOG_ERROR("No free event handles available. Unable to create timer.");
|
||||||
return false;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
HANDLE handle = create_timer_object();
|
*handle.value() = create_timer_object();
|
||||||
if (!handle) {
|
if (*handle.value() == NULL) {
|
||||||
LOG_ERROR("CreateWaitableTimer failed with status %x", GetLastError());
|
LOG_ERROR("CreateWaitableTimer failed with status %x", GetLastError());
|
||||||
set_callback_inactive(index.value());
|
return {};
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
callback *cb = &this->callbacks[index.value()];
|
callback cb(routine, due_time_seconds, period_seconds);
|
||||||
cb->callback_routine = routine;
|
if (!set_timer_object(*handle.value(), &cb.due_time, cb.period)) {
|
||||||
cb->due_time.QuadPart = helper::seconds_to_nanoseconds(due_time_seconds);
|
|
||||||
cb->period = helper::seconds_to_milliseconds(period_seconds);
|
|
||||||
|
|
||||||
this->handles[index.value()] = handle;
|
|
||||||
if (!set_timer_object(handle, &cb->due_time, cb->period)) {
|
|
||||||
LOG_ERROR("SetWaitableTimer failed with status %x", GetLastError());
|
LOG_ERROR("SetWaitableTimer failed with status %x", GetLastError());
|
||||||
close_handle_entry(handle);
|
|
||||||
set_callback_inactive(index.value());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<HANDLE, callback> entry(*handle.value(), cb);
|
||||||
|
this->callbacks.insert(entry);
|
||||||
|
this->insert_handle(*handle.value());
|
||||||
this->active_callbacks++;
|
this->active_callbacks++;
|
||||||
return true;
|
return *handle.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* assumes lock is held by caller */
|
/* assumes lock is held by caller */
|
||||||
std::optional<int> dispatcher::timer::find_free_handle_index() {
|
std::optional<HANDLE *> dispatcher::timer::find_free_handle() {
|
||||||
for (int index = 0; index < MAXIMUM_WAIT_OBJECTS; index++) {
|
for (int index = 0; index < MAXIMUM_WAIT_OBJECTS; index++) {
|
||||||
if (callbacks[index].in_use == false) {
|
if (handles[index] == INVALID_HANDLE_VALUE)
|
||||||
callbacks[index].in_use = true;
|
return &handles[index];
|
||||||
return index;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispatcher::timer::close_handle_entry(HANDLE handle) {
|
/* assumes lock is held */
|
||||||
for (auto &entry : handles) {
|
void dispatcher::timer::insert_handle(HANDLE handle) {
|
||||||
if (entry == handle) {
|
for (HANDLE entry : this->handles) {
|
||||||
entry = INVALID_HANDLE_VALUE;
|
if (entry == INVALID_HANDLE_VALUE) {
|
||||||
CloseHandle(entry);
|
entry = handle;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispatcher::timer::set_callback_inactive(int index) {
|
/* assumes lock is held */
|
||||||
this->callbacks[index].in_use = false;
|
void dispatcher::timer::close_handle_entry(HANDLE handle) {
|
||||||
|
this->callbacks.erase(handle);
|
||||||
|
for (int entry = 0; entry < MAXIMUM_WAIT_OBJECTS; entry++) {
|
||||||
|
if (this->handles[entry] == handle) {
|
||||||
|
CloseHandle(handle);
|
||||||
|
this->handles[entry] = INVALID_HANDLE_VALUE;
|
||||||
|
/* ordering doesnt matter, aslong as the valid handles are at the front of
|
||||||
|
* the array and are contiguous */
|
||||||
|
std::sort(this->handles.begin(), this->handles.end());
|
||||||
|
this->active_callbacks--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispatcher::timer::dispatch_callback_for_index(unsigned long index) {
|
void dispatcher::timer::dispatch_callback_for_index(unsigned long index) {
|
||||||
this->callbacks[index].callback_routine();
|
std::unordered_map<HANDLE, callback>::const_iterator it =
|
||||||
|
this->callbacks.find(handles[index]);
|
||||||
|
if (it == this->callbacks.end())
|
||||||
|
return;
|
||||||
|
it->second.callback_routine();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* assumes lock is held */
|
||||||
|
void dispatcher::timer::query_removal_queue() {
|
||||||
|
if (callbacks_to_remove.empty())
|
||||||
|
return;
|
||||||
|
while (!callbacks_to_remove.empty()) {
|
||||||
|
HANDLE entry = callbacks_to_remove.front();
|
||||||
|
this->close_handle_entry(entry);
|
||||||
|
this->callbacks_to_remove.pop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dispatcher::timer::run_timer_thread() {
|
void dispatcher::timer::run_timer_thread() {
|
||||||
|
@ -84,6 +118,22 @@ void dispatcher::timer::run_timer_thread() {
|
||||||
unsigned long index = WaitForMultipleObjects(
|
unsigned long index = WaitForMultipleObjects(
|
||||||
this->active_callbacks, reinterpret_cast<HANDLE *>(&handles), false,
|
this->active_callbacks, reinterpret_cast<HANDLE *>(&handles), false,
|
||||||
INFINITE);
|
INFINITE);
|
||||||
this->dispatch_callback_for_index(index);
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(this->lock);
|
||||||
|
this->dispatch_callback_for_index(index);
|
||||||
|
this->query_removal_queue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we remove a callback whilst the main loop is sleeping, it means the
|
||||||
|
* information passed to KeWaitForMultipleObjects will be wrong, hence we need
|
||||||
|
* to wait until our thread is run by the scheduler, perform the operation for
|
||||||
|
* the alerted handle and THEN remove any entries from the removal queue. Then
|
||||||
|
* once we recall KeWaitForMultipleObjects the new handle array will be valid.
|
||||||
|
*/
|
||||||
|
void dispatcher::timer::remove_callback(HANDLE handle) {
|
||||||
|
std::lock_guard<std::mutex> lock(this->lock);
|
||||||
|
this->callbacks_to_remove.push(handle);
|
||||||
}
|
}
|
|
@ -7,6 +7,8 @@
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* array of handles which we pass to WaitForMultipleEvents
|
* array of handles which we pass to WaitForMultipleEvents
|
||||||
|
@ -38,28 +40,34 @@ class timer {
|
||||||
std::function<void()> callback_routine;
|
std::function<void()> callback_routine;
|
||||||
LARGE_INTEGER due_time;
|
LARGE_INTEGER due_time;
|
||||||
unsigned long period;
|
unsigned long period;
|
||||||
|
|
||||||
|
callback(std::function<void()> routine, int due_time_seconds,
|
||||||
|
int period_seconds);
|
||||||
};
|
};
|
||||||
|
|
||||||
std::optional<int> find_free_handle_index();
|
std::optional<HANDLE *> find_free_handle();
|
||||||
void close_handle_entry(HANDLE handle);
|
void close_handle_entry(HANDLE handle);
|
||||||
void dispatch_callback_for_index(unsigned long index);
|
void dispatch_callback_for_index(unsigned long index);
|
||||||
HANDLE create_timer_object();
|
HANDLE create_timer_object();
|
||||||
bool set_timer_object(HANDLE handle, LARGE_INTEGER *due_time,
|
bool set_timer_object(HANDLE handle, LARGE_INTEGER *due_time,
|
||||||
unsigned long period);
|
unsigned long period);
|
||||||
void set_callback_inactive(int index);
|
void query_removal_queue();
|
||||||
|
void insert_handle(HANDLE handle);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::mutex lock;
|
std::mutex lock;
|
||||||
std::array<HANDLE, MAXIMUM_WAIT_OBJECTS> handles;
|
std::array<HANDLE, MAXIMUM_WAIT_OBJECTS> handles;
|
||||||
std::array<callback, MAXIMUM_WAIT_OBJECTS> callbacks;
|
std::unordered_map<HANDLE, callback> callbacks;
|
||||||
|
std::queue<HANDLE> callbacks_to_remove;
|
||||||
|
|
||||||
int active_callbacks;
|
int active_callbacks;
|
||||||
|
|
||||||
timer();
|
timer();
|
||||||
~timer();
|
~timer();
|
||||||
|
|
||||||
bool insert_callback(std::function<void()> routine, int due_time_seconds,
|
std::optional<HANDLE> insert_callback(std::function<void()> routine, int due_time_seconds,
|
||||||
int period_seconds);
|
int period_seconds);
|
||||||
|
void remove_callback(HANDLE handle);
|
||||||
void run_timer_thread();
|
void run_timer_thread();
|
||||||
};
|
};
|
||||||
} // namespace dispatcher
|
} // namespace dispatcher
|
|
@ -2,7 +2,10 @@
|
||||||
|
|
||||||
#include "module.h"
|
#include "module.h"
|
||||||
|
|
||||||
DWORD WINAPI Init(HINSTANCE hinstDLL) { module::run(hinstDLL); }
|
DWORD WINAPI Init(HINSTANCE hinstDLL) {
|
||||||
|
module::run(hinstDLL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call,
|
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call,
|
||||||
LPVOID lpReserved) {
|
LPVOID lpReserved) {
|
||||||
|
|
|
@ -110,8 +110,9 @@
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<PreprocessorDefinitions>_DEBUG;MODULE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>_DEBUG;MODULE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<ConformanceMode>true</ConformanceMode>
|
<ConformanceMode>true</ConformanceMode>
|
||||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
|
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
|
|
|
@ -1,87 +1,27 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="Source Files">
|
<ClCompile Include="dispatcher\timer.cpp" />
|
||||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
<ClCompile Include="helper.cpp" />
|
||||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
<ClCompile Include="imports.cpp" />
|
||||||
</Filter>
|
<ClCompile Include="module.cpp" />
|
||||||
<Filter Include="Header Files">
|
<ClCompile Include="client\message_queue.cpp" />
|
||||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
<ClCompile Include="client\pipe.cpp" />
|
||||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
<ClCompile Include="dispatcher\dispatcher.cpp" />
|
||||||
</Filter>
|
<ClCompile Include="dispatcher\threadpool.cpp" />
|
||||||
<Filter Include="Resource Files">
|
<ClCompile Include="main.cpp" />
|
||||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
<ClCompile Include="kernel_interface\kernel_interface.cpp" />
|
||||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
|
||||||
</Filter>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="main.cpp">
|
<ClInclude Include="client\message_queue.h" />
|
||||||
<Filter>Source Files</Filter>
|
<ClInclude Include="client\pipe.h" />
|
||||||
</ClCompile>
|
<ClInclude Include="dispatcher\dispatcher.h" />
|
||||||
<ClCompile Include="kernel_interface\kernel_interface.cpp">
|
<ClInclude Include="dispatcher\threadpool.h" />
|
||||||
<Filter>Source Files</Filter>
|
<ClInclude Include="common.h" />
|
||||||
</ClCompile>
|
<ClInclude Include="dispatcher\timer.h" />
|
||||||
<ClCompile Include="dispatcher\dispatcher.cpp">
|
<ClInclude Include="helper.h" />
|
||||||
<Filter>Source Files</Filter>
|
<ClInclude Include="imports.h" />
|
||||||
</ClCompile>
|
<ClInclude Include="kernel_interface\kernel_interface.h" />
|
||||||
<ClCompile Include="dispatcher\threadpool.cpp">
|
<ClInclude Include="module.h" />
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="client\message_queue.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="client\pipe.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="module.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="helper.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="imports.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
um-rewrite-final
|
|
||||||
<ClCompile Include="dispatcher\timer.cpp">
|
|
||||||
<Filter>Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
=======
|
|
||||||
master
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="common.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="kernel_interface\kernel_interface.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="dispatcher\dispatcher.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="dispatcher\threadpool.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="client\message_queue.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="client\pipe.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="module.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="helper.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="imports.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
um-rewrite-final
|
|
||||||
<ClInclude Include="dispatcher\timer.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
=======
|
|
||||||
master
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
Loading…
Reference in a new issue