-
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
fba1e58
commit fcdb1ea
Showing
9 changed files
with
301 additions
and
77 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
#pragma once | ||
#include "../config/config.h" | ||
|
||
#include <cinttypes> | ||
|
||
#include "data_layout_policy.h" | ||
|
||
namespace gaia { | ||
namespace mem { | ||
namespace detail { | ||
template <uint32_t Size, uint32_t Alignment> | ||
struct raw_data_holder { | ||
static_assert(Size > 0); | ||
|
||
GAIA_ALIGNAS(Alignment) uint8_t data[Size]; | ||
|
||
constexpr operator uint8_t*() noexcept { | ||
return &data[0]; | ||
} | ||
|
||
constexpr operator const uint8_t*() const noexcept { | ||
return &data[0]; | ||
} | ||
}; | ||
|
||
template <uint32_t Size> | ||
struct raw_data_holder<Size, 0> { | ||
static_assert(Size > 0); | ||
|
||
uint8_t data[Size]; | ||
|
||
constexpr operator uint8_t*() noexcept { | ||
return &data[0]; | ||
} | ||
|
||
constexpr operator const uint8_t*() const noexcept { | ||
return &data[0]; | ||
} | ||
}; | ||
} // namespace detail | ||
|
||
template <typename T, uint32_t N> | ||
using raw_data_holder = detail::raw_data_holder<N, auto_view_policy<T>::Alignment>; | ||
} // namespace mem | ||
} // namespace gaia |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
#pragma once | ||
#include "../config/config.h" | ||
|
||
#include <cinttypes> | ||
|
||
#include "raw_data_holder.h" | ||
|
||
namespace gaia { | ||
namespace mem { | ||
namespace detail { | ||
struct AllocationInfo { | ||
//! Byte offset of the previous allocation | ||
uint32_t prev; | ||
//! Offset of data area from info area in bytes | ||
uint32_t off : 8; | ||
//! The number of requested bytes to allocate | ||
uint32_t cnt : 24; | ||
void (*dtor)(void*, uint32_t); | ||
}; | ||
} // namespace detail | ||
|
||
//! Stack allocator capable of instantiating any default-constructible object on stack. | ||
//! Every allocation comes with a 16-bytes long sentinel object. | ||
template <uint32_t CapacityInBytes = 1024> | ||
class StackAllocator { | ||
using alloc_info = detail::AllocationInfo; | ||
|
||
//! Internal stack buffer aligned to 16B boundary | ||
detail::raw_data_holder<CapacityInBytes, 16> m_buffer; | ||
//! Current byte offset | ||
uint32_t m_pos = 0; | ||
//! Byte offset of the previous allocatoin | ||
uint32_t m_posPrev = 0; | ||
//! Number of allocations made | ||
uint32_t m_allocs = 0; | ||
|
||
public: | ||
StackAllocator() { | ||
// Aligned used so the sentinel object can be stored properly | ||
const auto bufferMemAddr = (uintptr_t)((uint8_t*)m_buffer); | ||
m_posPrev = m_pos = padding<alignof(alloc_info)>(bufferMemAddr); | ||
} | ||
|
||
~StackAllocator() { | ||
reset(); | ||
} | ||
|
||
StackAllocator(const StackAllocator&) = delete; | ||
StackAllocator(StackAllocator&&) = delete; | ||
StackAllocator& operator=(const StackAllocator&) = delete; | ||
StackAllocator& operator=(StackAllocator&&) = delete; | ||
|
||
//! Allocates \param cnt objects of type \tparam T inside the buffer. | ||
//! No default initialization is done so the object is returned in a non-initialized | ||
//! state unless a custom constructor is provided. | ||
//! \return Pointer to the first allocated object | ||
template <typename T> | ||
GAIA_NODISCARD T* alloc(uint32_t cnt) { | ||
constexpr auto sizeT = (uint32_t)sizeof(T); | ||
const auto addrBuff = (uintptr_t)((uint8_t*)m_buffer); | ||
const auto addrAllocInfo = align<alignof(alloc_info)>(addrBuff + m_pos); | ||
const auto addrAllocData = align<alignof(T)>(addrAllocInfo + sizeof(alloc_info)); | ||
const auto off = (uint32_t)(addrAllocData - addrAllocInfo); | ||
|
||
// There has to be some space left in the buffer | ||
const bool isFull = (uint32_t)(addrAllocData - addrBuff) + sizeT * cnt >= CapacityInBytes; | ||
if GAIA_UNLIKELY (isFull) { | ||
GAIA_ASSERT(!isFull && "Allocation space exceeded on StackAllocator"); | ||
return nullptr; | ||
} | ||
|
||
// Memory sentinel | ||
auto* pInfo = (alloc_info*)addrAllocInfo; | ||
pInfo->prev = m_posPrev; | ||
pInfo->off = off; | ||
pInfo->cnt = cnt; | ||
pInfo->dtor = [](void* ptr, uint32_t cnt) { | ||
core::call_dtor_n((T*)ptr, cnt); | ||
}; | ||
|
||
// Constuction the object is necessary | ||
auto* pData = (T*)addrAllocData; | ||
core::call_ctor_raw_n(pData, cnt); | ||
|
||
// Allocation start offset | ||
m_posPrev = addrAllocInfo - addrBuff; | ||
// Point to the next free space (not necessary alligned yet) | ||
m_pos = m_posPrev + pInfo->off + sizeT * cnt; | ||
|
||
++m_allocs; | ||
return pData; | ||
} | ||
|
||
//! Frees the last allocated object from the stack. | ||
//! \param pData Pointer to the last allocated object on the stack | ||
//! \param cnt Number of objects that were allocated on the given memory address | ||
void free([[maybe_unused]] void* pData, [[maybe_unused]] uint32_t cnt) { | ||
GAIA_ASSERT(pData != nullptr); | ||
GAIA_ASSERT(cnt > 0); | ||
GAIA_ASSERT(m_allocs > 0); | ||
|
||
const auto addrBuff = (uintptr_t)((uint8_t*)m_buffer); | ||
|
||
// Destroy the last allocated object | ||
const auto addrAllocInfo = addrBuff + m_posPrev; | ||
auto* pInfo = (alloc_info*)addrAllocInfo; | ||
const auto addrAllocData = addrAllocInfo + pInfo->off; | ||
void* pInfoData = (void*)addrAllocData; | ||
GAIA_ASSERT(pData == pInfoData); | ||
GAIA_ASSERT(pInfo->cnt == cnt); | ||
pInfo->dtor(pInfoData, pInfo->cnt); | ||
|
||
m_pos = m_posPrev; | ||
m_posPrev = pInfo->prev; | ||
--m_allocs; | ||
} | ||
|
||
//! Frees all allocated objects from the buffer | ||
void reset() { | ||
const auto addrBuff = (uintptr_t)((uint8_t*)m_buffer); | ||
|
||
// Destroy allocated objects back-to-front | ||
auto pos = m_posPrev; | ||
while (m_allocs > 0) { | ||
const auto addrAllocInfo = addrBuff + pos; | ||
auto* pInfo = (alloc_info*)addrAllocInfo; | ||
const auto addrAllocData = addrAllocInfo + pInfo->off; | ||
pInfo->dtor((void*)addrAllocData, pInfo->cnt); | ||
pos = pInfo->prev; | ||
|
||
--m_allocs; | ||
} | ||
|
||
GAIA_ASSERT(m_allocs == 0); | ||
|
||
m_pos = 0; | ||
m_posPrev = 0; | ||
m_allocs = 0; | ||
} | ||
|
||
GAIA_NODISCARD constexpr uint32_t capacity() { | ||
return CapacityInBytes; | ||
} | ||
}; | ||
} // namespace mem | ||
} // namespace gaia |
This file contains 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
Oops, something went wrong.