Permalink
Fetching contributors…
Cannot retrieve contributors at this time
220 lines (181 sloc) 4.98 KB
// 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();
}