Free Electron
src/core/ptr.h
Go to the documentation of this file.
1 /* Copyright (C) 2003-2021 Free Electron Organization
2  Any use of this software requires a license. If a valid license
3  was not distributed with this file, visit freeelectron.org. */
4 
5 /** @file */
6 
7 #ifndef __core_sp_h__
8 #define __core_sp_h__
9 
10 #if FE_CODEGEN<=FE_DEBUG
11 #define FE_PTR_NULL_CHECK TRUE
12 #else
13 #define FE_PTR_NULL_CHECK FALSE
14 #endif
15 
16 #define FE_PTR_STACK_CHECK FE_CHECK_HEAP
17 
18 #if FE_CODEGEN<FE_DEBUG
19 #define FE_PTR_TRACK TRUE
20 #else
21 #define FE_PTR_TRACK FALSE
22 #endif
23 
24 #define FE_PTR_DEBUG FALSE
25 
26 namespace fe
27 {
28 
29 template<typename T> class hp;
30 /**************************************************************************//**
31  @brief Intrusive Smart Pointer
32 
33  @ingroup core
34 
35  In the spectrum of "smart" pointers, this is a shared pointer. It is
36  held from several points and let go when all contacts have released it.
37  The elimination of the pointed-to object is left to the object itself.
38  It is presumed that the object holds a reference count which tracks
39  each acquire and release. A common resolution is self-deletion.
40 
41  For an interchangable weak reference, see hp<>.
42 
43  FE doesn't currently have direct support for a scoped or auto pointer
44  with just one owner.
45 
46  The reason this class breaks fe naming convention is for clarity during
47  usage. The short lowercase 'sp' name obscures the pointed-to class less.
48 
49  Attempt to reference a pointer on the stack is illegal and should cause
50  an exception.
51 *//***************************************************************************/
52 template<typename T>
53 class sp
54 {
55  public:
56  sp(void): m_tPtr(NULL) {}
57 
58 explicit sp(T* pT): m_tPtr(pT)
59  {
60 #if FE_PTR_STACK_CHECK
61  if(pT && !Memory::isHeapOrCannotTell(pT))
62  feX(("fe::sp< "+FE_TYPESTRING(T)+" >::sp").c_str(),
63  "attempt to reference stack value");
64 #endif
65  if(m_tPtr)
66  m_tPtr->acquire();
67  track();
68  }
69 
70  sp(const sp<T>& rspT)
71  {
72  if(rspT.m_tPtr)
73  rspT.m_tPtr->acquire();
74  m_tPtr = rspT.m_tPtr;
75  track();
76  }
77 
78  template<typename X>
79  sp(const sp<X>& rspX): m_tPtr(NULL)
80  { operator=(rspX); }
81 
82  template<typename X>
83  sp(const hp<X>& rhpX): m_tPtr(NULL)
84  { operator=(rhpX.object()); }
85 
86 #if FE_PTR_TRACK
87 virtual ~sp(void)
88 #else
89  ~sp(void)
90 #endif
91  {
92  untrack();
93  if(m_tPtr)
94  m_tPtr->release();
95  }
96 
97  sp<T> &operator=(T* pT)
98  {
99  if(pT!=raw())
100  {
101 #if FE_PTR_STACK_CHECK
102  if(pT && !Memory::isHeapOrCannotTell(pT))
103  {
104  feX(("fe::sp< "+FE_TYPESTRING(T)+
105  " >::operator=").c_str(),
106  "attempt to reference stack value");
107  }
108 #endif
109  if(pT)
110  pT->acquire();
111  untrack();
112  if(m_tPtr)
113  m_tPtr->release();
114  m_tPtr = pT;
115  track();
116  }
117  return *this;
118  }
119 
120  sp<T> &operator=(const sp<T>& rspT)
121  {
122  if(rspT.raw() != raw())
123  {
124  if(rspT.m_tPtr)
125  rspT.m_tPtr->acquire();
126  untrack();
127  if(m_tPtr)
128  m_tPtr->release();
129  m_tPtr = rspT.m_tPtr;
130  track();
131  }
132  return *this;
133  }
134 
135  template<typename X>
136  sp<T> &operator=(const sp<X>& rspX)
137  {
138 #if FE_PTR_DEBUG
139  T* pT=fe_cast<T>(rspX.raw());
140 
141  if(!pT && rspX.raw())
142  {
143  feLog(">> sp<%s> could not convert %p"
144  " from \"%s\" \n",
145  FE_TYPESTRING(T).c_str(),
146  rspX.raw(),
147  FE_TYPESTRING(X).c_str());
148 // FEASSERT(0);
149  }
150  return operator=(pT);
151 #else
152  return operator=(fe_cast<T>(rspX.raw()));
153 #endif
154  }
155 
156  template<typename X>
157  bool is(void)
158  {
159  return (fe_cast<X>(raw()) != NULL);
160  }
161 
162  template<typename X>
163  sp<T> &operator=(const hp<X>& rhpX)
164  {
165  untrack();
166  if(m_tPtr)
167  m_tPtr->release();
168  m_tPtr = NULL;
169  operator=(rhpX.object());
170  return *this;
171  }
172 
173  T& operator*(void)
174  {
175 #if FE_PTR_NULL_CHECK
176  if(!m_tPtr)
177  feX(("fe::sp< "+FE_TYPESTRING(T)+
178  " >::operator*").c_str(),
179  "attempt to dereference invalid sp<>");
180 #endif
181  FEASSERT(m_tPtr);
182  return *m_tPtr;
183  }
184 
185  //* is this meaningful? The sp is const, not the T.
186 const T& operator*(void) const
187  {
188 #if FE_PTR_NULL_CHECK
189  if(!m_tPtr)
190  feX(("fe::sp< "+FE_TYPESTRING(T)+
191  " >::operator*").c_str(),
192  "attempt to dereference invalid sp<>");
193 #endif
194  FEASSERT(m_tPtr);
195  return *m_tPtr;
196  }
197 
198  T* operator->(void) const
199  {
200 #if FE_PTR_NULL_CHECK
201  if(!m_tPtr)
202  feX(("fe::sp< "+FE_TYPESTRING(T)+
203  " >::operator->").c_str(),
204  ("attempt to use invalid sp<"+
205  FE_TYPESTRING(T)+">").c_str());
206 #endif
207  FEASSERT(m_tPtr);
208  return m_tPtr;
209  }
210 
211 const T* asConst(void) const
212  {
213 #if FE_PTR_NULL_CHECK
214  if(!m_tPtr)
215  feX(("fe::sp< "+FE_TYPESTRING(T)+
216  " >::asConst").c_str(),
217  ("attempt to use invalid sp<"+
218  FE_TYPESTRING(T)+">").c_str());
219 #endif
220  FEASSERT(m_tPtr);
221  return m_tPtr;
222  }
223 
224  T* abandon(void)
225  {
226 #if FE_PTR_NULL_CHECK
227  if(!m_tPtr)
228  feX(("fe::sp< "+FE_TYPESTRING(T)+
229  " >::abandon").c_str(),
230  ("attempt to use invalid sp<"+
231  FE_TYPESTRING(T)+">").c_str());
232 #endif
233  FEASSERT(m_tPtr);
234  untrack();
235  T *pT = m_tPtr;
236  m_tPtr->abandon();
237  m_tPtr = NULL;
238  return pT;
239  }
240  T* raw(void) const { return m_tPtr; }
241  BWORD isValid(void) const { return m_tPtr != NULL; }
242  BWORD isNull(void) const { return m_tPtr == NULL; }
243 
244  private:
245 #if FE_PTR_TRACK
246  //* NOTE only virtual if tracking is on
247 virtual void track(void)
248  {
249  if(m_tPtr)
250  {
251  m_tPtr->trackReference(this,"sp<> "+m_tPtr->name());
252  }
253  }
254  void untrack(void)
255  {
256  if(m_tPtr)
257  {
258  m_tPtr->untrackReference(this);
259  }
260  }
261 #else
262  void track(void) {}
263  void untrack(void) {}
264 #endif
265  T* m_tPtr;
266 };
267 
268 /// @relates sp
269 template <class T,class X>
270 inline BWORD operator==(const sp<T>& rspLeft,const sp<X>& rspRight)
271 {
272  return (rspLeft.raw() == sp<T>(rspRight).raw());
273 }
274 
275 /// @relates sp
276 template <class T,class X>
277 inline BWORD operator!=(const sp<T>& rspLeft,const sp<X>& rspRight)
278 {
279  return (rspLeft.raw() != sp<T>(rspRight).raw());
280 }
281 
282 // this is so an sp<> can be used as a std::map key
283 /// @relates sp
284 template <class T,class X>
285 inline BWORD operator<(const sp<T>& rspLeft,const sp<X>& rspRight)
286 {
287  return (FE_UWORD)(rspLeft.raw()) < (FE_UWORD)(sp<T>(rspRight).raw());
288 }
289 
290 template<class T>
291 struct hash_sp
292 {
293  FE_UWORD operator()(const sp<T>& rspT) const
294  { return reinterpret_cast<FE_UWORD>(rspT.raw()); }
295 };
296 
297 template<class T>
298 struct eq_sp
299 {
300  bool operator()(const sp<T>& rspT1, const sp<T>& rspT2) const
301  { return rspT1 == rspT2; }
302 };
303 
304 template<typename T, typename U>
305 class AutoHashMap< sp<T>, U >:
306  public HashMap< sp<T>, U, hash_sp<T>, eq_sp<T> > {};
307 
308 } /* namespace */
309 
310 #endif /* __core_sp_h__ */
BWORD operator!=(const sp< T > &rspLeft, const sp< X > &rspRight)
Definition: src/core/ptr.h:277
kernel
Definition: namespace.dox:3
BWORD operator==(const sp< T > &rspLeft, const sp< X > &rspRight)
Definition: src/core/ptr.h:270
sp< T > object(void) const
Returns a smart pointer of the same templated type.
Definition: Handled.h:176
Safe handle for shared pointer.
Definition: Handled.h:61
Intrusive Smart Pointer.
Definition: src/core/ptr.h:53