PcapPlusPlus  Next
ObjectPool.h
1 #pragma once
2 
3 #include <stack>
4 #include <mutex>
5 #include <memory>
6 #include <stdexcept>
7 #include <limits>
8 #include <type_traits>
9 
10 namespace pcpp
11 {
12  namespace internal
13  {
22  template <class T, std::enable_if_t<std::is_default_constructible<T>::value, bool> = true>
24  {
25  public:
26  constexpr static std::size_t DEFAULT_POOL_SIZE = 100;
27 #pragma push_macro("max") // Undefine max to avoid conflict with std::numeric_limits<std::size_t>::max()
28 #undef max
29  constexpr static std::size_t INFINITE_POOL_SIZE = std::numeric_limits<std::size_t>::max();
30 #pragma pop_macro("max")
31 
35  explicit DynamicObjectPool(std::size_t maxPoolSize = DEFAULT_POOL_SIZE, std::size_t initialSize = 0)
36  : m_MaxPoolSize(maxPoolSize)
37  {
38  if (initialSize > maxPoolSize)
39  {
40  throw std::invalid_argument("Preallocated objects cannot exceed the maximum pool size");
41  }
42 
43  if (initialSize > 0)
44  {
45  this->preallocate(initialSize);
46  }
47  }
48 
49  // These don't strictly need to be deleted, but don't need to be implemented for now either.
50  DynamicObjectPool(const DynamicObjectPool&) = delete;
52  DynamicObjectPool& operator=(const DynamicObjectPool&) = delete;
53  DynamicObjectPool& operator=(DynamicObjectPool&&) = delete;
54 
57  {
58  clear();
59  }
60 
67  std::unique_ptr<T> acquireObject()
68  {
69  return std::unique_ptr<T>(acquireObjectRaw());
70  }
71 
79  {
80  std::unique_lock<std::mutex> lock(m_Mutex);
81 
82  if (m_Pool.empty())
83  {
84  // We don't need the lock anymore, so release it.
85  lock.unlock();
86  return new T();
87  }
88 
89  T* obj = m_Pool.top();
90  m_Pool.pop();
91  return obj;
92  }
93 
100  void releaseObject(std::unique_ptr<T> obj)
101  {
102  releaseObjectRaw(obj.release());
103  }
104 
111  void releaseObjectRaw(T* obj)
112  {
113  std::unique_lock<std::mutex> lock(m_Mutex);
114 
115  if (m_MaxPoolSize == INFINITE_POOL_SIZE || m_Pool.size() < m_MaxPoolSize)
116  {
117  m_Pool.push(obj);
118  }
119  else
120  {
121  // We don't need the lock anymore, so release it.
122  lock.unlock();
123  delete obj;
124  }
125  }
126 
128  std::size_t size() const
129  {
130  std::lock_guard<std::mutex> lock(m_Mutex);
131  return m_Pool.size();
132  }
133 
135  std::size_t maxSize() const
136  {
137  std::lock_guard<std::mutex> lock(m_Mutex);
138  return m_MaxPoolSize;
139  }
140 
142  void setMaxSize(std::size_t maxSize)
143  {
144  std::lock_guard<std::mutex> lock(m_Mutex);
145  m_MaxPoolSize = maxSize;
146 
147  // If the new max size is less than the current size, we need to remove some objects from the pool.
148  while (m_Pool.size() > m_MaxPoolSize)
149  {
150  delete m_Pool.top();
151  m_Pool.pop();
152  }
153  }
154 
157  void preallocate(std::size_t count)
158  {
159  std::unique_lock<std::mutex> lock(m_Mutex);
160 
161  if (m_MaxPoolSize < count)
162  {
163  throw std::invalid_argument("Preallocated objects cannot exceed the maximum pool size");
164  }
165 
166  // If the pool is already larger than the requested count, we don't need to do anything.
167  for (std::size_t i = m_Pool.size(); i < count; i++)
168  {
169  m_Pool.push(new T());
170  }
171  }
172 
174  void clear()
175  {
176  std::unique_lock<std::mutex> lock(m_Mutex);
177  while (!m_Pool.empty())
178  {
179  delete m_Pool.top();
180  m_Pool.pop();
181  }
182  }
183 
184  private:
185  std::size_t m_MaxPoolSize;
186  mutable std::mutex m_Mutex;
187  std::stack<T*> m_Pool;
188  };
189  } // namespace internal
190 } // namespace pcpp
A generic object pool implementation.
Definition: ObjectPool.h:24
void releaseObject(std::unique_ptr< T > obj)
Releases a unique pointer to an object back to the pool.
Definition: ObjectPool.h:100
DynamicObjectPool(std::size_t maxPoolSize=DEFAULT_POOL_SIZE, std::size_t initialSize=0)
Definition: ObjectPool.h:35
void clear()
Deallocates and releases all objects currently held by the pool.
Definition: ObjectPool.h:174
void releaseObjectRaw(T *obj)
Releases a raw pointer to an object back to the pool.
Definition: ObjectPool.h:111
std::size_t size() const
Gets the current number of objects in the pool.
Definition: ObjectPool.h:128
~DynamicObjectPool()
A destructor for this class that deletes all objects in the pool.
Definition: ObjectPool.h:56
void setMaxSize(std::size_t maxSize)
Sets the maximum number of objects in the pool.
Definition: ObjectPool.h:142
T * acquireObjectRaw()
Acquires a raw pointer to an object from the pool.
Definition: ObjectPool.h:78
void preallocate(std::size_t count)
Pre-allocates up to a minimum number of objects in the pool.
Definition: ObjectPool.h:157
std::size_t maxSize() const
Gets the maximum number of objects in the pool.
Definition: ObjectPool.h:135
std::unique_ptr< T > acquireObject()
Acquires a unique pointer to an object from the pool.
Definition: ObjectPool.h:67
The main namespace for the PcapPlusPlus lib.