Gray C++ Libraries  0.0.2
A set of C++ libraries for MSVC, GNU on Windows, WinCE, Linux
cRefPtr.h
Go to the documentation of this file.
1 //
5 //
6 
7 #ifndef _INC_cRefPtr_H
8 #define _INC_cRefPtr_H
9 #ifndef NO_PRAGMA_ONCE
10 #pragma once
11 #endif
12 
13 #include "cPtrFacade.h"
14 #include "cInterlockedVal.h"
15 #include "IUnknown.h"
16 #include "cTimeSys.h" // TIMESYSD_t
17 #include "cMem.h"
18 
19 namespace Gray
20 {
21  class GRAYCORE_LINK cRefBase : public IUnknown // virtual
22  {
29 
30 #ifdef _DEBUG
31  static const int k_REFCOUNT_DEBUG = 0x20000000;
32 #endif
33  static const int k_REFCOUNT_STATIC = 0x40000000;
34  static const int k_REFCOUNT_DESTRUCT = 0x80000000;
35  static const int k_REFCOUNT_MASK = 0xE0000000;
36 
37  private:
38  mutable cInterlockedInt m_nRefCount;
39 
40  private:
41  void _InternalAddRef() noexcept
42  {
43 #ifdef _DEBUG
44  DEBUG_CHECK(isValidObj());
45  DEBUG_CHECK(!isDestructing());
46  const int iRefCount = get_RefCount();
47  if (isSmartDebug())
48  {
49  ASSERT(iRefCount != 123123); // dummy for breakpoint.
50  }
51  ASSERT(iRefCount < (~k_REFCOUNT_MASK));
52 #endif
53  m_nRefCount.IncV();
54  }
55  void _InternalRelease()
56  {
57 #ifdef _DEBUG
58  ASSERT(isValidObj());
59  ASSERT(!isDestructing());
60  const int iRefCount2 = get_RefCount();
61  if (isSmartDebug())
62  {
63  ASSERT(iRefCount2 != 123123); // dummy for breakpoint.
64  }
65 #endif
66  const int iRefCount = m_nRefCount.Dec();
67  if (iRefCount == 0)
68  {
69  onFinalRelease();
70  }
71  else
72  {
73  ASSERT(iRefCount > 0);
74  }
75  }
76 
77  public:
78 
79  explicit cRefBase(int iRefCount = 0) noexcept
80  : m_nRefCount(iRefCount)
81  {
82  }
83  virtual ~cRefBase()
84  {
86  ASSERT(get_RefCount() == 0);
87  }
88 
89  int get_RefCount() const noexcept
90  {
91  return m_nRefCount.get_Value() & ~k_REFCOUNT_MASK;
92  }
93  HASHCODE_t get_HashCode() const noexcept
94  {
96  return ((HASHCODE_t)(UINT_PTR)(void*)this);
97  }
98  STDMETHOD_(HASHCODE_t, get_HashCodeX)() const noexcept
99  {
101  return get_HashCode();
102  }
103 
104  // do something when no-one wants this anymore. cache or delete?
105  virtual void onFinalRelease()
106  {
111  SetDestructing();
112  delete this;
113  }
114 
115  bool isValidObj() const noexcept
116  {
117  // Is this really a valid object?
118  // does it have proper vtable ?
119  if (!cMem::IsValid(this))
120  return false;
121 #if defined(_DEBUG) && ! defined(__GNUC__)
122  return IS_TYPE_OF(cRefBase, this);
123 #else
124  return true;
125 #endif
126  }
127 
128  // COM IUnknown compliant methods.
129  STDMETHOD_(ULONG, AddRef)(void) override
130  {
132  _InternalAddRef();
133  return (ULONG)get_RefCount();
134  }
135  STDMETHOD_(ULONG, Release)(void) override
136  {
138  int iRefCount = get_RefCount();
139  _InternalRelease(); // this could get deleted here!
140  return (ULONG)(iRefCount - 1);
141  }
142  STDMETHOD(QueryInterface)(const IID& riid, /* [iid_is][out] */ void __RPC_FAR* __RPC_FAR* ppvObject) override
143  {
145  if (cMem::Compare(&riid, &__uuidof(IUnknown), sizeof(riid)) == 0)
146  {
147  *ppvObject = this;
148  _InternalAddRef();
149  return S_OK;
150  }
151  *ppvObject = nullptr;
152  return E_NOINTERFACE; // E_NOTIMPL
153  }
154 
155 #if 0 // def _DEBUG // for testing.
156  void IncRefCount()
157  {
158  AddRef();
159  } // always go through the COM interface!
160  void DecRefCount()
161  {
162  Release();
163  }
164 #else
165  void IncRefCount()
166  {
167  _InternalAddRef();
168  }
169  void DecRefCount()
170  {
171  _InternalRelease();
172  }
173 #endif
174 
175  bool isStaticConstruct() const noexcept
176  {
178  return(m_nRefCount.get_Value() & k_REFCOUNT_STATIC) ? true : false;
179  }
181  {
183  ASSERT(m_nRefCount.get_Value() == 0); // only call in constructor!
184  m_nRefCount.AddX(k_REFCOUNT_STATIC);
185  }
187  {
190  ASSERT(isStaticConstruct());
191  m_nRefCount.put_Value(0);
192  }
193 
194  bool isDestructing() noexcept
195  {
196  return(m_nRefCount.get_Value() & k_REFCOUNT_DESTRUCT) ? true : false;
197  }
199  {
201  if (isDestructing())
202  return;
203  ASSERT(get_RefCount() == 0);
204  m_nRefCount.put_Value(k_REFCOUNT_DESTRUCT);
205  }
206 
207 #ifdef _DEBUG
208  bool isSmartDebug() const
209  {
210  return(m_nRefCount.get_Value() & k_REFCOUNT_DEBUG) ? true : false;
211  }
212  void SetSmartDebug()
213  {
215  if (isSmartDebug())
216  return;
217  m_nRefCount.AddX(k_REFCOUNT_DEBUG);
218  }
219 #endif
220  };
221 
222  template<class TYPE = cRefBase >
223  class cRefPtr
224  : public cPtrFacade < TYPE >
225  {
232 
233  typedef cRefPtr<TYPE> THIS_t;
234  typedef cPtrFacade<TYPE> SUPER_t;
235 
236  protected:
237  void IncRefFirst()
238  {
240  if (this->m_p != nullptr)
241  {
242  cRefBase* p = this->m_p;
243  p->IncRefCount();
244 #ifdef _DEBUG
245  ASSERT(!isCorruptPtr());
246 #endif
247  }
248  }
249 
250  public:
251  cRefPtr() noexcept
252  {
253  }
254  cRefPtr(const TYPE* p2)
255  : cPtrFacade<TYPE>(const_cast<TYPE*>(p2))
256  {
258  IncRefFirst();
259  }
260  cRefPtr(const THIS_t& ref)
261  : cPtrFacade<TYPE>(ref.get_Ptr())
262  {
264  IncRefFirst();
265  }
266 
267 #if 0
268  cRefPtr(THIS_t&& ref)
269  : cPtrFacade<TYPE>(ref)
270  {
272  }
273 #endif
274 
275  cRefPtr(const TYPE* p2, TIMESYSD_t dwWaitMS)
276  : cPtrFacade<TYPE>(const_cast<TYPE*>(p2))
277  {
280  UNREFERENCED_PARAMETER(dwWaitMS);
281  IncRefFirst();
282  }
284  {
285  ReleasePtr();
286  }
287 
288  bool isValidPtr() const
289  {
291 #ifdef _DEBUG
292  ASSERT(!isCorruptPtr());
293 #endif
294  return this->m_p != nullptr;
295  }
296  bool isCorruptPtr() const
297  {
300  if (this->m_p == nullptr) // nullptr is not corrupt.
301  return false;
302  // ASSERT( DYNPTR_CAST(TYPE,this->m_p) != nullptr );
303  cRefBase* p = DYNPTR_CAST(cRefBase, this->m_p);
304  if (p == nullptr)
305  return true;
306  if (p->get_RefCount() <= 0)
307  return true;
308  return false;
309  }
310  void put_Ptr(TYPE* p)
311  {
313  if (p != this->m_p)
314  {
315  ReleasePtr();
316  this->AttachPtr(p);
317  IncRefFirst();
318  }
319  }
320  void ReleasePtr()
321  {
323  TYPE* p2 = this->m_p;
324  if (p2 != nullptr)
325  {
326 #ifdef _DEBUG
327  ASSERT(!isCorruptPtr());
328 #endif
329  this->m_p = nullptr; // make sure possible destructors called in DecRefCount don't reuse this.
330  p2->DecRefCount(); // this might delete this ?
331  }
332  }
333  int get_RefCount() const
334  {
336  if (this->m_p == nullptr)
337  return 0;
338  return this->m_p->get_RefCount();
339  }
340 
341  // Assignment ops.
342  THIS_t& operator = (const TYPE* p2)
343  {
344  put_Ptr(const_cast<TYPE*>(p2));
345  return *this;
346  }
347  THIS_t& operator = (const THIS_t& ref)
348  {
351  put_Ptr(ref.get_Ptr());
352  return *this;
353  }
354 
355 #if 0
356  THIS_t& operator = (THIS_t&& ref)
357  {
359  this->m_p = ref.m_p; ref.m_p = nullptr;
360  return *this;
361  }
362 #endif
363 
364 #if 1
365  template<class _TYPE_2> operator cRefPtr<_TYPE_2>() const
366  {
369  return cRefPtr<_TYPE_2>((this->m_p)); // this will automatically give an error if classes are unrelated. static_cast<_TYPE_2>
370  }
371 #endif
372 
373  };
374 
375  // The lowest (un-type checked) smart pointer.
377 
378 #ifdef GRAY_DLL // force implementation/instantiate for DLL/SO.
380 #endif
381 
382 }
383 
384 #endif // _INC_cRefPtr_H
#define GRAYCORE_LINK
Definition: GrayCore.h:47
#define IS_TYPE_OF(t, p)
Definition: PtrCast.h:23
#define DYNPTR_CAST(t, p)
Definition: PtrCast.h:22
#define TYPE
Definition: StrT.cpp:38
#define UNREFERENCED_PARAMETER(P)
< _WIN32 type thing. get rid of stupid warning.
Definition: SysTypes.h:299
#define ASSERT(exp)
Definition: cDebugAssert.h:87
#define DEBUG_CHECK(exp)
Definition: cDebugAssert.h:90
Definition: cPtrFacade.h:19
cRefBase * m_p
Pointer to some object of TYPE.
Definition: cPtrFacade.h:28
void AttachPtr(cRefBase *p) noexcept
Definition: cPtrFacade.h:71
cRefBase * get_Ptr() const noexcept
Definition: cPtrFacade.h:53
Definition: cRefPtr.h:22
void SetDestructing()
Definition: cRefPtr.h:198
virtual ~cRefBase()
Definition: cRefPtr.h:83
void StaticConstruct()
Definition: cRefPtr.h:180
bool isStaticConstruct() const noexcept
Definition: cRefPtr.h:175
void IncRefCount()
Definition: cRefPtr.h:165
int get_RefCount() const noexcept
Definition: cRefPtr.h:89
void DecRefCount()
Definition: cRefPtr.h:169
STDMETHOD_(ULONG, Release)(void) override
Definition: cRefPtr.h:135
STDMETHOD_(HASHCODE_t, get_HashCodeX)() const noexcept
Definition: cRefPtr.h:98
virtual void onFinalRelease()
Definition: cRefPtr.h:105
cRefBase(int iRefCount=0) noexcept
Definition: cRefPtr.h:79
bool isValidObj() const noexcept
Definition: cRefPtr.h:115
void StaticDestruct()
Definition: cRefPtr.h:186
bool isDestructing() noexcept
Definition: cRefPtr.h:194
HASHCODE_t get_HashCode() const noexcept
Definition: cRefPtr.h:93
STDMETHOD_(ULONG, AddRef)(void) override
Definition: cRefPtr.h:129
Definition: cRefPtr.h:225
THIS_t & operator=(const TYPE *p2)
Definition: cRefPtr.h:342
bool isValidPtr() const
Definition: cRefPtr.h:288
void IncRefFirst()
Definition: cRefPtr.h:237
void ReleasePtr()
Definition: cRefPtr.h:320
cRefPtr(const TYPE *p2, TIMESYSD_t dwWaitMS)
Definition: cRefPtr.h:275
cRefPtr() noexcept
Definition: cRefPtr.h:251
bool isCorruptPtr() const
Definition: cRefPtr.h:296
~cRefPtr()
Definition: cRefPtr.h:283
int get_RefCount() const
Definition: cRefPtr.h:333
cRefPtr(const THIS_t &ref)
Definition: cRefPtr.h:260
void put_Ptr(TYPE *p)
Definition: cRefPtr.h:310
cRefPtr(const TYPE *p2)
Definition: cRefPtr.h:254
Definition: IUnknown.h:68
< The main namespace for all Core functions.
Definition: GrayCore.cpp:14
INT32 TIMESYSD_t
Time delta. signed milli-Seconds Span. cTimeSys::k_DMAX, cTimeSys::k_INF = MAILSLOT_WAIT_FOREVER.
Definition: cTimeSys.h:28
__DECL_IMPORT cRefPtr cRefBasePtr
Definition: cRefPtr.h:376
UINT_PTR HASHCODE_t
could hold a pointer converted to a number? maybe 64 or 32 bit ? same as size_t.
Definition: GrayCore.h:116
static bool __stdcall IsValid(const void *pData, size_t nSize=1, bool bWriteAccess=false) noexcept
Definition: cMem.cpp:33
static COMPARE_t Compare(const void *p1, const void *p2, size_t nSizeBlock) noexcept
Definition: cMem.h:78
Definition: IUnknown.h:34