Artec 3D Scanning SDK  2.0
TRef.h
Go to the documentation of this file.
1 /********************************************************************
2  *
3  * Project Artec 3D Scanning SDK
4  *
5  * Purpose: Helper class for safe intefrace storage
6  *
7  * Copyright: Artec Group
8  *
9  ********************************************************************/
10 
11 #ifndef _TREF_H_
12 #define _TREF_H_
13 
14 #include <stddef.h>
15 #include <assert.h>
16 #include <artec/sdk/base/IRef.h>
17 #include <artec/sdk/base/Log.h>
18 
19 namespace artec { namespace sdk { namespace base
20 {
21 
22 /**
23  * This class is intended for safe manipulation of supported classes in terms of their
24  * time frame. Those classes should implement IRef interface that provides reference
25  * counting support.
26  * TRef objects should hold pointers to the instances of such classes.
27  * Below is an example of how to create an instance of an IFrameMesh
28  * implementation:
29  * TRef<IFrameMesh> mesh;
30  * createFrameMesh( &mesh );
31  * Operator &() is overloaded so that the createFrameMesh() function can fill the passed TRef
32  * with a newly created instance. At the very moment of definition TRef object has a count
33  * of references equal to 1.
34  *
35  * TRef instance represents a smart pointer paradigm, so the ->() operator is also overloaded
36  * in order for the object to be used as a normal pointer:
37  * bool isTextured = mesh->isTextured();
38  *
39  * TRef can also be used as a deletion controller:
40  * {
41  * TRef<IFrameMesh> mesh;
42  * createFrameMesh( &mesh );
43  * bool isTextured = mesh->isTextured();
44  * }
45  * At this point, the TRef object is to be deleted. This will causes deletion of the FrameMesh instance,
46  * once the number of references counts downs to 0.
47  *
48  * Note that all objects in the API should be created using the appropriate createXXX()
49  * functions. So, in order to use this technique, one should create an IRef implementation
50  * and the createXXX() function as it is not permitted to use clauses like the following one:
51  * TRef<IMyObject> mine( new MyObject );
52  * This leads to memory leak as the count of references will equal 2 (1 from the object
53  * constructor and 1 from the TRef constructor. If you need to initialize TRef directly,
54  * do it as follows:
55  * TRef<IMyObject> object;
56  * object.attach( new MyObject() );
57  */
58 
59 template <class T> class TRef
60 {
61 public:
62  typedef T base;
63 
64  TRef(T* p = NULL)
65  {
66  tObject_ = p;
67  if (p)
68  p->addRef();
69  }
70 
71  TRef(const TRef<T>& p)
72  {
73  tObject_ = p.tObject_;
74 
75  if (tObject_)
76  tObject_->addRef();
77  }
78 
80  {
81  tObject_ = p.tObject_;
82  p.tObject_ = NULL;
83  }
84 
86  {
87  if (tObject_)
88  tObject_->release();
89  }
90 
91  operator bool() const { return tObject_ != NULL; }
92 
93  T* operator ->() const { assert( tObject_ != NULL ); return tObject_; }
94 
95  operator T*() const { return tObject_; }
96 
97  const T& operator *() const { assert( tObject_ != NULL ); return *tObject_; }
98 
99  T& operator *() { assert( tObject_ != NULL ); return *tObject_; }
100 
102  {
103  T* tmpObject = tObject_;
104 
105  tObject_ = p;
106 
107  if (tObject_)
108  tObject_->addRef();
109 
110  if (tmpObject)
111  tmpObject->release();
112 
113  return *this;
114  }
115 
117  {
118  T* tmpObject = tObject_;
119 
120  tObject_ = p;
121 
122  if (tObject_)
123  tObject_->addRef();
124 
125  if (tmpObject)
126  tmpObject->release();
127 
128  return *this;
129  }
130 
131  /// Move operator
133  {
134  // Disable operator&() overloading
135  void* addressP = reinterpret_cast<void*>(&const_cast<char&>(reinterpret_cast<const volatile char&>(p)));
136 
137  if (this != addressP)
138  {
139  if (tObject_)
140  tObject_->release();
141 
142  tObject_ = p.tObject_;
143  p.tObject_ = NULL;
144  }
145  return *this;
146  }
147 
148  T** operator&()
149  {
150  if (tObject_ != NULL)
151  {
152  ABASESDK_ERROR(L"Please release your TRef before using operator&");
153  return NULL;
154  }
155 
156  return &tObject_;
157  }
158 
159  bool operator==(T* p) const
160  {
161  return tObject_ == p;
162  }
163 
164  bool operator!=(T* p) const
165  {
166  return !(tObject_ == p);
167  }
168 
169  /// Attach to the interface pointer without calling addref() for it
170  void attach(T* p)
171  {
172  if (tObject_)
173  tObject_->release();
174 
175  tObject_ = p;
176  }
177 
178  /// Detach the interface pointer without calling release() for it
179  T* detach()
180  {
181  T* tmpObject = tObject_;
182  tObject_ = NULL;
183  return tmpObject;
184  }
185 
186  void release()
187  {
188  if (tObject_ == NULL)
189  return;
190 
191  tObject_->release();
192  tObject_ = NULL;
193  }
194 
195 protected:
197 
198 };
199 
200 } } } // namespace artec::sdk::base
201 
202 #endif // _TREF_H_
TRef(const TRef< T > &p)
Definition: TRef.h:71
TRef(TRef< T > &&p)
Definition: TRef.h:79
void attach(T *p)
Attach to the interface pointer without calling addref() for it.
Definition: TRef.h:170
#define ABASESDK_ERROR(...)
Definition: Log.h:66
TRef< T > & operator=(T *p)
Definition: TRef.h:101
T * operator->() const
Definition: TRef.h:93
TRef(T *p=NULL)
Definition: TRef.h:64
TRef< T > & operator=(TRef< T > &&p)
Move operator.
Definition: TRef.h:132
bool operator==(T *p) const
Definition: TRef.h:159
This class is intended for safe manipulation of supported classes in terms of their time frame...
Definition: TRef.h:59
const T & operator*() const
Definition: TRef.h:97
T * detach()
Detach the interface pointer without calling release() for it.
Definition: TRef.h:179
bool operator!=(T *p) const
Definition: TRef.h:164
TRef< T > & operator=(const TRef< T > &p)
Definition: TRef.h:116