ObjectPool.hpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  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_ObjectPool_hpp
  25. #define oatpp_base_memory_ObjectPool_hpp
  26. #include "./Allocator.hpp"
  27. #include "./MemoryPool.hpp"
  28. namespace oatpp { namespace base { namespace memory {
  29. /**
  30. * Macro to declare object pool class which uses &id:oatpp::base::memory::PoolSharedObjectAllocator; to allocate objects.
  31. * @param NAME - name of the memory pool.
  32. * @param TYPE - type of the object.
  33. * @param CHUNK_SIZE - chunk size for &id:oatpp::base::memory::MemoryPool;.
  34. */
  35. #define SHARED_OBJECT_POOL(NAME, TYPE, CHUNK_SIZE) \
  36. class NAME { \
  37. public: \
  38. typedef TYPE ObjectType; \
  39. typedef oatpp::base::memory::PoolSharedObjectAllocator<TYPE> Allocator; \
  40. public: \
  41. \
  42. static const oatpp::base::memory::AllocatorPoolInfo& getPoolInfo(){ \
  43. static oatpp::base::memory::AllocatorPoolInfo info(#NAME"<"#TYPE">", CHUNK_SIZE); \
  44. return info; \
  45. } \
  46. \
  47. static Allocator& getAllocator (){ \
  48. static Allocator allocator(getPoolInfo()); \
  49. return allocator; \
  50. } \
  51. \
  52. template<typename ... Args> \
  53. static std::shared_ptr<TYPE> allocateShared(Args... args){ \
  54. return std::allocate_shared<TYPE, Allocator>(getAllocator(), args...); \
  55. } \
  56. \
  57. };
  58. /**
  59. * Macro to declare object pool class which uses &id:oatpp::base::memory::ThreadLocalPoolSharedObjectAllocator; to allocate objects.
  60. * @param NAME - name of the memory pool.
  61. * @param TYPE - type of the object.
  62. * @param CHUNK_SIZE - chunk size for &id:oatpp::base::memory::MemoryPool;.
  63. */
  64. #define SHARED_OBJECT_POOL_THREAD_LOCAL(NAME, TYPE, CHUNK_SIZE) \
  65. class NAME { \
  66. public: \
  67. typedef TYPE ObjectType; \
  68. typedef oatpp::base::memory::ThreadLocalPoolSharedObjectAllocator<TYPE> Allocator; \
  69. public: \
  70. \
  71. static const oatpp::base::memory::AllocatorPoolInfo& getPoolInfo(){ \
  72. static oatpp::base::memory::AllocatorPoolInfo info(#NAME"<"#TYPE">", CHUNK_SIZE); \
  73. return info; \
  74. } \
  75. \
  76. static Allocator& getAllocator (){ \
  77. static Allocator allocator(getPoolInfo()); \
  78. return allocator; \
  79. } \
  80. \
  81. template<typename ... Args> \
  82. static std::shared_ptr<TYPE> allocateShared(Args... args){ \
  83. return std::allocate_shared<TYPE, Allocator>(getAllocator(), args...); \
  84. } \
  85. \
  86. };
  87. /**
  88. * Macro to declare: &id:oatpp::base::memory::MemoryPool; for object, plus class-specific operators
  89. * `static void* operator new(std::size_t sz)`, `static void operator delete(void* ptr, std::size_t sz)`,
  90. * `static void* operator new(std::size_t sz, void* entry)`, `static void operator delete(void* ptr, void* entry)`.
  91. * @param NAME - name of the memory pool.
  92. * @param TYPE - type of the object.
  93. * @param CHUNK_SIZE - chunk size for &id:oatpp::base::memory::MemoryPool;.
  94. */
  95. #define OBJECT_POOL(POOL_NAME, TYPE, CHUNK_SIZE) \
  96. class POOL_NAME { \
  97. public: \
  98. \
  99. static oatpp::base::memory::ThreadDistributedMemoryPool& getPool(){ \
  100. static auto pool = new oatpp::base::memory::ThreadDistributedMemoryPool(#POOL_NAME"<"#TYPE">", sizeof(TYPE), CHUNK_SIZE); \
  101. return *pool; \
  102. } \
  103. \
  104. }; \
  105. \
  106. static void* operator new(std::size_t sz) { \
  107. if(sz != sizeof(TYPE)){ \
  108. throw std::runtime_error("wrong object size"); \
  109. } \
  110. static auto& pool = POOL_NAME::getPool(); \
  111. return pool.obtain(); \
  112. } \
  113. \
  114. static void operator delete(void* ptr, std::size_t sz) { \
  115. if(sz != sizeof(TYPE)){ \
  116. oatpp::base::Environment::log(2, #POOL_NAME, "[ERROR|CRITICAL]: MemoryPool malfunction. Deleting object of wrong size"); \
  117. } \
  118. oatpp::base::memory::MemoryPool::free(ptr); \
  119. } \
  120. \
  121. static void* operator new(std::size_t sz, void* entry) { \
  122. if(sz != sizeof(TYPE)){ \
  123. throw std::runtime_error("wrong object size"); \
  124. } \
  125. return entry; \
  126. } \
  127. \
  128. static void operator delete(void* ptr, void* entry) { \
  129. (void)ptr; \
  130. (void)entry; \
  131. }
  132. #ifndef OATPP_COMPAT_BUILD_NO_THREAD_LOCAL
  133. /**
  134. * Macro to declare: `thread_local` &id:oatpp::base::memory::MemoryPool; for object, plus class-specific operators <br>
  135. * `static void* operator new(std::size_t sz)`, `static void operator delete(void* ptr, std::size_t sz)`, <br>
  136. * `static void* operator new(std::size_t sz, void* entry)`, `static void operator delete(void* ptr, void* entry)`. <br>
  137. * *Memory pool is NOT `thread_local` if built with `-DOATPP_COMPAT_BUILD_NO_THREAD_LOCAL` flag*
  138. * @param NAME - name of the memory pool.
  139. * @param TYPE - type of the object.
  140. * @param CHUNK_SIZE - chunk size for &id:oatpp::base::memory::MemoryPool;.
  141. */
  142. #define OBJECT_POOL_THREAD_LOCAL(POOL_NAME, TYPE, CHUNK_SIZE) \
  143. class POOL_NAME { \
  144. public: \
  145. \
  146. static oatpp::base::memory::MemoryPool& getPool(){ \
  147. static thread_local oatpp::base::memory::MemoryPool pool(#POOL_NAME"<"#TYPE">", sizeof(TYPE), CHUNK_SIZE); \
  148. return pool; \
  149. } \
  150. \
  151. }; \
  152. \
  153. static void* operator new(std::size_t sz) { \
  154. if(sz != sizeof(TYPE)){ \
  155. throw std::runtime_error("wrong object size"); \
  156. } \
  157. static thread_local auto& pool = POOL_NAME::getPool(); \
  158. return pool.obtain(); \
  159. } \
  160. \
  161. static void operator delete(void* ptr, std::size_t sz) { \
  162. if(sz != sizeof(TYPE)){ \
  163. oatpp::base::Environment::log(2, #POOL_NAME, "[ERROR|CRITICAL]: MemoryPool malfunction. Deleting object of wrong size"); \
  164. } \
  165. oatpp::base::memory::MemoryPool::free(ptr); \
  166. } \
  167. \
  168. static void* operator new(std::size_t sz, void* entry) { \
  169. if(sz != sizeof(TYPE)){ \
  170. throw std::runtime_error("wrong object size"); \
  171. } \
  172. return entry; \
  173. } \
  174. \
  175. static void operator delete(void* ptr, void* entry) { \
  176. (void)ptr; \
  177. (void)entry; \
  178. }
  179. #else
  180. #define OBJECT_POOL_THREAD_LOCAL(POOL_NAME, TYPE, CHUNK_SIZE) \
  181. class POOL_NAME { \
  182. public: \
  183. \
  184. static oatpp::base::memory::MemoryPool& getPool(){ \
  185. static auto pool = new oatpp::base::memory::MemoryPool(#POOL_NAME"<"#TYPE">", sizeof(TYPE), CHUNK_SIZE); \
  186. return *pool; \
  187. } \
  188. \
  189. };
  190. #endif
  191. }}}
  192. #endif /* oatpp_base_memory_ObjectPool_hpp */