allocators
parent
68f6a0af44
commit
8a32d6b675
|
@ -26,6 +26,40 @@
|
||||||
|
|
||||||
namespace blt
|
namespace blt
|
||||||
{
|
{
|
||||||
|
|
||||||
|
template<typename value_type, typename pointer, typename const_pointer>
|
||||||
|
class allocator_base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
template<class U, class... Args>
|
||||||
|
inline void construct(U* p, Args&& ... args)
|
||||||
|
{
|
||||||
|
::new((void*) p) U(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class U>
|
||||||
|
inline void destroy(U* p)
|
||||||
|
{
|
||||||
|
if (p != nullptr)
|
||||||
|
p->~U();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] inline size_t max_size() const
|
||||||
|
{
|
||||||
|
return std::numeric_limits<size_t>::max();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const_pointer address(const value_type& val)
|
||||||
|
{
|
||||||
|
return std::addressof(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline pointer address(value_type& val)
|
||||||
|
{
|
||||||
|
return std::addressof(val);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T, size_t BLOCK_SIZE = 8192>
|
template<typename T, size_t BLOCK_SIZE = 8192>
|
||||||
class area_allocator
|
class area_allocator
|
||||||
{
|
{
|
||||||
|
@ -47,6 +81,7 @@ namespace blt
|
||||||
{
|
{
|
||||||
typedef blt::area_allocator<U, BLOCK_SIZE> other;
|
typedef blt::area_allocator<U, BLOCK_SIZE> other;
|
||||||
};
|
};
|
||||||
|
using allocator_base<value_type, pointer, const_pointer>::allocator_base;
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Stores a view to a region of memory that has been deallocated
|
* Stores a view to a region of memory that has been deallocated
|
||||||
|
@ -225,6 +260,129 @@ namespace blt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~area_allocator()
|
||||||
|
{
|
||||||
|
for (auto*& blk : blocks)
|
||||||
|
{
|
||||||
|
free(blk->data);
|
||||||
|
delete blk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<block_storage*> blocks;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class bump_allocator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using value = T;
|
||||||
|
using type = T;
|
||||||
|
using value_type = type;
|
||||||
|
using pointer = type*;
|
||||||
|
using const_pointer = const type*;
|
||||||
|
using void_pointer = void*;
|
||||||
|
using const_void_pointer = const void*;
|
||||||
|
using reference = value_type&;
|
||||||
|
using const_reference = const value_type&;
|
||||||
|
using size_type = size_t;
|
||||||
|
using difference_type = size_t;
|
||||||
|
using propagate_on_container_move_assignment = std::false_type;
|
||||||
|
template<class U>
|
||||||
|
struct rebind
|
||||||
|
{
|
||||||
|
typedef blt::bump_allocator<U> other;
|
||||||
|
};
|
||||||
|
using allocator_base<value_type, pointer, const_pointer>::allocator_base;
|
||||||
|
private:
|
||||||
|
pointer buffer_;
|
||||||
|
blt::size_t offset_;
|
||||||
|
blt::size_t size_;
|
||||||
|
public:
|
||||||
|
explicit bump_allocator(blt::size_t size): buffer_(malloc(size * sizeof(T))), size_(size), offset_(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
explicit bump_allocator(blt::size_t size, Args&& ... defaults): buffer_(malloc(size * sizeof(type))), size_(size), offset_(0)
|
||||||
|
{
|
||||||
|
for (blt::size_t i = 0; i < size_; i++)
|
||||||
|
::new(&buffer_[i]) T(std::forward<Args>(defaults)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
bump_allocator(pointer buffer, blt::size_t size): buffer_(buffer), size_(size), offset_(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bump_allocator(const bump_allocator& copy) = delete;
|
||||||
|
|
||||||
|
bump_allocator(bump_allocator&& move) noexcept
|
||||||
|
{
|
||||||
|
buffer_ = move.buffer_;
|
||||||
|
size_ = move.size_;
|
||||||
|
offset_ = move.offset_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bump_allocator& operator=(const bump_allocator& copy) = delete;
|
||||||
|
|
||||||
|
bump_allocator& operator=(bump_allocator&& move) noexcept
|
||||||
|
{
|
||||||
|
std::swap(move.buffer_, buffer_);
|
||||||
|
std::swap(move.size_, size_);
|
||||||
|
std::swap(move.offset_, offset_);
|
||||||
|
}
|
||||||
|
|
||||||
|
pointer allocate(blt::size_t n)
|
||||||
|
{
|
||||||
|
auto nv = offset_ + n;
|
||||||
|
if (nv > size_)
|
||||||
|
throw std::bad_alloc();
|
||||||
|
pointer b = &buffer_[offset_];
|
||||||
|
offset_ = nv;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void deallocate(pointer, blt::size_t)
|
||||||
|
{}
|
||||||
|
|
||||||
|
~bump_allocator()
|
||||||
|
{
|
||||||
|
free(buffer_);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class multi_type_area_allocator
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
struct pointer_view
|
||||||
|
{
|
||||||
|
blt::u8* p;
|
||||||
|
size_t n;
|
||||||
|
};
|
||||||
|
|
||||||
|
blt::u8* buffer_;
|
||||||
|
blt::u8* offset_;
|
||||||
|
blt::size_t size_;
|
||||||
|
public:
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
[[nodiscard]] T* allocate()
|
||||||
|
{
|
||||||
|
size_t remaining_num_bytes = size_ - static_cast<size_t>(buffer_ - offset_);
|
||||||
|
auto pointer = static_cast<void*>(offset_);
|
||||||
|
const auto aligned_address = std::align(alignof(T), sizeof(T), pointer, remaining_num_bytes);
|
||||||
|
if (aligned_address == nullptr)
|
||||||
|
throw std::bad_alloc{};
|
||||||
|
offset_ = static_cast<blt::u8*>(aligned_address) + sizeof(T);
|
||||||
|
return static_cast<T*>(aligned_address);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename... Args>
|
||||||
|
[[nodiscard]] T* emplace(Args&& ... args)
|
||||||
|
{
|
||||||
|
const auto allocated_memory = allocate<T>();
|
||||||
|
return new(allocated_memory) T{std::forward<Args>(args)...};
|
||||||
|
}
|
||||||
|
|
||||||
template<class U, class... Args>
|
template<class U, class... Args>
|
||||||
inline void construct(U* p, Args&& ... args)
|
inline void construct(U* p, Args&& ... args)
|
||||||
{
|
{
|
||||||
|
@ -238,32 +396,10 @@ namespace blt
|
||||||
p->~U();
|
p->~U();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline size_t max_size() const
|
~multi_type_area_allocator()
|
||||||
{
|
{
|
||||||
return std::numeric_limits<size_t>::max();
|
delete[] buffer_;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const_pointer address(const value_type& val)
|
|
||||||
{
|
|
||||||
return std::addressof(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline pointer address(value_type& val)
|
|
||||||
{
|
|
||||||
return std::addressof(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
~area_allocator()
|
|
||||||
{
|
|
||||||
for (auto*& blk : blocks)
|
|
||||||
{
|
|
||||||
free(blk->data);
|
|
||||||
delete blk;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<block_storage*> blocks;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* <Short Description>
|
||||||
|
* Copyright (C) 2024 Brett Terpstra
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BLT_SIMD_H
|
||||||
|
#define BLT_SIMD_H
|
||||||
|
|
||||||
|
#include <xmmintrin.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // BLT_SIMD_H
|
Loading…
Reference in New Issue