diff options
Diffstat (limited to 'src/gc/windows/gcenv.windows.cpp')
-rw-r--r-- | src/gc/windows/gcenv.windows.cpp | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/src/gc/windows/gcenv.windows.cpp b/src/gc/windows/gcenv.windows.cpp index 30232bfb09..3749f06a68 100644 --- a/src/gc/windows/gcenv.windows.cpp +++ b/src/gc/windows/gcenv.windows.cpp @@ -626,3 +626,145 @@ void CLRCriticalSection::Leave() { ::LeaveCriticalSection(&m_cs); } + +// WindowsEvent is an implementation of GCEvent that forwards +// directly to Win32 APIs. +class GCEvent::Impl +{ +private: + HANDLE m_hEvent; + +public: + Impl() : m_hEvent(INVALID_HANDLE_VALUE) {} + + bool IsValid() const + { + return m_hEvent != INVALID_HANDLE_VALUE; + } + + void Set() + { + assert(IsValid()); + BOOL result = SetEvent(m_hEvent); + assert(result && "SetEvent failed"); + } + + void Reset() + { + assert(IsValid()); + BOOL result = ResetEvent(m_hEvent); + assert(result && "ResetEvent failed"); + } + + uint32_t Wait(uint32_t timeout, bool alertable) + { + UNREFERENCED_PARAMETER(alertable); + assert(IsValid()); + + return WaitForSingleObject(m_hEvent, timeout); + } + + void CloseEvent() + { + assert(IsValid()); + BOOL result = CloseHandle(m_hEvent); + assert(result && "CloseHandle failed"); + m_hEvent = INVALID_HANDLE_VALUE; + } + + bool CreateAutoEvent(bool initialState) + { + m_hEvent = CreateEvent(nullptr, false, initialState, nullptr); + return IsValid(); + } + + bool CreateManualEvent(bool initialState) + { + m_hEvent = CreateEvent(nullptr, true, initialState, nullptr); + return IsValid(); + } +}; + +GCEvent::GCEvent() + : m_impl(nullptr) +{ +} + +void GCEvent::CloseEvent() +{ + assert(m_impl != nullptr); + m_impl->CloseEvent(); +} + +void GCEvent::Set() +{ + assert(m_impl != nullptr); + m_impl->Set(); +} + +void GCEvent::Reset() +{ + assert(m_impl != nullptr); + m_impl->Reset(); +} + +uint32_t GCEvent::Wait(uint32_t timeout, bool alertable) +{ + assert(m_impl != nullptr); + return m_impl->Wait(timeout, alertable); +} + +bool GCEvent::CreateAutoEventNoThrow(bool initialState) +{ + // [DESKTOP TODO] The difference between events and OS events is + // whether or not the hosting API is made aware of them. When (if) + // we implement hosting support for Local GC, we will need to be + // aware of the host here. + return CreateOSAutoEventNoThrow(initialState); +} + +bool GCEvent::CreateManualEventNoThrow(bool initialState) +{ + // [DESKTOP TODO] The difference between events and OS events is + // whether or not the hosting API is made aware of them. When (if) + // we implement hosting support for Local GC, we will need to be + // aware of the host here. + return CreateOSManualEventNoThrow(initialState); +} + +bool GCEvent::CreateOSAutoEventNoThrow(bool initialState) +{ + assert(m_impl == nullptr); + std::unique_ptr<GCEvent::Impl> event(new (std::nothrow) GCEvent::Impl()); + if (!event) + { + return false; + } + + if (!event->CreateAutoEvent(initialState)) + { + return false; + } + + m_impl = event.release(); + return true; +} + +bool GCEvent::CreateOSManualEventNoThrow(bool initialState) +{ + assert(m_impl == nullptr); + std::unique_ptr<GCEvent::Impl> event(new (std::nothrow) GCEvent::Impl()); + if (!event) + { + return false; + } + + if (!event->CreateManualEvent(initialState)) + { + return false; + } + + m_impl = event.release(); + return true; +} + |