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#include "pedigree/kernel/processor/types.h"
23
24#include <config.h>
25#if THREADS
26#include "pedigree/kernel/LockGuard.h"
27#include "pedigree/kernel/Spinlock.h"
28#endif
29#include "pedigree/kernel/utilities/Vector.h"
30#include "pedigree/kernel/utilities/assert.h"
31
33
42template <class T, size_t poolSize = 16>
44 public:
46 : m_Pool()
47#if THREADS
48 ,
49 m_Spinlock()
50#endif
51 {
52 }
53
54 virtual ~ObjectPool() {
55 for (auto it = m_Pool.begin(); it != m_Pool.end(); ++it) {
56 delete *it;
57 }
58 }
59
60 template <typename... Args>
61 T* allocate(Args... args) {
62 if (!poolSize) {
63 return new T(args...);
64 }
65
66#if THREADS
67 LockGuard<Spinlock> guard(m_Spinlock);
68#endif
69
70 m_Pool.reserve(poolSize, true);
71 if (m_Pool.count()) {
72 // popping from the rear of a vector is much faster
73 return m_Pool.popBack();
74 } else {
75 return new T(args...);
76 }
77 }
78
79 template <typename... Args>
80 T* tryAllocate(Args... args) {
81 if (!poolSize)
82 return new T(args...);
83#if THREADS
84 LockGuard<Spinlock> guard(m_Spinlock);
85#endif
86 // Admit the return slot before lending an object, so rollback need not allocate.
87 if (!m_Pool.tryReserve(poolSize, true))
88 return nullptr;
89 if (m_Pool.count())
90 return m_Pool.popBack();
91 return new T(args...);
92 }
93
94 void deallocate(T* object) {
95 if (!poolSize) {
96 delete object;
97 return;
98 }
99
100 assert(object != nullptr);
101 if (!object) {
102 return;
103 }
104
105#if THREADS
106 LockGuard<Spinlock> guard(m_Spinlock);
107#endif
108
109 // We only add the object back to the pool if we aren't already at
110 // capacity (otherwise we'd resize the Vector).
111 if (m_Pool.tryReserve(poolSize, true) && m_Pool.count() < poolSize) {
112 m_Pool.pushBack(object);
113 } else {
114 delete object;
115 }
116 }
117
118 private:
119 Vector<T*> m_Pool;
120#if THREADS
121 Spinlock m_Spinlock;
122#endif
123};
124
125#endif // KERNEL_UTILITY_OBJECT_POOL_H
A vector / dynamic array.
Definition Vector.h:33
Iterator end()
Definition Vector.h:172
Iterator begin()
Definition Vector.h:162
void reserve(size_t size, bool copy)
Definition Vector.h:453
T popBack()
Definition Vector.h:303
void pushBack(const T &value)
Definition Vector.h:275
size_t count() const
Definition Vector.h:270