91 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			91 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
 | 
						|
#pragma once
 | 
						|
 | 
						|
#if !defined(MIJIN_MEMORY_DATA_POOL_HPP_INCLUDED)
 | 
						|
#define MIJIN_MEMORY_DATA_POOL_HPP_INCLUDED 1
 | 
						|
 | 
						|
#include <array>
 | 
						|
#include <cassert>
 | 
						|
#include <cstddef>
 | 
						|
#include <cstdint>
 | 
						|
#include <memory>
 | 
						|
#include <vector>
 | 
						|
 | 
						|
namespace mijin
 | 
						|
{
 | 
						|
 | 
						|
//
 | 
						|
// public defines
 | 
						|
//
 | 
						|
 | 
						|
//
 | 
						|
// public constants
 | 
						|
//
 | 
						|
 | 
						|
//
 | 
						|
// public types
 | 
						|
//
 | 
						|
 | 
						|
template<std::size_t PAGE_SIZE = 4096ul * 1024ul>
 | 
						|
struct DataPool
 | 
						|
{
 | 
						|
    static_assert(PAGE_SIZE % alignof(std::max_align_t) == 0);
 | 
						|
    
 | 
						|
    struct alignas(std::max_align_t) Page : std::array<std::uint8_t, PAGE_SIZE> {};
 | 
						|
 | 
						|
    using page_ptr_t = std::unique_ptr<Page>;
 | 
						|
 | 
						|
    std::vector<page_ptr_t> pages;
 | 
						|
    std::size_t offset = 0;
 | 
						|
 | 
						|
    DataPool() = default;
 | 
						|
    DataPool(const DataPool&) = delete;
 | 
						|
    DataPool(DataPool&&) noexcept = default;
 | 
						|
 | 
						|
    DataPool& operator=(const DataPool&) = delete;
 | 
						|
    DataPool& operator=(DataPool&&) noexcept = default;
 | 
						|
 | 
						|
    void* allocate(std::size_t bytes, std::size_t alignment = 1);
 | 
						|
    inline void reset() { offset = 0; }
 | 
						|
 | 
						|
    template<typename T>
 | 
						|
    T* allocateAs(std::size_t elements = 1) {
 | 
						|
        return static_cast<T*>(allocate(sizeof(T) * elements, alignof(T)));
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
//
 | 
						|
// public functions
 | 
						|
//
 | 
						|
 | 
						|
template<std::size_t PAGE_SIZE>
 | 
						|
void* DataPool<PAGE_SIZE>::allocate(std::size_t bytes, std::size_t alignment)
 | 
						|
{
 | 
						|
    assert(bytes > 0 && bytes <= PAGE_SIZE);
 | 
						|
    assert(alignment > 0 && alignment <= alignof(std::max_align_t));
 | 
						|
 | 
						|
    if (offset % alignment != 0) {
 | 
						|
        offset += alignment - (offset % alignment);
 | 
						|
    }
 | 
						|
 | 
						|
    const std::size_t remainingOnPage = PAGE_SIZE - (offset % PAGE_SIZE);
 | 
						|
    const std::size_t page = offset / PAGE_SIZE;
 | 
						|
    const std::size_t localOffset = offset % PAGE_SIZE;
 | 
						|
    if (remainingOnPage == PAGE_SIZE || remainingOnPage < bytes)
 | 
						|
    {
 | 
						|
        // next page
 | 
						|
        if (page + 1 >= pages.size()) {
 | 
						|
            pages.push_back(std::make_unique<Page>());
 | 
						|
        }
 | 
						|
        offset = PAGE_SIZE * (pages.size() - 1);
 | 
						|
    }
 | 
						|
    std::uint8_t* result = &(*pages[page])[localOffset];
 | 
						|
    offset += bytes;
 | 
						|
    assert(reinterpret_cast<std::uintptr_t>(result) % alignment == 0);
 | 
						|
    return result;
 | 
						|
}
 | 
						|
 | 
						|
} // namespace mijin
 | 
						|
 | 
						|
#endif // !defined(MIJIN_MEMORY_DATA_POOL_HPP_INCLUDED)
 |