Gray C++ Libraries  0.0.2
A set of C++ libraries for MSVC, GNU on Windows, WinCE, Linux
cIUnkPtr.h
Go to the documentation of this file.
1 //
5 //
6 
7 #ifndef _INC_cIUnkPtr_H
8 #define _INC_cIUnkPtr_H
9 #ifndef NO_PRAGMA_ONCE
10 #pragma once
11 #endif
12 
13 #include "cPtrFacade.h"
14 #include "cPtrTrace.h"
15 #include "IUnknown.h"
16 
17 #if defined(_DEBUG) && ! defined(UNDER_CE)
18 #define USE_IUNK_TRACE
19 #endif
20 
21 namespace Gray
22 {
23  template<class TYPE = IUnknown> class cIUnkTraceOpaque;
24  class cLogProcessor;
25 
26  template<class TYPE = IUnknown>
27  class cIUnkPtr
28  : public cPtrFacade < TYPE >
29 #ifdef USE_IUNK_TRACE
30  , public cPtrTrace
31 #endif
32  {
37 
38 #ifdef USE_IUNK_TRACE
39  friend class cIUnkTraceOpaque < TYPE >;
40  friend class cIUnkTraceOpaque < IUnknown >;
41 #endif
42  typedef cIUnkPtr<TYPE> THIS_t;
43  typedef cPtrFacade<TYPE> SUPER_t;
44 
45  protected:
46 #ifdef _DEBUG
47  static void AssertIUnk(TYPE* p2)
48  {
49  if (p2 == nullptr)
50  return;
51  ASSERT(static_cast<TYPE*>(p2) != nullptr); // must be based on TYPE
52  ASSERT(static_cast<IUnknown*>(p2) != nullptr); // must be based on IUnknown
53  }
54 #endif
55 
56  void SetFirstIUnk(TYPE* p2)
57  {
61  if (p2 != nullptr)
62  {
63 #ifdef _DEBUG
64  int iRefCount = (int)p2->AddRef();
65  ASSERT(iRefCount >= 1);
66  AssertIUnk(p2);
67 #else
68  p2->AddRef();
69 #endif
70 #ifdef USE_IUNK_TRACE
71  TraceOpen(p2); // NOTE: m_Src not set! use IUNK_ATTACH()
72 #endif
73  }
74  this->m_p = p2;
75  }
76 
77  public:
80 #ifdef USE_IUNK_TRACE
81  : cPtrTrace(typeid(TYPE))
82 #endif
83  {
84  }
85  cIUnkPtr(const TYPE* p2)
86 #ifdef USE_IUNK_TRACE
87  : cPtrTrace(typeid(TYPE))
88 #endif
89  {
90  SetFirstIUnk(const_cast<TYPE*>(p2));
91  }
92  cIUnkPtr(const THIS_t& ref)
93 #ifdef USE_IUNK_TRACE
94  : cPtrTrace(typeid(TYPE))
95 #endif
96  {
98  SetFirstIUnk(ref.get_Ptr());
99  }
100 
101 #if 1
102  cIUnkPtr(THIS_t&& ref) // noexcept
103 #ifdef USE_IUNK_TRACE
104  : cPtrTrace(ref)
105 #endif
106  {
109  this->m_p = ref.m_p; ref.m_p = nullptr;
110  }
111 #endif
112 
114  {
115  ReleasePtr();
116  }
117 
118  int get_RefCount() const
119  {
121  if (this->m_p == nullptr)
122  return 0;
123  int iRefCount = (int) this->m_p->AddRef(); // ULONG
124  this->m_p->Release();
125  return iRefCount - 1;
126  }
128  {
131  ReleasePtr();
132  ASSERT(!this->isValidPtr());
133  return &this->m_p;
134  }
135  void** get_PPtrV()
136  {
141  ReleasePtr();
142  ASSERT(!this->isValidPtr());
143  TYPE** ppObj = &this->m_p;
144  return reinterpret_cast<void**>(ppObj);
145  }
147  {
149  return this->m_p;
150  }
151 
152  void put_Ptr(TYPE* p2)
153  {
154  if (p2 != this->m_p)
155  {
156  ReleasePtr();
157  SetFirstIUnk(p2);
158  }
159  }
160 
161  HRESULT SetQI(IUnknown* p2, const IID& riid)
162  {
164  if (p2 == nullptr)
165  {
166  ReleasePtr();
167  return E_NOINTERFACE;
168  }
169  // Query for TYPE interface. acts like IUNK_GETPPTRV(pInterface, riid)
170  TYPE* pInterface = nullptr;
171  HRESULT hRes = p2->QueryInterface(riid, reinterpret_cast<void**>(&pInterface));
172  if (FAILED(hRes))
173  {
174  // pInterface = nullptr;
175  ReleasePtr();
176  return hRes;
177  }
178 
179 #ifdef _DEBUG
180  ASSERT(pInterface != nullptr);
181  AssertIUnk(pInterface);
182 #endif
183 #ifdef USE_IUNK_TRACE
184  TraceOpen(pInterface); // NOTE: m_Src not set! use IUNK_ATTACH()
185 #endif
186 
187  // Save the interface without AddRef()ing. ASSUME QueryInterface already did that.
188  this->m_p = pInterface;
189  return hRes;
190  }
191 
192 #ifdef _MSC_VER
193  static const IID& GetIID()
194  {
197  return __uuidof(TYPE);
198  }
199  HRESULT SetQI(IUnknown* p2)
200  {
203  return SetQI(p2, GetIID());
204  }
205 #endif // _MSC_VER
206 
208  {
211  if (this->m_p == nullptr)
212  return 0;
213 
214  TYPE* p2 = this->m_p;
215 #ifdef _DEBUG
216  AssertIUnk(this->m_p);
217 #endif
218 #ifdef USE_IUNK_TRACE
219  TraceClose(p2);
220 #endif
221  this->m_p = nullptr; // make sure possible destructors called in DecRefCount don't reuse this.
222  int iRefCount = (int)p2->Release(); // this might delete this ?
223  return iRefCount;
224  }
225 
227  THIS_t& operator = (const TYPE* p2)
228  {
229  put_Ptr(const_cast<TYPE*>(p2));
230  return *this;
231  }
233  {
235  put_Ptr(p2.get_Ptr());
236  return *this;
237  }
238 #if 0
239  THIS_t& operator = (THIS_t&& ref)
240  {
242  this->m_p = ref.m_p; ref.m_p = nullptr;
243  return *this;
244  }
245 #endif
246 
248  TYPE& operator * () const
249  {
250  ASSERT(this->isValidPtr()); return *this->m_p;
251  }
252 
253  TYPE* operator -> () const
254  {
255  ASSERT(this->isValidPtr()); return(this->m_p);
256  }
257  };
258 
259  // The lowest (un-type checked) smart pointer.
261 
262 #ifdef USE_IUNK_TRACE
263  template<class TYPE>
264  class cIUnkTraceOpaque
265  {
271  private:
272  cIUnkPtr<TYPE>& m_rpIObj;
273 
274  public:
276  : m_rpIObj(rpObj)
277  {
278  ASSERT(rpObj.get_Ptr() == nullptr);
279  rpObj.m_Src = src; // last open on this handle.
280  }
282  {
284  TYPE* p = m_rpIObj.get_Ptr();
285  if (p != nullptr)
286  {
287 #ifdef _DEBUG
288  m_rpIObj.AssertIUnk(p);
289 #endif
290  m_rpIObj.TraceOpen(p);
291  }
292  }
293  operator TYPE** () const
294  {
295  // the opaque function wants TYPE**
296  return m_rpIObj.get_PPtr();
297  }
298  operator void** () const
299  {
300  // the opaque function wants void**
301  return m_rpIObj.get_PPtrV();
302  }
303  };
304 
305 #define IUNK_GETPPTR(p,TYPE) cIUnkTraceOpaque<TYPE>(p,DEBUGSOURCELINE)
306 #define IUNK_GETPPTRV(p,TYPE) cIUnkTraceOpaque<TYPE>(p,DEBUGSOURCELINE)
307 #define IUNK_ATTACH(p) ASSERT((p).get_Ptr()!=nullptr); (p).m_Src = DEBUGSOURCELINE; (p).TraceOpen((p).get_Ptr()); // attach trace.
308 #else
309 #define IUNK_GETPPTR(p,TYPE) (p).get_PPtr()
310 #define IUNK_GETPPTRV(p,TYPE) (p).get_PPtrV()
311 #define IUNK_ATTACH(p) __noop // No trace.
312 #endif // USE_IUNK_TRACE
313 
314 #ifdef GRAY_DLL // force implementation/instantiate for DLL/SO.
316 #endif
317 
318 }
319 #endif // _INC_IUnkPtr_H
#define GRAYCORE_LINK
Definition: GrayCore.h:47
#define FAILED(x)
Definition: HResult.h:30
#define TYPE
Definition: StrT.cpp:38
INT32 HRESULT
_WIN32 style error codes. INT32
Definition: SysTypes.h:465
#define ASSERT(exp)
Definition: cDebugAssert.h:87
Definition: cIUnkPtr.h:32
TYPE ** get_PPtr()
Definition: cIUnkPtr.h:127
cIUnkPtr(THIS_t &&ref)
Definition: cIUnkPtr.h:102
THIS_t & operator=(const TYPE *p2)
Assignment ops.
Definition: cIUnkPtr.h:227
int get_RefCount() const
Definition: cIUnkPtr.h:118
cIUnkPtr(const TYPE *p2)
Definition: cIUnkPtr.h:85
void SetFirstIUnk(TYPE *p2)
Definition: cIUnkPtr.h:56
void ** get_PPtrV()
Definition: cIUnkPtr.h:135
void put_Ptr(TYPE *p2)
Definition: cIUnkPtr.h:152
cIUnkPtr()
Construct and destruction.
Definition: cIUnkPtr.h:79
cIUnkPtr(const THIS_t &ref)
Definition: cIUnkPtr.h:92
TYPE & operator*() const
Accessor ops.
Definition: cIUnkPtr.h:248
~cIUnkPtr()
Definition: cIUnkPtr.h:113
TYPE * operator->() const
Definition: cIUnkPtr.h:253
TYPE * GetInterfacePtr() const
Definition: cIUnkPtr.h:146
int ReleasePtr()
Definition: cIUnkPtr.h:207
HRESULT SetQI(IUnknown *p2, const IID &riid)
Definition: cIUnkPtr.h:161
Definition: cIUnkPtr.h:23
Definition: cLogAppender.h:168
Definition: cPtrFacade.h:19
IUnknown * m_p
Pointer to some object of TYPE.
Definition: cPtrFacade.h:28
bool isValidPtr() const noexcept
Definition: cPtrFacade.h:41
TYPE * get_Ptr() const noexcept
Definition: cPtrFacade.h:53
Definition: cPtrTrace.h:21
Definition: IUnknown.h:68
< The main namespace for all Core functions.
Definition: GrayCore.cpp:14
__DECL_IMPORT cIUnkPtr cIUnkBasePtr
Definition: cIUnkPtr.h:260
const cDebugSourceLine & src
Definition: cDebugAssert.h:51
Definition: cDebugAssert.h:29
Definition: IUnknown.h:34