Created
November 3, 2018 18:21
-
-
Save arrieta/42ee41713b9a54fdea7fc7be9335ada1 to your computer and use it in GitHub Desktop.
Aligned Object Pool
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cassert> | |
#include <iostream> | |
#include <memory> | |
#include <type_traits> | |
#include <vector> | |
template <typename T> | |
class Pool { | |
public: | |
using Block = typename std::aligned_storage<sizeof(T), alignof(T)>::type; | |
using Page = std::unique_ptr<Block[]>; | |
using Pages = std::vector<Page>; | |
constexpr std::size_t blocks_per_page() const { | |
return PAGE_SIZE / sizeof(Block); | |
} | |
constexpr std::size_t size() const { return m_size; } | |
std::size_t capacity() const { return m_pages.size() * blocks_per_page(); } | |
template <typename... Args> | |
void emplace(Args&&... args) { | |
if (size() == capacity()) { | |
m_pages.emplace_back(std::make_unique<Block[]>(blocks_per_page())); | |
} | |
auto page = m_pages.back().get(); | |
auto offset = sizeof(Block) * ((m_size++) % blocks_per_page()); | |
new (std::next(page, offset)) T(std::forward<Args>(args)...); | |
} | |
const T& at(std::size_t n) const { | |
auto page = m_pages.at(n / blocks_per_page()).get(); | |
auto offset = sizeof(Block) * (n % blocks_per_page()); | |
return *reinterpret_cast<T*>(std::next(page, offset)); | |
} | |
T& at(std::size_t n) { | |
auto page = m_pages.at(n / blocks_per_page()).get(); | |
auto offset = sizeof(Block) * (n % blocks_per_page()); | |
return *reinterpret_cast<T*>(std::next(page, offset)); | |
} | |
private: | |
std::size_t m_size{0}; | |
Pages m_pages{}; | |
}; | |
struct alignas(16) Vector { | |
Vector() {} | |
Vector(double x, double y, double z) : x{x}, y{y}, z{z} {} | |
double x{0}; | |
double y{0}; | |
double z{0}; | |
}; | |
std::ostream& operator<<(std::ostream& os, const Vector& v) { | |
return os << v.x << ", " << v.y << ", " << v.z; | |
} | |
int main() { | |
Pool<Vector> pool; | |
pool.emplace(); | |
pool.emplace(1, 2, 3); | |
pool.emplace(4, 5, 6); | |
std::cout << pool.size() << "\n" << pool.capacity() << "\n"; | |
std::cout << pool.at(0) << "\n" << pool.at(1) << "\n" << pool.at(2) << "\n"; | |
pool.at(2).x += 10; | |
std::cout << pool.at(2) << "\n"; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Type erasure