Free Electron
Handled.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_Handled_h__
8 #define __core_Handled_h__
9 
10 namespace fe
11 {
12 
13 class FE_DL_EXPORT HandleToken: public Counted
14 {
15  public:
16  HandleToken(void):
17 #if FE_COUNTED_TRACK
18  m_name("HandleToken"),
19 #endif
20  m_valid(TRUE)
21  { suppressReport(); }
22 
23 virtual ~HandleToken(void) {}
24 
25  BWORD valid(void) { return m_valid; }
26  void invalidate(void)
27  { suppressReport();
28  m_valid=FALSE; }
29 #if FE_COUNTED_TRACK
30  public:
31 const String& name(void) const { return m_name; }
32 virtual void setName(String name)
33  {
34  RecursiveMutex::Guard guard(
35  ms_counted_mutex);
36  m_name.sPrintf("HandleToken %s",name.c_str());
37  }
38  private:
39  String m_name;
40 #endif
41  private:
42  BWORD m_valid;
43 };
44 
45 /**************************************************************************//**
46  @brief Safe handle for shared pointer
47 
48  @ingroup core
49 
50  Unlike sp<>, the pointed to object can easily become invalid
51  since the handle's existance doesn't prop up the object's existance.
52  Unless there is another mechanism, such as a known sp<>,
53  that is known to guarantee the object's persistence,
54  it would be wise to judiciously verify currency with isValid().
55 
56  A hp<> can be automatically cast to a sp<> (smart pointer).
57 
58  A sp<> based on a Handled object can be automatically cast to a hp<>.
59 *//***************************************************************************/
60 template<class T>
61 class FE_DL_EXPORT hp
62 {
63  public:
64  hp(void) {}
65 
66  hp(const T* pT)
67  {
68  operator=(pT);
69  }
70 
71  template<class X>
72  hp(const X* pX)
73  {
74  operator=(pX);
75  }
76 
77  hp(const hp<T>& rhpT)
78  { m_spHandleToken=rhpT.m_spHandleToken;
79  m_pObject=rhpT.m_pObject; }
80 
81  template<class X>
82  hp(const sp<X>& rspX)
83  { operator=(rspX->getHandle()); }
84 
85  template<class X>
86  hp(const hp<X>& rhpX)
87  { m_spHandleToken=rhpX.handleToken();
88  m_pObject=fe_cast<T>(rhpX.raw()); }
89 
90  /** @brief Initialize during Handled construction
91 
92  @internal */
93  void initialize(T* pObject)
94  { m_spHandleToken=new HandleToken();
95  m_pObject=pObject; }
96 
97  /** @brief Converts from a smart pointer of any type
98 
99  If the object in the smart pointer does not have
100  a method @em getHandle returning a hp<>,
101  the conversion should fail to compile. */
102  template<class X>
103 const hp<T>& operator=(const sp<X>& rspX)
104  {
105  if(rspX.isValid())
106  operator=(rspX->getHandle());
107  else
108  {
109  m_spHandleToken=NULL;
110  m_pObject=NULL;
111  }
112  return *this;
113  }
114 
115 //* NOTE no auto-conversion from hp<X> to hp<T> (use an sp<X>)
116 /* template<class X>
117 const hp<T>& operator=(const hp<X>& rhpX)
118  { operator=(fe_cast<T>(rhpX.raw()));
119  return *this; }
120 */
121 
122  template<class X>
123 const hp<T>& operator=(const X* pX)
124  {
125  if(pX)
126  operator=(pX->getHandle());
127  else
128  {
129  m_spHandleToken=NULL;
130  m_pObject=NULL;
131  }
132  return *this;
133  }
134  hp<T>& operator=(const hp<T>& rhpT)
135  { m_spHandleToken=rhpT.m_spHandleToken;
136  m_pObject=rhpT.m_pObject;
137  return *this; }
138 
139  // this is so ptr can be used as a std::map key
140  BWORD operator<(const hp<T>& rhpT) const
141  { return (FE_UWORD)(m_pObject) < (FE_UWORD)(rhpT.m_pObject); }
142 
143  /// @brief Returns the handled pointer, potentially NULL
144  T* raw(void) const
145  { if(!handleToken() || !handleToken()->valid())
146  return NULL;
147  return m_pObject; }
148 
149  /// @brief Use the handled pointer
150  T* operator->(void) const
151  {
152  if(!handleToken() || !handleToken()->valid())
153  feX(e_invalidHandle,("fe::hp< "+FE_TYPESTRING(T)+
154  " >::operator->").c_str(),
155  "attempt to use invalid Handle");
156  FEASSERT(m_pObject);
157  return m_pObject;
158  }
159 
160  /// @brief Dereference to the handled pointer
161  T& operator*(void) const
162  {
163  if(!handleToken() || !handleToken()->valid())
164  feX(e_invalidHandle,("fe::hp< "+FE_TYPESTRING(T)+
165  " >::operator->").c_str(),
166  "attempt to use invalid Handle");
167  FEASSERT(m_pObject);
168  return *m_pObject;
169  }
170 
171  /** @brief Returns a smart pointer of the same
172  templated type
173 
174  You usually don't need to use this method directly
175  since sp<> can auto-convert. */
176  sp<T> object(void) const { return sp<T>(raw()); }
177 
178  /// @brief Returns true if the pointer is set
179  BWORD isValid(void) const
180  { return handleToken() && handleToken()->valid(); }
181 
182  /// @brief Returns true if the pointer is not set
183  BWORD isNull(void) const
184  { return !isValid(); }
185 
186  /** @brief Nulls the shared pointer
187 
188  @internal */
189  void invalidate(void)
190  { if(handleToken())
191  handleToken()->invalidate();
192  m_spHandleToken=NULL; }
193 
194  /** @brief Access the shared token
195 
196  @internal */
197  HandleToken* handleToken(void) const
198  { return m_spHandleToken.raw(); }
199 
200  private:
201  sp<HandleToken> m_spHandleToken;
202  T* m_pObject;
203 };
204 
205 /**************************************************************************//**
206  @brief Base class providing an fe::Handle to the derived class
207 *//***************************************************************************/
208 template <class T>
209 class FE_DL_EXPORT Handled: public Protectable
210 {
211  public:
212  Handled(void) { m_handle.initialize((T*)this); }
213 virtual ~Handled(void) { abandonHandle(); }
214 
215  /** @brief Get a safe handle to this object
216 
217  Unlike the smart pointer sp<>, this handle does not
218  force the object to persist. Instead, it can be
219  checked to determine if it is still valid. */
220 const hp<T>& getHandle(void) const
221  {
222 #if FE_COUNTED_TRACK
223  m_handle.handleToken()->setName(name());
224 #endif
225  return m_handle;
226  }
227 
228  protected:
229  void abandonHandle(void) { m_handle.invalidate(); }
230 
231  private:
232  hp<T> m_handle;
233 };
234 
235 /// @relates hp
236 template <class T,class X>
237 inline BWORD operator==(const hp<T>& rhpLeft,const hp<X>& rhpRight)
238 {
239  return (rhpLeft.handleToken()==rhpRight.handleToken());
240 }
241 
242 /// @relates hp
243 template <class T,class X>
244 inline BWORD operator==(const hp<T>& rhpLeft,const sp<X>& rspRight)
245 {
246  return (rhpLeft.raw()==rspRight.raw());
247 }
248 
249 /// @relates hp
250 template <class T,class X>
251 inline BWORD operator==(const sp<X>& rspLeft,const hp<T>& rhpRight)
252 {
253  return (rspLeft.raw()==rhpRight.raw());
254 }
255 
256 /// @relates hp
257 template <class T>
258 inline BWORD operator!=(const hp<T>& rhpLeft,const hp<T>& rhpRight)
259 {
260  return (rhpLeft.handleToken()!=rhpRight.handleToken());
261 }
262 
263 /// @relates hp
264 template <class T,class X>
265 inline BWORD operator!=(const hp<T>& rhpLeft,const sp<X>& rspRight)
266 {
267  return (rhpLeft.raw()!=rspRight.raw());
268 }
269 
270 /// @relates hp
271 template <class T,class X>
272 inline BWORD operator!=(const sp<X>& rspLeft,const hp<T>& rhpRight)
273 {
274  return (rspLeft.raw()!=rhpRight.raw());
275 }
276 
277 template<class T>
278 struct hash_hp
279 {
280  FE_UWORD operator()(const hp<T>& rhpT) const
281  { return reinterpret_cast<FE_UWORD>(rhpT.raw()); }
282 };
283 
284 template<class T>
285 struct eq_hp
286 {
287  bool operator()(const hp<T>& rhpT1, const hp<T>& rhpT2) const
288  { return rhpT1 == rhpT2; }
289 };
290 
291 template<typename T, typename U>
292 class AutoHashMap< hp<T>, U >:
293  public HashMap< hp<T>, U, hash_hp<T>, eq_hp<T> > {};
294 
295 } /* namespace */
296 
297 #endif /* __core_Handled_h__ */
298 
BWORD isNull(void) const
Returns true if the pointer is not set.
Definition: Handled.h:183
BWORD operator==(const sp< X > &rspLeft, const hp< T > &rhpRight)
Definition: Handled.h:251
Base class providing protection counting for cp<>
Definition: Protectable.h:28
kernel
Definition: namespace.dox:3
BWORD operator==(const hp< T > &rhpLeft, const sp< X > &rspRight)
Definition: Handled.h:244
sp< T > object(void) const
Returns a smart pointer of the same templated type.
Definition: Handled.h:176
T * operator->(void) const
Use the handled pointer.
Definition: Handled.h:150
HandleToken * handleToken(void) const
Access the shared token.
Definition: Handled.h:197
BWORD operator!=(const sp< X > &rspLeft, const hp< T > &rhpRight)
Definition: Handled.h:272
Safe handle for shared pointer.
Definition: Handled.h:61
void initialize(T *pObject)
Initialize during Handled construction.
Definition: Handled.h:93
BWORD operator!=(const hp< T > &rhpLeft, const sp< X > &rspRight)
Definition: Handled.h:265
void invalidate(void)
Nulls the shared pointer.
Definition: Handled.h:189
T * raw(void) const
Returns the handled pointer, potentially NULL.
Definition: Handled.h:144
const hp< T > & operator=(const sp< X > &rspX)
Converts from a smart pointer of any type.
Definition: Handled.h:103
Intrusive Smart Pointer.
Definition: src/core/ptr.h:53
const hp< T > & getHandle(void) const
Get a safe handle to this object.
Definition: Handled.h:220
Base class providing an fe::Handle to the derived class.
Definition: Handled.h:209
BWORD isValid(void) const
Returns true if the pointer is set.
Definition: Handled.h:179
BWORD operator!=(const hp< T > &rhpLeft, const hp< T > &rhpRight)
Definition: Handled.h:258
BWORD operator==(const hp< T > &rhpLeft, const hp< X > &rhpRight)
Definition: Handled.h:237
T & operator*(void) const
Dereference to the handled pointer.
Definition: Handled.h:161