siplasplas
A library for C++ reflection and introspection
deadpool.hpp
1 #ifndef SIPLASPLAS_TYPEERASURE_ANYSTORAGE_DEADPOOL_HPP
2 #define SIPLASPLAS_TYPEERASURE_ANYSTORAGE_DEADPOOL_HPP
3 
4 #include <siplasplas/utility/memory_manip.hpp>
5 #include <siplasplas/typeerasure/typeinfo.hpp>
6 #include <type_traits>
7 
8 namespace cpp
9 {
10 
24 template<std::size_t PreallocatedSize, std::size_t PreallocatedAlignment = alignof(std::uint8_t)>
26 {
27 public:
28  static_assert(PreallocatedSize >= sizeof(void*),
29  "At least sizeof(void*) bytes of preallocated storage is needed");
30 
31  void* storage(cpp::typeerasure::TypeInfo typeInfo) const
32  {
33  if(dynamicAllocStorage() &&
34  _dynamicAllocStorageSize == typeInfo.sizeOf() &&
35  cpp::detail::is_aligned(dynamicAllocStoragePointer(), typeInfo.alignment()))
36  {
37  return dynamicAllocStoragePointer();
38  }
39  else
40  {
41  if(dynamicAllocStorage())
42  {
43  cpp::detail::aligned_free(dynamicAllocStoragePointer());
44  }
45 
46  char* storagePtr = reinterpret_cast<char*>(&_preallocatedStorage);
47  char* alignedPointerToFixedStorage = cpp::detail::aligned_ptr(
48  storagePtr,
49  typeInfo.alignment()
50  );
51 
52  if(alignedPointerToFixedStorage + typeInfo.sizeOf() <= storagePtr + PreallocatedSize)
53  {
54  _dynamicAllocStorageSize = 0;
55  return alignedPointerToFixedStorage;
56  }
57  else
58  {
59  dynamicAllocStoragePointer(
60  cpp::detail::aligned_malloc(typeInfo.sizeOf(), typeInfo.alignment())
61  );
62 
63  _dynamicAllocStorageSize = typeInfo.sizeOf();
64 
65  return dynamicAllocStoragePointer();
66  }
67  }
68  }
69 
70  template<typename T>
71  constexpr bool objectFitsInStorage() const
72  {
73  return true;
74  }
75 
77  {
78  if(dynamicAllocStorage())
79  {
80  cpp::detail::aligned_free(dynamicAllocStoragePointer());
81  }
82  }
83 
84  std::size_t dynamicAllocStorageSize() const
85  {
86  return _dynamicAllocStorageSize;
87  }
88 
89 private:
90  mutable std::size_t _dynamicAllocStorageSize = 0;
91  mutable std::aligned_storage_t<PreallocatedSize, PreallocatedAlignment> _preallocatedStorage;
92 
93  bool dynamicAllocStorage() const
94  {
95  return _dynamicAllocStorageSize > 0;
96  }
97 
98  void* dynamicAllocStoragePointer() const
99  {
100  return cpp::detail::read_at<void*>(&_preallocatedStorage);
101  }
102 
103  void dynamicAllocStoragePointer(void* pointer) const
104  {
105  cpp::detail::write_at(&_preallocatedStorage, pointer);
106  }
107 };
108 
109 }
110 
111 #endif // SIPLASPLAS_TYPEERASURE_ANYSTORAGE_DEADPOOL_HPP
SIPLASPLAS_UTILITY_EXPORT void * aligned_malloc(std::size_t size, std::size_t alignment, std::size_t offset=0)
Allocates a block of memory of memory aligned to an specific boundary.
Definition: canary_allocator.hpp:7
SIPLASPLAS_UTILITY_EXPORT char * aligned_ptr(char *pointer, std::size_t alignment)
Returns an address aligned to an specific boundary.
std::size_t alignment() const
returns the alignment of the type
Definition: typeinfo.hpp:260
Implements fixed-size with fallback to dynamic allocation.
Definition: deadpool.hpp:25
Contains minimal information to execute the value semantics operations of a type. ...
Definition: typeinfo.hpp:108
std::size_t sizeOf() const
Returns the size of the type.
Definition: typeinfo.hpp:126
SIPLASPLAS_UTILITY_EXPORT bool is_aligned(char *pointer, std::size_t alignment)
Checks if an address is aligned to a given boundary.
SIPLASPLAS_UTILITY_EXPORT void aligned_free(void *pointer, std::size_t offset=0)
Deallocates a block allocated by cpp::aligned_malloc()