3 #include "../utility/assert.h"
4 #include "../utility/empty_base.h"
5 #include "../utility/meta.h"
12 #include <type_traits>
16 template<
typename Alloc,
typename Stream>
20 static_assert(detail::has_no_value_type_v<Alloc>,
"Building on top of typed allocators is not allowed. Use allocators without a type");
26 static constexpr
unsigned int OVERFLOW_PATTERN = 0b10100101101001011010010110100101;
27 static constexpr
unsigned char OVERFLOW_TEST = 0b10100101;
28 static constexpr
size_t OVERFLOW_SIZE = 64;
36 noexcept(std::is_nothrow_default_constructible_v<Alloc>) :
45 template<
typename... Args,
46 typename = std::enable_if_t<
47 std::is_constructible_v<Alloc, Args...>>>
48 explicit overflow(Stream& stream, Args&&... args)
49 noexcept(std::is_nothrow_constructible_v<Alloc, Args...>) :
51 m_Alloc(std::forward<Args>(args)...),
63 m_Stream <<
"--------MEMORY LEAK DETECTED--------\nAllocator destroyed while having:\n";
65 m_Stream <<
" Allocated memory (" << m_Allocs <<
" bytes)\n";
67 m_Stream <<
" Too many frees (" << -m_Allocs <<
" bytes)\n";
70 if (m_Constructs != 0)
72 m_Stream <<
"--------POSSIBLE LOGIC ERROR DETECTED--------\nAllocator destroyed while having:\n";
74 m_Stream <<
" Too many constructor calls (" << m_Constructs <<
")\n";
76 m_Stream <<
" Too many destructor calls (" << -m_Constructs <<
")\n";
85 noexcept(detail::has_nothrow_equal_v<Alloc>)
87 return m_Alloc == rhs.m_Alloc;
91 noexcept(detail::has_nothrow_not_equal_v<Alloc>)
93 return m_Alloc != rhs.m_Alloc;
96 #pragma region Allocation
105 noexcept(detail::has_nothrow_allocate_v<Alloc>)
110 char* ptr =
reinterpret_cast<char*
>(m_Alloc.allocate(size));
115 std::memset(ptr, OVERFLOW_PATTERN, OVERFLOW_SIZE);
116 std::memset(ptr + OVERFLOW_SIZE + n, OVERFLOW_PATTERN, OVERFLOW_SIZE);
118 return ptr + OVERFLOW_SIZE;
127 noexcept(detail::has_nothrow_deallocate_v<Alloc>)
135 unsigned char* ptr =
reinterpret_cast<unsigned char*
>(p);
141 for (
unsigned char* i = ptr - 1; i >= ptr - OVERFLOW_SIZE; i--)
143 if (*i != OVERFLOW_TEST)
147 for (
unsigned char* i = ptr + n; i < ptr + n + OVERFLOW_SIZE; i++)
149 if (*i != OVERFLOW_TEST)
150 after = i - ptr - n + 1;
155 m_Stream <<
"--------MEMORY CORRUPTION DETECTED--------\nThe area around " << p <<
" (" << n <<
" bytes) has been illegally modified\n";
158 m_Stream <<
" Before (" << before <<
" bytes)\n";
161 m_Stream <<
" After (" << after <<
" bytes)\n";
165 m_Alloc.deallocate(ptr - OVERFLOW_SIZE, size);
170 #pragma region Construction
178 template<
typename T,
typename... Args>
180 (detail::has_construct_v<Alloc, T*, Args...> && detail::has_nothrow_construct_v<Alloc, T*, Args...>) ||
181 std::is_nothrow_constructible_v<T, Args...>)
185 if constexpr (detail::has_construct_v<Alloc, T*, Args...>)
186 m_Alloc.construct(p, std::forward<Args>(args)...);
188 ::new(p) T(std::forward<Args>(args)...);
198 (detail::has_destroy_v<Alloc, T*>&& detail::has_nothrow_destroy_v<Alloc, T*>) ||
199 std::is_nothrow_destructible_v<T>)
203 if constexpr (detail::has_destroy_v<Alloc, T*>)
210 #pragma region Utility
216 template<
typename A = Alloc>
217 typename std::enable_if<detail::has_max_size_v<A>,
size_type>::type
221 return m_Alloc.max_size();
230 template<
typename A = Alloc>
231 typename std::enable_if<detail::has_owns_v<A>,
bool>::type
233 noexcept(detail::has_nothrow_owns_v<A>)
235 return m_Alloc.owns(p);
279 int64_t m_Constructs;
#define KTL_ASSERT(x)
Definition: assert.h:17
Definition: overflow.h:18
const Alloc & get_allocator() const noexcept
Returns a const reference to the underlying allocator.
Definition: overflow.h:252
void * allocate(size_type n) noexcept(detail::has_nothrow_allocate_v< Alloc >)
Attempts to allocate a chunk of memory defined by n.
Definition: overflow.h:104
void construct(T *p, Args &&... args) noexcept((detail::has_construct_v< Alloc, T *, Args... > &&detail::has_nothrow_construct_v< Alloc, T *, Args... >)||std::is_nothrow_constructible_v< T, Args... >)
Constructs an object of T with the given ...args at the given location.
Definition: overflow.h:179
~overflow()
Definition: overflow.h:59
void destroy(T *p) noexcept((detail::has_destroy_v< Alloc, T * > &&detail::has_nothrow_destroy_v< Alloc, T * >)||std::is_nothrow_destructible_v< T >)
Destructs an object of T at the given location.
Definition: overflow.h:197
Alloc & get_allocator() noexcept
Returns a reference to the underlying allocator.
Definition: overflow.h:243
std::enable_if< detail::has_owns_v< A >, bool >::type owns(void *p) const noexcept(detail::has_nothrow_owns_v< A >)
Returns whether or not the allocator owns the given location in memory.
Definition: overflow.h:232
overflow(const overflow &)=default
detail::get_size_type_t< Alloc > size_type
Definition: overflow.h:20
std::enable_if< detail::has_max_size_v< A >, size_type >::type max_size() const noexcept(detail::has_nothrow_max_size_v< A >)
Returns the maximum size that an allocation can be.
Definition: overflow.h:218
overflow & operator=(overflow &&)=default
overflow & operator=(const overflow &)=default
bool operator!=(const overflow &rhs) const noexcept(detail::has_nothrow_not_equal_v< Alloc >)
Definition: overflow.h:90
Stream & get_stream() noexcept
Return a reference to the stream that will be used when leaks or corruption occur.
Definition: overflow.h:261
overflow(Stream &stream, Args &&... args) noexcept(std::is_nothrow_constructible_v< Alloc, Args... >)
Constructor for forwarding any arguments to the underlying allocator.
Definition: overflow.h:48
const Stream & get_stream() const noexcept
Return a const reference to the stream that will be used when leaks or corruption occur.
Definition: overflow.h:270
bool operator==(const overflow &rhs) const noexcept(detail::has_nothrow_equal_v< Alloc >)
Definition: overflow.h:84
void deallocate(void *p, size_type n) noexcept(detail::has_nothrow_deallocate_v< Alloc >)
Attempts to deallocate the memory at location p.
Definition: overflow.h:126
overflow(overflow &&)=default
overflow(Stream &stream) noexcept(std::is_nothrow_default_constructible_v< Alloc >)
Construct the allocator with a reference to a stream object.
Definition: overflow.h:35
#define KTL_EMPTY_BASE
Definition: empty_base.h:6
typename get_size_type< Alloc, void >::type get_size_type_t
Definition: meta.h:31
constexpr bool has_nothrow_max_size_v
Definition: meta.h:122
Definition: cascading.h:15