1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5
6#include "common.h"
7#include "eventstore.hpp"
8#include "synch.h"
9
10// A class to maintain a pool of available events.
11
12const int EventStoreLength = 8;
13class EventStore
14{
15public:
16 // Note: No constructors/destructors - global instance
17
18 void Init()
19 {
20 WRAPPER_NO_CONTRACT;
21
22 m_EventStoreCrst.Init(CrstEventStore, CRST_UNSAFE_ANYMODE);
23 m_Store = NULL;
24 }
25
26 void Destroy()
27 {
28 WRAPPER_NO_CONTRACT;
29
30 _ASSERTE (g_fEEShutDown);
31
32 m_EventStoreCrst.Destroy();
33
34 EventStoreElem *walk;
35 EventStoreElem *next;
36
37 walk = m_Store;
38 while (walk) {
39 next = walk->next;
40 delete (walk);
41 walk = next;
42 }
43 }
44
45 void StoreHandleForEvent (CLREvent* handle)
46 {
47 CONTRACTL {
48 THROWS;
49 GC_NOTRIGGER;
50 } CONTRACTL_END;
51
52 _ASSERTE (handle);
53 CrstHolder ch(&m_EventStoreCrst);
54 if (m_Store == NULL) {
55 m_Store = new EventStoreElem ();
56 }
57 EventStoreElem *walk;
58#ifdef _DEBUG
59 // See if we have some leakage.
60 LONG count = 0;
61 walk = m_Store;
62 while (walk) {
63 count += walk->AvailableEventCount();
64 walk = walk->next;
65 }
66 // The number of events stored in the pool should be small.
67 _ASSERTE (count <= ThreadStore::s_pThreadStore->ThreadCountInEE() * 2 + 10);
68#endif
69 walk = m_Store;
70 while (walk) {
71 if (walk->StoreHandleForEvent (handle) )
72 return;
73 if (walk->next == NULL) {
74 break;
75 }
76 walk = walk->next;
77 }
78 if (walk != NULL)
79 {
80 walk->next = new EventStoreElem ();
81 walk->next->hArray[0] = handle;
82 }
83 }
84
85 CLREvent* GetHandleForEvent ()
86 {
87 CONTRACTL {
88 THROWS;
89 GC_NOTRIGGER;
90 } CONTRACTL_END;
91
92 CLREvent* handle;
93 CrstHolder ch(&m_EventStoreCrst);
94 EventStoreElem *walk = m_Store;
95 while (walk) {
96 handle = walk->GetHandleForEvent();
97 if (handle != NULL) {
98 return handle;
99 }
100 walk = walk->next;
101 }
102 handle = new CLREvent;
103 _ASSERTE (handle != NULL);
104 handle->CreateManualEvent(TRUE);
105 return handle;
106 }
107
108private:
109 struct EventStoreElem
110 {
111 CLREvent *hArray[EventStoreLength];
112 EventStoreElem *next;
113
114 EventStoreElem ()
115 {
116 LIMITED_METHOD_CONTRACT;
117
118 next = NULL;
119 for (int i = 0; i < EventStoreLength; i ++) {
120 hArray[i] = NULL;
121 }
122 }
123
124 ~EventStoreElem ()
125 {
126 LIMITED_METHOD_CONTRACT;
127
128 for (int i = 0; i < EventStoreLength; i++) {
129 if (hArray[i]) {
130 delete hArray[i];
131 hArray[i] = NULL;
132 }
133 }
134 }
135
136 // Store a handle in the current EventStoreElem. Return TRUE if succeessful.
137 // Return FALSE if failed due to no free slot.
138 BOOL StoreHandleForEvent (CLREvent* handle)
139 {
140 LIMITED_METHOD_CONTRACT;
141
142 int i;
143 for (i = 0; i < EventStoreLength; i++) {
144 if (hArray[i] == NULL) {
145 hArray[i] = handle;
146 return TRUE;
147 }
148 }
149 return FALSE;
150 }
151
152 // Get a handle from the current EventStoreElem.
153 CLREvent* GetHandleForEvent ()
154 {
155 LIMITED_METHOD_CONTRACT;
156
157 int i;
158 for (i = 0; i < EventStoreLength; i++) {
159 if (hArray[i] != NULL) {
160 CLREvent* handle = hArray[i];
161 hArray[i] = NULL;
162 return handle;
163 }
164 }
165
166 return NULL;
167 }
168
169#ifdef _DEBUG
170 LONG AvailableEventCount ()
171 {
172 LIMITED_METHOD_CONTRACT;
173
174 LONG count = 0;
175 for (int i = 0; i < EventStoreLength; i++) {
176 if (hArray[i] != NULL) {
177 count ++;
178 }
179 }
180 return count;
181 }
182#endif
183 };
184
185 EventStoreElem *m_Store;
186
187 // Critical section for adding and removing event used for Object::Wait
188 CrstStatic m_EventStoreCrst;
189};
190
191static EventStore s_EventStore;
192
193CLREvent* GetEventFromEventStore()
194{
195 WRAPPER_NO_CONTRACT;
196
197 return s_EventStore.GetHandleForEvent();
198}
199
200void StoreEventToEventStore(CLREvent* hEvent)
201{
202 WRAPPER_NO_CONTRACT;
203
204 s_EventStore.StoreHandleForEvent(hEvent);
205}
206
207void InitEventStore()
208{
209 WRAPPER_NO_CONTRACT;
210
211 s_EventStore.Init();
212}
213
214void TerminateEventStore()
215{
216 WRAPPER_NO_CONTRACT;
217
218 s_EventStore.Destroy();
219}
220