You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
49 lines
3.0 KiB
49 lines
3.0 KiB
#pragma once
|
|
|
|
namespace detail::refcount_hive
|
|
{
|
|
// The element as allocated in memory needs to be at-least 2*skipfield_type width in order to support free list indexes in
|
|
// erased element memory space, so: make the size of this struct the larger of alignof(T), sizeof(T) or 2*skipfield_type
|
|
// (the latter is only relevant for type char/uchar), and make the alignment alignof(T). This type is used mainly for
|
|
// correct pointer arithmetic while iterating over elements in memory.
|
|
template <typename element_type, typename skipfield_type, typename refcount_type>
|
|
struct alignas(alignof(element_type)) aligned_element_struct {
|
|
// Using char as sizeof is always guaranteed to be 1 byte regardless of the number of bits in a byte on given computer,
|
|
// whereas for example, uint8_t would fail on machines where there are more than 8 bits in a byte eg. Texas Instruments
|
|
// C54x DSPs.
|
|
char
|
|
data[(sizeof(element_type) < (sizeof(skipfield_type) * 2))
|
|
? ((sizeof(skipfield_type) * 2) < alignof(element_type) ? alignof(element_type) : (sizeof(skipfield_type) * 2))
|
|
: ((sizeof(element_type) < alignof(element_type)) ? alignof(element_type) : sizeof(element_type))];
|
|
};
|
|
|
|
// We combine the allocation of elements and skipfield into one allocation to save performance. This memory must be
|
|
// allocated as an aligned type with the same alignment as T in order for the elements to align with memory boundaries
|
|
// correctly (which won't happen if we allocate as char or uint_8). But the larger the sizeof in the type we use for
|
|
// allocation, the greater the chance of creating a lot of unused memory in the skipfield portion of the allocated block. So
|
|
// we create a type that is sizeof(alignof(T)), as in most cases alignof(T) < sizeof(T). If alignof(t) >= sizeof(t) this
|
|
// makes no difference.
|
|
template <typename element_type>
|
|
struct alignas(alignof(element_type)) aligned_allocation_struct {
|
|
char data[alignof(element_type)];
|
|
};
|
|
|
|
// Calculate the capacity of a group's elements+skipfield memory block when expressed in multiples of the value_type's
|
|
// alignment (rounding up).
|
|
template <typename element_type, typename skipfield_type, typename refcount_type>
|
|
static size_t get_aligned_block_capacity(const skipfield_type elements_per_group)
|
|
{
|
|
using aligned_element_struct = aligned_element_struct<element_type, skipfield_type, refcount_type>;
|
|
using aligned_allocation_struct = aligned_allocation_struct<element_type>;
|
|
return ((elements_per_group * (sizeof(aligned_element_struct) + sizeof(skipfield_type))) + sizeof(skipfield_type)
|
|
+ sizeof(aligned_allocation_struct) - 1)
|
|
/ sizeof(aligned_allocation_struct);
|
|
}
|
|
|
|
// To enable conversion when allocator supplies non-raw pointers:
|
|
template <class destination_pointer_type, class source_pointer_type>
|
|
static constexpr destination_pointer_type pointer_cast(const source_pointer_type source_pointer) noexcept
|
|
{
|
|
return destination_pointer_type(&*source_pointer);
|
|
}
|
|
} // namespace detail::refcount_hive
|