Allocator.hpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. /***************************************************************************
  2. *
  3. * Project _____ __ ____ _ _
  4. * ( _ ) /__\ (_ _)_| |_ _| |_
  5. * )(_)( /(__)\ )( (_ _)(_ _)
  6. * (_____)(__)(__)(__) |_| |_|
  7. *
  8. *
  9. * Copyright 2018-present, Leonid Stryzhevskyi <lganzzzo@gmail.com>
  10. *
  11. * Licensed under the Apache License, Version 2.0 (the "License");
  12. * you may not use this file except in compliance with the License.
  13. * You may obtain a copy of the License at
  14. *
  15. * http://www.apache.org/licenses/LICENSE-2.0
  16. *
  17. * Unless required by applicable law or agreed to in writing, software
  18. * distributed under the License is distributed on an "AS IS" BASIS,
  19. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  20. * See the License for the specific language governing permissions and
  21. * limitations under the License.
  22. *
  23. ***************************************************************************/
  24. #ifndef oatpp_base_memory_Allocator_hpp
  25. #define oatpp_base_memory_Allocator_hpp
  26. #include "./MemoryPool.hpp"
  27. #include <memory>
  28. namespace oatpp { namespace base { namespace memory {
  29. /**
  30. * Pool Information for Pool Allocators.
  31. */
  32. class AllocatorPoolInfo {
  33. public:
  34. /**
  35. * Constructor.
  36. * @param pPoolName - memory pool name.
  37. * @param pPoolChunkSize - memory pool chunk size. For more about chunk size see &id:oatpp::base::memory::MemoryPool::MemoryPool;.
  38. */
  39. AllocatorPoolInfo(const char* pPoolName, v_buff_size pPoolChunkSize);
  40. /**
  41. * Memory pool name.
  42. */
  43. const char* const poolName;
  44. /**
  45. * Memory pool chunk size.
  46. * For more about chunk size see &id:oatpp::base::memory::MemoryPool::MemoryPool;.
  47. */
  48. const v_buff_size poolChunkSize;
  49. };
  50. /**
  51. * Allocator to allocate shared object on &id:oatpp::base::memory::MemoryPool;
  52. * Used to allocate shared_ptr control block and an object in the same memory entry of the pool.
  53. * @tparam T - type of the object to allocate.
  54. */
  55. template<class T>
  56. class PoolSharedObjectAllocator {
  57. public:
  58. typedef T value_type;
  59. public:
  60. const AllocatorPoolInfo& m_poolInfo;
  61. public:
  62. static ThreadDistributedMemoryPool& getPool(const AllocatorPoolInfo& info){
  63. static auto pool = new ThreadDistributedMemoryPool(info.poolName, sizeof(T), info.poolChunkSize);
  64. return *pool;
  65. }
  66. public:
  67. PoolSharedObjectAllocator(const AllocatorPoolInfo& info)
  68. : m_poolInfo(info)
  69. {};
  70. template<typename U>
  71. PoolSharedObjectAllocator(const PoolSharedObjectAllocator<U>& other)
  72. : m_poolInfo(other.m_poolInfo)
  73. {}
  74. T* allocate(std::size_t n) {
  75. (void)n;
  76. return static_cast<T*>(getPool(m_poolInfo).obtain());
  77. }
  78. void deallocate(T* ptr, size_t n) {
  79. (void)n;
  80. oatpp::base::memory::MemoryPool::free(ptr);
  81. }
  82. };
  83. template <typename T, typename U>
  84. inline bool operator == (const PoolSharedObjectAllocator<T>&, const PoolSharedObjectAllocator<U>&) {
  85. return true;
  86. }
  87. template <typename T, typename U>
  88. inline bool operator != (const PoolSharedObjectAllocator<T>& a, const PoolSharedObjectAllocator<U>& b) {
  89. return !(a == b);
  90. }
  91. /**
  92. * Same as &l:PoolSharedObjectAllocator; but uses `thread_local` &id:oatpp::base::memory::MemoryPool;. <br>
  93. * *If built with OATPP_COMPAT_BUILD_NO_THREAD_LOCAL flag - same as &l:PoolSharedObjectAllocator;.*
  94. * @tparam T - type of the object to allocate.
  95. */
  96. template<class T>
  97. class ThreadLocalPoolSharedObjectAllocator {
  98. public:
  99. typedef T value_type;
  100. public:
  101. const AllocatorPoolInfo& m_poolInfo;
  102. public:
  103. static oatpp::base::memory::MemoryPool& getPool(const AllocatorPoolInfo& info){
  104. #ifndef OATPP_COMPAT_BUILD_NO_THREAD_LOCAL
  105. static thread_local oatpp::base::memory::MemoryPool pool(info.poolName, sizeof(T), info.poolChunkSize);
  106. return pool;
  107. #else
  108. static auto pool = new MemoryPool(info.poolName, sizeof(T), info.poolChunkSize);
  109. return *pool;
  110. #endif
  111. }
  112. public:
  113. ThreadLocalPoolSharedObjectAllocator(const AllocatorPoolInfo& info)
  114. : m_poolInfo(info)
  115. {};
  116. template<typename U>
  117. ThreadLocalPoolSharedObjectAllocator(const ThreadLocalPoolSharedObjectAllocator<U>& other)
  118. : m_poolInfo(other.m_poolInfo)
  119. {}
  120. T* allocate(std::size_t n) {
  121. (void)n;
  122. return static_cast<T*>(getPool(m_poolInfo).obtain());
  123. }
  124. void deallocate(T* ptr, size_t n) {
  125. (void)n;
  126. oatpp::base::memory::MemoryPool::free(ptr);
  127. }
  128. };
  129. template <typename T, typename U>
  130. inline bool operator == (const ThreadLocalPoolSharedObjectAllocator<T>&, const ThreadLocalPoolSharedObjectAllocator<U>&) {
  131. return true;
  132. }
  133. template <typename T, typename U>
  134. inline bool operator != (const ThreadLocalPoolSharedObjectAllocator<T>& a, const ThreadLocalPoolSharedObjectAllocator<U>& b) {
  135. return !(a == b);
  136. }
  137. /**
  138. * Extra information for, and about allocation.
  139. * Used for variable-size objects allocations. (ex.: for strings).
  140. */
  141. class AllocationExtras {
  142. public:
  143. AllocationExtras(v_buff_size pExtraWanted)
  144. : extraWanted(pExtraWanted)
  145. {}
  146. const v_buff_size extraWanted;
  147. void* extraPtr;
  148. v_buff_size baseSize;
  149. };
  150. /**
  151. * Allocator for shared objects.
  152. * Used to allocate object and shared_ptr's control block in the same memory entry.
  153. * @tparam T - type of the object to allocate.
  154. */
  155. template<class T>
  156. class SharedObjectAllocator {
  157. public:
  158. typedef T value_type;
  159. public:
  160. AllocationExtras& m_info;
  161. public:
  162. SharedObjectAllocator(AllocationExtras& info)
  163. : m_info(info)
  164. {};
  165. template<typename U>
  166. SharedObjectAllocator(const SharedObjectAllocator<U>& other)
  167. : m_info(other.m_info)
  168. {}
  169. T* allocate(std::size_t n) {
  170. (void)n;
  171. void* mem = ::operator new(sizeof(T) + m_info.extraWanted);
  172. m_info.baseSize = sizeof(T);
  173. m_info.extraPtr = &((p_char8) mem)[sizeof(T)];
  174. return static_cast<T*>(mem);
  175. }
  176. void deallocate(T* ptr, size_t n) {
  177. (void)n;
  178. ::operator delete(ptr);
  179. }
  180. };
  181. /**
  182. * Allocator for shared objects. Allocates objects on the pool provided.
  183. * @tparam T - type of object to allocate.
  184. * @tparam P - type of memory pool to allocate object on.
  185. */
  186. template<class T, class P>
  187. class CustomPoolSharedObjectAllocator {
  188. public:
  189. typedef T value_type;
  190. public:
  191. AllocationExtras& m_info;
  192. P& m_pool;
  193. public:
  194. CustomPoolSharedObjectAllocator(AllocationExtras& info, P& pool)
  195. : m_info(info)
  196. , m_pool(pool)
  197. {};
  198. template<typename U>
  199. CustomPoolSharedObjectAllocator(const CustomPoolSharedObjectAllocator<U, P>& other)
  200. : m_info(other.m_info)
  201. , m_pool(other.m_pool)
  202. {}
  203. T* allocate(std::size_t n) {
  204. (void)n;
  205. void* mem = m_pool.obtain();
  206. m_info.baseSize = sizeof(T);
  207. m_info.extraPtr = &((p_char8) mem)[sizeof(T)];
  208. return static_cast<T*>(mem);
  209. }
  210. void deallocate(T* ptr, size_t n) {
  211. (void)n;
  212. oatpp::base::memory::MemoryPool::free(ptr);
  213. }
  214. };
  215. template <typename T, typename U>
  216. inline bool operator == (const SharedObjectAllocator<T>&, const SharedObjectAllocator<U>&) {
  217. return true;
  218. }
  219. template <typename T, typename U>
  220. inline bool operator != (const SharedObjectAllocator<T>& a, const SharedObjectAllocator<U>& b) {
  221. return !(a == b);
  222. }
  223. template<typename T, typename ... Args>
  224. static std::shared_ptr<T> allocateSharedWithExtras(AllocationExtras& extras, Args... args){
  225. typedef SharedObjectAllocator<T> _Allocator;
  226. _Allocator allocator(extras);
  227. return std::allocate_shared<T, _Allocator>(allocator, args...);
  228. }
  229. template<typename T, typename P, typename ... Args>
  230. static std::shared_ptr<T> customPoolAllocateSharedWithExtras(AllocationExtras& extras, P& pool, Args... args){
  231. typedef CustomPoolSharedObjectAllocator<T, P> _Allocator;
  232. _Allocator allocator(extras, pool);
  233. return std::allocate_shared<T, _Allocator>(allocator, args...);
  234. }
  235. }}}
  236. #endif /* oatpp_base_memory_Allocator_hpp */