diff options
Diffstat (limited to 'src/vm/eventstore.cpp')
-rw-r--r-- | src/vm/eventstore.cpp | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/src/vm/eventstore.cpp b/src/vm/eventstore.cpp new file mode 100644 index 0000000000..13382c0a0c --- /dev/null +++ b/src/vm/eventstore.cpp @@ -0,0 +1,219 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + + +#include "common.h" +#include "eventstore.hpp" +#include "synch.h" + +// A class to maintain a pool of available events. + +const int EventStoreLength = 8; +class EventStore +{ +public: + // Note: No constructors/destructors - global instance + + void Init() + { + WRAPPER_NO_CONTRACT; + + m_EventStoreCrst.Init(CrstEventStore, CRST_UNSAFE_ANYMODE); + m_Store = NULL; + } + + void Destroy() + { + WRAPPER_NO_CONTRACT; + + _ASSERTE (g_fEEShutDown); + + m_EventStoreCrst.Destroy(); + + EventStoreElem *walk; + EventStoreElem *next; + + walk = m_Store; + while (walk) { + next = walk->next; + delete (walk); + walk = next; + } + } + + void StoreHandleForEvent (CLREvent* handle) + { + CONTRACTL { + THROWS; + GC_NOTRIGGER; + } CONTRACTL_END; + + _ASSERTE (handle); + CrstHolder ch(&m_EventStoreCrst); + if (m_Store == NULL) { + m_Store = new EventStoreElem (); + } + EventStoreElem *walk; +#ifdef _DEBUG + // See if we have some leakage. + LONG count = 0; + walk = m_Store; + while (walk) { + count += walk->AvailableEventCount(); + walk = walk->next; + } + // The number of events stored in the pool should be small. + _ASSERTE (count <= ThreadStore::s_pThreadStore->ThreadCountInEE() * 2 + 10); +#endif + walk = m_Store; + while (walk) { + if (walk->StoreHandleForEvent (handle) ) + return; + if (walk->next == NULL) { + break; + } + walk = walk->next; + } + if (walk != NULL) + { + walk->next = new EventStoreElem (); + walk->next->hArray[0] = handle; + } + } + + CLREvent* GetHandleForEvent () + { + CONTRACTL { + THROWS; + GC_NOTRIGGER; + } CONTRACTL_END; + + CLREvent* handle; + CrstHolder ch(&m_EventStoreCrst); + EventStoreElem *walk = m_Store; + while (walk) { + handle = walk->GetHandleForEvent(); + if (handle != NULL) { + return handle; + } + walk = walk->next; + } + handle = new CLREvent; + _ASSERTE (handle != NULL); + handle->CreateManualEvent(TRUE); + return handle; + } + +private: + struct EventStoreElem + { + CLREvent *hArray[EventStoreLength]; + EventStoreElem *next; + + EventStoreElem () + { + LIMITED_METHOD_CONTRACT; + + next = NULL; + for (int i = 0; i < EventStoreLength; i ++) { + hArray[i] = NULL; + } + } + + ~EventStoreElem () + { + LIMITED_METHOD_CONTRACT; + + for (int i = 0; i < EventStoreLength; i++) { + if (hArray[i]) { + delete hArray[i]; + hArray[i] = NULL; + } + } + } + + // Store a handle in the current EventStoreElem. Return TRUE if succeessful. + // Return FALSE if failed due to no free slot. + BOOL StoreHandleForEvent (CLREvent* handle) + { + LIMITED_METHOD_CONTRACT; + + int i; + for (i = 0; i < EventStoreLength; i++) { + if (hArray[i] == NULL) { + hArray[i] = handle; + return TRUE; + } + } + return FALSE; + } + + // Get a handle from the current EventStoreElem. + CLREvent* GetHandleForEvent () + { + LIMITED_METHOD_CONTRACT; + + int i; + for (i = 0; i < EventStoreLength; i++) { + if (hArray[i] != NULL) { + CLREvent* handle = hArray[i]; + hArray[i] = NULL; + return handle; + } + } + + return NULL; + } + +#ifdef _DEBUG + LONG AvailableEventCount () + { + LIMITED_METHOD_CONTRACT; + + LONG count = 0; + for (int i = 0; i < EventStoreLength; i++) { + if (hArray[i] != NULL) { + count ++; + } + } + return count; + } +#endif + }; + + EventStoreElem *m_Store; + + // Critical section for adding and removing event used for Object::Wait + CrstStatic m_EventStoreCrst; +}; + +static EventStore s_EventStore; + +CLREvent* GetEventFromEventStore() +{ + WRAPPER_NO_CONTRACT; + + return s_EventStore.GetHandleForEvent(); +} + +void StoreEventToEventStore(CLREvent* hEvent) +{ + WRAPPER_NO_CONTRACT; + + s_EventStore.StoreHandleForEvent(hEvent); +} + +void InitEventStore() +{ + WRAPPER_NO_CONTRACT; + + s_EventStore.Init(); +} + +void TerminateEventStore() +{ + WRAPPER_NO_CONTRACT; + + s_EventStore.Destroy(); +} |