The Pedigree Project  0.1
ObjectPool.h
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #ifndef KERNEL_UTILITY_OBJECT_POOL_H
21 #define KERNEL_UTILITY_OBJECT_POOL_H
22 
23 #include "pedigree/kernel/processor/types.h"
24 #ifdef THREADS
25 #include "pedigree/kernel/LockGuard.h"
26 #include "pedigree/kernel/Spinlock.h"
27 #endif
28 #include "pedigree/kernel/utilities/Vector.h"
29 #include "pedigree/kernel/utilities/assert.h"
30 
32 
41 template <class T, size_t poolSize = 16>
43 {
44  public:
45  ObjectPool()
46  : m_Pool()
47 #ifdef THREADS
48  ,
49  m_Spinlock()
50 #endif
51  {
52  }
53 
54  virtual ~ObjectPool()
55  {
56  for (auto it = m_Pool.begin(); it != m_Pool.end(); ++it)
57  {
58  delete *it;
59  }
60  }
61 
62  template <typename... Args>
63  T *allocate(Args... args)
64  {
65  if (!poolSize)
66  {
67  return new T(args...);
68  }
69 
70 #ifdef THREADS
71  LockGuard<Spinlock> guard(m_Spinlock);
72 #endif
73 
74  m_Pool.reserve(poolSize, true);
75  if (m_Pool.count())
76  {
77  // popping from the rear of a vector is much faster
78  return m_Pool.popBack();
79  }
80  else
81  {
82  return new T(args...);
83  }
84  }
85 
86  void deallocate(T *object)
87  {
88  if (!poolSize)
89  {
90  delete object;
91  return;
92  }
93 
94  assert(object != nullptr);
95  if (!object)
96  {
97  return;
98  }
99 
100 #ifdef THREADS
101  LockGuard<Spinlock> guard(m_Spinlock);
102 #endif
103 
104  // We only add the object back to the pool if we aren't already at
105  // capacity (otherwise we'd resize the Vector).
106  m_Pool.reserve(poolSize, true);
107  if (m_Pool.count() < poolSize)
108  {
109  m_Pool.pushBack(object);
110  }
111  else
112  {
113  delete object;
114  }
115  }
116 
117  private:
118  Vector<T *> m_Pool;
119 #ifdef THREADS
120  Spinlock m_Spinlock;
121 #endif
122 };
123 
124 #endif // KERNEL_UTILITY_OBJECT_POOL_H
void pushBack(const T &value)
Definition: Vector.h:270
T popBack()
Definition: Vector.h:286
Iterator begin()
Definition: Vector.h:148
Iterator end()
Definition: Vector.h:160
size_t count() const
Definition: Vector.h:264
#define assert(x)
Definition: assert.h:37
void reserve(size_t size, bool copy)
Definition: Vector.h:390