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 | #ifndef _GCHANDLEUTILITIES_H_ |
6 | #define _GCHANDLEUTILITIES_H_ |
7 | |
8 | #include "gcinterface.h" |
9 | |
10 | #ifdef FEATURE_COMINTEROP |
11 | #include <weakreference.h> |
12 | #endif |
13 | |
14 | extern "C" IGCHandleManager* g_pGCHandleManager; |
15 | |
16 | class GCHandleUtilities |
17 | { |
18 | public: |
19 | // Retrieves the GC handle table. |
20 | static IGCHandleManager* GetGCHandleManager() |
21 | { |
22 | LIMITED_METHOD_CONTRACT; |
23 | |
24 | assert(g_pGCHandleManager != nullptr); |
25 | return g_pGCHandleManager; |
26 | } |
27 | |
28 | private: |
29 | // This class should never be instantiated. |
30 | GCHandleUtilities() = delete; |
31 | }; |
32 | |
33 | void ValidateObjectAndAppDomain(OBJECTREF objRef, ADIndex appDomainIndex); |
34 | void ValidateHandleAssignment(OBJECTHANDLE handle, OBJECTREF objRef); |
35 | void DiagHandleCreated(OBJECTHANDLE handle, OBJECTREF object); |
36 | void DiagHandleDestroyed(OBJECTHANDLE handle); |
37 | |
38 | // Given a handle, returns an OBJECTREF for the object it refers to. |
39 | inline OBJECTREF ObjectFromHandle(OBJECTHANDLE handle) |
40 | { |
41 | _ASSERTE(handle); |
42 | |
43 | #if defined(_DEBUG_IMPL) && !defined(DACCESS_COMPILE) |
44 | // not allowed to dispatch virtually on a IGCHandleManager when compiling for DAC |
45 | DWORD context = (DWORD)GCHandleUtilities::GetGCHandleManager()->GetHandleContext(handle); |
46 | OBJECTREF objRef = ObjectToOBJECTREF(*(Object**)handle); |
47 | |
48 | ValidateObjectAndAppDomain(objRef, ADIndex(context)); |
49 | #endif // defined(_DEBUG_IMPL) && !defined(DACCESS_COMPILE) |
50 | |
51 | // Wrap the raw OBJECTREF and return it |
52 | return UNCHECKED_OBJECTREF_TO_OBJECTREF(*PTR_UNCHECKED_OBJECTREF(handle)); |
53 | } |
54 | |
55 | // Quick inline check for whether a handle is null |
56 | inline BOOL IsHandleNullUnchecked(OBJECTHANDLE handle) |
57 | { |
58 | LIMITED_METHOD_CONTRACT; |
59 | |
60 | return (handle == NULL || (*(_UNCHECKED_OBJECTREF *)handle) == NULL); |
61 | } |
62 | |
63 | inline BOOL ObjectHandleIsNull(OBJECTHANDLE handle) |
64 | { |
65 | LIMITED_METHOD_CONTRACT; |
66 | |
67 | return *(Object **)handle == NULL; |
68 | } |
69 | |
70 | #ifndef DACCESS_COMPILE |
71 | |
72 | // Handle creation convenience functions |
73 | inline OBJECTHANDLE CreateHandleCommon(IGCHandleStore* store, OBJECTREF object, HandleType type) |
74 | { |
75 | OBJECTHANDLE hnd = store->CreateHandleOfType(OBJECTREFToObject(object), type); |
76 | if (!hnd) |
77 | { |
78 | COMPlusThrowOM(); |
79 | } |
80 | |
81 | DiagHandleCreated(hnd, object); |
82 | return hnd; |
83 | } |
84 | |
85 | inline OBJECTHANDLE CreateHandle(IGCHandleStore* store, OBJECTREF object) |
86 | { |
87 | return CreateHandleCommon(store, object, HNDTYPE_DEFAULT); |
88 | } |
89 | |
90 | inline OBJECTHANDLE CreateWeakHandle(IGCHandleStore* store, OBJECTREF object) |
91 | { |
92 | return CreateHandleCommon(store, object, HNDTYPE_WEAK_DEFAULT); |
93 | } |
94 | |
95 | inline OBJECTHANDLE CreateShortWeakHandle(IGCHandleStore* store, OBJECTREF object) |
96 | { |
97 | return CreateHandleCommon(store, object, HNDTYPE_WEAK_SHORT); |
98 | } |
99 | |
100 | inline OBJECTHANDLE CreateLongWeakHandle(IGCHandleStore* store, OBJECTREF object) |
101 | { |
102 | return CreateHandleCommon(store, object, HNDTYPE_WEAK_LONG); |
103 | } |
104 | |
105 | inline OBJECTHANDLE CreateStrongHandle(IGCHandleStore* store, OBJECTREF object) |
106 | { |
107 | return CreateHandleCommon(store, object, HNDTYPE_STRONG); |
108 | } |
109 | |
110 | inline OBJECTHANDLE CreatePinningHandle(IGCHandleStore* store, OBJECTREF object) |
111 | { |
112 | return CreateHandleCommon(store, object, HNDTYPE_PINNED); |
113 | } |
114 | |
115 | inline OBJECTHANDLE CreateAsyncPinningHandle(IGCHandleStore* store, OBJECTREF object) |
116 | { |
117 | return CreateHandleCommon(store, object, HNDTYPE_ASYNCPINNED); |
118 | } |
119 | |
120 | inline OBJECTHANDLE CreateRefcountedHandle(IGCHandleStore* store, OBJECTREF object) |
121 | { |
122 | return CreateHandleCommon(store, object, HNDTYPE_REFCOUNTED); |
123 | } |
124 | |
125 | inline OBJECTHANDLE CreateSizedRefHandle(IGCHandleStore* store, OBJECTREF object) |
126 | { |
127 | return CreateHandleCommon(store, object, HNDTYPE_SIZEDREF); |
128 | } |
129 | |
130 | inline OBJECTHANDLE CreateSizedRefHandle(IGCHandleStore* store, OBJECTREF object, int heapToAffinitizeTo) |
131 | { |
132 | OBJECTHANDLE hnd = store->CreateHandleOfType(OBJECTREFToObject(object), HNDTYPE_SIZEDREF, heapToAffinitizeTo); |
133 | if (!hnd) |
134 | { |
135 | COMPlusThrowOM(); |
136 | } |
137 | |
138 | DiagHandleCreated(hnd, object); |
139 | return hnd; |
140 | } |
141 | |
142 | inline OBJECTHANDLE CreateDependentHandle(IGCHandleStore* store, OBJECTREF primary, OBJECTREF secondary) |
143 | { |
144 | OBJECTHANDLE hnd = store->CreateDependentHandle(OBJECTREFToObject(primary), OBJECTREFToObject(secondary)); |
145 | if (!hnd) |
146 | { |
147 | COMPlusThrowOM(); |
148 | } |
149 | |
150 | DiagHandleCreated(hnd, primary); |
151 | return hnd; |
152 | } |
153 | |
154 | // Global handle creation convenience functions |
155 | inline OBJECTHANDLE CreateGlobalHandleCommon(OBJECTREF object, HandleType type) |
156 | { |
157 | CONDITIONAL_CONTRACT_VIOLATION(ModeViolation, object == NULL); |
158 | OBJECTHANDLE hnd = GCHandleUtilities::GetGCHandleManager()->CreateGlobalHandleOfType(OBJECTREFToObject(object), type); |
159 | if (!hnd) |
160 | { |
161 | COMPlusThrowOM(); |
162 | } |
163 | |
164 | DiagHandleCreated(hnd, object); |
165 | return hnd; |
166 | |
167 | } |
168 | |
169 | inline OBJECTHANDLE CreateGlobalHandle(OBJECTREF object) |
170 | { |
171 | return CreateGlobalHandleCommon(object, HNDTYPE_DEFAULT); |
172 | } |
173 | |
174 | inline OBJECTHANDLE CreateGlobalWeakHandle(OBJECTREF object) |
175 | { |
176 | return CreateGlobalHandleCommon(object, HNDTYPE_WEAK_DEFAULT); |
177 | } |
178 | |
179 | inline OBJECTHANDLE CreateGlobalShortWeakHandle(OBJECTREF object) |
180 | { |
181 | return CreateGlobalHandleCommon(object, HNDTYPE_WEAK_SHORT); |
182 | } |
183 | |
184 | inline OBJECTHANDLE CreateGlobalLongWeakHandle(OBJECTREF object) |
185 | { |
186 | return CreateGlobalHandleCommon(object, HNDTYPE_WEAK_LONG); |
187 | } |
188 | |
189 | inline OBJECTHANDLE CreateGlobalStrongHandle(OBJECTREF object) |
190 | { |
191 | return CreateGlobalHandleCommon(object, HNDTYPE_STRONG); |
192 | } |
193 | |
194 | inline OBJECTHANDLE CreateGlobalPinningHandle(OBJECTREF object) |
195 | { |
196 | return CreateGlobalHandleCommon(object, HNDTYPE_PINNED); |
197 | } |
198 | |
199 | inline OBJECTHANDLE CreateGlobalRefcountedHandle(OBJECTREF object) |
200 | { |
201 | return CreateGlobalHandleCommon(object, HNDTYPE_REFCOUNTED); |
202 | } |
203 | |
204 | // Special handle creation convenience functions |
205 | |
206 | #ifdef FEATURE_COMINTEROP |
207 | inline OBJECTHANDLE CreateWinRTWeakHandle(IGCHandleStore* store, OBJECTREF object, IWeakReference* pWinRTWeakReference) |
208 | { |
209 | OBJECTHANDLE hnd = store->CreateHandleWithExtraInfo(OBJECTREFToObject(object), HNDTYPE_WEAK_WINRT, (void*)pWinRTWeakReference); |
210 | if (!hnd) |
211 | { |
212 | COMPlusThrowOM(); |
213 | } |
214 | |
215 | DiagHandleCreated(hnd, object); |
216 | return hnd; |
217 | } |
218 | #endif // FEATURE_COMINTEROP |
219 | |
220 | // Creates a variable-strength handle |
221 | inline OBJECTHANDLE CreateVariableHandle(IGCHandleStore* store, OBJECTREF object, uint32_t type) |
222 | { |
223 | OBJECTHANDLE hnd = store->CreateHandleWithExtraInfo(OBJECTREFToObject(object), HNDTYPE_VARIABLE, (void*)((uintptr_t)type)); |
224 | if (!hnd) |
225 | { |
226 | COMPlusThrowOM(); |
227 | } |
228 | |
229 | DiagHandleCreated(hnd, object); |
230 | return hnd; |
231 | } |
232 | |
233 | // Handle object manipulation convenience functions |
234 | |
235 | inline void StoreObjectInHandle(OBJECTHANDLE handle, OBJECTREF object) |
236 | { |
237 | ValidateHandleAssignment(handle, object); |
238 | |
239 | GCHandleUtilities::GetGCHandleManager()->StoreObjectInHandle(handle, OBJECTREFToObject(object)); |
240 | } |
241 | |
242 | inline bool StoreFirstObjectInHandle(OBJECTHANDLE handle, OBJECTREF object) |
243 | { |
244 | ValidateHandleAssignment(handle, object); |
245 | |
246 | return GCHandleUtilities::GetGCHandleManager()->StoreObjectInHandleIfNull(handle, OBJECTREFToObject(object)); |
247 | } |
248 | |
249 | inline void* InterlockedCompareExchangeObjectInHandle(OBJECTHANDLE handle, OBJECTREF object, OBJECTREF comparandObject) |
250 | { |
251 | ValidateHandleAssignment(handle, object); |
252 | |
253 | return GCHandleUtilities::GetGCHandleManager()->InterlockedCompareExchangeObjectInHandle(handle, OBJECTREFToObject(object), OBJECTREFToObject(comparandObject)); |
254 | } |
255 | |
256 | inline void ResetOBJECTHANDLE(OBJECTHANDLE handle) |
257 | { |
258 | GCHandleUtilities::GetGCHandleManager()->StoreObjectInHandle(handle, NULL); |
259 | } |
260 | |
261 | // Handle destruction convenience functions |
262 | inline void DestroyHandleCommon(OBJECTHANDLE handle, HandleType type) |
263 | { |
264 | CONTRACTL |
265 | { |
266 | NOTHROW; |
267 | GC_NOTRIGGER; |
268 | MODE_ANY; |
269 | CAN_TAKE_LOCK; |
270 | SO_TOLERANT; |
271 | } |
272 | CONTRACTL_END; |
273 | |
274 | DiagHandleDestroyed(handle); |
275 | GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, type); |
276 | } |
277 | |
278 | inline void DestroyHandle(OBJECTHANDLE handle) |
279 | { |
280 | DestroyHandleCommon(handle, HNDTYPE_DEFAULT); |
281 | } |
282 | |
283 | inline void DestroyWeakHandle(OBJECTHANDLE handle) |
284 | { |
285 | DestroyHandleCommon(handle, HNDTYPE_WEAK_DEFAULT); |
286 | } |
287 | |
288 | inline void DestroyShortWeakHandle(OBJECTHANDLE handle) |
289 | { |
290 | DestroyHandleCommon(handle, HNDTYPE_WEAK_SHORT); |
291 | } |
292 | |
293 | inline void DestroyLongWeakHandle(OBJECTHANDLE handle) |
294 | { |
295 | DestroyHandleCommon(handle, HNDTYPE_WEAK_LONG); |
296 | } |
297 | |
298 | inline void DestroyStrongHandle(OBJECTHANDLE handle) |
299 | { |
300 | DestroyHandleCommon(handle, HNDTYPE_STRONG); |
301 | } |
302 | |
303 | inline void DestroyPinningHandle(OBJECTHANDLE handle) |
304 | { |
305 | DestroyHandleCommon(handle, HNDTYPE_PINNED); |
306 | } |
307 | |
308 | inline void DestroyAsyncPinningHandle(OBJECTHANDLE handle) |
309 | { |
310 | DestroyHandleCommon(handle, HNDTYPE_ASYNCPINNED); |
311 | } |
312 | |
313 | inline void DestroyRefcountedHandle(OBJECTHANDLE handle) |
314 | { |
315 | DestroyHandleCommon(handle, HNDTYPE_REFCOUNTED); |
316 | } |
317 | |
318 | inline void DestroyDependentHandle(OBJECTHANDLE handle) |
319 | { |
320 | DestroyHandleCommon(handle, HNDTYPE_DEPENDENT); |
321 | } |
322 | |
323 | inline void DestroyVariableHandle(OBJECTHANDLE handle) |
324 | { |
325 | DestroyHandleCommon(handle, HNDTYPE_VARIABLE); |
326 | } |
327 | |
328 | inline void DestroyGlobalHandle(OBJECTHANDLE handle) |
329 | { |
330 | DestroyHandleCommon(handle, HNDTYPE_DEFAULT); |
331 | } |
332 | |
333 | inline void DestroyGlobalWeakHandle(OBJECTHANDLE handle) |
334 | { |
335 | DestroyHandleCommon(handle, HNDTYPE_WEAK_DEFAULT); |
336 | } |
337 | |
338 | inline void DestroyGlobalShortWeakHandle(OBJECTHANDLE handle) |
339 | { |
340 | DestroyHandleCommon(handle, HNDTYPE_WEAK_SHORT); |
341 | } |
342 | |
343 | inline void DestroyGlobalLongWeakHandle(OBJECTHANDLE handle) |
344 | { |
345 | DestroyHandleCommon(handle, HNDTYPE_WEAK_LONG); |
346 | } |
347 | |
348 | inline void DestroyGlobalStrongHandle(OBJECTHANDLE handle) |
349 | { |
350 | DestroyHandleCommon(handle, HNDTYPE_STRONG); |
351 | } |
352 | |
353 | inline void DestroyGlobalPinningHandle(OBJECTHANDLE handle) |
354 | { |
355 | DestroyHandleCommon(handle, HNDTYPE_PINNED); |
356 | } |
357 | |
358 | inline void DestroyGlobalRefcountedHandle(OBJECTHANDLE handle) |
359 | { |
360 | DestroyHandleCommon(handle, HNDTYPE_REFCOUNTED); |
361 | } |
362 | |
363 | inline void DestroyTypedHandle(OBJECTHANDLE handle) |
364 | { |
365 | DiagHandleDestroyed(handle); |
366 | GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfUnknownType(handle); |
367 | } |
368 | |
369 | #ifdef FEATURE_COMINTEROP |
370 | inline void DestroyWinRTWeakHandle(OBJECTHANDLE handle) |
371 | { |
372 | CONTRACTL |
373 | { |
374 | NOTHROW; |
375 | GC_NOTRIGGER; |
376 | MODE_ANY; |
377 | CAN_TAKE_LOCK; |
378 | SO_TOLERANT; |
379 | } |
380 | CONTRACTL_END; |
381 | |
382 | // Release the WinRT weak reference if we have one. We're assuming that this will not reenter the |
383 | // runtime, since if we are pointing at a managed object, we should not be using HNDTYPE_WEAK_WINRT |
384 | // but rather HNDTYPE_WEAK_SHORT or HNDTYPE_WEAK_LONG. |
385 | void* pExtraInfo = GCHandleUtilities::GetGCHandleManager()->GetExtraInfoFromHandle(handle); |
386 | IWeakReference* pWinRTWeakReference = reinterpret_cast<IWeakReference*>(pExtraInfo); |
387 | if (pWinRTWeakReference != nullptr) |
388 | { |
389 | pWinRTWeakReference->Release(); |
390 | } |
391 | |
392 | DiagHandleDestroyed(handle); |
393 | GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_WEAK_WINRT); |
394 | } |
395 | #endif |
396 | |
397 | // Handle holders/wrappers |
398 | |
399 | #ifndef FEATURE_REDHAWK |
400 | typedef Wrapper<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyHandle> OHWrapper; |
401 | typedef Wrapper<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyPinningHandle, NULL> PinningHandleHolder; |
402 | typedef Wrapper<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyAsyncPinningHandle, NULL> AsyncPinningHandleHolder; |
403 | typedef Wrapper<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyRefcountedHandle> RefCountedOHWrapper; |
404 | |
405 | typedef Holder<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyLongWeakHandle> LongWeakHandleHolder; |
406 | typedef Holder<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyGlobalStrongHandle> GlobalStrongHandleHolder; |
407 | typedef Holder<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyGlobalShortWeakHandle> GlobalShortWeakHandleHolder; |
408 | typedef Holder<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, ResetOBJECTHANDLE> ObjectInHandleHolder; |
409 | |
410 | class RCOBJECTHANDLEHolder : public RefCountedOHWrapper |
411 | { |
412 | public: |
413 | FORCEINLINE RCOBJECTHANDLEHolder(OBJECTHANDLE p = NULL) : RefCountedOHWrapper(p) |
414 | { |
415 | LIMITED_METHOD_CONTRACT; |
416 | } |
417 | FORCEINLINE void operator=(OBJECTHANDLE p) |
418 | { |
419 | WRAPPER_NO_CONTRACT; |
420 | |
421 | RefCountedOHWrapper::operator=(p); |
422 | } |
423 | }; |
424 | |
425 | class OBJECTHANDLEHolder : public OHWrapper |
426 | { |
427 | public: |
428 | FORCEINLINE OBJECTHANDLEHolder(OBJECTHANDLE p = NULL) : OHWrapper(p) |
429 | { |
430 | LIMITED_METHOD_CONTRACT; |
431 | } |
432 | FORCEINLINE void operator=(OBJECTHANDLE p) |
433 | { |
434 | WRAPPER_NO_CONTRACT; |
435 | |
436 | OHWrapper::operator=(p); |
437 | } |
438 | }; |
439 | |
440 | #endif // !FEATURE_REDHAWK |
441 | |
442 | #endif // !DACCESS_COMPILE |
443 | |
444 | #endif // _GCHANDLEUTILITIES_H_ |
445 | |
446 | |