Line data Source code
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 <immer/config.hpp> 12 : #include <immer/heap/identity_heap.hpp> 13 : 14 : #include <cassert> 15 : #include <cstddef> 16 : #include <type_traits> 17 : #include <memory> 18 : 19 : namespace immer { 20 : 21 : #if IMMER_ENABLE_DEBUG_SIZE_HEAP 22 : 23 : /*! 24 : * A heap that in debug mode ensures that the sizes for allocation and 25 : * deallocation do match. 26 : */ 27 : template <typename Base> 28 : struct debug_size_heap 29 : { 30 : #if defined(__MINGW32__) && !defined(__MINGW64__) 31 : // There is a bug in MinGW 32bit: 32 : // https://sourceforge.net/p/mingw-w64/bugs/778/ It causes different 33 : // versions of std::max_align_t to be defined, depending on inclusion order 34 : // of stddef.h and stdint.h. As we have no control over the inclusion order 35 : // here (as it might be set in stone by the outside world), we can't easily 36 : // pin it to one of both versions of std::max_align_t. This means, we have 37 : // to hardcode extra_size for MinGW 32bit builds until the mentioned bug is 38 : // fixed. 39 : constexpr static auto extra_size = 8; 40 : #else 41 : constexpr static auto extra_size = sizeof( 42 : std::aligned_storage_t<sizeof(std::size_t), alignof(std::max_align_t)>); 43 : #endif 44 : 45 : template <typename... Tags> 46 66954 : static void* allocate(std::size_t size, Tags... tags) 47 : { 48 66954 : auto p = (std::size_t*) Base::allocate(size + extra_size, tags...); 49 30239 : new (p) std::size_t{size}; 50 30239 : return ((char*) p) + extra_size; 51 : } 52 : 53 : template <typename... Tags> 54 65790 : static void deallocate(std::size_t size, void* data, Tags... tags) 55 : { 56 65790 : auto p = (std::size_t*) (((char*) data) - extra_size); 57 65790 : assert(*p == size); 58 65790 : Base::deallocate(size + extra_size, p, tags...); 59 65790 : } 60 : }; 61 : 62 : #else // IMMER_ENABLE_DEBUG_SIZE_HEAP 63 : 64 : template <typename Base> 65 : using debug_size_heap = identity_heap<Base>; 66 : 67 : #endif // !IMMER_ENABLE_DEBUG_SIZE_HEAP 68 : 69 : } // namespace immer