Free Electron
CountedPool.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 __thread_CountedPool_h__
8 #define __thread_CountedPool_h__
9 
10 #define FE_CP_DEBUG FALSE
11 
12 #define FE_CP_TSS (FE_USE_TSS && FE_OS!=FE_WIN32 && \
13  FE_OS!=FE_WIN64 && FE_OS!=FE_OSX)
14 
15 #define FE_CP_TSS_CLEANUP FE_CP_TSS
16 
17 //#include "boost/thread.hpp"
18 
19 namespace fe
20 {
21 namespace ext
22 {
23 
24 class CountedPoolCore
25 {
26  public:
27  CountedPoolCore(void) {}
28 virtual ~CountedPoolCore(void) {}
29 
30 virtual sp<Counted> get(void) { return sp<Counted>(NULL); }
31 };
32 
33 /**************************************************************************//**
34  @brief Pool of Counted elements
35 
36  @ingroup architecture
37 
38  The templated type needs to provide a reset(void) method
39  to facilitate reuse of objects (when they are only referenced
40  by this container).
41 
42  The class is designed to be declared mutable and as such still be
43  functional as a member of a const object.
44  Objects of this class are non-locking thread-safe by the use of
45  thread specific pointers.
46  Each thread accesses an independant pool.
47 
48  If thread specific pointers are not deemed available or reliable,
49  this object may devolve to simple new() allocation.
50  For example, boost::thread_specific_ptr can throw thread_resource_error
51  if threading is not in use.
52  This is caught by CountedPool which will degenerate into no pooling.
53 *//***************************************************************************/
54 template<class T>
55 class CountedPool: public CountedPoolCore
56 {
57  public:
58  CountedPool(void)
59  {
60 #if FE_CP_TSS
61  try
62  {
63  m_pTssArray=new boost::thread_specific_ptr
64  < Array< sp<T> > >(
65 #if FE_CP_TSS_CLEANUP
66  &cleanup
67 #endif
68  );
69 #if FE_CP_DEBUG
70  feLog("CountedPool<T>::CountedPool %p %p %p\n",
71  this,m_pTssArray,m_pTssArray->get());
72 #endif
73  }
74  catch(...)
75  {
76  feLog("CountedPool<T>() TSS failed\n");
77  m_pTssArray=NULL;
78  }
79 #else
80 // feLog("CountedPool<T>() TSS not used\n");
81 #endif
82  }
83  ~CountedPool(void)
84  {
85 #if FE_CP_DEBUG
86  feLog("CountedPool<T>::~CountedPool %p %p %p\n",
87  this,m_pTssArray,m_pTssArray->get());
88 #endif
89  //* TODO shouldn't delete m_pTssArray if any
90  //* participating threads are still alive
91 #if FE_CP_TSS
92 // m_pTssArray->reset();
93  delete m_pTssArray;
94 #endif
95  }
96 
97  sp<Counted> get(void);
98 
99  private:
100 
101 #if FE_CP_TSS_CLEANUP
102 static void cleanup(Array< sp<T> >* a_pArray);
103 #endif
104 
105 #if FE_CP_TSS
106  boost::thread_specific_ptr< Array< sp<T> > >* m_pTssArray;
107 #endif
108 };
109 
110 #if FE_CP_TSS_CLEANUP
111 template<class T>
112 void CountedPool<T>::cleanup(Array< sp<T> >* a_pArray)
113 {
114 #if FE_CP_DEBUG
115  feLog("CountedPool<T>::cleanup %p\n",a_pArray);
116 #endif
117  if(a_pArray)
118  {
119  a_pArray->clear();
120  delete a_pArray;
121  }
122 }
123 #endif
124 
125 template<class T>
127 {
128 #if FE_CP_DEBUG
129  feLog("CountedPool<T>::get %p %p %p\n",
130  this,m_pTssArray,m_pTssArray->get());
131 #endif
132 
133 #if FE_CP_TSS
134  if(m_pTssArray)
135  {
136  Array< sp<T> >* pArray;
137  if(!(pArray=m_pTssArray->get()))
138  {
139  pArray=new Array< sp<T> >();
140  m_pTssArray->reset(pArray);
141 #if FE_CP_DEBUG
142  feLog("CountedPool<T>::get new vector %p %p %p\n",
143  this,m_pTssArray,pArray);
144 #endif
145  }
146  Array< sp<T> >& array= *pArray;
147 
148  //* find an unused slot
149  const U32 size=array.size();
150  for(U32 m=0;m<size;m++)
151  {
152  FEASSERT(array[m].isValid());
153  FEASSERT(array[m]->count()>0);
154 #if FE_CP_DEBUG
155  feLog("CountedPool<T>::get %p %p %p %d/%d %d\n",
156  this,m_pTssArray,pArray,m,size,array[m]->count());
157 #endif
158  if(array[m]->count()>100)
159  {
160  //* probably uninitialized
161  feX(e_notInitialized,"CountedPool<T>::get",
162  "excessive reference count"
163  " suggests uninitialized data");
164  }
165  if(array[m]->count()==1)
166  {
167  array[m]->reset();
168  return array[m];
169  }
170  }
171 
172  //* else make a new slot
173  array.resize(size+1);
174  array[size]=new T();
175 #if FE_CP_DEBUG
176  feLog("CountedPool<T>::get %p NEW %d %d\n",
177  this,size,array[size]->count());
178 #endif
179  return array[size];
180  }
181 #endif
182 
183  return sp<T>(new T);
184 }
185 
186 } /* namespace ext */
187 } /* namespace fe */
188 
189 #endif /* __thread_CountedPool_h__ */
Pool of Counted elements.
Definition: CountedPool.h:55
kernel
Definition: namespace.dox:3
Wrapper for std::vector.
Definition: Array.h:21
Intrusive Smart Pointer.
Definition: src/core/ptr.h:53