summaryrefslogtreecommitdiff
path: root/src/gc/windows/gcenv.windows.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gc/windows/gcenv.windows.cpp')
-rw-r--r--src/gc/windows/gcenv.windows.cpp142
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;
+}
+