12 #include <type_traits> 20 #define DENSITY_VERSION 0x00020000 24 #if __cpp_constexpr >= 201304 25 #define DENSITY_CPP14_CONSTEXPR constexpr 27 #define DENSITY_CPP14_CONSTEXPR 30 #if __cpp_noexcept_function_type >= 201510 31 #define DENSITY_CPP17_NOEXCEPT noexcept 33 #define DENSITY_CPP17_NOEXCEPT 37 #if defined(__has_cpp_attribute) 38 #if __has_cpp_attribute(nodiscard) >= 201603 40 #define DENSITY_NODISCARD [[nodiscard]] 44 #ifndef DENSITY_NODISCARD 45 #define DENSITY_NODISCARD 112 return (i_number & (i_number - 1)) == 0;
122 return (reinterpret_cast<uintptr_t>(i_address) & (i_alignment - 1)) == 0;
128 template <
typename UINT>
inline bool uint_is_aligned(UINT i_uint, UINT i_alignment) noexcept
131 std::numeric_limits<UINT>::is_integer && !std::numeric_limits<UINT>::is_signed,
132 "UINT mus be an unsigned integer");
135 return (i_uint & (i_alignment - 1)) == 0;
142 inline void *
address_add(
void * i_address,
size_t i_offset) noexcept
144 const uintptr_t uint_pointer =
reinterpret_cast<uintptr_t
>(i_address);
145 return reinterpret_cast<void *
>(uint_pointer + i_offset);
152 inline const void *
address_add(
const void * i_address,
size_t i_offset) noexcept
154 const uintptr_t uint_pointer =
reinterpret_cast<uintptr_t
>(i_address);
155 return reinterpret_cast<const void *
>(uint_pointer + i_offset);
162 inline void *
address_sub(
void * i_address,
size_t i_offset) noexcept
164 const uintptr_t uint_pointer =
reinterpret_cast<uintptr_t
>(i_address);
166 return reinterpret_cast<void *
>(uint_pointer - i_offset);
173 inline const void *
address_sub(
const void * i_address,
size_t i_offset) noexcept
175 const uintptr_t uint_pointer =
reinterpret_cast<uintptr_t
>(i_address);
177 return reinterpret_cast<const void *
>(uint_pointer - i_offset);
184 inline uintptr_t
address_diff(
const void * i_end_address,
const void * i_start_address) noexcept
188 const uintptr_t end_uint_pointer =
reinterpret_cast<uintptr_t
>(i_end_address);
189 const uintptr_t start_uint_pointer =
reinterpret_cast<uintptr_t
>(i_start_address);
191 return end_uint_pointer - start_uint_pointer;
203 const uintptr_t uint_pointer =
reinterpret_cast<uintptr_t
>(i_address);
205 const size_t mask = i_alignment - 1;
207 return reinterpret_cast<void *
>(uint_pointer & ~mask);
219 const uintptr_t uint_pointer =
reinterpret_cast<uintptr_t
>(i_address);
221 const size_t mask = i_alignment - 1;
223 return reinterpret_cast<void *
>(uint_pointer & ~mask);
234 void * address =
address_add(i_address, i_alignment_offset);
238 address =
address_sub(address, i_alignment_offset);
249 const void * i_address,
size_t i_alignment,
size_t i_alignment_offset) noexcept
251 const void * address =
address_add(i_address, i_alignment_offset);
255 address =
address_sub(address, i_alignment_offset);
269 const uintptr_t uint_pointer =
reinterpret_cast<uintptr_t
>(i_address);
271 const size_t mask = i_alignment - 1;
273 return reinterpret_cast<void *
>((uint_pointer + mask) & ~mask);
285 const uintptr_t uint_pointer =
reinterpret_cast<uintptr_t
>(i_address);
287 const size_t mask = i_alignment - 1;
289 return reinterpret_cast<void *
>((uint_pointer + mask) & ~mask);
296 template <
typename UINT>
300 std::numeric_limits<UINT>::is_integer && !std::numeric_limits<UINT>::is_signed,
301 "UINT must be an unsigned integer");
302 return (i_uint + (i_alignment - 1)) & ~(i_alignment - 1);
310 template <
typename UINT>
314 std::numeric_limits<UINT>::is_integer && !std::numeric_limits<UINT>::is_signed,
315 "UINT must be an unsigned integer");
316 return i_uint & ~(i_alignment - 1);
327 void * address =
address_add(i_address, i_alignment_offset);
331 address =
address_sub(address, i_alignment_offset);
342 const void * i_address,
size_t i_alignment,
size_t i_alignment_offset) noexcept
344 const void * address =
address_add(i_address, i_alignment_offset);
348 address =
address_sub(address, i_alignment_offset);
358 constexpr
inline size_t size_min(
size_t i_first,
size_t i_second) noexcept
360 return i_first < i_second ? i_first : i_second;
364 constexpr
inline size_t size_max(
size_t i_first,
size_t i_second) noexcept
366 return i_first > i_second ? i_first : i_second;
368 constexpr
inline size_t size_max(
size_t i_first,
size_t i_second,
size_t i_third) noexcept
370 return size_max(size_max(i_first, i_second), i_third);
372 constexpr
inline size_t 373 size_max(
size_t i_first,
size_t i_second,
size_t i_third,
size_t i_fourth) noexcept
375 return size_max(size_max(i_first, i_second), size_max(i_third, i_fourth));
378 struct AlignmentHeader
383 constexpr
auto mem_relaxed =
385 constexpr
auto mem_acquire =
387 constexpr
auto mem_release =
389 constexpr
auto mem_acq_rel =
391 constexpr
auto mem_seq_cst =
396 constexpr
size_t size_log2(
size_t i_size) noexcept
398 return i_size <= 1 ? 0 : size_log2(i_size / 2) + 1;
403 inline bool ConstConditional(
bool i_value) noexcept {
return i_value; }
408 size_t m_size, m_alignment;
412 template <
typename TYPE>
struct size_of
414 static constexpr
size_t value = std::is_empty<TYPE>::value ? 0 :
sizeof(TYPE);
418 #if defined(__GLIBCXX__) 419 constexpr
size_t MaxAlignment =
alignof(max_align_t);
421 constexpr
size_t MaxAlignment =
alignof(std::max_align_t);
427 #define DENSITY_INTERNAL_RETHROW_FROM_NOEXCEPT \ 428 __pragma(warning(push)) __pragma(warning(disable : 4297)) throw; \ 429 __pragma(warning(pop)) 430 #elif defined(__GNUG__) && __GNUG__ >= 6 && !defined(__clang__) 431 #define DENSITY_INTERNAL_RETHROW_FROM_NOEXCEPT \ 432 _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wterminate\"") throw; \ 433 _Pragma("GCC diagnostic pop") 435 #define DENSITY_INTERNAL_RETHROW_FROM_NOEXCEPT throw; 460 inline void *
aligned_allocate(
size_t i_size,
size_t i_alignment,
size_t i_alignment_offset = 0)
467 if (i_alignment <= detail::MaxAlignment && i_alignment_offset == 0)
469 user_block =
operator new(i_size);
474 size_t const extra_size =
475 detail::size_max(i_alignment,
sizeof(detail::AlignmentHeader));
476 size_t const actual_size = i_size + extra_size;
477 auto const complete_block =
operator new(actual_size);
479 address_add(complete_block, extra_size), i_alignment, i_alignment_offset);
480 detail::AlignmentHeader & header =
481 *(
static_cast<detail::AlignmentHeader *
>(user_block) - 1);
482 header.m_block = complete_block;
484 user_block >= complete_block &&
511 size_t i_size,
size_t i_alignment,
size_t i_alignment_offset = 0) noexcept
518 if (i_alignment <= detail::MaxAlignment && i_alignment_offset == 0)
520 user_block =
operator new(i_size, std::nothrow);
525 size_t const extra_size =
526 detail::size_max(i_alignment,
sizeof(detail::AlignmentHeader));
527 size_t const actual_size = i_size + extra_size;
528 auto const complete_block =
operator new(actual_size, std::nothrow);
529 if (complete_block !=
nullptr)
532 address_add(complete_block, extra_size), i_alignment, i_alignment_offset);
533 detail::AlignmentHeader & header =
534 *(
static_cast<detail::AlignmentHeader *
>(user_block) - 1);
535 header.m_block = complete_block;
537 user_block >= complete_block &&
542 user_block =
nullptr;
565 void * i_block,
size_t i_size,
size_t i_alignment,
size_t i_alignment_offset = 0) noexcept
570 if (i_alignment <= detail::MaxAlignment && i_alignment_offset == 0)
572 #if __cpp_sized_deallocation >= 201309 573 operator delete(i_block, i_size);
576 operator delete(i_block);
581 if (i_block !=
nullptr)
583 const auto & header = *(
static_cast<detail::AlignmentHeader *
>(i_block) - 1);
584 #if __cpp_sized_deallocation >= 201309 // since C++14 585 size_t const extra_size =
586 detail::size_max(i_alignment,
sizeof(detail::AlignmentHeader));
587 size_t const actual_size = i_size + extra_size;
588 operator delete(header.m_block, actual_size);
591 operator delete(header.m_block);
void * address_add(void *i_address, size_t i_offset) noexcept
Definition: density_common.h:142
Definition: density_common.h:70
bool address_is_aligned(const void *i_address, size_t i_alignment) noexcept
Definition: density_common.h:118
constexpr char version[]
Definition: density_common.h:53
concurrency_cardinality
Definition: density_common.h:56
constexpr bool enable_relaxed_atomics
Definition: density_config.h:118
Definition: conc_function_queue.h:11
Definition: density_common.h:67
Definition: density_common.h:60
Definition: density_common.h:86
Definition: density_common.h:90
Definition: density_common.h:58
uintptr_t address_diff(const void *i_end_address, const void *i_start_address) noexcept
Definition: density_common.h:184
#define DENSITY_ASSERT(...)
Definition: density_config.h:19
constexpr UINT uint_lower_align(UINT i_uint, size_t i_alignment) noexcept
Definition: density_common.h:311
Definition: density_common.h:99
void * address_sub(void *i_address, size_t i_offset) noexcept
Definition: density_common.h:162
Definition: density_common.h:88
progress_guarantee
Definition: density_common.h:84
Definition: density_common.h:101
constexpr bool is_power_of_2(size_t i_number) noexcept
Definition: density_common.h:109
void * aligned_allocate(size_t i_size, size_t i_alignment, size_t i_alignment_offset=0)
Definition: density_common.h:460
void * address_upper_align(void *i_address, size_t i_alignment) noexcept
Definition: density_common.h:264
#define DENSITY_ASSERT_INTERNAL(...)
Definition: density_config.h:28
void * address_lower_align(void *i_address, size_t i_alignment) noexcept
Definition: density_common.h:198
void * try_aligned_allocate(size_t i_size, size_t i_alignment, size_t i_alignment_offset=0) noexcept
Definition: density_common.h:510
Definition: density_common.h:92
constexpr UINT uint_upper_align(UINT i_uint, size_t i_alignment) noexcept
Definition: density_common.h:297
void aligned_deallocate(void *i_block, size_t i_size, size_t i_alignment, size_t i_alignment_offset=0) noexcept
Definition: density_common.h:564
function_type_erasure
Definition: density_common.h:97
consistency_model
Definition: density_common.h:65
#define DENSITY_ASSUME(bool_expr,...)
Definition: density_config.h:46
bool uint_is_aligned(UINT i_uint, UINT i_alignment) noexcept
Definition: density_common.h:128