Free Electron
Counted.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_Counted_h__
8 #define __core_Counted_h__
9 
10 #define FE_COUNTED_MT FE_COUNT_MT
11 
12 #if FE_CODEGEN<FE_DEBUG
13 #define FE_COUNTED_TRACK TRUE
14 #else
15 #define FE_COUNTED_TRACK FALSE
16 #endif
17 
18 //* if you wanted cross-debug/optimize linking, this shouldn't vary by CODEGEN
19 #define FE_COUNTED_STORE_TRACKER FE_COUNTED_TRACK
20 
21 #if FE_COUNTED_TRACK && !FE_COUNTED_STORE_TRACKER
22 #error Cannot have FE_COUNTED_TRACK without FE_COUNTED_STORE_TRACKER
23 #endif
24 
25 namespace fe
26 {
27 
28 /**************************************************************************//**
29  @brief Heap-based support for classes participating in fe::ptr <>
30 
31  @ingroup core
32 
33  acquire() and release() are required methods for fe::ptr <>.
34 *//***************************************************************************/
35 class FE_DL_PUBLIC FE_CORE_PORT Counted: public CastableAs<Counted>
36 {
37  public:
38  Counted(void):
40  m_count(0)
41  {
42 #if FE_COUNTED_STORE_TRACKER
43  m_countedName="Counted";
44 #endif
45 #if FE_COUNTED_TRACK
46  m_zeroed=FALSE;
47 #endif
48  }
49 
50 virtual ~Counted(void)
51  {
52 #if FE_CODEGEN<=FE_DEBUG
53  if(m_count)
54  {
55  feLog("Counted::~Counted invalid m_count %d\n",
56  m_count);
58  }
59 #endif
60  FEASSERT(!m_count);
61  }
62 
63  /// @brief Increment the reference count
64 virtual void acquire(void)
65  {
66 #if FE_COUNTED_MT && (FE_COUNTED_TRACK || !defined(FE_COUNT_ASM_IMPL))
67  RecursiveMutex::Guard guard(ms_counted_mutex);
68 #endif
69 
70 #ifdef FE_COUNT_ASM_IMPL
71  feAsmIncr(&m_count, 1);
72 #else /* FE_COUNT_ASM_IMPL */
73 #if FE_COUNTED_TRACK
74  FEASSERT(!m_zeroed);
75 #endif
76  m_count++;
77 #endif /* FE_COUNT_ASM_IMPL */
78 
79 #if FE_COUNTED_TRACK
80  if(ms_pTracker)
81  {
82  ms_pTracker->acquire(this,verboseName(),m_count);
83  }
84 #endif
85  }
86 
87  /// @brief Increment the reference count (and get the count)
88 virtual void acquire(int& rCount)
89  {
90 #if FE_COUNTED_MT && (FE_COUNTED_TRACK || !defined(FE_COUNT_ASM_IMPL))
91  RecursiveMutex::Guard guard(ms_counted_mutex);
92 #endif
93 
94 #if FE_COUNTED_TRACK
95  FEASSERT(!m_zeroed);
96 #endif
97 
98 #ifdef FE_COUNT_ASM_IMPL
99  rCount=feAsmSwapIncr(&m_count, 1) + 1;
100 #else
101  rCount= ++m_count;
102 #endif
103 
104 #if FE_COUNTED_TRACK
105  if(ms_pTracker)
106  {
107  ms_pTracker->acquire(this,verboseName(),rCount);
108  }
109 #endif
110  }
111 
112  /** @brief Decrement the reference count
113 
114  When the count reaches zero, the object is deleted. */
115 virtual void release(void)
116  {
117  if(!releaseInternal())
118  delete this;
119  }
120 
121  /** @brief Decrement the reference count
122 
123  Do not delete, even if count reaches zero.
124  This is used to abandon a Counted from reference counting,
125  although it remains valid to be picked up by reference
126  counting again. */
127 virtual void abandon(void)
128  {
129 #if FE_COUNTED_MT && (FE_COUNTED_TRACK || !defined(FE_COUNT_ASM_IMPL))
130  RecursiveMutex::Guard guard(ms_counted_mutex);
131 #endif
132 #if FE_COUNTED_TRACK
133  if(ms_pTracker)
134  {
135  ms_pTracker->release(this,verboseName(),m_count-1);
136  }
137 #endif
138 #if FE_CODEGEN<=FE_DEBUG
139  if(m_count<=0)
140  {
141  feX(e_corrupt,"Counted::abandon",
142  "invalid m_count %d\n",m_count);
143  }
144 #endif
145  FEASSERT(m_count>0);
146 #ifdef FE_COUNT_ASM_IMPL
147  feAsmIncr(&m_count, -1);
148 #else
149  /* not releaseInternal since object is presumably still
150  'live' even at count 0 */
151  m_count--;
152 #endif
153  }
154 
155  /// @brief Return the count of references
156  int count(void) const
157  {
158 #if FE_COUNTED_MT
159  RecursiveMutex::Guard guard(ms_counted_mutex);
160 #endif
161  return m_count;
162  }
163 
164  protected:
165  /** @brief Decrement the reference count
166 
167  Returns the count after decrementing the references.
168  The intent is that a substitute release() can call
169  releaseInternal(), then conditionally delete the object
170  after doing some custom cleanup that is not suitable
171  for putting in the destructor. */
172  int releaseInternal(void)
173  {
174 #if FE_COUNTED_MT && (FE_COUNTED_TRACK || !defined(FE_COUNT_ASM_IMPL))
175  RecursiveMutex::Guard guard(ms_counted_mutex);
176 #endif
177 
178 #if FE_COUNTED_TRACK
179  if(ms_pTracker)
180  {
181  ms_pTracker->release(this,verboseName(),m_count-1);
182  }
183  if(m_count==1)
184  {
185  m_zeroed=TRUE;
186  }
187 #endif
188 #if FE_CODEGEN<=FE_DEBUG
189  if(m_count<=0)
190  {
191  feX(e_corrupt,"Counted::releaseInternal",
192  "invalid m_count %d\n",m_count);
193  }
194 #endif
195  FEASSERT(m_count>0);
196 #ifdef FE_COUNT_ASM_IMPL
197  return feAsmSwapIncr(&m_count, -1) - 1;
198 #else
199  return --m_count;
200 #endif
201  }
202 
203  void suppressReport(void)
204  {
205 #if FE_COUNTED_TRACK
206  if(ms_pTracker)
207  {
208  ms_pTracker->suppress(this);
209  }
210 #endif
211  }
212 
213 #if (FE_COUNTED_MT || FE_COUNTED_TRACK)
214  protected:
215 static FE_DL_PUBLIC RecursiveMutex ms_counted_mutex;
216 #endif
217 
218  private:
219  int m_count;
220 
221 #if FE_COUNTED_STORE_TRACKER
222  String m_countedName;
223  BWORD m_zeroed;
224 
225 static FE_DL_PUBLIC Tracker* ms_pTracker;
226 static FE_DL_PUBLIC U32 ms_trackerCount;
227  public:
228  /*** NOTE name methods are only virtual if
229  FE_COUNTED_STORE_TRACKER is TRUE */
230  void setName(const String& name) { m_countedName=name; }
231 virtual
232 const String verboseName(void) const { return name(); }
233 virtual
234 const String& name(void) const { return m_countedName; }
235 #else
236  public:
237  void setName(const String&) {}
238 #endif
239 
240 
241  public:
242 #if FE_COUNTED_TRACK
243 static void startTracker(void)
244  { ms_pTracker=new Tracker("Counted "); }
245 static void stopTracker(void)
246  { ms_trackerCount=trackerCount();
247  delete ms_pTracker;
248  ms_pTracker=NULL; }
249 static String reportTracker(void)
250  { FEASSERT(ms_pTracker);
251  return ms_pTracker->report(); }
252 static U32 trackerCount(void)
253  { return ms_pTracker?
254  ms_pTracker->totalCount(): ms_trackerCount; }
255 
256  //* non-Counted references
257 static void trackReference(void* pPtr,void* pReference,String what)
258  { if(ms_pTracker)
259  ms_pTracker->addReference(pPtr,pReference,what); }
260 static void untrackReference(void* pPtr,void* pReference)
261  { if(ms_pTracker)
262  ms_pTracker->removeReference(pPtr,pReference); }
263 
264  //* non-Counted related regions
265 static void registerRegion(void* pPtr,U32 bytes,String name)
266  { if(ms_pTracker)
267  ms_pTracker->registerRegion(pPtr,pPtr,bytes,name); }
268 static void deregisterRegion(void* pPtr)
269  { if(ms_pTracker)
270  ms_pTracker->deregisterRegion(pPtr); }
271 
272  void trackReference(void* pReference,String what)
273  { if(ms_pTracker)
274  ms_pTracker->addReference(this,pReference,what); }
275  void untrackReference(void* pReference)
276  { if(ms_pTracker)
277  ms_pTracker->removeReference(this,pReference); }
278 
279  void acquireRegion(void* pPtr,String name,int count)
280  { if(ms_pTracker)
281  ms_pTracker->acquire(pPtr,name,count); }
282  void releaseRegion(void* pPtr,String name,int count)
283  { if(ms_pTracker)
284  ms_pTracker->release(pPtr,name,count); }
285 
286  //* Counted regions
287  void registerRegion(void* pT,U32 bytes)
288  {
289  if(ms_pTracker)
290  {
291  ms_pTracker->registerRegion(this,pT,bytes,
292  verboseName());
293  }
294  }
295 #else
296 static String reportTracker(void) { return ""; }
297 static U32 trackerCount(void) { return 0; }
298  void trackReference(void* pReference,String what) {}
299  void untrackReference(void* pReference) {}
300  void registerRegion(void* pT,U32 bytes) {}
301 #endif
302 };
303 
304 } /* namespace */
305 
306 #endif /* __core_Counted_h__ */
virtual void acquire(void)
Increment the reference count.
Definition: Counted.h:64
virtual void acquire(int &rCount)
Increment the reference count (and get the count)
Definition: Counted.h:88
Heap-based support for classes participating in fe::ptr <>
Definition: Counted.h:35
kernel
Definition: namespace.dox:3
Watches the usage of reference counted objects.
Definition: Tracker.h:25
Automatically reference-counted string container.
Definition: String.h:128
virtual void abandon(void)
Decrement the reference count.
Definition: Counted.h:127
int count(void) const
Return the count of references.
Definition: Counted.h:156
virtual void release(void)
Decrement the reference count.
Definition: Counted.h:115
void feLogBacktrace(U32 skip)
Dump the program stack.
Definition: backtrace.cc:274
int releaseInternal(void)
Decrement the reference count.
Definition: Counted.h:172
Per-class participation non-RTTI fallback dynamic casting mechanism.
Definition: Castable.h:192