Diligent Engine API Reference
RefCntAutoPtr.h
1 /* Copyright 2015-2018 Egor Yusov
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
10  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
12  *
13  * In no event and under no legal theory, whether in tort (including negligence),
14  * contract, or otherwise, unless required by applicable law (such as deliberate
15  * and grossly negligent acts) or agreed to in writing, shall any Contributor be
16  * liable for any damages, including any direct, indirect, special, incidental,
17  * or consequential damages of any character arising as a result of this License or
18  * out of the use or inability to use the software (including but not limited to damages
19  * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
20  * all other commercial damages or losses), even if such Contributor has been advised
21  * of the possibility of such damages.
22  */
23 
24 #pragma once
25 
26 #include "DebugUtilities.h"
27 #include "LockHelper.h"
28 #include "Atomics.h"
29 #include "ValidatedCast.h"
30 #include "RefCountedObjectImpl.h"
31 #include "Object.h"
32 
33 namespace Diligent
34 {
35 
36 
37 template <typename T>
39 
40 // The main advantage of RefCntAutoPtr over the std::shared_ptr is that you can
41 // attach the same raw pointer to different smart pointers.
42 //
43 // For instance, the following code will crash since p will be released twice:
44 //
45 // auto *p = new char;
46 // std::shared_ptr<char> pTmp1(p);
47 // std::shared_ptr<char> pTmp2(p);
48 // ...
49 
50 // This code, in contrast, works perfectly fine:
51 //
52 // ObjectBase *pRawPtr(new ObjectBase);
53 // RefCntAutoPtr<ObjectBase> pSmartPtr1(pRawPtr);
54 // RefCntAutoPtr<ObjectBase> pSmartPtr2(pRawPtr);
55 // ...
56 
57 // Other advantage is that weak pointers remain valid until the
58 // object is alive, even if all smart pointers were destroyed:
59 //
60 // RefCntWeakPtr<ObjectBase> pWeakPtr(pSmartPtr1);
61 // pSmartPtr1.Release();
62 // auto pSmartPtr3 = pWeakPtr.Lock();
63 // ..
64 
65 // Weak pointers can also be attached directly to the object:
66 // RefCntWeakPtr<ObjectBase> pWeakPtr(pRawPtr);
67 //
68 
70 template <typename T>
72 {
73 public:
74  explicit RefCntAutoPtr(T *pObj = nullptr) :
75  m_pObject(pObj)
76  {
77  if( m_pObject )
78  m_pObject->AddRef();
79  }
80 
81  RefCntAutoPtr(IObject *pObj, const INTERFACE_ID &IID) :
82  m_pObject(nullptr)
83  {
84  if(pObj)
85  pObj->QueryInterface( IID, reinterpret_cast<IObject**>(&m_pObject) );
86  }
87 
88  RefCntAutoPtr(const RefCntAutoPtr &AutoPtr) :
89  m_pObject(AutoPtr.m_pObject)
90  {
91  if(m_pObject)
92  m_pObject->AddRef();
93  }
94 
95  RefCntAutoPtr(RefCntAutoPtr &&AutoPtr) :
96  m_pObject(std::move(AutoPtr.m_pObject))
97  {
98  //Make sure original pointer has no references to the object
99  AutoPtr.m_pObject = nullptr;
100  }
101 
102  ~RefCntAutoPtr()
103  {
104  Release();
105  }
106 
107  void swap(RefCntAutoPtr &AutoPtr)
108  {
109  std::swap(m_pObject, AutoPtr.m_pObject);
110  }
111 
112  void Attach(T *pObj)
113  {
114  Release();
115  m_pObject = pObj;
116  }
117 
118  T* Detach()
119  {
120  T* pObj = m_pObject;
121  m_pObject = nullptr;
122  return pObj;
123  }
124 
125  void Release()
126  {
127  if( m_pObject )
128  {
129  m_pObject->Release();
130  m_pObject = nullptr;
131  }
132  }
133 
134  RefCntAutoPtr& operator = (T *pObj)
135  {
136  if( static_cast<T*>(*this) == pObj )
137  return *this;
138 
139  return operator= (RefCntAutoPtr(pObj));
140  }
141 
142  RefCntAutoPtr& operator = (const RefCntAutoPtr &AutoPtr)
143  {
144  if( *this == AutoPtr )
145  return *this;
146 
147  Release();
148  m_pObject = AutoPtr.m_pObject;
149  if(m_pObject)
150  m_pObject->AddRef();
151 
152  return *this;
153  }
154 
155  RefCntAutoPtr& operator = (RefCntAutoPtr &&AutoPtr)
156  {
157  if( *this == AutoPtr )
158  return *this;
159 
160  Release();
161  m_pObject = std::move( AutoPtr.m_pObject );
162  //Make sure original pointer has no references to the object
163  AutoPtr.m_pObject = nullptr;
164  return *this;
165  }
166 
167  // All the access functions do not require locking reference counters pointer because if it is valid,
168  // the smart pointer holds strong reference to the object and it thus cannot be released by
169  // ohter thread
170  bool operator ! () const{return m_pObject == nullptr;}
171  operator bool () const{return m_pObject != nullptr;}
172  bool operator == (const RefCntAutoPtr& Ptr)const{return m_pObject == Ptr.m_pObject;}
173  bool operator != (const RefCntAutoPtr& Ptr)const{return m_pObject != Ptr.m_pObject;}
174  bool operator < (const RefCntAutoPtr& Ptr)const{return static_cast<const T*>(*this) < static_cast<const T*>(Ptr);}
175 
176  T& operator * () { return *m_pObject; }
177  const T& operator * ()const { return *m_pObject; }
178 
179  T* RawPtr() { return m_pObject; }
180  const T* RawPtr()const{ return m_pObject; }
181 
182  operator T* () { return RawPtr(); }
183  operator const T* ()const { return RawPtr(); }
184 
185  T* operator -> () { return m_pObject; }
186  const T* operator -> ()const{ return m_pObject; }
187 
188 private:
189  // Note that the DoublePtrHelper is a private class, and can be created only by RefCntWeakPtr
190  // Thus if no special effort is made, the lifetime of the instances of this class cannot be
191  // longer than the lifetime of the creating object
192  class DoublePtrHelper
193  {
194  public:
195  DoublePtrHelper(RefCntAutoPtr &AutoPtr) :
196  NewRawPtr( static_cast<T*>(AutoPtr) ),
197  m_pAutoPtr( std::addressof(AutoPtr) )
198  {
199  }
200 
201  DoublePtrHelper(DoublePtrHelper&& Helper) :
202  NewRawPtr(Helper.NewRawPtr),
203  m_pAutoPtr(Helper.m_pAutoPtr)
204  {
205  Helper.m_pAutoPtr = nullptr;
206  Helper.NewRawPtr = nullptr;
207  }
208 
209  ~DoublePtrHelper()
210  {
211  if( m_pAutoPtr && static_cast<T*>(*m_pAutoPtr) != NewRawPtr )
212  {
213  m_pAutoPtr->Attach(NewRawPtr);
214  }
215  }
216 
217  T*& operator*(){return NewRawPtr;}
218  const T* operator*()const{return NewRawPtr;}
219 
220  operator T**(){return &NewRawPtr;}
221  operator const T**()const{return &NewRawPtr;}
222  private:
223  T *NewRawPtr;
224  RefCntAutoPtr *m_pAutoPtr;
225  DoublePtrHelper(const DoublePtrHelper&);
226  DoublePtrHelper& operator = (const DoublePtrHelper&);
227  DoublePtrHelper& operator = (DoublePtrHelper&&);
228  };
229 
230 public:
231  DoublePtrHelper operator& ()
232  {
233  return DoublePtrHelper(*this);
234  }
235 
236  const DoublePtrHelper operator& ()const
237  {
238  return DoublePtrHelper(*this);
239  }
240 
241  T** GetRawDblPtr() {return &m_pObject;}
242  const T** GetRawDblPtr()const{return &m_pObject;}
243 
244 private:
245  T *m_pObject;
246 };
247 
249 template <typename T>
250 class RefCntWeakPtr
251 {
252 public:
253  explicit RefCntWeakPtr(T *pObj = nullptr) :
254  m_pObject(pObj),
255  m_pRefCounters(nullptr)
256  {
257  if( m_pObject )
258  {
259  m_pRefCounters = ValidatedCast<RefCountersImpl>( m_pObject->GetReferenceCounters() );
260  m_pRefCounters->AddWeakRef();
261  }
262  }
263 
264  ~RefCntWeakPtr()
265  {
266  Release();
267  }
268 
269  RefCntWeakPtr(const RefCntWeakPtr& WeakPtr) :
270  m_pObject(WeakPtr.m_pObject),
271  m_pRefCounters(WeakPtr.m_pRefCounters)
272  {
273  if( m_pRefCounters )
274  m_pRefCounters->AddWeakRef();
275  }
276 
277  RefCntWeakPtr(RefCntWeakPtr&& WeakPtr) :
278  m_pObject(std::move(WeakPtr.m_pObject)),
279  m_pRefCounters(std::move(WeakPtr.m_pRefCounters))
280  {
281  WeakPtr.m_pRefCounters = nullptr;
282  WeakPtr.m_pObject = nullptr;
283  }
284 
285  explicit RefCntWeakPtr(RefCntAutoPtr<T>& AutoPtr) :
286  m_pObject( static_cast<T*>(AutoPtr) ),
287  m_pRefCounters(AutoPtr ? ValidatedCast<RefCountersImpl>( AutoPtr->GetReferenceCounters() ) : nullptr)
288  {
289  if( m_pRefCounters )
290  m_pRefCounters->AddWeakRef();
291  }
292 
293  RefCntWeakPtr& operator = (const RefCntWeakPtr& WeakPtr)
294  {
295  if( *this == WeakPtr )
296  return *this;
297 
298  Release();
299  m_pObject = WeakPtr.m_pObject;
300  m_pRefCounters = WeakPtr.m_pRefCounters;
301  if( m_pRefCounters )
302  m_pRefCounters->AddWeakRef();
303  return *this;
304  }
305 
306  RefCntWeakPtr& operator = (T *pObj)
307  {
308  return operator= (RefCntWeakPtr(pObj));
309  }
310 
311  RefCntWeakPtr& operator = (RefCntWeakPtr&& WeakPtr)
312  {
313  if( *this == WeakPtr )
314  return *this;
315 
316  Release();
317  m_pObject = std::move(WeakPtr.m_pObject);
318  m_pRefCounters = std::move(WeakPtr.m_pRefCounters);
319  WeakPtr.m_pRefCounters = nullptr;
320  WeakPtr.m_pObject = nullptr;
321  return *this;
322  }
323 
324  RefCntWeakPtr& operator = (RefCntAutoPtr<T>& AutoPtr)
325  {
326  Release();
327  m_pObject = static_cast<T*>( AutoPtr );
328  m_pRefCounters = m_pObject ? ValidatedCast<RefCountersImpl>( m_pObject->GetReferenceCounters() ) : nullptr;
329  if( m_pRefCounters )
330  m_pRefCounters->AddWeakRef();
331  return *this;
332  }
333 
334  void Release()
335  {
336  if( m_pRefCounters )
337  m_pRefCounters->ReleaseWeakRef();
338  m_pRefCounters = nullptr;
339  m_pObject = nullptr;
340  }
341 
345  bool IsValid()
346  {
347  return m_pObject != nullptr && m_pRefCounters != nullptr && m_pRefCounters->GetNumStrongRefs() > 0;
348  }
349 
352  {
353  RefCntAutoPtr<T> spObj;
354  if( m_pRefCounters )
355  {
356  // Try to obtain pointer to the owner object.
357  // spOwner is only used to keep the object
358  // alive while obtaining strong reference from
359  // the raw pointer m_pObject
361  m_pRefCounters->GetObject( &spOwner );
362  if( spOwner )
363  {
364  // If owner is alive, we can use our RAW pointer to
365  // create strong reference
366  spObj = m_pObject;
367  }
368  else
369  {
370  // Owner object has been destroyed. There is no reason
371  // to keep this weak reference anymore
372  Release();
373  }
374  }
375  return spObj;
376  }
377 
378  bool operator == (const RefCntWeakPtr& Ptr)const{return m_pRefCounters == Ptr.m_pRefCounters;}
379  bool operator != (const RefCntWeakPtr& Ptr)const{return m_pRefCounters != Ptr.m_pRefCounters;}
380 
381 protected:
382  RefCountersImpl *m_pRefCounters;
383  // We need to store raw pointer to object itself,
384  // because if the object is owned by another object,
385  // m_pRefCounters->GetObject( &pObj ) will return
386  // pointer to owner, which is not what we need.
387  T *m_pObject;
388 };
389 
390 }
Namespace for the OpenGL implementation of the graphics engine.
Definition: BufferD3D11Impl.h:34
Definition: AdvancedMath.h:316
RefCntAutoPtr< T > Lock()
Obtains a strong reference to the object.
Definition: RefCntAutoPtr.h:351
Implementation of weak pointers.
Definition: RefCntAutoPtr.h:38
Template class that implements reference counting.
Definition: RefCntAutoPtr.h:71
bool IsValid()
Definition: RefCntAutoPtr.h:345