Free Electron
ptr.h
Go to the documentation of this file.
1 /* Copyright (C) 2003-2015 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 const T& operator*(void) const
186  {
187 #if FE_PTR_NULL_CHECK
188  if(!m_tPtr)
189  feX(("fe::sp< "+FE_TYPESTRING(T)+
190  " >::operator*").c_str(),
191  "attempt to dereference invalid sp<>");
192 #endif
193  FEASSERT(m_tPtr);
194  return *m_tPtr;
195  }
196 
197  T* operator->(void) const
198  {
199 #if FE_PTR_NULL_CHECK
200  if(!m_tPtr)
201  feX(("fe::sp< "+FE_TYPESTRING(T)+
202  " >::operator->").c_str(),
203  ("attempt to use invalid sp<"+
204  FE_TYPESTRING(T)+">").c_str());
205 #endif
206  FEASSERT(m_tPtr);
207  return m_tPtr;
208  }
209  T* abandon(void)
210  {
211 #if FE_PTR_NULL_CHECK
212  if(!m_tPtr)
213  feX(("fe::sp< "+FE_TYPESTRING(T)+
214  " >::abandon").c_str(),
215  ("attempt to use invalid sp<"+
216  FE_TYPESTRING(T)+">").c_str());
217 #endif
218  FEASSERT(m_tPtr);
219  untrack();
220  T *pT = m_tPtr;
221  m_tPtr->abandon();
222  m_tPtr = NULL;
223  return pT;
224  }
225  T* raw(void) const { return m_tPtr; }
226  BWORD isValid(void) const { return m_tPtr != NULL; }
227  BWORD isNull(void) const { return m_tPtr == NULL; }
228 
229  private:
230 #if FE_PTR_TRACK
231  //* NOTE only virtual if tracking is on
232 virtual void track(void)
233  {
234  if(m_tPtr)
235  {
236  m_tPtr->trackReference(this,"sp<> "+m_tPtr->name());
237  }
238  }
239  void untrack(void)
240  {
241  if(m_tPtr)
242  {
243  m_tPtr->untrackReference(this);
244  }
245  }
246 #else
247  void track(void) {}
248  void untrack(void) {}
249 #endif
250  T* m_tPtr;
251 };
252 
253 /// @relates sp
254 template <class T,class X>
255 inline BWORD operator==(const sp<T>& rspLeft,const sp<X>& rspRight)
256 {
257  return (rspLeft.raw() == sp<T>(rspRight).raw());
258 }
259 
260 /// @relates sp
261 template <class T,class X>
262 inline BWORD operator!=(const sp<T>& rspLeft,const sp<X>& rspRight)
263 {
264  return (rspLeft.raw() != sp<T>(rspRight).raw());
265 }
266 
267 // this is so an sp<> can be used as a std::map key
268 /// @relates sp
269 template <class T,class X>
270 inline BWORD operator<(const sp<T>& rspLeft,const sp<X>& rspRight)
271 {
272  return (FE_UWORD)(rspLeft.raw()) < (FE_UWORD)(sp<T>(rspRight).raw());
273 }
274 
275 template<class T>
276 struct hash_sp
277 {
278  FE_UWORD operator()(const sp<T>& rspT) const
279  { return reinterpret_cast<FE_UWORD>(rspT.raw()); }
280 };
281 
282 template<class T>
283 struct eq_sp
284 {
285  bool operator()(const sp<T>& rspT1, const sp<T>& rspT2) const
286  { return rspT1 == rspT2; }
287 };
288 
289 template<typename T, typename U>
290 class AutoHashMap< sp<T>, U >:
291  public HashMap< sp<T>, U, hash_sp<T>, eq_sp<T> > {};
292 
293 } /* namespace */
294 
295 #endif /* __core_sp_h__ */
BWORD operator!=(const sp< T > &rspLeft, const sp< X > &rspRight)
Definition: ptr.h:262
kernel
Definition: namespace.dox:3
BWORD operator==(const sp< T > &rspLeft, const sp< X > &rspRight)
Definition: ptr.h:255
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: ptr.h:53