density
C++11 library for paged memory management, function queues, heterogeneous queues and lifo memory management
density_config.h
Go to the documentation of this file.
1 
2 // Copyright Giuseppe Campana (giu.campana@gmail.com) 2016-2018.
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 
7 #pragma once
8 #include <cstdlib>
9 #include <type_traits>
10 #include <utility>
11 
15 #if !defined(DENSITY_ASSERT)
16 #if defined(DENSITY_DEBUG)
17 #define DENSITY_ASSERT DENSITY_CHECKING_ASSERT
18 #else
19 #define DENSITY_ASSERT(...) ((void)(0))
20 #endif
21 #endif
22 
24 #if !defined(DENSITY_ASSERT_INTERNAL)
25 #if defined(DENSITY_DEBUG_INTERNAL)
26 #define DENSITY_ASSERT_INTERNAL DENSITY_CHECKING_ASSERT
27 #else
28 #define DENSITY_ASSERT_INTERNAL(...) ((void)(0))
29 #endif
30 #endif
31 
33 #if defined(DENSITY_DEBUG)
34 #define DENSITY_ASSUME DENSITY_CHECKING_ASSERT
35 #else
36 #if defined(__clang__)
37 #define DENSITY_ASSUME(bool_expr, ...) \
38  _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wassume\"") \
39  __builtin_assume((bool_expr)) _Pragma("clang diagnostic pop")
40 #elif defined(_MSC_VER)
41 #define DENSITY_ASSUME(bool_expr, ...) __assume((bool_expr))
42 #elif defined(__GNUC__)
43 // https://stackoverflow.com/questions/25667901/assume-clause-in-gcc
44 #define DENSITY_ASSUME(bool_expr, ...) (!(bool_expr) ? __builtin_unreachable() : (void)0)
45 #else
46 #define DENSITY_ASSUME(bool_expr, ...) (void)0
47 #endif
48 #endif
49 
51 #if defined(DENSITY_DEBUG)
52 #define DENSITY_ASSUME_ALIGNED(address, constexpr_alignment) \
53  DENSITY_ASSERT(::density::address_is_aligned( \
54  (address), ::density::detail::ConstSizeT<(constexpr_alignment)>::value))
55 #elif defined(__GNUC__)
56 #define DENSITY_ASSUME_ALIGNED(address, constexpr_alignment) \
57  __builtin_assume_aligned(address, constexpr_alignment)
58 #else
59 #define DENSITY_ASSUME_ALIGNED(address, constexpr_alignment) \
60  DENSITY_ASSUME((uintptr_t(address) & ((constexpr_alignment)-1)) == 0)
61 #endif
62 
63 #if defined(DENSITY_DEBUG)
64 #define DENSITY_ASSUME_UINT_ALIGNED(address, constexpr_alignment) \
65  DENSITY_ASSERT(::density::uint_is_aligned( \
66  (address), ::density::detail::ConstSizeT<(constexpr_alignment)>::value))
67 #else
68 #define DENSITY_ASSUME_UINT_ALIGNED(address, constexpr_alignment) \
69  DENSITY_ASSUME(((address) & ((constexpr_alignment)-1)) == 0)
70 #endif
71 
73 #if defined(__GNUC__) && !defined(_MSC_VER)
74 #define DENSITY_LIKELY(bool_expr) (__builtin_expect((bool_expr), true), (bool_expr))
75 #else
76 #define DENSITY_LIKELY(bool_expr) (bool_expr)
77 #endif
78 
81 #ifdef _MSC_VER
82 #define DENSITY_NO_INLINE __declspec(noinline)
83 #elif defined(__GNUC__)
84 #define DENSITY_NO_INLINE __attribute__((noinline))
85 #else
86 #define DENSITY_NO_INLINE
87 #endif
88 
90 #ifdef _MSC_VER
91 #define DENSITY_CHECKING_ASSERT(bool_expr, ...) (!(bool_expr) ? __debugbreak() : (void)0)
92 #elif defined(__GNUC__)
93 #define DENSITY_CHECKING_ASSERT(bool_expr, ...) (!(bool_expr) ? __builtin_trap() : (void)0)
94 #else
95 #define DENSITY_CHECKING_ASSERT(bool_expr, ...) (!(bool_expr) ? std::abort() : (void)0)
96 #endif
97 
98 namespace density
99 {
106  constexpr size_t destructive_interference_size = 64;
107 
112  constexpr size_t default_page_capacity = 1024 * 64;
113 
118  constexpr bool enable_relaxed_atomics = false;
119 
120  template <size_t PAGE_CAPACITY_AND_ALIGNMENT> class basic_default_allocator;
121 
125 
127 #ifdef DENSITY_USER_DATA_STACK
128  namespace user_data_stack
129  {
130  constexpr size_t alignment = alignof(void *);
131 
132  void * allocate(size_t i_size);
133 
134  void * allocate_empty() noexcept;
135 
136  void * reallocate(void * i_block, size_t i_old_size, size_t i_new_size);
137 
138  void deallocate(void * i_block, size_t i_size) noexcept;
139  } // namespace user_data_stack
140 #endif
141 
142  /* Very minimal implementation of std::optional, that can be used as target for density::optional. */
143  template <typename TYPE> class builtin_optional
144  {
145  public:
146  builtin_optional() noexcept = default;
147 
148  template <typename OTHER_TYPE> builtin_optional(OTHER_TYPE && i_value) : m_has_value(true)
149  {
150  new (&m_storage) TYPE(std::forward<OTHER_TYPE>(i_value));
151  }
152 
153  builtin_optional(const builtin_optional & i_source) : m_has_value(i_source.m_has_value)
154  {
155  if (m_has_value)
156  {
157  new (&m_storage) TYPE(*i_source.ptr());
158  }
159  }
160 
161  builtin_optional(builtin_optional && i_source) : m_has_value(i_source.m_has_value)
162  {
163  if (m_has_value)
164  new (&m_storage) TYPE(std::move(*i_source.ptr()));
165  }
166 
167  builtin_optional & operator=(const builtin_optional & i_source)
168  {
169  swap(*this, builtin_optional(i_source));
170  }
171 
172  builtin_optional & operator=(builtin_optional && i_source) noexcept
173  {
174  swap(*this, i_source);
175  }
176 
177  TYPE * operator->() const noexcept { return ptr(); }
178  TYPE & operator*() noexcept { return *ptr(); }
179  const TYPE & operator*() const noexcept { return *ptr(); }
180 
181  explicit operator bool() const noexcept { return m_has_value; }
182 
183  ~builtin_optional()
184  {
185  if (m_has_value)
186  ptr()->TYPE::~TYPE();
187  }
188 
189  friend void swap(builtin_optional & i_first, builtin_optional & i_second) noexcept
190  {
191  using std::swap;
192  swap(i_first.m_has_value, i_second.m_has_value);
193  if (i_first.m_has_value && i_second.m_has_value)
194  {
195  swap(*i_first.ptr(), *i_second.ptr());
196  }
197  else if (i_first.m_has_value)
198  {
199  new (i_first.ptr()) TYPE(std::move(*i_second.ptr()));
200  }
201  else if (i_second.m_has_value)
202  {
203  new (i_second.ptr()) TYPE(std::move(*i_first.ptr()));
204  }
205  }
206 
207  private:
208  TYPE * ptr() noexcept { return reinterpret_cast<TYPE *>(&m_storage); }
209  const TYPE * ptr() const noexcept { return reinterpret_cast<const TYPE *>(&m_storage); }
210 
211  private:
212  typename std::aligned_storage<sizeof(TYPE), alignof(TYPE)>::type m_storage;
213  bool m_has_value = false;
214  };
215 
218  template <typename TYPE> using optional = builtin_optional<TYPE>;
219 
220  namespace detail
221  {
222  template <size_t VALUE> struct ConstSizeT
223  {
224  constexpr static size_t value = VALUE;
225  };
226  } // namespace detail
227 
228 } // namespace density
constexpr size_t default_page_capacity
Definition: density_config.h:112
constexpr bool enable_relaxed_atomics
Definition: density_config.h:118
Definition: conc_function_queue.h:11
Definition: default_allocator.h:149
builtin_optional< TYPE > optional
Definition: density_config.h:218
constexpr size_t destructive_interference_size
Definition: density_config.h:106