From abb87f497f109d9d37b908325197bb5ea4aefcd1 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin <stenzek@gmail.com> Date: Sun, 5 Apr 2020 22:57:35 +1000 Subject: [PATCH] Common: Port Event class from YBaseLib over --- src/common/CMakeLists.txt | 2 + src/common/common.vcxproj | 2 + src/common/common.vcxproj.filters | 2 + src/common/event.cpp | 138 ++++++++++++++++++++++++++++++ src/common/event.h | 30 +++++++ 5 files changed, 174 insertions(+) create mode 100644 src/common/event.cpp create mode 100644 src/common/event.h diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 64416c592..e0f111d84 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -19,6 +19,8 @@ add_library(common cpu_detect.h cubeb_audio_stream.cpp cubeb_audio_stream.h + event.cpp + event.h fifo_queue.h file_system.cpp file_system.h diff --git a/src/common/common.vcxproj b/src/common/common.vcxproj index 5c958f25d..9e59e7caa 100644 --- a/src/common/common.vcxproj +++ b/src/common/common.vcxproj @@ -48,6 +48,7 @@ <ClInclude Include="d3d11\staging_texture.h" /> <ClInclude Include="d3d11\stream_buffer.h" /> <ClInclude Include="d3d11\texture.h" /> + <ClInclude Include="event.h" /> <ClInclude Include="fifo_queue.h" /> <ClInclude Include="file_system.h" /> <ClInclude Include="gl\program.h" /> @@ -87,6 +88,7 @@ <ClCompile Include="d3d11\staging_texture.cpp" /> <ClCompile Include="d3d11\stream_buffer.cpp" /> <ClCompile Include="d3d11\texture.cpp" /> + <ClCompile Include="event.cpp" /> <ClCompile Include="file_system.cpp" /> <ClCompile Include="gl\program.cpp" /> <ClCompile Include="gl\shader_cache.cpp" /> diff --git a/src/common/common.vcxproj.filters b/src/common/common.vcxproj.filters index bc01bd681..a741709c2 100644 --- a/src/common/common.vcxproj.filters +++ b/src/common/common.vcxproj.filters @@ -56,6 +56,7 @@ <ClInclude Include="gl\shader_cache.h"> <Filter>gl</Filter> </ClInclude> + <ClInclude Include="event.h" /> </ItemGroup> <ItemGroup> <ClCompile Include="jit_code_buffer.cpp" /> @@ -108,6 +109,7 @@ <ClCompile Include="gl\shader_cache.cpp"> <Filter>gl</Filter> </ClCompile> + <ClCompile Include="event.cpp" /> </ItemGroup> <ItemGroup> <Natvis Include="bitfield.natvis" /> diff --git a/src/common/event.cpp b/src/common/event.cpp new file mode 100644 index 000000000..aad3b3a81 --- /dev/null +++ b/src/common/event.cpp @@ -0,0 +1,138 @@ +#include "event.h" +#include "assert.h" + +#if defined(WIN32) +#include <malloc.h> +#include "windows_headers.h" +#elif defined(__linux__) || defined(__APPLE__) +#include <fcntl.h> +#include <poll.h> +#include <unistd.h> +#ifdef __APPLE__ +#include <stdlib.h> +#else +#include <malloc.h> +#endif +#endif + +namespace Common { + +#if defined(WIN32) + +Event::Event(bool auto_reset /* = false */) +{ + m_event_handle = reinterpret_cast<void*>(CreateEvent(nullptr, auto_reset ? FALSE : TRUE, FALSE, nullptr)); + Assert(m_event_handle != nullptr); +} + +Event::~Event() +{ + CloseHandle(reinterpret_cast<HANDLE>(m_event_handle)); +} + +void Event::Signal() +{ + SetEvent(reinterpret_cast<HANDLE>(m_event_handle)); +} + +void Event::Wait() +{ + WaitForSingleObject(reinterpret_cast<HANDLE>(m_event_handle), INFINITE); +} + +bool Event::TryWait(u32 timeout_in_ms) +{ + return (WaitForSingleObject(reinterpret_cast<HANDLE>(m_event_handle), timeout_in_ms) == WAIT_OBJECT_0); +} + +void Event::Reset() +{ + ResetEvent(reinterpret_cast<HANDLE>(m_event_handle)); +} + +void Event::WaitForMultipleEvents(Event** events, u32 num_events) +{ + DebugAssert(num_events > 0); + + HANDLE* event_handles = (HANDLE*)alloca(sizeof(HANDLE) * num_events); + for (u32 i = 0; i < num_events; i++) + event_handles[i] = reinterpret_cast<HANDLE>(events[i]->m_event_handle); + + WaitForMultipleObjects(num_events, event_handles, TRUE, INFINITE); +} + +#elif defined(__linux__) || defined(__APPLE__) + +Event::Event(bool auto_reset /*= false*/) : m_auto_reset(auto_reset) +{ + m_pipe_fds[0] = m_pipe_fds[1] = -1; +#if defined(__linux__) + pipe2(m_pipe_fds, O_NONBLOCK); +#else + pipe(m_pipe_fds); + fcntl(m_pipe_fds[0], F_SETFL, fcntl(m_pipe_fds[0], F_GETFL) | O_NONBLOCK); + fcntl(m_pipe_fds[1], F_SETFL, fcntl(m_pipe_fds[1], F_GETFL) | O_NONBLOCK); +#endif + Assert(m_pipe_fds[0] >= 0 && m_pipe_fds[1] >= 0); +} + +Event::~Event() +{ + close(m_pipe_fds[0]); + close(m_pipe_fds[1]); +} + +void Event::Signal() +{ + char buf[1] = {0}; + write(m_pipe_fds[1], buf, sizeof(buf)); +} + +void Event::Wait() +{ + pollfd pd = {}; + pd.fd = m_pipe_fds[0]; + pd.events = POLLRDNORM; + poll(&pd, 1, -1); + + if (m_auto_reset) + Reset(); +} + +bool Event::TryWait(u32 timeout_in_ms) +{ + pollfd pd; + pd.fd = m_pipe_fds[0]; + pd.events = POLLRDNORM; + if (poll(&pd, 1, timeout_in_ms) == 0) + return false; + + if (m_auto_reset) + Reset(); + + return true; +} + +void Event::Reset() +{ + char buf[1]; + while (read(m_pipe_fds[0], buf, sizeof(buf)) > 0) + ; +} + +void Event::WaitForMultipleEvents(Event** events, u32 num_events) +{ + DebugAssert(num_events > 0); + + pollfd pd = {}; + pd.events = POLLRDNORM; + for (u32 i = 0; i < num_events; i++) + { + pd.fd = events[i]->m_pipe_fds[0]; + poll(&pd, 1, -1); + } +} + +#endif + +} // namespace Common diff --git a/src/common/event.h b/src/common/event.h new file mode 100644 index 000000000..b975ea0c0 --- /dev/null +++ b/src/common/event.h @@ -0,0 +1,30 @@ +#pragma once +#include "types.h" + +namespace Common { + +class Event +{ +public: + Event(bool auto_reset = false); + ~Event(); + + void Reset(); + void Signal(); + void Wait(); + bool TryWait(u32 timeout_in_ms); + + static void WaitForMultipleEvents(Event** events, u32 num_events); + +private: +#ifdef WIN32 + void* m_event_handle; +#elif defined(__linux__) || defined(__APPLE__) + int m_pipe_fds[2]; + bool m_auto_reset; +#else +#error Unknown platform. +#endif +}; + +} // namespace Common \ No newline at end of file