allocPool: First commit
This commit is contained in:
commit
0af20178b8
66
.clang-format
Normal file
66
.clang-format
Normal file
@ -0,0 +1,66 @@
|
||||
# Generated from CLion C/C++ Code Style settings
|
||||
BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: None
|
||||
AlignOperands: Align
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AllowAllConstructorInitializersOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: Always
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortIfStatementsOnASingleLine: Always
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: Never
|
||||
AfterEnum: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterUnion: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyRecord: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakInheritanceList: BeforeColon
|
||||
ColumnLimit: 0
|
||||
CompactNamespaces: false
|
||||
ContinuationIndentWidth: 8
|
||||
IndentCaseLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 4
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
MaxEmptyLinesToKeep: 2
|
||||
NamespaceIndentation: All
|
||||
ObjCSpaceAfterProperty: false
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PointerAlignment: Right
|
||||
ReflowComments: false
|
||||
SpaceAfterCStyleCast: true
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceBeforeRangeBasedForLoopColon: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 0
|
||||
SpacesInAngles: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
8
.idea/.gitignore
vendored
Normal file
8
.idea/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
8
CMakeLists.txt
Normal file
8
CMakeLists.txt
Normal file
@ -0,0 +1,8 @@
|
||||
cmake_minimum_required(VERSION 3.27)
|
||||
project(allocPool)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
|
||||
add_executable(allocPool main.cpp
|
||||
allocPool.cpp
|
||||
allocPool.hpp)
|
13
README.md
Normal file
13
README.md
Normal file
@ -0,0 +1,13 @@
|
||||
# allocPool - A simple & high performance object pool using modern C++
|
||||
|
||||
This is allocPool, a pool of objects that allow you to avoid expensive allocations
|
||||
during runtime. This preallocates objects in the constructor (with threads) then
|
||||
offers you two functions: getPtr() and returnPtr(ptr).
|
||||
|
||||
Using C++ concepts, we can use templates and require the class given to have a
|
||||
default constructor and to have a .reset() function. It will be used to clean the
|
||||
objects before giving them to another caller.
|
||||
|
||||
This pool uses a hashmap and a pivot to make returnPtr(ptr) extremely fast.
|
||||
|
||||
It will automatically grow when the max capacity is reached.
|
71
allocPool.cpp
Normal file
71
allocPool.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
#include "allocPool.hpp"
|
||||
|
||||
template<class T>
|
||||
requires std::default_initializable<T> && resetable<T>
|
||||
allocPool<T>::allocPool(size_t defaultAllocNumbers)
|
||||
: vec(defaultAllocNumbers), pivot{defaultAllocNumbers} {
|
||||
memset(&(vec[0]), 0, sizeof(vec[0]) * vec.size());
|
||||
initArray(defaultAllocNumbers);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
requires std::default_initializable<T> && resetable<T>
|
||||
T *allocPool<T>::getPtr() {
|
||||
if (pivot == 0)
|
||||
resizeVec();
|
||||
|
||||
auto *ptrToReturn{vec[0]};
|
||||
std::swap(vec[0], vec[pivot - 1]);
|
||||
positionMap[vec[0]] = 0;
|
||||
positionMap[vec[pivot - 1]] = pivot - 1;
|
||||
pivot--;
|
||||
return ptrToReturn;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
requires std::default_initializable<T> && resetable<T>
|
||||
void allocPool<T>::returnPtr(T *ptr) {
|
||||
size_t pos = positionMap[ptr];
|
||||
vec[pos].reset();
|
||||
std::swap(vec[pos], vec[pivot]);
|
||||
pivot++;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
requires std::default_initializable<T> && resetable<T>
|
||||
void allocPool<T>::initArray(size_t amount) {
|
||||
const auto amountOfThreads{std::thread::hardware_concurrency()};
|
||||
assert(amountOfThreads);
|
||||
const auto amountPerThreads{amount / amountOfThreads};
|
||||
|
||||
std::vector<std::thread> threads;
|
||||
threads.reserve(amountOfThreads);
|
||||
|
||||
for (size_t i{}; i < amountOfThreads; i++)
|
||||
threads.emplace_back(&allocPool::initObjects, this, i, amountPerThreads);
|
||||
|
||||
for (auto &t: threads)
|
||||
t.join();
|
||||
|
||||
// Remainder
|
||||
initObjects(vec[vec.size() - (amount % amountOfThreads)], amount % amountOfThreads);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
requires std::default_initializable<T> && resetable<T>
|
||||
void allocPool<T>::initObjects(size_t startIdx, size_t amount) {
|
||||
for (size_t i{}; i < amount; i++) {
|
||||
// TODO: Be more cache friendly by making a vector per thread, then doing memcpy into the original vector.
|
||||
vec[startIdx + i] = new T;
|
||||
positionMap[startIdx + i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
requires std::default_initializable<T> && resetable<T>
|
||||
void allocPool<T>::resizeVec() {
|
||||
size_t size{vec.size()};
|
||||
vec.resize(2 * size);
|
||||
memcpy(&(vec[size]), &(vec[0]), size);
|
||||
initArray(size);
|
||||
}
|
34
allocPool.hpp
Normal file
34
allocPool.hpp
Normal file
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
template<class T>
|
||||
concept resetable = requires(T val) {
|
||||
val.reset();
|
||||
};
|
||||
|
||||
template<class T>
|
||||
requires std::default_initializable<T> && resetable<T>
|
||||
class allocPool {
|
||||
public:
|
||||
explicit allocPool(size_t defaultAllocNumbers = 1000);
|
||||
|
||||
T *getPtr();
|
||||
void returnPtr(T *ptr);
|
||||
|
||||
private:
|
||||
std::vector<T *> vec;
|
||||
std::unordered_map<T *, size_t> positionMap;
|
||||
size_t pivot;
|
||||
|
||||
void initArray(size_t amount);
|
||||
void initObjects(size_t startIdx, size_t amount);
|
||||
void resizeVec();
|
||||
};
|
Loading…
Reference in New Issue
Block a user