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 | |
12 | const int EventStoreLength = 8; |
13 | class EventStore |
14 | { |
15 | public: |
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 | |
108 | private: |
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 | |
191 | static EventStore s_EventStore; |
192 | |
193 | CLREvent* GetEventFromEventStore() |
194 | { |
195 | WRAPPER_NO_CONTRACT; |
196 | |
197 | return s_EventStore.GetHandleForEvent(); |
198 | } |
199 | |
200 | void StoreEventToEventStore(CLREvent* hEvent) |
201 | { |
202 | WRAPPER_NO_CONTRACT; |
203 | |
204 | s_EventStore.StoreHandleForEvent(hEvent); |
205 | } |
206 | |
207 | void InitEventStore() |
208 | { |
209 | WRAPPER_NO_CONTRACT; |
210 | |
211 | s_EventStore.Init(); |
212 | } |
213 | |
214 | void TerminateEventStore() |
215 | { |
216 | WRAPPER_NO_CONTRACT; |
217 | |
218 | s_EventStore.Destroy(); |
219 | } |
220 |