1//
2// immer: immutable data structures for C++
3// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
4//
5// This software is distributed under the Boost Software License, Version 1.0.
6// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
7//
8
9#pragma once
10
11#include <cassert>
12#include <cstddef>
13#include <immer/config.hpp>
14#include <immer/heap/identity_heap.hpp>
15
16namespace immer {
17
18#if IMMER_ENABLE_DEBUG_SIZE_HEAP
19
20/*!
21 * A heap that in debug mode ensures that the sizes for allocation and
22 * deallocation do match.
23 */
24template <typename Base>
25struct debug_size_heap
26{
27#if defined(__MINGW32__) && !defined(__MINGW64__)
28 // There is a bug in MinGW 32bit: https://sourceforge.net/p/mingw-w64/bugs/778/
29 // It causes different versions of std::max_align_t to be defined, depending on inclusion order of stddef.h
30 // and stdint.h. As we have no control over the inclusion order here (as it might be set in stone by the outside
31 // world), we can't easily pin it to one of both versions of std::max_align_t. This means, we have to hardcode
32 // extra_size for MinGW 32bit builds until the mentioned bug is fixed.
33 constexpr static auto extra_size = 8;
34#else
35 constexpr static auto extra_size = sizeof(
36 std::aligned_storage_t<sizeof(std::size_t),
37 alignof(std::max_align_t)>);
38#endif
39
40 template <typename... Tags>
41 static void* allocate(std::size_t size, Tags... tags)
42 {
43 auto p = (std::size_t*) Base::allocate(size + extra_size, tags...);
44 new (p) std::size_t{ size };
45 return ((char*)p) + extra_size;
46 }
47
48 template <typename... Tags>
49 static void deallocate(std::size_t size, void* data, Tags... tags)
50 {
51 auto p = (std::size_t*) (((char*) data) - extra_size);
52 assert(*p == size);
53 Base::deallocate(size + extra_size, p, tags...);
54 }
55};
56
57#else // IMMER_ENABLE_DEBUG_SIZE_HEAP
58
59template <typename Base>
60using debug_size_heap = identity_heap<Base>;
61
62#endif // !IMMER_ENABLE_DEBUG_SIZE_HEAP
63
64} // namespace immer
65