Trying to learn windows internals and made my first work with Events and Threads. What do you think about my code? Any advice?
#include <windows.h>
#include <iostream>
#include <vector>
enum class EventType : UINT8
{
EVENT_TYPE_1,
EVENT_TYPE_N
};
using EventFnc = void (*)(void);
struct Event
{
EventType type;
EventFnc on_event_fnc;
};
class Events
{
private:
std::vector<Event> _events;
std::vector<HANDLE> _handles;
HANDLE events_changed_evt{INVALID_HANDLE_VALUE};
HANDLE events_dtor_evt{INVALID_HANDLE_VALUE};
HANDLE wait_event_thread_hwnd{INVALID_HANDLE_VALUE};
DWORD wait_event_thread_id{0};
private:
static DWORD WINAPI _WaitEventThreadStatic(LPVOID param)
{
return ((Events *)param)->_WaitEventProc();
}
DWORD WINAPI _WaitEventProc()
{
while (true)
{
DWORD event_index = WaitForMultipleObjects(_handles.size(), _handles.data(), FALSE, INFINITE);
if (event_index == WAIT_FAILED)
{
throw std::runtime_error("WaitForMultipleObjects failed");
}
event_index -= WAIT_OBJECT_0;
switch (event_index)
{
case 0:
/* events_changed_evt */
continue;
case 1:
/* events_dtor_evt */
return 0;
default:
/* user events */
SIZE_T idx = event_index - (_handles.size() - _events.size());
_events[idx].on_event_fnc();
break;
}
}
return 0;
}
public:
Events()
{
events_dtor_evt = ::CreateEventW(NULL, FALSE, FALSE, NULL);
if (events_dtor_evt == NULL)
{
throw std::runtime_error("Failed to create event");
}
events_changed_evt = ::CreateEventW(NULL, FALSE, FALSE, NULL);
if (events_changed_evt == NULL)
{
throw std::runtime_error("Failed to create event");
}
wait_event_thread_hwnd = ::CreateThread(NULL, 0, _WaitEventThreadStatic, (LPVOID)this, CREATE_SUSPENDED, &wait_event_thread_id);
if (wait_event_thread_hwnd == NULL)
{
throw std::runtime_error("Failed to create thread");
}
_handles.push_back(events_changed_evt);
_handles.push_back(events_dtor_evt);
if (::ResumeThread(wait_event_thread_hwnd) == (DWORD)-1)
{
throw std::runtime_error("Failed to resume thread");
}
}
~Events()
{
::SetEvent(events_dtor_evt);
for (const auto hwnd : _handles)
{
::CloseHandle(hwnd);
}
::CloseHandle(wait_event_thread_hwnd);
}
Events(const Event &) = delete;
Events(Event &&) = delete;
Events &operator=(const Event &) = delete;
Events &operator=(Event &&) = delete;
public:
SIZE_T AddEvent(const Event &event)
{
HANDLE hwnd = ::CreateEventW(NULL, FALSE, FALSE, NULL);
if (hwnd == NULL)
{
throw std::runtime_error("Failed to create event");
}
_events.push_back(event);
_handles.push_back(hwnd);
::SetEvent(events_changed_evt);
return _handles.size()-1;
}
bool TriggerEvent(SIZE_T event_id) const
{
if (event_id < _handles.size())
{
::SetEvent(_handles[event_id]);
return true;
}
return false;
}
// bool TriggerEvent(EventType event_type) const
// {
// bool res{false};
// for (const auto &event : _events)
// {
// if (event.type == event_type)
// {
// ::SetEvent(_handles[event.id]);
// res = true;
// }
// }
// return res;
// }
};
void OnEvent(void){
std::cout << "Event 1";
}
int APIENTRY main()
{
Events evts;
SIZE_T id = evts.AddEvent({EventType::EVENT_TYPE_1,&OnEvent});
evts.TriggerEvent(id);
while(true);
return 0;
}