Free Electron
Protectable.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_Protectable_h__
8 #define __core_Protectable_h__
9 
10 #define FE_PROTECTED_DEBUG FALSE
11 #define FE_CP_DEBUG FALSE
12 
13 #define FE_PROTECTED_MT TRUE
14 
15 #if FE_PROTECTED_MT
16 #define SAFEGUARD_PROTECTED \
17  RecursiveMutex::Guard __fe_thread_safeguard(m_counted_mutex)
18 #else
19 #define SAFEGUARD_PROTECTED
20 #endif
21 
22 namespace fe
23 {
24 
25 /**************************************************************************//**
26  @brief Base class providing protection counting for cp<>
27 *//***************************************************************************/
28 class FE_DL_EXPORT Protectable: public Counted
29 {
30  public:
31  Protectable(void):
32  m_protection(0) {}
33 
34 virtual I32 protection(void) const
35  {
36 #if FE_PROTECTED_DEBUG
37  feLog("Protectable::protection"
38  " %p SAFEGUARD_PROTECTED\n",this);
39 #endif
40  SAFEGUARD_PROTECTED;
41  FEASSERT(m_protection>=0);
42  return m_protection;
43  }
44 virtual void protect(void)
45  {
46 #if FE_PROTECTED_DEBUG
47  feLog("Protectable::protect"
48  " %p SAFEGUARD_PROTECTED\n",this);
49 #endif
50  SAFEGUARD_PROTECTED;
51  FEASSERT(m_protection>=0);
52  m_protection++;
53  }
54 virtual void unprotect(void)
55  {
56 #if FE_PROTECTED_DEBUG
57  feLog("Protectable::unprotect"
58  " %p SAFEGUARD_PROTECTED\n",this);
59 #endif
60  SAFEGUARD_PROTECTED;
61  m_protection--;
62  FEASSERT(m_protection>=0);
63  }
64 
65 virtual Protectable* clone(Protectable* pInstance=NULL)
66  {
67  return NULL;
68  }
69 
70  private:
71  I32 m_protection;
72 
73 #if FE_PROTECTED_MT
74 mutable RecursiveMutex m_counted_mutex;
75 #endif
76 };
77 
78 /**************************************************************************//**
79  @brief Copy-On-Write shared pointer
80 
81  @ingroup core
82 
83  This mechanism is very similar to sp<> except that the
84  plain pointer operator will return only as const.
85 
86  To access a member in a writable fashion, you must use
87  the writable() method.
88  If the shared object is protected by any cp<> except the caller,
89  the writable() method will clone the object.
90  A clone starts unprotected.
91 *//***************************************************************************/
92 template<typename T>
93 class cp: public sp<T>
94 {
95  public:
96  cp(void): sp<T>(), m_protection(0)
97  {
98 #if FE_CP_DEBUG
99  feLog("cp< %s >::cp\n",FE_TYPESTRING(T));
100 #endif
101  }
102 explicit cp(T* pT): sp<T>(pT), m_protection(0)
103  {
104 #if FE_CP_DEBUG
105  feLog("cp< %s >::cp(T*) %p\n",pT,FE_TYPESTRING(T));
106 #endif
107  }
108  cp(const cp<T>& rcpT): sp<T>(rcpT), m_protection(0)
109  {
110 #if FE_CP_DEBUG
111  feLog("cp< %s >::cp(const cp<T>&) %p\n",
112  FE_TYPESTRING(T),rcpT.raw());
113 #endif
114  }
115  cp(const sp<T>& rspT): sp<T>(rspT), m_protection(0)
116  {
117 #if FE_CP_DEBUG
118  feLog("cp< %s >::cp(const sp<T>&) %p\n",
119  FE_TYPESTRING(T),rspT.raw());
120 #endif
121  }
122  template<typename X>
123  cp(const cp<X>& rcpX): sp<T>(rcpX), m_protection(0)
124  {
125 #if FE_CP_DEBUG
126  feLog("cp< %s >::cp(const cp<X>&) %p\n",
127  FE_TYPESTRING(T),rcpX.raw());
128 #endif
129  }
130  template<typename X>
131  cp(const sp<X>& rspX): sp<T>(rspX), m_protection(0)
132  {
133 #if FE_CP_DEBUG
134  feLog("cp< %s >::cp(const sp<X>&) %p\n",
135  FE_TYPESTRING(T),rspX.raw());
136 #endif
137  }
138  template<typename X>
139  cp(const hp<X>& rhpX): sp<T>(rhpX), m_protection(0)
140  {
141 #if FE_CP_DEBUG
142  feLog("cp< %s >::cp(const hp<X>&) %p\n",
143  FE_TYPESTRING(T),rhpX.raw());
144 #endif
145  }
146 
147  // not virtual
148  ~cp(void)
149  {
150 #if FE_CP_DEBUG
151  feLog("cp< %s >::~cp %p %d\n",
152  FE_TYPESTRING(T),sp<T>::raw(),m_protection);
153 #endif
154  releaseProtection();
155  }
156 
157  cp<T> &operator=(T* pT)
158  {
159 #if FE_CP_DEBUG
160  feLog("cp< %s >::operator=(T*) %p -> %p\n",
161  FE_TYPESTRING(T),sp<T>::raw(),pT);
162 #endif
163  if(pT!=sp<T>::raw())
164  {
165  releaseProtection();
166  sp<T>::operator=(pT);
167  }
168  return *this;
169  }
170  cp<T> &operator=(const cp<T>& rcpT)
171  {
172 #if FE_CP_DEBUG
173  feLog("cp< %s >::operator=(const cp<T>) %p -> %p\n",
174  FE_TYPESTRING(T),sp<T>::raw(),rcpT.raw());
175 #endif
176  if(rcpT.raw() != sp<T>::raw())
177  {
178  releaseProtection();
179  sp<T>::operator=(rcpT);
180  }
181  return *this;
182  }
183  cp<T> &operator=(const sp<T>& rspT)
184  {
185 #if FE_CP_DEBUG
186  feLog("cp< %s >::operator=(const sp<T>& rspT) %p -> %p\n",
187  FE_TYPESTRING(T),sp<T>::raw(),rspT.raw());
188 #endif
189  if(rspT.sp<T>::raw() != sp<T>::raw())
190  {
191  releaseProtection();
192  sp<T>::operator=(rspT);
193  }
194  return *this;
195  }
196  template<typename X>
197  cp<T> &operator=(const cp<X>& rcpX)
198  {
199 #if FE_CP_DEBUG
200  feLog("cp< %s >::operator=(const cp<X>& rcpX) %p -> %p\n",
201  FE_TYPESTRING(T),sp<T>::raw(),rcpX.raw());
202 #endif
203  releaseProtection();
204  sp<T>::operator=(rcpX);
205  return *this;
206  }
207  template<typename X>
208  cp<T> &operator=(const sp<X>& rspX)
209  {
210 #if FE_CP_DEBUG
211  feLog("cp< %s >::operator=(const sp<X>& rspX) %p -> %p\n",
212  FE_TYPESTRING(T),sp<T>::raw(),rspX.raw());
213 #endif
214  releaseProtection();
215  sp<T>::operator=(rspX);
216  return *this;
217  }
218  template<typename X>
219  cp<T> &operator=(const hp<X>& rhpX)
220  {
221 #if FE_CP_DEBUG
222  feLog("cp< %s >::operator=(const hp<X>& rhpX) %p -> %p\n",
223  FE_TYPESTRING(T),sp<T>::raw(),rhpX.raw());
224 #endif
225  releaseProtection();
226  sp<T>::operator=(rhpX);
227  return *this;
228  }
229 
230 const T* operator->(void) const
231  {
232  return sp<T>::operator->();
233  }
234 
235 const T* raw(void) const
236  {
237  return sp<T>::raw();
238  }
239 
240  T* writable(void)
241  {
242 #if FE_CP_DEBUG
243  feLog("cp< %s >::writable %p %d\n",
244  FE_TYPESTRING(T),sp<T>::raw(),m_protection);
245 #endif
246  // if anyone else is protecting this data
247  if(sp<T>::raw()->protection()>m_protection)
248  {
249  U32 reprotect=m_protection;
250  releaseProtection();
251 
253  fe_cast<T>(sp<T>::raw()->clone()));
254  while(reprotect)
255  {
256  protect();
257  reprotect--;
258  }
259  }
260  return sp<T>::operator->();
261  }
262 
263  I32 protection(void) const
264  { FEASSERT(m_protection>=0);
265  return m_protection; }
266  void protect(void)
267  {
268 #if FE_CP_DEBUG
269  feLog("cp< %s >::protect %p %d\n",
270  FE_TYPESTRING(T),sp<T>::raw(),m_protection);
271 #endif
272  FEASSERT(m_protection>=0);
273  if(!m_protection)
274  {
275  m_protection++;
276  sp<T>::raw()->protect();
277  }
278  }
279  void unprotect(void)
280  {
281 #if FE_CP_DEBUG
282  feLog("cp< %s >::unprotect %p %d\n",
283  FE_TYPESTRING(T),sp<T>::raw(),m_protection);
284 #endif
285  if(m_protection)
286  {
287  m_protection--;
288  sp<T>::raw()->unprotect();
289  }
290  FEASSERT(m_protection>=0);
291  }
292 
293  private:
294  void releaseProtection(void)
295  {
296 #if FE_CP_DEBUG
297  feLog("cp< %s >::releaseProtection %p %d\n",
298  FE_TYPESTRING(T),
299  sp<T>::raw(),m_protection);
300 #endif
301  while(m_protection)
302  {
303  m_protection--;
304  sp<T>::raw()->unprotect();
305  }
306  }
307 
308  I32 m_protection;
309 
310 #if FE_PTR_TRACK
311 virtual void track(void)
312  {
313  if(sp<T>::raw())
314  {
315  sp<T>::raw()->trackReference(this,
316  "cp<"+sp<T>::raw()->name()+">");
317  }
318  }
319 #endif
320 };
321 
322 } /* namespace */
323 
324 #endif /* __core_Protectable_h__ */
325 
Heap-based support for classes participating in fe::ptr <>
Definition: Counted.h:35
Base class providing protection counting for cp<>
Definition: Protectable.h:28
kernel
Definition: namespace.dox:3
Safe handle for shared pointer.
Definition: Handled.h:61
T * raw(void) const
Returns the handled pointer, potentially NULL.
Definition: Handled.h:144
Intrusive Smart Pointer.
Definition: src/core/ptr.h:53
Copy-On-Write shared pointer.
Definition: Protectable.h:93