gwnavruntime/kernel/SF_RefCount.h Source File

SF_RefCount.h
Go to the documentation of this file.
1 /*
2 * Copyright 2016 Autodesk, Inc. All rights reserved.
3 * Use of this software is subject to the terms of the Autodesk license agreement and any attachments or Appendices thereto provided at the time of installation or download,
4 * or which otherwise accompanies this software in either electronic or hard copy form, or which is signed by you and accepted by Autodesk.
5 */
6 
7 /**************************************************************************
8 
9 PublicHeader: Kernel
10 Filename : KY_RefCount.h
11 Content : Reference counting implementation headers
12 Created : January 14, 1999
13 Authors : Michael Antonov, Maxim Shemanarev, Sergey Sikorskiy
14 
15 **************************************************************************/
16 
17 #ifndef INC_KY_Kernel_RefCount_H
18 #define INC_KY_Kernel_RefCount_H
19 
22 
23 namespace Kaim {
24 
25 // ***** Reference Counting
26 
27 // There are three types of reference counting base classes:
28 //
29 // RefCountBase - Provides thread-safe reference counting (Default).
30 // RefCountBaseNTS - Non Thread Safe version of reference counting.
31 // RefCountBaseWeakSupport - Non Thread Safe ref-counting with WeakPtr support.
32 
33 
34 // ***** Declared classes
35 
36 template<class C, int StatType>
37 class RefCountBase;
38 template<class C, int StatType>
39 class RefCountBaseNTS;
40 template<class C, int StatType>
41 class RefCountBaseWeakSupport;
42 
43 class RefCountImpl;
44 class RefCountNTSImpl;
45 class RefCountWeakSupportImpl;
46 //class RefCountImpl;
47 
48 template<class C>
49 class WeakPtr;
50 class WeakPtrProxy;
51 
52 
53 // *** Macros for RefCountBase
54 
55 // These macros specify whether reference counting is configured to be
56 // thread safe or not. By default, reference counting is not thread-safe
57 // for most classes.
58 #define KY_REFCOUNT_NORMAL 0x00000000
59 #define KY_REFCOUNT_THREADSAFE 0x00000001
60 
61 
62 // ***** Implementation For Reference Counting
63 
64 // RefCountImplCore holds RefCount value and defines a few utility
65 // functions shared by all implementations.
66 
67 class RefCountImplCore
68 {
69 protected:
70  std::atomic<int> RefCount;
71 
72 public:
73  // RefCountImpl constructor always initializes RefCount to 1 by default.
74  KY_INLINE RefCountImplCore() : RefCount(1) { }
75 
76  // Need virtual destructor
77  // This: 1. Makes sure the right destructor's called.
78  // 2. Makes us have VTable, necessary if we are going to have format needed by InitNewMem()
79  virtual ~RefCountImplCore();
80 
81  // Debug method only.
82  int GetRefCount() const { return RefCount; }
83 
84  // This logic is used to detect invalid 'delete' calls of reference counted
85  // objects. Direct delete calls are not allowed on them unless they come in
86  // internally from Release.
87 #ifdef KY_CONFIG_DEBUG
88  static void reportInvalidDelete(void *pmem);
89  inline static void checkInvalidDelete(RefCountImplCore *pmem)
90  {
91  if (pmem->RefCount != 0)
92  reportInvalidDelete(pmem);
93  }
94 #else
95  inline static void checkInvalidDelete(RefCountImplCore *) { }
96 #endif
97 
98  // Base class ref-count content should not be copied.
99  RefCountImplCore(const RefCountImplCore &) : RefCount(1) { }
100  void operator = (const RefCountImplCore &) { }
101 };
102 
103 class RefCountNTSImplCore
104 {
105 protected:
106  mutable int RefCount;
107 
108 public:
109  // RefCountImpl constructor always initializes RefCount to 1 by default.
110  KY_INLINE RefCountNTSImplCore() : RefCount(1) { }
111 
112  // Need virtual destructor
113  // This: 1. Makes sure the right destructor's called.
114  // 2. Makes us have VTable, necessary if we are going to have format needed by InitNewMem()
115  virtual ~RefCountNTSImplCore();
116 
117  // Debug method only.
118  int GetRefCount() const { return RefCount; }
119 
120  // This logic is used to detect invalid 'delete' calls of reference counted
121  // objects. Direct delete calls are not allowed on them unless they come in
122  // internally from Release.
123 #ifdef KY_CONFIG_DEBUG
124  static void reportInvalidDelete(void *pmem);
125  KY_INLINE static void checkInvalidDelete(RefCountNTSImplCore *pmem)
126  {
127  if (pmem->RefCount != 0)
128  reportInvalidDelete(pmem);
129  }
130 #else
131  KY_INLINE static void checkInvalidDelete(RefCountNTSImplCore *) { }
132 #endif
133 
134  // Base class ref-count content should not be copied.
135  RefCountNTSImplCore(const RefCountNTSImplCore &) : RefCount(1) { }
136  void operator = (const RefCountNTSImplCore &) { }
137 };
138 
139 
140 
141 // RefCountImpl provides Thread-Safe implementation of reference counting, so
142 // it should be used by default in most places.
143 
144 class RefCountImpl : public RefCountImplCore
145 {
146 public:
147  // Thread-Safe Ref-Count Implementation.
148  void AddRef();
149  void Release();
150 };
151 
152 // RefCountVImpl provides Thread-Safe implementation of reference counting, plus,
153 // virtual AddRef and Release.
154 
155 class RefCountVImpl : public RefCountImplCore
156 {
157 public:
158  // Thread-Safe Ref-Count Implementation.
159  virtual void AddRef();
160  virtual void Release();
161 };
162 
163 
164 // RefCountImplNTS provides Non-Thread-Safe implementation of reference counting,
165 // which is slightly more efficient since it doesn't use atomics.
166 
167 class RefCountNTSImpl : public RefCountNTSImplCore
168 {
169 public:
170  KY_INLINE void AddRef() const { RefCount++; }
171  void Release() const;
172 };
173 
174 // RefCountWeakSupportImpl provides reference counting with WeakProxy support,
175 // allowing for WeakPtr<> to be used on objects derived from this class. Weak pointer
176 // support is non-thread safe. Weak pointers are used for some ActionScript objects,
177 // especially when GC is disabled.
178 
179 class RefCountWeakSupportImpl : public RefCountNTSImpl
180 {
181 protected:
182  mutable WeakPtrProxy* pWeakProxy;
183 public:
184  RefCountWeakSupportImpl() { pWeakProxy = 0; }
185  virtual ~RefCountWeakSupportImpl();
186 
187  // Create/return create proxy, users must release proxy when no longer needed.
188  WeakPtrProxy* CreateWeakProxy() const;
189 };
190 
191 
192 // RefCountBaseStatImpl<> is a common class that adds new/delete override with Stat tracking
193 // to the reference counting implemenation. Base must be one of the RefCountImpl classes.
194 
195 template<class Base, int StatType>
196 class RefCountBaseStatImpl : public Base
197 {
198 public:
199  RefCountBaseStatImpl() { }
200 
201  // *** Override New and Delete
202 
203  // DOM-IGNORE-BEGIN
204  // Undef new temporarily if it is being redefined
205 #ifdef KY_BUILD_DEFINE_NEW
206 #ifdef KY_DEFINE_NEW
207 #undef new
208 #endif
209 #endif
210 
211 #ifdef KY_CONFIG_DEBUG
212  // Custom check used to detect incorrect calls of 'delete' on ref-counted objects.
213  #define KY_REFCOUNTALLOC_CHECK_DELETE(class_name, p) \
214  do {if (p) Base::checkInvalidDelete((class_name*)p); } while(0)
215 #else
216  #define KY_REFCOUNTALLOC_CHECK_DELETE(class_name, p)
217 #endif
218 
219  // Redefine all new & delete operators.
220  KY_MEMORY_REDEFINE_NEW_IMPL(Base, KY_REFCOUNTALLOC_CHECK_DELETE, StatType)
221 
222 #ifdef KY_DEFINE_NEW
223 #define new KY_DEFINE_NEW
224 #endif
225  // KY_BUILD_DEFINE_NEW
226  // DOM-IGNORE-END
227 };
228 
229 
230 
231 
232 // *** End user RefCountBase<> classes
233 
234 
235 // RefCountBase is a base class for classes that require thread-safe reference
236 // counting; it also overrides the new and delete operators to use MemoryHeap.
237 //
238 // Reference counted objects start out with RefCount value of 1. Further lifetame
239 // management is done through the AddRef() and Release() methods, typically
240 // hidden by Ptr<>.
241 
242 template<class C, int Stat>
243 class RefCountBase : public RefCountBaseStatImpl<RefCountImpl, Stat>
244 {
245 public:
246  enum { StatType = Stat };
247  // Constructor.
248  KY_INLINE RefCountBase() : RefCountBaseStatImpl<RefCountImpl, Stat>() { }
249 };
250 
251 // RefCountBaseV is the same as RefCountBase but with virtual AddRef/Release
252 
253 template<class C, int Stat>
254 class RefCountBaseV : public RefCountBaseStatImpl<RefCountVImpl, Stat>
255 {
256 public:
257  enum { StatType = Stat };
258  // Constructor.
259  KY_INLINE RefCountBaseV() : RefCountBaseStatImpl<RefCountVImpl, Stat>() { }
260 };
261 
262 
263 // RefCountBaseNTS is a base class for classes that require Non-Thread-Safe reference
264 // counting; it also overrides the new and delete operators to use MemoryHeap.
265 // This class should only be used if all pointers to it are known to be assigned,
266 // destroyed and manipulated within one thread.
267 //
268 // Reference counted objects start out with RefCount value of 1. Further lifetame
269 // management is done through the AddRef() and Release() methods, typically
270 // hidden by Ptr<>.
271 
272 template<class C, int Stat>
273 class RefCountBaseNTS : public RefCountBaseStatImpl<RefCountNTSImpl, Stat>
274 {
275 public:
276  enum { StatType = Stat };
277  // Constructor.
278  KY_INLINE RefCountBaseNTS() : RefCountBaseStatImpl<RefCountNTSImpl, Stat>() { }
279 };
280 
281 // RefCountBaseWeakSupport is a base class for classes that require Non-Thread-Safe
282 // reference counting and WeakPtr<> support; it also overrides the new and delete
283 // operators to use MemoryHeap. This class should only be used if all pointers to it
284 // are known to be assigned, destroyed and manipulated within one thread.
285 //
286 // Reference counted objects start out with RefCount value of 1. Further lifetame
287 // management is done through the AddRef() and Release() methods, typically
288 // hidden by Ptr<>.
289 
290 template<class C, int Stat>
291 class RefCountBaseWeakSupport : public RefCountBaseStatImpl<RefCountWeakSupportImpl, Stat>
292 {
293 public:
294  enum { StatType = Stat };
295  // Constructor.
296  KY_INLINE RefCountBaseWeakSupport() : RefCountBaseStatImpl<RefCountWeakSupportImpl, Stat>() { }
297 };
298 
299 
300 
301 // ***** Pickable template pointer
302 enum PickType { PickValue };
303 
304 template <typename T>
305 class Pickable
306 {
307 public:
308  Pickable() : pV(NULL) {}
309  explicit Pickable(T* p) : pV(p) {}
310  Pickable(T* p, PickType) : pV(p)
311  {
312  KY_ASSERT(pV);
313  if (pV)
314  pV->AddRef();
315  }
316  template <typename OT>
317  Pickable(const Pickable<OT>& other) : pV(other.GetPtr()) {}
318 
319 public:
320  Pickable& operator =(const Pickable& other)
321  {
322  KY_ASSERT(pV == NULL);
323  pV = other.pV;
324  // Extra check.
325  //other.pV = NULL;
326  return *this;
327  }
328 
329 public:
330  T* GetPtr() const { return pV; }
331  T* operator->() const
332  {
333  return pV;
334  }
335  T& operator*() const
336  {
337  KY_ASSERT(pV);
338  return *pV;
339  }
340 
341 private:
342  T* pV;
343 };
344 
345 template <typename T>
346 KY_INLINE
347 Pickable<T> MakePickable(T* p)
348 {
349  return Pickable<T>(p);
350 }
351 
352 // ***** Ref-Counted template pointer
353 
354 // Automatically AddRefs and Releases interfaces
355 
356 void* ReturnArg0(void* p);
357 
358 template<class C>
359 class Ptr
360 {
361 
362 protected:
363  C *pObject;
364 
365 public:
366 
367  // Constructors
368  KY_INLINE Ptr() : pObject(0)
369  { }
370  KY_INLINE Ptr(C &robj) : pObject(&robj)
371  { }
372  KY_INLINE Ptr(Pickable<C> v) : pObject(v.GetPtr())
373  {
374  // No AddRef() on purpose.
375  }
376  KY_INLINE Ptr(Ptr<C>& other, PickType) : pObject(other.pObject)
377  {
378  other.pObject = NULL;
379  // No AddRef() on purpose.
380  }
381  KY_INLINE Ptr(C *pobj)
382  {
383  if (pobj) pobj->AddRef();
384  pObject = pobj;
385  }
386  KY_INLINE Ptr(const Ptr<C> &src)
387  {
388  if (src.pObject) src.pObject->AddRef();
389  pObject = src.pObject;
390  }
391 
392  template<class R>
393  KY_INLINE Ptr(Ptr<R> &src)
394  {
395  if (src) src->AddRef();
396  pObject = src;
397  }
398  template<class R>
399  KY_INLINE Ptr(Pickable<R> v) : pObject(v.GetPtr())
400  {
401  // No AddRef() on purpose.
402  }
403 
404  // Destructor
405  KY_INLINE ~Ptr()
406  {
407  if (pObject) pObject->Release();
408  }
409 
410  // Compares
411  KY_INLINE bool operator == (const Ptr &other) const { return pObject == other.pObject; }
412  KY_INLINE bool operator != (const Ptr &other) const { return pObject != other.pObject; }
413 
414  KY_INLINE bool operator == (C *pother) const { return pObject == pother; }
415  KY_INLINE bool operator != (C *pother) const { return pObject != pother; }
416 
417 
418  KY_INLINE bool operator < (const Ptr &other) const { return pObject < other.pObject; }
419 
420  // Assignment
421  template<class R>
422  KY_INLINE const Ptr<C>& operator = (const Ptr<R> &src)
423  {
424  if (src) src->AddRef();
425  if (pObject) pObject->Release();
426  pObject = src;
427  return *this;
428  }
429  // Specialization
430  KY_INLINE const Ptr<C>& operator = (const Ptr<C> &src)
431  {
432  if (src) src->AddRef();
433  if (pObject) pObject->Release();
434  pObject = src;
435  return *this;
436  }
437 
438  KY_INLINE const Ptr<C>& operator = (C *psrc)
439  {
440  if (psrc) psrc->AddRef();
441  if (pObject) pObject->Release();
442  pObject = psrc;
443  return *this;
444  }
445  KY_INLINE const Ptr<C>& operator = (C &src)
446  {
447  if (pObject) pObject->Release();
448  pObject = &src;
449  return *this;
450  }
451  KY_INLINE Ptr<C>& operator = (Pickable<C> src)
452  {
453  return Pick(src);
454  }
455  template<class R>
456  KY_INLINE Ptr<C>& operator = (Pickable<R> src)
457  {
458  return Pick(src);
459  }
460 
461  // Set Assignment
462  template<class R>
463  KY_INLINE Ptr<C>& SetPtr(const Ptr<R> &src)
464  {
465  if (src) src->AddRef();
466  if (pObject) pObject->Release();
467  pObject = src;
468  return *this;
469  }
470  // Specialization
471  KY_INLINE Ptr<C>& SetPtr(const Ptr<C> &src)
472  {
473  if (src) src->AddRef();
474  if (pObject) pObject->Release();
475  pObject = src;
476  return *this;
477  }
478 
479  KY_INLINE Ptr<C>& SetPtr(C *psrc)
480  {
481  if (psrc) psrc->AddRef();
482  if (pObject) pObject->Release();
483  pObject = psrc;
484  return *this;
485  }
486  KY_INLINE Ptr<C>& SetPtr(C &src)
487  {
488  if (pObject) pObject->Release();
489  pObject = &src;
490  return *this;
491  }
492  KY_INLINE Ptr<C>& SetPtr(Pickable<C> src)
493  {
494  return Pick(src);
495  }
496 
497  // Nulls ref-counted pointer without decrement
498  KY_INLINE void NullWithoutRelease()
499  {
500  pObject = 0;
501  }
502 
503  // Clears the pointer to the object
504  KY_INLINE void Clear()
505  {
506  if (pObject) pObject->Release();
507  pObject = 0;
508  }
509 
510  // Obtain pointer reference directly, for D3D interfaces
511  KY_INLINE C*& GetRawRef() { return pObject; }
512 
513  // Access Operators
514  KY_INLINE C* GetPtr() const { return pObject; }
515  KY_INLINE C& operator * () const { return *pObject; }
516  KY_INLINE C* operator -> () const { return pObject; }
517  // Conversion
518  KY_INLINE operator C* () const { return pObject; }
519 
520  // Pickers.
521 
522  // Pick a value.
523  KY_INLINE Ptr<C>& Pick(Ptr<C>& other)
524  {
525  if (&other != this)
526  {
527  if (pObject) pObject->Release();
528  pObject = other.pObject;
529  other.pObject = 0;
530  }
531 
532  return *this;
533  }
534 
535  KY_INLINE Ptr<C>& Pick(Pickable<C> v)
536  {
537  if (v.GetPtr() != pObject)
538  {
539  if (pObject) pObject->Release();
540  pObject = v.GetPtr();
541  }
542 
543  return *this;
544  }
545 
546  template<class R>
547  KY_INLINE Ptr<C>& Pick(Pickable<R> v)
548  {
549  if (v.GetPtr() != pObject)
550  {
551  if (pObject) pObject->Release();
552  pObject = v.GetPtr();
553  }
554 
555  return *this;
556  }
557 
558  KY_INLINE Ptr<C>& Pick(C* p)
559  {
560  if (p != pObject)
561  {
562  if (pObject) pObject->Release();
563  pObject = p;
564  }
565 
566  return *this;
567  }
568 };
569 
570 
571 
572 // *** Weak Pointer Support
573 
574 // Helper for making objects that can have weak_ptr's.
575 // TBD: Converted WeakPtr logic is not thread-safe, need to work this out
576 
577 class WeakPtrProxy : public NewOverrideBase<Stat_Default_Mem>
578 {
579 public:
580  WeakPtrProxy(RefCountWeakSupportImpl* pobject)
581  : RefCount(1), pObject(pobject)
582  { }
583 
584  // WeakPtr calls this to determine if its pointer is valid or not
585  KY_INLINE bool IsAlive() const { return (pObject != 0); }
586 
587  // Objects call this to inform of their death
588  KY_INLINE void NotifyObjectDied() { pObject = 0; }
589 
590  RefCountWeakSupportImpl* GetObject() const { return pObject; }
591 
592  KY_INLINE void AddRef()
593  {
594  RefCount++;
595  // Uncomment this to track potential bad use of Ptr
596  //KY_ASSERT(RefCount > -1 && RefCount < 0x00FFFFFF);
597  }
598 
599  KY_INLINE void Release()
600  {
601  // Uncomment this to track potential bad use of Ptr
602  //KY_ASSERT(RefCount > -1 && RefCount < 0x00FFFFFF);
603 
604  RefCount--;
605  if (RefCount == 0)
606  delete this;
607  }
608 
609 private:
610  // Hidden
611  WeakPtrProxy(const WeakPtrProxy& w) { KY_UNUSED(w); }
612  void operator=(const WeakPtrProxy& w) { KY_UNUSED(w); }
613 
614  int RefCount;
615  RefCountWeakSupportImpl* pObject;
616 };
617 
618 
619 // A weak pointer points at an object, but the object may be deleted
620 // at any time, in which case the weak pointer automatically becomes
621 // NULL. The only way to use a weak pointer is by converting it to a
622 // strong pointer (i.e. for temporary use).
623 //
624 // The class pointed to must have a "WeakPtrProxy* GetWeakPtrProxy()" method.
625 //
626 // Usage idiom:
627 //
628 // if (Ptr<my_type> ptr = weak_ptr_to_my_type) { ... use ptr->whatever() safely in here ... }
629 
630 
631 template<class C>
632 class WeakPtr
633 {
634 public:
635  WeakPtr()
636  { }
637 
638  KY_INLINE WeakPtr(C* ptr)
639  : pProxy(*(ptr ? ptr->CreateWeakProxy() : (WeakPtrProxy*)0))
640  { }
641  KY_INLINE WeakPtr(const Ptr<C>& ptr)
642  : pProxy(*(ptr.GetPtr() ? ptr->CreateWeakProxy() : (WeakPtrProxy*)0))
643  { }
644 
645  // Default constructor and assignment from WeakPtr<C> are OK
646  KY_INLINE void operator = (C* ptr)
647  {
648  if (ptr)
649  {
650  pProxy = *ptr->CreateWeakProxy();
651  }
652  else
653  {
654  pProxy.Clear();
655  }
656  }
657 
658  KY_INLINE void operator = (const Ptr<C>& ptr)
659  { operator=(ptr.GetPtr()); }
660 
661  // Conversion to Ptr
662  inline operator Ptr<C>() const
663  {
664  return Ptr<C>(GetObjectThroughProxy());
665  }
666 
667  KY_INLINE bool operator == (C* ptr)
668  { return GetObjectThroughProxy() == ptr; }
669  KY_INLINE bool operator == (const Ptr<C>& ptr)
670  { return GetObjectThroughProxy() == ptr.GetPtr(); }
671 
672 private:
673 
674  // Set pObject to NULL if the object died
675  KY_INLINE C* GetObjectThroughProxy() const
676  {
677  C* pobject = 0;
678 
679  if (pProxy)
680  {
681  if (pProxy->IsAlive())
682  {
683  pobject = (C*)pProxy->GetObject();
684  }
685  else
686  {
687  // Release proxy if the underlying object went away.
688  pProxy.Clear();
689  }
690  }
691  return pobject;
692  }
693 
694  mutable Ptr<WeakPtrProxy> pProxy;
695 };
696 
697 } // Scaleform
698 
699 #endif
The Autodesk Navigation namespace.
Definition: gamekitcrowddispersion.cpp:17
Vec2f operator*(KyFloat32 s, const Vec2f &v)
scalar * vec operator
Definition: vec2f.h:120