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