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 //*****************************************************************************
9 // public helpers for debugger.
10 //*****************************************************************************
15 //-----------------------------------------------------------------------------
16 // Smartpointer for internal Addref/Release
17 // Using Wrapper / Holder infrastructure from src\inc\Holder.h
18 //-----------------------------------------------------------------------------
19 template <typename TYPE>
20 inline void HolderRSRelease(TYPE *value)
22 _ASSERTE(value != NULL);
23 value->InternalRelease();
26 template <typename TYPE>
27 inline void HolderRSAddRef(TYPE *value)
29 _ASSERTE(value != NULL);
30 value->InternalAddRef();
33 // Smart ptrs for external refs. External refs are important
34 // b/c they may keep an object alive.
35 template <typename TYPE>
36 inline void HolderRSReleaseExternal(TYPE *value)
38 _ASSERTE(value != NULL);
42 template <typename TYPE>
43 inline void HolderRSAddRefExternal(TYPE *value)
45 _ASSERTE(value != NULL);
49 // The CordbBase::m_pProcess backpointer needs to adjust the external reference count, but manipulate it from
50 // within the RS. This means we need to skip debugging checks that ensure
51 // that the external count is only manipulated from outside the RS. Since we're
52 // skipping these checks, we call this an "Unsafe" pointer.
53 template <typename TYPE>
54 inline void HolderRSUnsafeExtRelease(TYPE *value)
56 _ASSERTE(value != NULL);
59 template <typename TYPE>
60 inline void HolderRSUnsafeExtAddRef(TYPE *value)
62 _ASSERTE(value != NULL);
66 //-----------------------------------------------------------------------------
67 // Base Smart pointer implementation.
68 // This abstracts out the AddRef + Release methods.
69 //-----------------------------------------------------------------------------
70 template <typename TYPE, void (*ACQUIREF)(TYPE*), void (*RELEASEF)(TYPE*)>
75 // Ensure that these smart-ptrs are really ptr-sized.
76 static_assert_no_msg(sizeof(*this) == sizeof(void*));
79 explicit BaseSmartPtr (TYPE * ptr) : m_ptr(NULL) {
90 FORCEINLINE void Assign(TYPE * ptr)
92 // Do the AddRef before the release to avoid the release pinging 0 if we assign to ourself.
104 FORCEINLINE void Clear()
112 FORCEINLINE operator TYPE*() const
117 FORCEINLINE TYPE* GetValue() const
122 FORCEINLINE TYPE** operator & ()
124 // We allow getting the address so we can pass it in as an outparam.
125 // BTW/@TODO: this is a subtle and dangerous thing to do, since it easily leads to situations
126 // when pointer gets assigned without the ref counter being incremented.
127 // This can cause premature freeing of the object after the pointer dtor was called.
129 // But if we have a non-null m_Ptr, then it may get silently overwritten,
130 // and thus we'll lose the chance to call release on it.
131 // So we'll just avoid that pattern and assert to enforce it.
132 _ASSERTE(m_ptr == NULL);
136 // For legacy purposes, some pre smart-pointer code needs to be able to get the
137 // address of the pointer. This is needed for RSPtrArray::GetAddrOfIndex.
138 FORCEINLINE TYPE** UnsafeGetAddr()
143 FORCEINLINE TYPE* operator->()
148 FORCEINLINE int operator==(TYPE* p)
153 FORCEINLINE int operator!= (TYPE* p)
161 // Don't allow copy ctor. Explicitly don't define body to force linker errors if they're called.
162 BaseSmartPtr(BaseSmartPtr<TYPE,ACQUIREF,RELEASEF> & other);
163 void operator=(BaseSmartPtr<TYPE,ACQUIREF,RELEASEF> & other);
165 void RawAcquire(TYPE * p)
167 _ASSERTE(m_ptr == NULL);
173 _ASSERTE(m_ptr != NULL);
180 //-----------------------------------------------------------------------------
181 // Helper to make it easy to declare new SmartPtrs
182 //-----------------------------------------------------------------------------
183 #define DECLARE_MY_NEW_HOLDER(NAME, ADDREF, RELEASE) \
184 template<typename TYPE> \
185 class NAME : public BaseSmartPtr<TYPE, ADDREF, RELEASE> { \
188 NAME(NAME & other) { this->Assign(other.GetValue()); } \
189 explicit NAME(TYPE * p) : BaseSmartPtr<TYPE, ADDREF, RELEASE>(p) { }; \
190 FORCEINLINE NAME * GetAddr() { return this; } \
191 void operator=(NAME & other) { this->Assign(other.GetValue()); } \
194 //-----------------------------------------------------------------------------
195 // Declare the various smart ptrs.
196 //-----------------------------------------------------------------------------
197 DECLARE_MY_NEW_HOLDER(RSSmartPtr, HolderRSAddRef, HolderRSRelease);
198 DECLARE_MY_NEW_HOLDER(RSExtSmartPtr, HolderRSAddRefExternal, HolderRSReleaseExternal);
200 // The CordbBase::m_pProcess backpointer needs to adjust the external reference count, but manipulate it from
201 // within the RS. This means we need to skip debugging checks that ensure
202 // that the external count is only manipulated from outside the RS. Since we're
203 // skipping these checks, we call this an "Unsafe" pointer.
204 // This is purely used by CordbBase::m_pProcess.
205 DECLARE_MY_NEW_HOLDER(RSUnsafeExternalSmartPtr, HolderRSUnsafeExtAddRef, HolderRSUnsafeExtRelease);