passenger 6.0.1 → 6.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (453) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +145 -18
  3. data/CONTRIBUTORS +6 -0
  4. data/bin/passenger-install-nginx-module +1 -1
  5. data/bin/passenger-status +15 -0
  6. data/build/misc.rb +3 -1
  7. data/build/support/vendor/cxxcodebuilder/lib/cxxcodebuilder/builder.rb +56 -3
  8. data/dev/copy_boost_headers +1 -0
  9. data/package.json +1 -1
  10. data/passenger.gemspec +9 -1
  11. data/resources/templates/error_renderer/with_details/src/bootstrap/bootstrap.css +0 -0
  12. data/resources/templates/error_renderer/with_details/src/bootstrap/bootstrap.js +0 -0
  13. data/resources/templates/error_renderer/with_details/src/bootstrap/config.json +0 -0
  14. data/resources/templates/standalone/http.erb +2 -0
  15. data/resources/templates/standalone/server.erb +1 -0
  16. data/src/agent/Core/ApplicationPool/Group/ProcessListManagement.cpp +1 -1
  17. data/src/agent/Core/ApplicationPool/Group/StateInspection.cpp +1 -0
  18. data/src/agent/Core/ApplicationPool/Options.h +10 -0
  19. data/src/agent/Core/ApplicationPool/Pool/GarbageCollection.cpp +1 -1
  20. data/src/agent/Core/ApplicationPool/Pool/StateInspection.cpp +1 -1
  21. data/src/agent/Core/Config.h +14 -1
  22. data/src/agent/Core/Controller.h +1 -0
  23. data/src/agent/Core/Controller/Config.h +5 -1
  24. data/src/agent/Core/Controller/ForwardResponse.cpp +13 -0
  25. data/src/agent/Core/Controller/InitRequest.cpp +3 -0
  26. data/src/agent/Core/Controller/InitializationAndShutdown.cpp +1 -0
  27. data/src/agent/Core/CoreMain.cpp +2 -1
  28. data/src/agent/Core/OptionParser.h +3 -0
  29. data/src/agent/Core/SpawningKit/Context.h +1 -0
  30. data/src/agent/Core/SpawningKit/Handshake/Prepare.h +1 -1
  31. data/src/agent/Core/SpawningKit/Handshake/WorkDir.h +5 -2
  32. data/src/agent/TempDirToucher/TempDirToucherMain.cpp +2 -0
  33. data/src/agent/Watchdog/Config.h +15 -1
  34. data/src/agent/Watchdog/WatchdogMain.cpp +7 -0
  35. data/src/apache2_module/ConfigGeneral/AutoGeneratedDefinitions.cpp +10 -0
  36. data/src/apache2_module/ConfigGeneral/AutoGeneratedManifestDefaultsInitialization.cpp +10 -0
  37. data/src/apache2_module/ConfigGeneral/AutoGeneratedSetterFuncs.cpp +30 -0
  38. data/src/apache2_module/Hooks.cpp +6 -0
  39. data/src/apache2_module/ServerConfig/AutoGeneratedManifestGeneration.cpp +20 -0
  40. data/src/apache2_module/ServerConfig/AutoGeneratedStruct.h +24 -0
  41. data/src/cxx_supportlib/Constants.h +2 -1
  42. data/src/cxx_supportlib/LoggingKit/Config.h +2 -0
  43. data/src/cxx_supportlib/LoggingKit/Implementation.cpp +15 -9
  44. data/src/cxx_supportlib/ServerKit/HttpChunkedBodyParser.h +1 -1
  45. data/src/cxx_supportlib/SystemTools/ContainerHelpers.h +20 -19
  46. data/src/cxx_supportlib/WebSocketCommandReverseServer.h +11 -7
  47. data/src/cxx_supportlib/oxt/system_calls.cpp +10 -10
  48. data/src/cxx_supportlib/vendor-modified/boost/algorithm/string/finder.hpp +0 -4
  49. data/src/cxx_supportlib/vendor-modified/boost/asio/buffer.hpp +46 -37
  50. data/src/cxx_supportlib/vendor-modified/boost/asio/connect.hpp +16 -15
  51. data/src/cxx_supportlib/vendor-modified/boost/asio/detail/config.hpp +45 -26
  52. data/src/cxx_supportlib/vendor-modified/boost/asio/detail/future.hpp +33 -0
  53. data/src/cxx_supportlib/vendor-modified/boost/asio/detail/impl/socket_ops.ipp +1 -1
  54. data/src/cxx_supportlib/vendor-modified/boost/asio/detail/is_buffer_sequence.hpp +38 -14
  55. data/src/cxx_supportlib/vendor-modified/boost/asio/detail/timer_queue.hpp +2 -0
  56. data/src/cxx_supportlib/vendor-modified/boost/asio/impl/io_context.hpp +1 -1
  57. data/src/cxx_supportlib/vendor-modified/boost/asio/impl/read_until.hpp +3 -1
  58. data/src/cxx_supportlib/vendor-modified/boost/asio/impl/use_future.hpp +0 -1
  59. data/src/cxx_supportlib/vendor-modified/boost/asio/ip/bad_address_cast.hpp +6 -1
  60. data/src/cxx_supportlib/vendor-modified/boost/asio/ip/basic_resolver.hpp +6 -4
  61. data/src/cxx_supportlib/vendor-modified/boost/asio/ip/basic_resolver_results.hpp +4 -4
  62. data/src/cxx_supportlib/vendor-modified/boost/asio/packaged_task.hpp +3 -3
  63. data/src/cxx_supportlib/vendor-modified/boost/asio/read.hpp +4 -4
  64. data/src/cxx_supportlib/vendor-modified/boost/asio/read_at.hpp +4 -4
  65. data/src/cxx_supportlib/vendor-modified/boost/asio/read_until.hpp +8 -6
  66. data/src/cxx_supportlib/vendor-modified/boost/asio/ssl/context_base.hpp +17 -0
  67. data/src/cxx_supportlib/vendor-modified/boost/asio/ssl/impl/context.ipp +50 -5
  68. data/src/cxx_supportlib/vendor-modified/boost/asio/ssl/stream.hpp +2 -1
  69. data/src/cxx_supportlib/vendor-modified/boost/asio/thread_pool.hpp +1 -1
  70. data/src/cxx_supportlib/vendor-modified/boost/asio/use_future.hpp +3 -2
  71. data/src/cxx_supportlib/vendor-modified/boost/asio/version.hpp +1 -1
  72. data/src/cxx_supportlib/vendor-modified/boost/asio/write.hpp +4 -3
  73. data/src/cxx_supportlib/vendor-modified/boost/asio/write_at.hpp +5 -3
  74. data/src/cxx_supportlib/vendor-modified/boost/atomic/detail/ops_gcc_x86_dcas.hpp +13 -12
  75. data/src/cxx_supportlib/vendor-modified/boost/chrono/detail/inlined/mac/chrono.hpp +10 -10
  76. data/src/cxx_supportlib/vendor-modified/boost/chrono/detail/inlined/mac/process_cpu_clocks.hpp +34 -34
  77. data/src/cxx_supportlib/vendor-modified/boost/chrono/detail/inlined/mac/thread_clock.hpp +4 -4
  78. data/src/cxx_supportlib/vendor-modified/boost/chrono/detail/inlined/posix/chrono.hpp +8 -8
  79. data/src/cxx_supportlib/vendor-modified/boost/chrono/detail/inlined/posix/process_cpu_clocks.hpp +27 -27
  80. data/src/cxx_supportlib/vendor-modified/boost/chrono/detail/inlined/posix/thread_clock.hpp +4 -4
  81. data/src/cxx_supportlib/vendor-modified/boost/chrono/detail/system.hpp +5 -4
  82. data/src/cxx_supportlib/vendor-modified/boost/chrono/io/time_point_io.hpp +1 -1
  83. data/src/cxx_supportlib/vendor-modified/boost/circular_buffer.hpp +3 -3
  84. data/src/cxx_supportlib/vendor-modified/boost/circular_buffer/allocators.hpp +89 -0
  85. data/src/cxx_supportlib/vendor-modified/boost/circular_buffer/base.hpp +83 -74
  86. data/src/cxx_supportlib/vendor-modified/boost/circular_buffer/details.hpp +21 -33
  87. data/src/cxx_supportlib/vendor-modified/boost/circular_buffer/space_optimized.hpp +5 -5
  88. data/src/cxx_supportlib/vendor-modified/boost/concept/assert.hpp +1 -1
  89. data/src/cxx_supportlib/vendor-modified/boost/concept/detail/general.hpp +3 -3
  90. data/src/cxx_supportlib/vendor-modified/boost/concept/detail/has_constraints.hpp +3 -3
  91. data/src/cxx_supportlib/vendor-modified/boost/concept/usage.hpp +1 -1
  92. data/src/cxx_supportlib/vendor-modified/boost/concept_check.hpp +19 -19
  93. data/src/cxx_supportlib/vendor-modified/boost/config/auto_link.hpp +8 -0
  94. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/borland.hpp +5 -2
  95. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/clang.hpp +5 -1
  96. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/codegear.hpp +6 -2
  97. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/comeau.hpp +1 -1
  98. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/common_edg.hpp +4 -0
  99. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/cray.hpp +368 -52
  100. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/digitalmars.hpp +4 -1
  101. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/gcc.hpp +6 -3
  102. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/gcc_xml.hpp +3 -0
  103. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/greenhills.hpp +1 -1
  104. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/hp_acc.hpp +1 -1
  105. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/intel.hpp +6 -1
  106. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/kai.hpp +1 -1
  107. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/metrowerks.hpp +4 -1
  108. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/mpw.hpp +4 -1
  109. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/nvcc.hpp +3 -3
  110. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/pathscale.hpp +3 -0
  111. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/sunpro_cc.hpp +3 -0
  112. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/vacpp.hpp +4 -1
  113. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/visualc.hpp +9 -4
  114. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/xlcpp.hpp +4 -0
  115. data/src/cxx_supportlib/vendor-modified/boost/config/compiler/xlcpp_zos.hpp +1 -0
  116. data/src/cxx_supportlib/vendor-modified/boost/config/detail/select_compiler_config.hpp +1 -2
  117. data/src/cxx_supportlib/vendor-modified/boost/config/detail/suffix.hpp +13 -0
  118. data/src/cxx_supportlib/vendor-modified/boost/config/stdlib/dinkumware.hpp +2 -2
  119. data/src/cxx_supportlib/vendor-modified/boost/config/stdlib/libcpp.hpp +14 -4
  120. data/src/cxx_supportlib/vendor-modified/boost/config/stdlib/libstdcpp3.hpp +4 -4
  121. data/src/cxx_supportlib/vendor-modified/boost/container/adaptive_pool.hpp +262 -2
  122. data/src/cxx_supportlib/vendor-modified/boost/container/allocator.hpp +4 -3
  123. data/src/cxx_supportlib/vendor-modified/boost/container/allocator_traits.hpp +1 -1
  124. data/src/cxx_supportlib/vendor-modified/boost/container/deque.hpp +7 -0
  125. data/src/cxx_supportlib/vendor-modified/boost/container/detail/adaptive_node_pool.hpp +22 -19
  126. data/src/cxx_supportlib/vendor-modified/boost/container/detail/adaptive_node_pool_impl.hpp +833 -459
  127. data/src/cxx_supportlib/vendor-modified/boost/container/detail/advanced_insert_int.hpp +24 -6
  128. data/src/cxx_supportlib/vendor-modified/boost/container/detail/allocator_version_traits.hpp +2 -1
  129. data/src/cxx_supportlib/vendor-modified/boost/container/detail/compare_functors.hpp +61 -5
  130. data/src/cxx_supportlib/vendor-modified/boost/container/detail/copy_move_algo.hpp +33 -8
  131. data/src/cxx_supportlib/vendor-modified/boost/container/detail/flat_tree.hpp +132 -41
  132. data/src/cxx_supportlib/vendor-modified/boost/container/detail/iterator.hpp +16 -0
  133. data/src/cxx_supportlib/vendor-modified/boost/container/detail/math_functions.hpp +54 -0
  134. data/src/cxx_supportlib/vendor-modified/boost/container/detail/mpl.hpp +58 -0
  135. data/src/cxx_supportlib/vendor-modified/boost/container/detail/multiallocation_chain.hpp +28 -23
  136. data/src/cxx_supportlib/vendor-modified/boost/container/detail/node_alloc_holder.hpp +167 -115
  137. data/src/cxx_supportlib/vendor-modified/boost/container/detail/pair.hpp +55 -0
  138. data/src/cxx_supportlib/vendor-modified/boost/container/detail/std_fwd.hpp +3 -0
  139. data/src/cxx_supportlib/vendor-modified/boost/container/detail/thread_mutex.hpp +181 -0
  140. data/src/cxx_supportlib/vendor-modified/boost/container/detail/tree.hpp +167 -29
  141. data/src/cxx_supportlib/vendor-modified/boost/container/detail/type_traits.hpp +2 -0
  142. data/src/cxx_supportlib/vendor-modified/boost/container/detail/variadic_templates_tools.hpp +1 -1
  143. data/src/cxx_supportlib/vendor-modified/boost/container/detail/workaround.hpp +18 -0
  144. data/src/cxx_supportlib/vendor-modified/boost/container/flat_map.hpp +389 -3
  145. data/src/cxx_supportlib/vendor-modified/boost/container/flat_set.hpp +262 -0
  146. data/src/cxx_supportlib/vendor-modified/boost/container/list.hpp +52 -8
  147. data/src/cxx_supportlib/vendor-modified/boost/container/map.hpp +364 -0
  148. data/src/cxx_supportlib/vendor-modified/boost/container/pmr/monotonic_buffer_resource.hpp +4 -2
  149. data/src/cxx_supportlib/vendor-modified/boost/container/pmr/resource_adaptor.hpp +1 -1
  150. data/src/cxx_supportlib/vendor-modified/boost/container/pmr/synchronized_pool_resource.hpp +3 -2
  151. data/src/cxx_supportlib/vendor-modified/boost/container/set.hpp +286 -6
  152. data/src/cxx_supportlib/vendor-modified/boost/container/slist.hpp +56 -8
  153. data/src/cxx_supportlib/vendor-modified/boost/container/small_vector.hpp +43 -6
  154. data/src/cxx_supportlib/vendor-modified/boost/container/stable_vector.hpp +100 -31
  155. data/src/cxx_supportlib/vendor-modified/boost/container/static_vector.hpp +2 -1
  156. data/src/cxx_supportlib/vendor-modified/boost/container/string.hpp +126 -69
  157. data/src/cxx_supportlib/vendor-modified/boost/container/vector.hpp +75 -51
  158. data/src/cxx_supportlib/vendor-modified/boost/core/empty_value.hpp +136 -0
  159. data/src/cxx_supportlib/vendor-modified/boost/core/exchange.hpp +49 -0
  160. data/src/cxx_supportlib/vendor-modified/boost/core/explicit_operator_bool.hpp +9 -0
  161. data/src/cxx_supportlib/vendor-modified/boost/core/lightweight_test.hpp +101 -130
  162. data/src/cxx_supportlib/vendor-modified/boost/core/lightweight_test_trait.hpp +2 -2
  163. data/src/cxx_supportlib/vendor-modified/boost/core/noncopyable.hpp +16 -1
  164. data/src/cxx_supportlib/vendor-modified/boost/core/quick_exit.hpp +59 -0
  165. data/src/cxx_supportlib/vendor-modified/boost/core/ref.hpp +2 -1
  166. data/src/cxx_supportlib/vendor-modified/boost/core/swap.hpp +9 -2
  167. data/src/cxx_supportlib/vendor-modified/boost/core/typeinfo.hpp +26 -10
  168. data/src/cxx_supportlib/vendor-modified/boost/date_time/compiler_config.hpp +5 -0
  169. data/src/cxx_supportlib/vendor-modified/boost/date_time/posix_time/posix_time_duration.hpp +3 -3
  170. data/src/cxx_supportlib/vendor-modified/boost/date_time/time_duration.hpp +1 -1
  171. data/src/cxx_supportlib/vendor-modified/boost/detail/basic_pointerbuf.hpp +1 -1
  172. data/src/cxx_supportlib/vendor-modified/boost/detail/indirect_traits.hpp +38 -47
  173. data/src/cxx_supportlib/vendor-modified/boost/detail/lcast_precision.hpp +5 -5
  174. data/src/cxx_supportlib/vendor-modified/boost/detail/reference_content.hpp +7 -7
  175. data/src/cxx_supportlib/vendor-modified/boost/exception/exception.hpp +62 -58
  176. data/src/cxx_supportlib/vendor-modified/boost/function.hpp +1 -1
  177. data/src/cxx_supportlib/vendor-modified/boost/function/function_base.hpp +29 -29
  178. data/src/cxx_supportlib/vendor-modified/boost/function/function_template.hpp +38 -40
  179. data/src/cxx_supportlib/vendor-modified/boost/integer/common_factor_rt.hpp +4 -4
  180. data/src/cxx_supportlib/vendor-modified/boost/intrusive/avltree_algorithms.hpp +44 -44
  181. data/src/cxx_supportlib/vendor-modified/boost/intrusive/bstree_algorithms.hpp +39 -39
  182. data/src/cxx_supportlib/vendor-modified/boost/intrusive/circular_list_algorithms.hpp +15 -15
  183. data/src/cxx_supportlib/vendor-modified/boost/intrusive/circular_slist_algorithms.hpp +7 -7
  184. data/src/cxx_supportlib/vendor-modified/boost/intrusive/derivation_value_traits.hpp +1 -1
  185. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/any_node_and_algorithms.hpp +14 -14
  186. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/avltree_node.hpp +9 -9
  187. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/common_slist_algorithms.hpp +7 -7
  188. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/list_iterator.hpp +1 -1
  189. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/list_node.hpp +2 -2
  190. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/node_cloner_disposer.hpp +2 -2
  191. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/rbtree_node.hpp +6 -6
  192. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/simple_disposers.hpp +1 -1
  193. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/slist_iterator.hpp +1 -1
  194. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/slist_node.hpp +1 -1
  195. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/tree_iterator.hpp +1 -1
  196. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/tree_node.hpp +3 -3
  197. data/src/cxx_supportlib/vendor-modified/boost/intrusive/detail/tree_value_compare.hpp +33 -14
  198. data/src/cxx_supportlib/vendor-modified/boost/intrusive/hashtable.hpp +12 -12
  199. data/src/cxx_supportlib/vendor-modified/boost/intrusive/linear_slist_algorithms.hpp +4 -4
  200. data/src/cxx_supportlib/vendor-modified/boost/intrusive/pointer_plus_bits.hpp +3 -0
  201. data/src/cxx_supportlib/vendor-modified/boost/intrusive/rbtree_algorithms.hpp +39 -39
  202. data/src/cxx_supportlib/vendor-modified/boost/intrusive/sgtree_algorithms.hpp +61 -61
  203. data/src/cxx_supportlib/vendor-modified/boost/intrusive/slist.hpp +4 -4
  204. data/src/cxx_supportlib/vendor-modified/boost/intrusive/splaytree_algorithms.hpp +66 -66
  205. data/src/cxx_supportlib/vendor-modified/boost/intrusive/treap_algorithms.hpp +54 -54
  206. data/src/cxx_supportlib/vendor-modified/boost/intrusive/unordered_set.hpp +6 -2
  207. data/src/cxx_supportlib/vendor-modified/boost/intrusive/unordered_set_hook.hpp +3 -3
  208. data/src/cxx_supportlib/vendor-modified/boost/iterator/advance.hpp +1 -1
  209. data/src/cxx_supportlib/vendor-modified/boost/iterator/distance.hpp +65 -0
  210. data/src/cxx_supportlib/vendor-modified/boost/lexical_cast.hpp +1 -1
  211. data/src/cxx_supportlib/vendor-modified/boost/lexical_cast/bad_lexical_cast.hpp +1 -1
  212. data/src/cxx_supportlib/vendor-modified/boost/lexical_cast/detail/converter_lexical.hpp +23 -23
  213. data/src/cxx_supportlib/vendor-modified/boost/lexical_cast/detail/converter_lexical_streams.hpp +4 -4
  214. data/src/cxx_supportlib/vendor-modified/boost/lexical_cast/detail/converter_numeric.hpp +13 -13
  215. data/src/cxx_supportlib/vendor-modified/boost/lexical_cast/detail/inf_nan.hpp +1 -1
  216. data/src/cxx_supportlib/vendor-modified/boost/lexical_cast/detail/is_character.hpp +5 -4
  217. data/src/cxx_supportlib/vendor-modified/boost/lexical_cast/detail/lcast_char_constants.hpp +1 -1
  218. data/src/cxx_supportlib/vendor-modified/boost/lexical_cast/detail/lcast_unsigned_converters.hpp +5 -5
  219. data/src/cxx_supportlib/vendor-modified/boost/lexical_cast/detail/widest_char.hpp +5 -2
  220. data/src/cxx_supportlib/vendor-modified/boost/lexical_cast/try_lexical_convert.hpp +18 -13
  221. data/src/cxx_supportlib/vendor-modified/boost/libs/regex/src/cregex.cpp +4 -4
  222. data/src/cxx_supportlib/vendor-modified/boost/libs/system/src/error_code.cpp +16 -5
  223. data/src/cxx_supportlib/vendor-modified/boost/libs/thread/src/future.cpp +1 -1
  224. data/src/cxx_supportlib/vendor-modified/boost/libs/thread/src/pthread/thread.cpp +14 -8
  225. data/src/cxx_supportlib/vendor-modified/boost/libs/thread/src/tss_null.cpp +2 -2
  226. data/src/cxx_supportlib/vendor-modified/boost/math/special_functions/detail/fp_traits.hpp +13 -13
  227. data/src/cxx_supportlib/vendor-modified/boost/math/special_functions/math_fwd.hpp +27 -0
  228. data/src/cxx_supportlib/vendor-modified/boost/math/tools/config.hpp +1 -1
  229. data/src/cxx_supportlib/vendor-modified/boost/move/algo/adaptive_merge.hpp +29 -6
  230. data/src/cxx_supportlib/vendor-modified/boost/move/algo/adaptive_sort.hpp +12 -3
  231. data/src/cxx_supportlib/vendor-modified/boost/move/algo/detail/adaptive_sort_merge.hpp +1 -1
  232. data/src/cxx_supportlib/vendor-modified/boost/move/algo/move.hpp +1 -1
  233. data/src/cxx_supportlib/vendor-modified/boost/move/algorithm.hpp +1 -1
  234. data/src/cxx_supportlib/vendor-modified/boost/move/core.hpp +8 -8
  235. data/src/cxx_supportlib/vendor-modified/boost/move/detail/meta_utils.hpp +2 -0
  236. data/src/cxx_supportlib/vendor-modified/boost/move/detail/type_traits.hpp +3 -3
  237. data/src/cxx_supportlib/vendor-modified/boost/mpl/assert.hpp +23 -3
  238. data/src/cxx_supportlib/vendor-modified/boost/optional/detail/experimental_traits.hpp +9 -3
  239. data/src/cxx_supportlib/vendor-modified/boost/optional/detail/old_optional_implementation.hpp +10 -11
  240. data/src/cxx_supportlib/vendor-modified/boost/optional/detail/optional_reference_spec.hpp +20 -1
  241. data/src/cxx_supportlib/vendor-modified/boost/optional/detail/optional_trivially_copyable_base.hpp +3 -3
  242. data/src/cxx_supportlib/vendor-modified/boost/optional/optional.hpp +211 -101
  243. data/src/cxx_supportlib/vendor-modified/boost/parameter/python.hpp +5 -6
  244. data/src/cxx_supportlib/vendor-modified/boost/pool/detail/mutex.hpp +119 -25
  245. data/src/cxx_supportlib/vendor-modified/boost/predef/architecture.h +1 -0
  246. data/src/cxx_supportlib/vendor-modified/boost/predef/architecture/arm.h +5 -0
  247. data/src/cxx_supportlib/vendor-modified/boost/predef/architecture/ptx.h +44 -0
  248. data/src/cxx_supportlib/vendor-modified/boost/predef/compiler.h +1 -0
  249. data/src/cxx_supportlib/vendor-modified/boost/predef/compiler/compaq.h +1 -1
  250. data/src/cxx_supportlib/vendor-modified/boost/predef/compiler/nvcc.h +73 -0
  251. data/src/cxx_supportlib/vendor-modified/boost/predef/detail/endian_compat.h +3 -1
  252. data/src/cxx_supportlib/vendor-modified/boost/predef/language.h +1 -0
  253. data/src/cxx_supportlib/vendor-modified/boost/predef/language/cuda.h +52 -0
  254. data/src/cxx_supportlib/vendor-modified/boost/predef/make.h +4 -0
  255. data/src/cxx_supportlib/vendor-modified/boost/predef/os/cygwin.h +6 -1
  256. data/src/cxx_supportlib/vendor-modified/boost/predef/other/endian.h +1 -2
  257. data/src/cxx_supportlib/vendor-modified/boost/predef/version.h +1 -1
  258. data/src/cxx_supportlib/vendor-modified/boost/preprocessor/config/config.hpp +17 -8
  259. data/src/cxx_supportlib/vendor-modified/boost/preprocessor/stringize.hpp +4 -0
  260. data/src/cxx_supportlib/vendor-modified/boost/preprocessor/wstringize.hpp +4 -0
  261. data/src/cxx_supportlib/vendor-modified/boost/random/detail/gray_coded_qrng.hpp +166 -0
  262. data/src/cxx_supportlib/vendor-modified/boost/random/detail/niederreiter_base2_table.hpp +513 -0
  263. data/src/cxx_supportlib/vendor-modified/boost/random/detail/qrng_base.hpp +291 -0
  264. data/src/cxx_supportlib/vendor-modified/boost/random/detail/sobol_table.hpp +4106 -0
  265. data/src/cxx_supportlib/vendor-modified/boost/random/faure.hpp +367 -0
  266. data/src/cxx_supportlib/vendor-modified/boost/random/niederreiter_base2.hpp +360 -0
  267. data/src/cxx_supportlib/vendor-modified/boost/random/sobol.hpp +237 -0
  268. data/src/cxx_supportlib/vendor-modified/boost/range/as_literal.hpp +43 -0
  269. data/src/cxx_supportlib/vendor-modified/boost/range/begin.hpp +13 -5
  270. data/src/cxx_supportlib/vendor-modified/boost/range/concepts.hpp +1 -1
  271. data/src/cxx_supportlib/vendor-modified/boost/range/detail/common.hpp +1 -3
  272. data/src/cxx_supportlib/vendor-modified/boost/range/detail/implementation_help.hpp +2 -2
  273. data/src/cxx_supportlib/vendor-modified/boost/range/distance.hpp +11 -5
  274. data/src/cxx_supportlib/vendor-modified/boost/range/end.hpp +14 -6
  275. data/src/cxx_supportlib/vendor-modified/boost/range/has_range_iterator.hpp +3 -3
  276. data/src/cxx_supportlib/vendor-modified/boost/ratio/config.hpp +6 -2
  277. data/src/cxx_supportlib/vendor-modified/boost/rational.hpp +55 -37
  278. data/src/cxx_supportlib/vendor-modified/boost/regex/concepts.hpp +3 -2
  279. data/src/cxx_supportlib/vendor-modified/boost/regex/config.hpp +11 -1
  280. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/basic_regex.hpp +7 -1
  281. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/basic_regex_creator.hpp +3 -1
  282. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/basic_regex_parser.hpp +5 -2
  283. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/fileiter.hpp +0 -3
  284. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/instances.hpp +15 -4
  285. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/match_flags.hpp +1 -2
  286. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/match_results.hpp +12 -3
  287. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/perl_matcher.hpp +7 -2
  288. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/perl_matcher_common.hpp +7 -3
  289. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/perl_matcher_non_recursive.hpp +6 -2
  290. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/regex_format.hpp +0 -5
  291. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/regex_iterator.hpp +0 -8
  292. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/regex_raw_buffer.hpp +3 -3
  293. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/regex_split.hpp +3 -1
  294. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/regex_token_iterator.hpp +0 -8
  295. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/regex_traits_defaults.hpp +12 -11
  296. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/regex_workaround.hpp +7 -4
  297. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/u32regex_iterator.hpp +1 -9
  298. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/u32regex_token_iterator.hpp +2 -10
  299. data/src/cxx_supportlib/vendor-modified/boost/regex/v4/w32_regex_traits.hpp +2 -0
  300. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/allocate_shared_array.hpp +60 -115
  301. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/local_counted_base.hpp +3 -3
  302. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp +2 -1
  303. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_counted_base_aix.hpp +2 -1
  304. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_counted_base_clang.hpp +2 -1
  305. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp +2 -1
  306. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp +2 -1
  307. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp +2 -1
  308. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp +2 -1
  309. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp +2 -1
  310. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp +2 -1
  311. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp +2 -1
  312. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_counted_base_nt.hpp +2 -1
  313. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_counted_base_pt.hpp +2 -1
  314. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp +2 -1
  315. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_counted_base_solaris.hpp +2 -1
  316. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_counted_base_spin.hpp +2 -1
  317. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_counted_base_std_atomic.hpp +2 -1
  318. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_counted_base_sync.hpp +2 -1
  319. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp +2 -1
  320. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/sp_counted_impl.hpp +3 -3
  321. data/src/cxx_supportlib/vendor-modified/boost/smart_ptr/detail/yield_k.hpp +14 -8
  322. data/src/cxx_supportlib/vendor-modified/boost/system/config.hpp +4 -24
  323. data/src/cxx_supportlib/vendor-modified/boost/system/detail/config.hpp +57 -0
  324. data/src/cxx_supportlib/vendor-modified/boost/system/detail/generic_category.hpp +101 -0
  325. data/src/cxx_supportlib/vendor-modified/boost/system/detail/std_interoperability.hpp +141 -0
  326. data/src/cxx_supportlib/vendor-modified/boost/system/detail/system_category_posix.hpp +132 -0
  327. data/src/cxx_supportlib/vendor-modified/boost/system/error_code.hpp +775 -588
  328. data/src/cxx_supportlib/vendor-modified/boost/system/system_error.hpp +4 -4
  329. data/src/cxx_supportlib/vendor-modified/boost/thread/detail/config.hpp +6 -0
  330. data/src/cxx_supportlib/vendor-modified/boost/thread/detail/move.hpp +13 -6
  331. data/src/cxx_supportlib/vendor-modified/boost/thread/detail/nullary_function.hpp +8 -3
  332. data/src/cxx_supportlib/vendor-modified/boost/thread/detail/thread.hpp +3 -1
  333. data/src/cxx_supportlib/vendor-modified/boost/thread/detail/thread_safety.hpp +160 -0
  334. data/src/cxx_supportlib/vendor-modified/boost/thread/detail/tss_hooks.hpp +2 -2
  335. data/src/cxx_supportlib/vendor-modified/boost/thread/exceptions.hpp +3 -3
  336. data/src/cxx_supportlib/vendor-modified/boost/thread/executors/basic_thread_pool.hpp +24 -1
  337. data/src/cxx_supportlib/vendor-modified/boost/thread/future.hpp +10 -1
  338. data/src/cxx_supportlib/vendor-modified/boost/thread/lock_guard.hpp +4 -4
  339. data/src/cxx_supportlib/vendor-modified/boost/thread/lockable_traits.hpp +31 -0
  340. data/src/cxx_supportlib/vendor-modified/boost/thread/pthread/condition_variable.hpp +2 -2
  341. data/src/cxx_supportlib/vendor-modified/boost/thread/pthread/condition_variable_fwd.hpp +2 -2
  342. data/src/cxx_supportlib/vendor-modified/boost/thread/pthread/mutex.hpp +8 -53
  343. data/src/cxx_supportlib/vendor-modified/boost/thread/pthread/pthread_mutex_scoped_lock.hpp +73 -4
  344. data/src/cxx_supportlib/vendor-modified/boost/thread/pthread/recursive_mutex.hpp +6 -6
  345. data/src/cxx_supportlib/vendor-modified/boost/thread/pthread/thread_data.hpp +14 -9
  346. data/src/cxx_supportlib/vendor-modified/boost/thread/xtime.hpp +6 -6
  347. data/src/cxx_supportlib/vendor-modified/boost/throw_exception.hpp +9 -8
  348. data/src/cxx_supportlib/vendor-modified/boost/token_functions.hpp +1 -0
  349. data/src/cxx_supportlib/vendor-modified/boost/type_index/stl_type_index.hpp +21 -19
  350. data/src/cxx_supportlib/vendor-modified/boost/type_traits/detail/common_arithmetic_type.hpp +3 -1
  351. data/src/cxx_supportlib/vendor-modified/boost/type_traits/detail/config.hpp +9 -0
  352. data/src/cxx_supportlib/vendor-modified/boost/type_traits/detail/detector.hpp +1 -1
  353. data/src/cxx_supportlib/vendor-modified/boost/type_traits/detail/has_postfix_operator.hpp +55 -0
  354. data/src/cxx_supportlib/vendor-modified/boost/type_traits/detail/has_prefix_operator.hpp +72 -0
  355. data/src/cxx_supportlib/vendor-modified/boost/type_traits/detail/is_function_cxx_03.hpp +108 -0
  356. data/src/cxx_supportlib/vendor-modified/boost/type_traits/detail/is_function_cxx_11.hpp +501 -0
  357. data/src/cxx_supportlib/vendor-modified/boost/type_traits/detail/is_function_msvc10_fix.hpp +30 -0
  358. data/src/cxx_supportlib/vendor-modified/boost/type_traits/detail/is_likely_lambda.hpp +2 -2
  359. data/src/cxx_supportlib/vendor-modified/boost/type_traits/detail/is_member_function_pointer_cxx_03.hpp +117 -0
  360. data/src/cxx_supportlib/vendor-modified/boost/type_traits/detail/is_member_function_pointer_cxx_11.hpp +557 -0
  361. data/src/cxx_supportlib/vendor-modified/boost/type_traits/detail/is_rvalue_reference_msvc10_fix.hpp +43 -0
  362. data/src/cxx_supportlib/vendor-modified/boost/type_traits/detected.hpp +1 -1
  363. data/src/cxx_supportlib/vendor-modified/boost/type_traits/detected_or.hpp +1 -1
  364. data/src/cxx_supportlib/vendor-modified/boost/type_traits/enable_if.hpp +37 -0
  365. data/src/cxx_supportlib/vendor-modified/boost/type_traits/has_dereference.hpp +344 -0
  366. data/src/cxx_supportlib/vendor-modified/boost/type_traits/has_minus.hpp +5 -0
  367. data/src/cxx_supportlib/vendor-modified/boost/type_traits/has_minus_assign.hpp +5 -0
  368. data/src/cxx_supportlib/vendor-modified/boost/type_traits/has_plus_assign.hpp +5 -0
  369. data/src/cxx_supportlib/vendor-modified/boost/type_traits/has_post_decrement.hpp +21 -0
  370. data/src/cxx_supportlib/vendor-modified/boost/type_traits/has_post_increment.hpp +21 -0
  371. data/src/cxx_supportlib/vendor-modified/boost/type_traits/has_pre_decrement.hpp +21 -0
  372. data/src/cxx_supportlib/vendor-modified/boost/type_traits/has_pre_increment.hpp +22 -0
  373. data/src/cxx_supportlib/vendor-modified/boost/type_traits/has_trivial_move_assign.hpp +1 -1
  374. data/src/cxx_supportlib/vendor-modified/boost/type_traits/has_trivial_move_constructor.hpp +2 -1
  375. data/src/cxx_supportlib/vendor-modified/boost/type_traits/integral_constant.hpp +5 -15
  376. data/src/cxx_supportlib/vendor-modified/boost/type_traits/intrinsics.hpp +16 -6
  377. data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_complete.hpp +3 -1
  378. data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_copy_assignable.hpp +3 -4
  379. data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_copy_constructible.hpp +4 -6
  380. data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_detected.hpp +1 -1
  381. data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_detected_convertible.hpp +1 -1
  382. data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_detected_exact.hpp +1 -1
  383. data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_final.hpp +1 -1
  384. data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_function.hpp +4 -79
  385. data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_member_function_pointer.hpp +3 -97
  386. data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_noncopyable.hpp +39 -0
  387. data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_nothrow_move_assignable.hpp +2 -2
  388. data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_nothrow_move_constructible.hpp +2 -2
  389. data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_rvalue_reference.hpp +4 -0
  390. data/src/cxx_supportlib/vendor-modified/boost/type_traits/is_virtual_base_of.hpp +104 -63
  391. data/src/cxx_supportlib/vendor-modified/boost/type_traits/make_void.hpp +1 -1
  392. data/src/cxx_supportlib/vendor-modified/boost/type_traits/nonesuch.hpp +1 -1
  393. data/src/cxx_supportlib/vendor-modified/boost/typeof/constant.hpp +26 -0
  394. data/src/cxx_supportlib/vendor-modified/boost/typeof/dmc/typeof_impl.hpp +4 -4
  395. data/src/cxx_supportlib/vendor-modified/boost/typeof/encode_decode.hpp +0 -3
  396. data/src/cxx_supportlib/vendor-modified/boost/typeof/encode_decode_params.hpp +1 -1
  397. data/src/cxx_supportlib/vendor-modified/boost/typeof/int_encoding.hpp +4 -5
  398. data/src/cxx_supportlib/vendor-modified/boost/typeof/modifiers.hpp +5 -5
  399. data/src/cxx_supportlib/vendor-modified/boost/typeof/msvc/typeof_impl.hpp +9 -9
  400. data/src/cxx_supportlib/vendor-modified/boost/typeof/native.hpp +3 -3
  401. data/src/cxx_supportlib/vendor-modified/boost/typeof/pointers_data_members.hpp +2 -2
  402. data/src/cxx_supportlib/vendor-modified/boost/typeof/register_functions_iterate.hpp +6 -6
  403. data/src/cxx_supportlib/vendor-modified/boost/typeof/register_mem_functions.hpp +1 -1
  404. data/src/cxx_supportlib/vendor-modified/boost/typeof/template_encoding.hpp +4 -4
  405. data/src/cxx_supportlib/vendor-modified/boost/typeof/template_template_param.hpp +2 -2
  406. data/src/cxx_supportlib/vendor-modified/boost/typeof/type_encoding.hpp +2 -2
  407. data/src/cxx_supportlib/vendor-modified/boost/typeof/typeof_impl.hpp +16 -16
  408. data/src/cxx_supportlib/vendor-modified/boost/typeof/vector.hpp +5 -5
  409. data/src/cxx_supportlib/vendor-modified/boost/typeof/vector100.hpp +201 -201
  410. data/src/cxx_supportlib/vendor-modified/boost/typeof/vector150.hpp +301 -301
  411. data/src/cxx_supportlib/vendor-modified/boost/typeof/vector200.hpp +401 -401
  412. data/src/cxx_supportlib/vendor-modified/boost/typeof/vector50.hpp +101 -101
  413. data/src/cxx_supportlib/vendor-modified/boost/utility/detail/minstd_rand.hpp +3 -0
  414. data/src/cxx_supportlib/vendor-modified/boost/utility/string_ref.hpp +2 -0
  415. data/src/cxx_supportlib/vendor-modified/boost/utility/string_view.hpp +26 -6
  416. data/src/cxx_supportlib/vendor-modified/boost/version.hpp +2 -2
  417. data/src/helper-scripts/prespawn +1 -0
  418. data/src/nginx_module/ConfigGeneral/AutoGeneratedDefinitions.c +40 -0
  419. data/src/nginx_module/ConfigGeneral/AutoGeneratedManifestDefaultsInitialization.c +26 -0
  420. data/src/nginx_module/ConfigGeneral/AutoGeneratedSetterFuncs.c +48 -0
  421. data/src/nginx_module/Configuration.c +6 -2
  422. data/src/nginx_module/ContentHandler.c +5 -1
  423. data/src/nginx_module/LocationConfig/AutoGeneratedCreateFunction.c +15 -0
  424. data/src/nginx_module/LocationConfig/AutoGeneratedHeaderSerialization.c +15 -0
  425. data/src/nginx_module/LocationConfig/AutoGeneratedManifestGeneration.c +28 -0
  426. data/src/nginx_module/LocationConfig/AutoGeneratedMergeFunction.c +6 -0
  427. data/src/nginx_module/LocationConfig/AutoGeneratedStruct.h +11 -0
  428. data/src/nginx_module/MainConfig/AutoGeneratedCreateFunction.c +11 -0
  429. data/src/nginx_module/MainConfig/AutoGeneratedManifestGeneration.c +23 -0
  430. data/src/nginx_module/MainConfig/AutoGeneratedStruct.h +8 -0
  431. data/src/nginx_module/ngx_http_passenger_module.c +2 -0
  432. data/src/nodejs_supportlib/vendor-copy/winston/lib/winston/logger.js +0 -0
  433. data/src/ruby_native_extension/extconf.rb +7 -0
  434. data/src/ruby_supportlib/phusion_passenger.rb +7 -7
  435. data/src/ruby_supportlib/phusion_passenger/admin_tools/instance_registry.rb +8 -0
  436. data/src/ruby_supportlib/phusion_passenger/apache2/config_options.rb +23 -0
  437. data/src/ruby_supportlib/phusion_passenger/constants.rb +1 -0
  438. data/src/ruby_supportlib/phusion_passenger/loader_shared_helpers.rb +1 -3
  439. data/src/ruby_supportlib/phusion_passenger/nginx/config_options.rb +37 -0
  440. data/src/ruby_supportlib/phusion_passenger/platform_info/compiler.rb +1 -1
  441. data/src/ruby_supportlib/phusion_passenger/rack/thread_handler_extension.rb +10 -0
  442. data/src/ruby_supportlib/phusion_passenger/request_handler.rb +2 -2
  443. data/src/ruby_supportlib/phusion_passenger/request_handler/thread_handler.rb +5 -0
  444. data/src/ruby_supportlib/phusion_passenger/standalone/config_options_list.rb +11 -0
  445. data/src/ruby_supportlib/phusion_passenger/standalone/start_command/builtin_engine.rb +3 -0
  446. data/src/ruby_supportlib/phusion_passenger/standalone/start_command/nginx_engine.rb +1 -1
  447. data/src/ruby_supportlib/phusion_passenger/utils/tee_input.rb +6 -0
  448. data/src/ruby_supportlib/phusion_passenger/utils/unseekable_socket.rb +15 -11
  449. metadata +42 -8
  450. data/src/cxx_supportlib/vendor-modified/boost/call_traits.hpp +0 -20
  451. data/src/cxx_supportlib/vendor-modified/boost/detail/call_traits.hpp +0 -172
  452. data/src/cxx_supportlib/vendor-modified/boost/detail/no_exceptions_support.hpp +0 -17
  453. data/src/cxx_supportlib/vendor-modified/boost/system/detail/error_code.ipp +0 -496
@@ -284,7 +284,7 @@ class allocator
284
284
  //!This function is available only with Version == 2
285
285
  void allocate_many(size_type elem_size, std::size_t n_elements, multiallocation_chain &chain)
286
286
  {
287
- BOOST_STATIC_ASSERT(( Version > 1 ));/*
287
+ BOOST_STATIC_ASSERT(( Version > 1 ));
288
288
  dlmalloc_memchain ch;
289
289
  BOOST_CONTAINER_MEMCHAIN_INIT(&ch);
290
290
  if(!dlmalloc_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, &ch)){
@@ -293,10 +293,11 @@ class allocator
293
293
  chain.incorporate_after(chain.before_begin()
294
294
  ,(T*)BOOST_CONTAINER_MEMCHAIN_FIRSTMEM(&ch)
295
295
  ,(T*)BOOST_CONTAINER_MEMCHAIN_LASTMEM(&ch)
296
- ,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );*/
296
+ ,BOOST_CONTAINER_MEMCHAIN_SIZE(&ch) );
297
+ /*
297
298
  if(!dlmalloc_multialloc_nodes(n_elements, elem_size*sizeof(T), DL_MULTIALLOC_DEFAULT_CONTIGUOUS, reinterpret_cast<dlmalloc_memchain *>(&chain))){
298
299
  boost::container::throw_bad_alloc();
299
- }
300
+ }*/
300
301
  }
301
302
 
302
303
  //!Allocates n_elements elements, each one of size elem_sizes[i]
@@ -151,7 +151,7 @@ struct allocator_traits
151
151
  //! Allocator::void_pointer if such a type exists ; otherwise, pointer_traits<pointer>::rebind<void>.
152
152
  //!
153
153
  typedef see_documentation void_pointer;
154
- //! Allocator::const_void_pointer if such a type exists ; otherwis e, pointer_traits<pointer>::rebind<const
154
+ //! Allocator::const_void_pointer if such a type exists ; otherwise, pointer_traits<pointer>::rebind<const
155
155
  //!
156
156
  typedef see_documentation const_void_pointer;
157
157
  //! Allocator::difference_type if such a type exists ; otherwise, pointer_traits<pointer>::difference_type.
@@ -2238,6 +2238,13 @@ class deque : protected deque_base
2238
2238
  #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
2239
2239
  };
2240
2240
 
2241
+ #ifndef BOOST_CONTAINER_NO_CXX17_CTAD
2242
+ template <typename InputIterator>
2243
+ deque(InputIterator, InputIterator) -> deque<typename iterator_traits<InputIterator>::value_type>;
2244
+ template <typename InputIterator, typename Allocator>
2245
+ deque(InputIterator, InputIterator, Allocator const&) -> deque<typename iterator_traits<InputIterator>::value_type, Allocator>;
2246
+ #endif
2247
+
2241
2248
  }}
2242
2249
 
2243
2250
  #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
@@ -39,17 +39,6 @@ namespace boost {
39
39
  namespace container {
40
40
  namespace dtl {
41
41
 
42
- template<bool AlignOnly>
43
- struct select_private_adaptive_node_pool_impl
44
- {
45
- typedef boost::container::dtl::
46
- private_adaptive_node_pool_impl
47
- < fake_segment_manager
48
- , unsigned(AlignOnly)*::boost::container::adaptive_pool_flag::align_only
49
- | ::boost::container::adaptive_pool_flag::size_ordered | ::boost::container::adaptive_pool_flag::address_ordered
50
- > type;
51
- };
52
-
53
42
  //!Pooled memory allocator using an smart adaptive pool. Includes
54
43
  //!a reference count but the class does not delete itself, this is
55
44
  //!responsibility of user classes. Node size (NodeSize) and the number of
@@ -60,24 +49,38 @@ template< std::size_t NodeSize
60
49
  , std::size_t OverheadPercent
61
50
  >
62
51
  class private_adaptive_node_pool
63
- : public select_private_adaptive_node_pool_impl<(OverheadPercent == 0)>::type
52
+ : public private_adaptive_node_pool_impl_ct
53
+ < fake_segment_manager
54
+ , MaxFreeBlocks
55
+ , NodeSize
56
+ , NodesPerBlock
57
+ , OverheadPercent
58
+ , unsigned(OverheadPercent == 0)*::boost::container::adaptive_pool_flag::align_only
59
+ | ::boost::container::adaptive_pool_flag::size_ordered
60
+ | ::boost::container::adaptive_pool_flag::address_ordered
61
+ >
64
62
  {
65
- typedef typename select_private_adaptive_node_pool_impl<OverheadPercent == 0>::type base_t;
63
+ typedef private_adaptive_node_pool_impl_ct
64
+ < fake_segment_manager
65
+ , MaxFreeBlocks
66
+ , NodeSize
67
+ , NodesPerBlock
68
+ , OverheadPercent
69
+ , unsigned(OverheadPercent == 0)*::boost::container::adaptive_pool_flag::align_only
70
+ | ::boost::container::adaptive_pool_flag::size_ordered
71
+ | ::boost::container::adaptive_pool_flag::address_ordered
72
+ > base_t;
73
+
66
74
  //Non-copyable
67
75
  private_adaptive_node_pool(const private_adaptive_node_pool &);
68
76
  private_adaptive_node_pool &operator=(const private_adaptive_node_pool &);
69
77
 
70
78
  public:
71
- typedef typename base_t::multiallocation_chain multiallocation_chain;
72
79
  static const std::size_t nodes_per_block = NodesPerBlock;
73
80
 
74
81
  //!Constructor. Never throws
75
82
  private_adaptive_node_pool()
76
- : base_t(0
77
- , NodeSize
78
- , NodesPerBlock
79
- , MaxFreeBlocks
80
- , (unsigned char)OverheadPercent)
83
+ : base_t(0)
81
84
  {}
82
85
  };
83
86
 
@@ -87,7 +87,7 @@ template
87
87
  struct less_func<SizeType, adaptive_pool_flag::address_ordered>
88
88
  {
89
89
  static bool less(SizeType, SizeType, const void *la, const void *ra)
90
- { return &la < &ra; }
90
+ { return la < ra; }
91
91
  };
92
92
 
93
93
  template<class SizeType>
@@ -97,7 +97,7 @@ struct less_func
97
97
  { return (ls < rs) || ((ls == rs) && (la < ra)); }
98
98
  };
99
99
 
100
- template<class VoidPointer, class SizeType, bool ordered>
100
+ template<class VoidPointer, class SizeType, unsigned OrderFlags>
101
101
  struct block_container_traits
102
102
  {
103
103
  typedef typename bi::make_set_base_hook
@@ -116,11 +116,21 @@ struct block_container_traits
116
116
  static void reinsert_was_used(Container &container, typename Container::reference v, bool)
117
117
  {
118
118
  typedef typename Container::const_iterator const_block_iterator;
119
- const const_block_iterator this_block
120
- (Container::s_iterator_to(const_cast<typename Container::const_reference>(v)));
121
- const_block_iterator next_block(this_block);
122
- if(++next_block != container.cend()){
123
- if(this_block->free_nodes.size() > next_block->free_nodes.size()){
119
+ typedef typename Container::iterator block_iterator;
120
+ typedef typename Container::value_compare value_compare;
121
+
122
+ const block_iterator this_block(Container::s_iterator_to(v));
123
+ const const_block_iterator cendit(container.cend());
124
+ block_iterator next_block(this_block);
125
+
126
+ if(++next_block != cendit && value_compare()(*next_block, v)){
127
+ const_block_iterator next2_block(next_block);
128
+ //Test if v should be swapped with next (optimization)
129
+ if(++next2_block == cendit || !value_compare()(*next2_block, v)){
130
+ v.swap_nodes(*next_block);
131
+ BOOST_ASSERT(++next_block == this_block);
132
+ }
133
+ else{
124
134
  container.erase(this_block);
125
135
  container.insert(v);
126
136
  }
@@ -147,7 +157,7 @@ struct block_container_traits
147
157
  };
148
158
 
149
159
  template<class VoidPointer, class SizeType>
150
- struct block_container_traits<VoidPointer, SizeType, false>
160
+ struct block_container_traits<VoidPointer, SizeType, 0u>
151
161
  {
152
162
  typedef typename bi::make_list_base_hook
153
163
  < bi::void_pointer<VoidPointer>
@@ -193,11 +203,16 @@ struct block_container_traits
193
203
  }
194
204
  };
195
205
 
206
+ /////////////////////////////
207
+ //
208
+ // adaptive_pool_types
209
+ //
210
+ /////////////////////////////
196
211
  template<class MultiallocationChain, class VoidPointer, class SizeType, unsigned int Flags>
197
212
  struct adaptive_pool_types
198
213
  {
199
214
  typedef VoidPointer void_pointer;
200
- static const bool ordered = (Flags & (adaptive_pool_flag::size_ordered | adaptive_pool_flag::address_ordered)) != 0;
215
+ static const unsigned ordered = (Flags & (adaptive_pool_flag::size_ordered | adaptive_pool_flag::address_ordered));
201
216
  typedef block_container_traits<VoidPointer, SizeType, ordered> block_container_traits_t;
202
217
  typedef typename block_container_traits_t::hook_t hook_t;
203
218
  typedef hdr_offset_holder_t<SizeType> hdr_offset_holder;
@@ -222,95 +237,210 @@ struct adaptive_pool_types
222
237
  typedef typename block_container_traits_t:: template container<block_info_t>::type block_container_t;
223
238
  };
224
239
 
225
- template<class size_type>
226
- inline size_type calculate_alignment
227
- ( size_type overhead_percent, size_type real_node_size
228
- , size_type hdr_size, size_type hdr_offset_size, size_type payload_per_allocation)
240
+
241
+ /////////////////////////////////////////////
242
+ //
243
+ // candidate_power_of_2_ct
244
+ //
245
+ /////////////////////////////////////////////
246
+ template< std::size_t alignment
247
+ , std::size_t real_node_size
248
+ , std::size_t payload_per_allocation
249
+ , std::size_t min_elements_per_block
250
+ , std::size_t hdr_size
251
+ , std::size_t hdr_offset_size
252
+ , std::size_t overhead_percent>
253
+ struct candidate_power_of_2_ct_helper
229
254
  {
230
- //to-do: handle real_node_size != node_size
231
- const size_type divisor = overhead_percent*real_node_size;
232
- const size_type dividend = hdr_offset_size*100;
233
- size_type elements_per_subblock = (dividend - 1)/divisor + 1;
234
- size_type candidate_power_of_2 =
235
- upper_power_of_2(elements_per_subblock*real_node_size + hdr_offset_size);
236
- bool overhead_satisfied = false;
237
- //Now calculate the wors-case overhead for a subblock
238
- const size_type max_subblock_overhead = hdr_size + payload_per_allocation;
239
- while(!overhead_satisfied){
240
- elements_per_subblock = (candidate_power_of_2 - max_subblock_overhead)/real_node_size;
241
- const size_type overhead_size = candidate_power_of_2 - elements_per_subblock*real_node_size;
242
- if(overhead_size*100/candidate_power_of_2 < overhead_percent){
243
- overhead_satisfied = true;
244
- }
245
- else{
246
- candidate_power_of_2 <<= 1;
247
- }
248
- }
249
- return candidate_power_of_2;
250
- }
255
+ static const std::size_t hdr_subblock_elements_alone = (alignment - hdr_size - payload_per_allocation)/real_node_size;
256
+ static const std::size_t hdr_subblock_elements_first = (alignment - hdr_size - payload_per_allocation)/real_node_size;
257
+ static const std::size_t elements_per_b_subblock_mid = (alignment - hdr_offset_size)/real_node_size;
258
+ static const std::size_t elements_per_b_subblock_end = (alignment - hdr_offset_size - payload_per_allocation)/real_node_size;
259
+ static const std::size_t num_b_subblock =
260
+ hdr_subblock_elements_alone >= min_elements_per_block
261
+ ? 0
262
+ : ( ((hdr_subblock_elements_first + elements_per_b_subblock_end) >= min_elements_per_block)
263
+ ? 1
264
+ : 2 + (min_elements_per_block - hdr_subblock_elements_first - elements_per_b_subblock_end - 1)/elements_per_b_subblock_mid
265
+ )
266
+ ;
267
+
268
+ static const std::size_t num_b_subblock_mid = (num_b_subblock > 1) ? (num_b_subblock - 1) : 0;
269
+
270
+ static const std::size_t total_nodes = (num_b_subblock == 0)
271
+ ? hdr_subblock_elements_alone
272
+ : ( (num_b_subblock == 1)
273
+ ? (hdr_subblock_elements_first + elements_per_b_subblock_end)
274
+ : (hdr_subblock_elements_first + num_b_subblock_mid*elements_per_b_subblock_mid + elements_per_b_subblock_end)
275
+ )
276
+ ;
277
+ static const std::size_t total_data = total_nodes*real_node_size;
278
+ static const std::size_t total_size = alignment*(num_b_subblock+1);
279
+ static const bool overhead_satisfied = (total_size - total_data)*100/total_size < overhead_percent;
280
+ };
251
281
 
252
- template<class size_type>
253
- inline void calculate_num_subblocks
254
- (size_type alignment, size_type real_node_size, size_type elements_per_block
255
- , size_type &num_subblocks, size_type &real_num_node, size_type overhead_percent
256
- , size_type hdr_size, size_type hdr_offset_size, size_type payload_per_allocation)
282
+ template< std::size_t initial_alignment
283
+ , std::size_t real_node_size
284
+ , std::size_t payload_per_allocation
285
+ , std::size_t min_elements_per_block
286
+ , std::size_t hdr_size
287
+ , std::size_t hdr_offset_size
288
+ , std::size_t overhead_percent
289
+ , bool Loop = true>
290
+ struct candidate_power_of_2_ct
291
+ {
292
+ typedef candidate_power_of_2_ct_helper
293
+ < initial_alignment
294
+ , real_node_size
295
+ , payload_per_allocation
296
+ , min_elements_per_block
297
+ , hdr_size
298
+ , hdr_offset_size
299
+ , overhead_percent> helper_t;
300
+
301
+ static const std::size_t candidate_power_of_2 = initial_alignment << std::size_t(!helper_t::overhead_satisfied);
302
+
303
+ typedef typename candidate_power_of_2_ct
304
+ < candidate_power_of_2
305
+ , real_node_size
306
+ , payload_per_allocation
307
+ , min_elements_per_block
308
+ , hdr_size
309
+ , hdr_offset_size
310
+ , overhead_percent
311
+ , !helper_t::overhead_satisfied
312
+ >::type type;
313
+
314
+ static const std::size_t alignment = type::alignment;
315
+ static const std::size_t num_subblocks = type::num_subblocks;
316
+ static const std::size_t real_num_node = type::real_num_node;
317
+ };
318
+
319
+ template< std::size_t initial_alignment
320
+ , std::size_t real_node_size
321
+ , std::size_t payload_per_allocation
322
+ , std::size_t min_elements_per_block
323
+ , std::size_t hdr_size
324
+ , std::size_t hdr_offset_size
325
+ , std::size_t overhead_percent
326
+ >
327
+ struct candidate_power_of_2_ct
328
+ < initial_alignment
329
+ , real_node_size
330
+ , payload_per_allocation
331
+ , min_elements_per_block
332
+ , hdr_size
333
+ , hdr_offset_size
334
+ , overhead_percent
335
+ , false>
336
+ {
337
+ typedef candidate_power_of_2_ct
338
+ < initial_alignment
339
+ , real_node_size
340
+ , payload_per_allocation
341
+ , min_elements_per_block
342
+ , hdr_size
343
+ , hdr_offset_size
344
+ , overhead_percent
345
+ , false> type;
346
+
347
+ typedef candidate_power_of_2_ct_helper
348
+ < initial_alignment
349
+ , real_node_size
350
+ , payload_per_allocation
351
+ , min_elements_per_block
352
+ , hdr_size
353
+ , hdr_offset_size
354
+ , overhead_percent> helper_t;
355
+
356
+ static const std::size_t alignment = initial_alignment;
357
+ static const std::size_t num_subblocks = helper_t::num_b_subblock+1;
358
+ static const std::size_t real_num_node = helper_t::total_nodes;
359
+ };
360
+
361
+ /////////////////////////////////////////////
362
+ //
363
+ // candidate_power_of_2_rt
364
+ //
365
+ /////////////////////////////////////////////
366
+ inline void candidate_power_of_2_rt ( std::size_t initial_alignment
367
+ , std::size_t real_node_size
368
+ , std::size_t payload_per_allocation
369
+ , std::size_t min_elements_per_block
370
+ , std::size_t hdr_size
371
+ , std::size_t hdr_offset_size
372
+ , std::size_t overhead_percent
373
+ , std::size_t &alignment
374
+ , std::size_t &num_subblocks
375
+ , std::size_t &real_num_node)
257
376
  {
258
- const size_type hdr_subblock_elements = (alignment - hdr_size - payload_per_allocation)/real_node_size;
259
- size_type elements_per_subblock = (alignment - hdr_offset_size)/real_node_size;
260
- size_type possible_num_subblock = (elements_per_block - 1)/elements_per_subblock + 1;
261
- while(((possible_num_subblock-1)*elements_per_subblock + hdr_subblock_elements) < elements_per_block){
262
- ++possible_num_subblock;
263
- }
264
- elements_per_subblock = (alignment - hdr_offset_size)/real_node_size;
265
377
  bool overhead_satisfied = false;
266
- while(!overhead_satisfied){
267
- const size_type total_data = (elements_per_subblock*(possible_num_subblock-1) + hdr_subblock_elements)*real_node_size;
268
- const size_type total_size = alignment*possible_num_subblock;
269
- if((total_size - total_data)*100/total_size < overhead_percent){
270
- overhead_satisfied = true;
271
- }
272
- else{
273
- ++possible_num_subblock;
274
- }
378
+ std::size_t num_b_subblock = 0;
379
+ std::size_t total_nodes = 0;
380
+
381
+ while(!overhead_satisfied)
382
+ {
383
+ std::size_t hdr_subblock_elements_alone = (initial_alignment - hdr_size - payload_per_allocation)/real_node_size;
384
+ std::size_t hdr_subblock_elements_first = (initial_alignment - hdr_size - payload_per_allocation)/real_node_size;
385
+ std::size_t elements_per_b_subblock_mid = (initial_alignment - hdr_offset_size)/real_node_size;
386
+ std::size_t elements_per_b_subblock_end = (initial_alignment - hdr_offset_size - payload_per_allocation)/real_node_size;
387
+
388
+ num_b_subblock =
389
+ hdr_subblock_elements_alone >= min_elements_per_block
390
+ ? 0
391
+ : ( ((hdr_subblock_elements_first + elements_per_b_subblock_end) >= min_elements_per_block)
392
+ ? 1
393
+ : 2 + (min_elements_per_block - hdr_subblock_elements_first - elements_per_b_subblock_end - 1)/elements_per_b_subblock_mid
394
+ )
395
+ ;
396
+
397
+ std::size_t num_b_subblock_mid = (num_b_subblock > 1) ? (num_b_subblock - 1) : 0;
398
+
399
+ total_nodes = (num_b_subblock == 0)
400
+ ? hdr_subblock_elements_alone
401
+ : ( (num_b_subblock == 1)
402
+ ? (hdr_subblock_elements_first + elements_per_b_subblock_end)
403
+ : (hdr_subblock_elements_first + num_b_subblock_mid*elements_per_b_subblock_mid + elements_per_b_subblock_end)
404
+ )
405
+ ;
406
+ std::size_t total_data = total_nodes*real_node_size;
407
+ std::size_t total_size = initial_alignment*(num_b_subblock+1);
408
+ overhead_satisfied = (total_size - total_data)*100/total_size < overhead_percent;
409
+ initial_alignment = initial_alignment << std::size_t(!overhead_satisfied);
275
410
  }
276
- num_subblocks = possible_num_subblock;
277
- real_num_node = (possible_num_subblock-1)*elements_per_subblock + hdr_subblock_elements;
411
+ alignment = initial_alignment;
412
+ num_subblocks = num_b_subblock+1;
413
+ real_num_node = total_nodes;
278
414
  }
279
415
 
280
- template<class SegmentManagerBase, unsigned int Flags>
281
- class private_adaptive_node_pool_impl
416
+ /////////////////////////////////////////////
417
+ //
418
+ // private_adaptive_node_pool_impl_common
419
+ //
420
+ /////////////////////////////////////////////
421
+ template< class SegmentManagerBase, unsigned int Flags>
422
+ class private_adaptive_node_pool_impl_common
282
423
  {
283
- //Non-copyable
284
- private_adaptive_node_pool_impl();
285
- private_adaptive_node_pool_impl(const private_adaptive_node_pool_impl &);
286
- private_adaptive_node_pool_impl &operator=(const private_adaptive_node_pool_impl &);
287
- typedef private_adaptive_node_pool_impl this_type;
288
-
289
- typedef typename SegmentManagerBase::void_pointer void_pointer;
290
- static const typename SegmentManagerBase::
291
- size_type PayloadPerAllocation = SegmentManagerBase::PayloadPerAllocation;
424
+ public:
425
+ //!Segment manager typedef
426
+ typedef SegmentManagerBase segment_manager_base_type;
427
+ typedef typename SegmentManagerBase::multiallocation_chain multiallocation_chain;
428
+ typedef typename SegmentManagerBase::size_type size_type;
292
429
  //Flags
293
430
  //align_only
294
431
  static const bool AlignOnly = (Flags & adaptive_pool_flag::align_only) != 0;
295
432
  typedef bool_<AlignOnly> IsAlignOnly;
296
433
  typedef true_ AlignOnlyTrue;
297
434
  typedef false_ AlignOnlyFalse;
298
- //size_ordered
299
- static const bool SizeOrdered = (Flags & adaptive_pool_flag::size_ordered) != 0;
300
- typedef bool_<SizeOrdered> IsSizeOrdered;
301
- typedef true_ SizeOrderedTrue;
302
- typedef false_ SizeOrderedFalse;
303
- //address_ordered
304
- static const bool AddressOrdered = (Flags & adaptive_pool_flag::address_ordered) != 0;
305
- typedef bool_<AddressOrdered> IsAddressOrdered;
306
- typedef true_ AddressOrderedTrue;
307
- typedef false_ AddressOrderedFalse;
308
435
 
309
- public:
310
- typedef typename SegmentManagerBase::multiallocation_chain multiallocation_chain;
311
- typedef typename SegmentManagerBase::size_type size_type;
436
+ typedef typename SegmentManagerBase::void_pointer void_pointer;
437
+ static const typename SegmentManagerBase::
438
+ size_type PayloadPerAllocation = SegmentManagerBase::PayloadPerAllocation;
312
439
 
313
- private:
440
+ typedef typename boost::intrusive::pointer_traits
441
+ <void_pointer>::template rebind_pointer<segment_manager_base_type>::type segment_mngr_base_ptr_t;
442
+
443
+ protected:
314
444
  typedef adaptive_pool_types
315
445
  <multiallocation_chain, void_pointer, size_type, Flags> adaptive_pool_types_t;
316
446
  typedef typename adaptive_pool_types_t::free_nodes_t free_nodes_t;
@@ -320,70 +450,285 @@ class private_adaptive_node_pool_impl
320
450
  typedef typename block_container_t::iterator block_iterator;
321
451
  typedef typename block_container_t::const_iterator const_block_iterator;
322
452
  typedef typename adaptive_pool_types_t::hdr_offset_holder hdr_offset_holder;
453
+ typedef private_adaptive_node_pool_impl_common this_type;
323
454
 
324
455
  static const size_type MaxAlign = alignment_of<void_pointer>::value;
325
456
  static const size_type HdrSize = ((sizeof(block_info_t)-1)/MaxAlign+1)*MaxAlign;
326
457
  static const size_type HdrOffsetSize = ((sizeof(hdr_offset_holder)-1)/MaxAlign+1)*MaxAlign;
327
458
 
328
- public:
329
- //!Segment manager typedef
330
- typedef SegmentManagerBase segment_manager_base_type;
459
+ segment_mngr_base_ptr_t mp_segment_mngr_base; //Segment manager
460
+ block_container_t m_block_container; //Intrusive block list
461
+ size_type m_totally_free_blocks; //Free blocks
331
462
 
332
- //!Constructor from a segment manager. Never throws
333
- private_adaptive_node_pool_impl
334
- ( segment_manager_base_type *segment_mngr_base
335
- , size_type node_size
336
- , size_type nodes_per_block
337
- , size_type max_free_blocks
338
- , unsigned char overhead_percent
339
- )
340
- : m_max_free_blocks(max_free_blocks)
341
- , m_real_node_size(lcm(node_size, size_type(alignment_of<void_pointer>::value)))
342
- //Round the size to a power of two value.
343
- //This is the total memory size (including payload) that we want to
344
- //allocate from the general-purpose allocator
345
- , m_real_block_alignment
346
- (AlignOnly ?
347
- upper_power_of_2(HdrSize + m_real_node_size*nodes_per_block) :
348
- calculate_alignment( (size_type)overhead_percent, m_real_node_size
349
- , HdrSize, HdrOffsetSize, PayloadPerAllocation))
350
- //This is the real number of nodes per block
351
- , m_num_subblocks(0)
352
- , m_real_num_node(AlignOnly ? (m_real_block_alignment - PayloadPerAllocation - HdrSize)/m_real_node_size : 0)
353
- //General purpose allocator
354
- , mp_segment_mngr_base(segment_mngr_base)
355
- , m_block_container()
356
- , m_totally_free_blocks(0)
463
+ class block_destroyer;
464
+ friend class block_destroyer;
465
+
466
+ class block_destroyer
467
+ {
468
+ public:
469
+ block_destroyer(const this_type *impl, multiallocation_chain &chain, const size_type num_subblocks, const size_type real_block_alignment, const size_type real_num_node)
470
+ : mp_impl(impl), m_chain(chain), m_num_subblocks(num_subblocks), m_real_block_alignment(real_block_alignment), m_real_num_node(real_num_node)
471
+ {}
472
+
473
+ void operator()(typename block_container_t::pointer to_deallocate)
474
+ { return this->do_destroy(to_deallocate, IsAlignOnly()); }
475
+
476
+ private:
477
+ void do_destroy(typename block_container_t::pointer to_deallocate, AlignOnlyTrue)
478
+ {
479
+ BOOST_ASSERT(to_deallocate->free_nodes.size() == m_real_num_node);
480
+ m_chain.push_back(to_deallocate);
481
+ }
482
+
483
+ void do_destroy(typename block_container_t::pointer to_deallocate, AlignOnlyFalse)
484
+ {
485
+ BOOST_ASSERT(to_deallocate->free_nodes.size() == m_real_num_node);
486
+ BOOST_ASSERT(0 == to_deallocate->hdr_offset);
487
+ hdr_offset_holder *hdr_off_holder =
488
+ mp_impl->priv_first_subblock_from_block(boost::movelib::to_raw_pointer(to_deallocate), m_num_subblocks, m_real_block_alignment);
489
+ m_chain.push_back(hdr_off_holder);
490
+ }
491
+
492
+ const this_type *mp_impl;
493
+ multiallocation_chain &m_chain;
494
+ const size_type m_num_subblocks;
495
+ const size_type m_real_block_alignment;
496
+ const size_type m_real_num_node;
497
+ };
498
+
499
+ //This macro will activate invariant checking. Slow, but helpful for debugging the code.
500
+ //#define BOOST_CONTAINER_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS
501
+ void priv_invariants(const size_type real_num_node, const size_type num_subblocks, const size_type real_block_alignment) const
357
502
  {
358
- if(!AlignOnly){
359
- calculate_num_subblocks
360
- ( m_real_block_alignment
361
- , m_real_node_size
362
- , nodes_per_block
363
- , m_num_subblocks
364
- , m_real_num_node
365
- , (size_type)overhead_percent
366
- , HdrSize
367
- , HdrOffsetSize
368
- , PayloadPerAllocation);
503
+ (void)real_num_node; (void)num_subblocks; (void)real_block_alignment;
504
+ #ifdef BOOST_CONTAINER_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS
505
+ //Check that the total totally free blocks are correct
506
+ BOOST_ASSERT(m_block_container.size() >= m_totally_free_blocks);
507
+
508
+ const const_block_iterator itend(m_block_container.cend());
509
+ const const_block_iterator itbeg(m_block_container.cbegin());
510
+
511
+ { //Try to do checks in a single iteration
512
+ const_block_iterator it(itbeg);
513
+ size_type total_free_nodes = 0;
514
+ size_type total_free_blocks = 0u;
515
+ for(; it != itend; ++it){
516
+ if(it != itbeg){
517
+ //Check order invariant
518
+ const_block_iterator prev(it);
519
+ --prev;
520
+ BOOST_ASSERT(!(m_block_container.key_comp()(*it, *prev)));
521
+ (void)prev; (void)it;
522
+ }
523
+
524
+ //free_nodes invariant
525
+ const size_type free_nodes = it->free_nodes.size();
526
+ BOOST_ASSERT(free_nodes <= real_num_node);
527
+ BOOST_ASSERT(free_nodes != 0);
528
+
529
+ //Acummulate total_free_nodes and total_free_blocks
530
+ total_free_nodes += free_nodes;
531
+ total_free_blocks += it->free_nodes.size() == real_num_node;
532
+
533
+ if (!AlignOnly) {
534
+ //Check that header offsets are correct
535
+ hdr_offset_holder *hdr_off_holder = this->priv_first_subblock_from_block(const_cast<block_info_t *>(&*it), num_subblocks, real_block_alignment);
536
+ for (size_type i = 0, max = num_subblocks; i < max; ++i) {
537
+ const size_type offset = reinterpret_cast<char*>(const_cast<block_info_t *>(&*it)) - reinterpret_cast<char*>(hdr_off_holder);
538
+ (void)offset;
539
+ BOOST_ASSERT(hdr_off_holder->hdr_offset == offset);
540
+ BOOST_ASSERT(0 == (reinterpret_cast<std::size_t>(hdr_off_holder) & (real_block_alignment - 1)));
541
+ BOOST_ASSERT(0 == (hdr_off_holder->hdr_offset & (real_block_alignment - 1)));
542
+ hdr_off_holder = reinterpret_cast<hdr_offset_holder *>(reinterpret_cast<char*>(hdr_off_holder) + real_block_alignment);
543
+ }
544
+ }
545
+ }
546
+ BOOST_ASSERT(total_free_blocks == m_totally_free_blocks);
547
+ BOOST_ASSERT(total_free_nodes >= m_totally_free_blocks*real_num_node);
369
548
  }
549
+ #endif
370
550
  }
371
551
 
372
- //!Destructor. Deallocates all allocated blocks. Never throws
373
- ~private_adaptive_node_pool_impl()
374
- { this->priv_clear(); }
552
+ void priv_deallocate_free_blocks( const size_type max_free_blocks, const size_type real_num_node
553
+ , const size_type num_subblocks, const size_type real_block_alignment)
554
+ { //Trampoline function to ease inlining
555
+ if(m_totally_free_blocks > max_free_blocks){
556
+ this->priv_deallocate_free_blocks_impl(max_free_blocks, real_num_node, num_subblocks, real_block_alignment);
557
+ }
558
+ }
375
559
 
376
- size_type get_real_num_node() const
377
- { return m_real_num_node; }
560
+ hdr_offset_holder *priv_first_subblock_from_block(block_info_t *block, const size_type num_subblocks, const size_type real_block_alignment) const
561
+ { return this->priv_first_subblock_from_block(block, num_subblocks, real_block_alignment, IsAlignOnly()); }
378
562
 
379
- //!Returns the segment manager. Never throws
380
- segment_manager_base_type* get_segment_manager_base()const
381
- { return boost::movelib::to_raw_pointer(mp_segment_mngr_base); }
563
+ hdr_offset_holder *priv_first_subblock_from_block(block_info_t *block, const size_type num_subblocks, const size_type real_block_alignment, AlignOnlyFalse) const
564
+ {
565
+ hdr_offset_holder *const hdr_off_holder = reinterpret_cast<hdr_offset_holder*>
566
+ (reinterpret_cast<char*>(block) - (num_subblocks-1)*real_block_alignment);
567
+ BOOST_ASSERT(hdr_off_holder->hdr_offset == size_type(reinterpret_cast<char*>(block) - reinterpret_cast<char*>(hdr_off_holder)));
568
+ BOOST_ASSERT(0 == ((std::size_t)hdr_off_holder & (real_block_alignment - 1)));
569
+ BOOST_ASSERT(0 == (hdr_off_holder->hdr_offset & (real_block_alignment - 1)));
570
+ return hdr_off_holder;
571
+ }
572
+
573
+ hdr_offset_holder *priv_first_subblock_from_block(block_info_t *block, const size_type num_subblocks, const size_type real_block_alignment, AlignOnlyTrue) const
574
+ {
575
+ (void)num_subblocks; (void)real_block_alignment;
576
+ return reinterpret_cast<hdr_offset_holder*>(block);
577
+ }
578
+
579
+ void priv_deallocate_free_blocks_impl( const size_type max_free_blocks, const size_type real_num_node
580
+ , const size_type num_subblocks, const size_type real_block_alignment)
581
+ {
582
+ this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
583
+ //Now check if we've reached the free nodes limit
584
+ //and check if we have free blocks. If so, deallocate as much
585
+ //as we can to stay below the limit
586
+ multiallocation_chain chain;
587
+ {
588
+ if(Flags & adaptive_pool_flag::size_ordered){
589
+ const_block_iterator it = m_block_container.cend();
590
+ --it;
591
+ size_type totally_free_blocks = m_totally_free_blocks;
592
+
593
+ for( ; totally_free_blocks > max_free_blocks; --totally_free_blocks){
594
+ BOOST_ASSERT(it->free_nodes.size() == real_num_node);
595
+ void *addr = priv_first_subblock_from_block(const_cast<block_info_t*>(&*it), num_subblocks, real_block_alignment);
596
+ --it;
597
+ block_container_traits_t::erase_last(m_block_container);
598
+ chain.push_front(void_pointer(addr));
599
+ }
600
+ }
601
+ else{
602
+ const_block_iterator it = m_block_container.cend();
603
+ size_type totally_free_blocks = m_totally_free_blocks;
604
+
605
+ while(totally_free_blocks > max_free_blocks){
606
+ --it;
607
+ if(it->free_nodes.size() == real_num_node){
608
+ void *addr = priv_first_subblock_from_block(const_cast<block_info_t*>(&*it), num_subblocks, real_block_alignment);
609
+ it = m_block_container.erase(it);
610
+ chain.push_front(void_pointer(addr));
611
+ --totally_free_blocks;
612
+ }
613
+ }
614
+ }
615
+ BOOST_ASSERT((m_totally_free_blocks - max_free_blocks) == chain.size());
616
+ m_totally_free_blocks = max_free_blocks;
617
+ }
618
+ this->mp_segment_mngr_base->deallocate_many(chain);
619
+ this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
620
+ }
621
+
622
+ void priv_fill_chain_remaining_to_block
623
+ ( multiallocation_chain &chain, size_type target_elem_in_chain, block_info_t &c_info
624
+ , char *mem_address, size_type max_node_in_mem
625
+ , const size_type real_node_size)
626
+ {
627
+ BOOST_ASSERT(chain.size() <= target_elem_in_chain);
628
+
629
+ //First add all possible nodes to the chain
630
+ const size_type left = target_elem_in_chain - chain.size();
631
+ const size_type add_to_chain = (max_node_in_mem < left) ? max_node_in_mem : left;
632
+ char *free_mem_address = static_cast<char *>(boost::movelib::to_raw_pointer
633
+ (chain.incorporate_after(chain.last(), void_pointer(mem_address), real_node_size, add_to_chain)));
634
+ //Now store remaining nodes in the free list
635
+ if(const size_type free = max_node_in_mem - add_to_chain){
636
+ free_nodes_t & free_nodes = c_info.free_nodes;
637
+ free_nodes.incorporate_after(free_nodes.last(), void_pointer(free_mem_address), real_node_size, free);
638
+ }
639
+ }
640
+
641
+ //!Allocates a several blocks of nodes. Can throw
642
+ void priv_append_from_new_blocks( size_type min_elements, multiallocation_chain &chain
643
+ , const size_type max_free_blocks
644
+ , const size_type real_block_alignment, const size_type real_node_size
645
+ , const size_type real_num_node, const size_type num_subblocks
646
+ , AlignOnlyTrue)
647
+ {
648
+ (void)num_subblocks;
649
+ BOOST_ASSERT(m_block_container.empty());
650
+ BOOST_ASSERT(min_elements > 0);
651
+ const size_type n = (min_elements - 1)/real_num_node + 1;
652
+ const size_type real_block_size = real_block_alignment - PayloadPerAllocation;
653
+ const size_type target_elem_in_chain = chain.size() + min_elements;
654
+ for(size_type i = 0; i != n; ++i){
655
+ //We allocate a new NodeBlock and put it the last
656
+ //element of the tree
657
+ char *mem_address = static_cast<char*>
658
+ (mp_segment_mngr_base->allocate_aligned(real_block_size, real_block_alignment));
659
+ if(!mem_address){
660
+ //In case of error, free memory deallocating all nodes (the new ones allocated
661
+ //in this function plus previously stored nodes in chain).
662
+ this->priv_deallocate_nodes(chain, max_free_blocks, real_num_node, num_subblocks, real_block_alignment);
663
+ throw_bad_alloc();
664
+ }
665
+ block_info_t &c_info = *new(mem_address)block_info_t();
666
+ mem_address += HdrSize;
667
+ this->priv_fill_chain_remaining_to_block(chain, target_elem_in_chain, c_info, mem_address, real_num_node, real_node_size);
668
+ const size_type free_nodes = c_info.free_nodes.size();
669
+ if(free_nodes){
670
+ const bool is_full = free_nodes == real_num_node;
671
+ BOOST_ASSERT(free_nodes < real_num_node);
672
+ m_totally_free_blocks += static_cast<size_type>(is_full);
673
+ block_container_traits_t::insert_was_empty(m_block_container, c_info, is_full);
674
+ }
675
+ }
676
+ }
677
+
678
+ void priv_append_from_new_blocks( size_type min_elements, multiallocation_chain &chain
679
+ , const size_type max_free_blocks
680
+ , const size_type real_block_alignment, const size_type real_node_size
681
+ , const size_type real_num_node, const size_type num_subblocks
682
+ , AlignOnlyFalse)
683
+ {
684
+ BOOST_ASSERT(m_block_container.empty());
685
+ BOOST_ASSERT(min_elements > 0);
686
+ const size_type n = (min_elements - 1)/real_num_node + 1;
687
+ const size_type real_block_size = real_block_alignment*num_subblocks - PayloadPerAllocation;
688
+ const size_type elements_per_subblock_mid = (real_block_alignment - HdrOffsetSize)/real_node_size;
689
+ const size_type elements_per_subblock_end = (real_block_alignment - HdrOffsetSize - PayloadPerAllocation) / real_node_size;
690
+ const size_type hdr_subblock_elements = (real_block_alignment - HdrSize - PayloadPerAllocation)/real_node_size;
691
+ const size_type target_elem_in_chain = chain.size() + min_elements;
692
+
693
+ for(size_type i = 0; i != n; ++i){
694
+ //We allocate a new NodeBlock and put it the last
695
+ //element of the tree
696
+ char *mem_address = static_cast<char*>
697
+ (mp_segment_mngr_base->allocate_aligned(real_block_size, real_block_alignment));
698
+ if(!mem_address){
699
+ //In case of error, free memory deallocating all nodes (the new ones allocated
700
+ //in this function plus previously stored nodes in chain).
701
+ this->priv_deallocate_nodes(chain, max_free_blocks, real_num_node, num_subblocks, real_block_alignment);
702
+ throw_bad_alloc();
703
+ }
704
+ //First initialize header information on the last subblock
705
+ char *hdr_addr = mem_address + real_block_alignment*(num_subblocks-1);
706
+ block_info_t &c_info = *new(hdr_addr)block_info_t();
707
+ //Some structural checks
708
+ BOOST_ASSERT(static_cast<void*>(&static_cast<hdr_offset_holder&>(c_info).hdr_offset) ==
709
+ static_cast<void*>(&c_info)); (void)c_info;
710
+ for( size_type subblock = 0, maxsubblock = num_subblocks - 1
711
+ ; subblock < maxsubblock
712
+ ; ++subblock, mem_address += real_block_alignment){
713
+ //Initialize header offset mark
714
+ new(mem_address) hdr_offset_holder(size_type(hdr_addr - mem_address));
715
+ const size_type elements_per_subblock = (subblock != (maxsubblock - 1)) ? elements_per_subblock_mid : elements_per_subblock_end;
716
+ this->priv_fill_chain_remaining_to_block
717
+ (chain, target_elem_in_chain, c_info, mem_address + HdrOffsetSize, elements_per_subblock, real_node_size);
718
+ }
719
+ this->priv_fill_chain_remaining_to_block
720
+ (chain, target_elem_in_chain, c_info, hdr_addr + HdrSize, hdr_subblock_elements, real_node_size);
721
+ m_totally_free_blocks += static_cast<size_type>(c_info.free_nodes.size() == real_num_node);
722
+ if (c_info.free_nodes.size())
723
+ m_block_container.push_front(c_info);
724
+ }
725
+ }
382
726
 
383
727
  //!Allocates array of count elements. Can throw
384
- void *allocate_node()
728
+ void *priv_allocate_node( const size_type max_free_blocks, const size_type real_block_alignment, const size_type real_node_size
729
+ , const size_type real_num_node, const size_type num_subblocks)
385
730
  {
386
- this->priv_invariants();
731
+ this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
387
732
  //If there are no free nodes we allocate a new block
388
733
  if(!m_block_container.empty()){
389
734
  //We take the first free node the multiset can't be empty
@@ -394,51 +739,39 @@ class private_adaptive_node_pool_impl
394
739
  if(free_nodes.empty()){
395
740
  block_container_traits_t::erase_first(m_block_container);
396
741
  }
397
- m_totally_free_blocks -= static_cast<size_type>(free_nodes_count == m_real_num_node);
398
- this->priv_invariants();
742
+ m_totally_free_blocks -= static_cast<size_type>(free_nodes_count == real_num_node);
743
+ this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
399
744
  return first_node;
400
745
  }
401
746
  else{
402
747
  multiallocation_chain chain;
403
- this->priv_append_from_new_blocks(1, chain, IsAlignOnly());
404
- return boost::movelib::to_raw_pointer(chain.pop_front());
748
+ this->priv_append_from_new_blocks
749
+ (1, chain, max_free_blocks, real_block_alignment, real_node_size, real_num_node, num_subblocks, IsAlignOnly());
750
+ void *node = boost::movelib::to_raw_pointer(chain.pop_front());
751
+ this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
752
+ return node;
405
753
  }
406
754
  }
407
755
 
408
- //!Deallocates an array pointed by ptr. Never throws
409
- void deallocate_node(void *pElem)
410
- {
411
- this->priv_invariants();
412
- block_info_t &block_info = *this->priv_block_from_node(pElem);
413
- BOOST_ASSERT(block_info.free_nodes.size() < m_real_num_node);
414
-
415
- //We put the node at the beginning of the free node list
416
- block_info.free_nodes.push_back(void_pointer(pElem));
417
-
418
- //The loop reinserts all blocks except the last one
419
- this->priv_reinsert_block(block_info, block_info.free_nodes.size() == 1);
420
- this->priv_deallocate_free_blocks(m_max_free_blocks);
421
- this->priv_invariants();
422
- }
423
-
424
- //!Allocates n nodes.
425
- //!Can throw
426
- void allocate_nodes(const size_type n, multiallocation_chain &chain)
756
+ void priv_allocate_nodes( const size_type n, multiallocation_chain &chain
757
+ , const size_type max_free_blocks, const size_type real_block_alignment, const size_type real_node_size
758
+ , const size_type real_num_node, const size_type num_subblocks)
427
759
  {
428
760
  size_type i = 0;
429
761
  BOOST_TRY{
430
- this->priv_invariants();
762
+ this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
431
763
  while(i != n){
432
764
  //If there are no free nodes we allocate all needed blocks
433
765
  if (m_block_container.empty()){
434
- this->priv_append_from_new_blocks(n - i, chain, IsAlignOnly());
766
+ this->priv_append_from_new_blocks
767
+ (n - i, chain, max_free_blocks, real_block_alignment, real_node_size, real_num_node, num_subblocks, IsAlignOnly());
435
768
  BOOST_ASSERT(m_block_container.empty() || (++m_block_container.cbegin() == m_block_container.cend()));
436
769
  BOOST_ASSERT(chain.size() == n);
437
770
  break;
438
771
  }
439
772
  free_nodes_t &free_nodes = m_block_container.begin()->free_nodes;
440
773
  const size_type free_nodes_count_before = free_nodes.size();
441
- m_totally_free_blocks -= static_cast<size_type>(free_nodes_count_before == m_real_num_node);
774
+ m_totally_free_blocks -= static_cast<size_type>(free_nodes_count_before == real_num_node);
442
775
  const size_type num_left = n-i;
443
776
  const size_type num_elems = (num_left < free_nodes_count_before) ? num_left : free_nodes_count_before;
444
777
  typedef typename free_nodes_t::iterator free_nodes_iterator;
@@ -466,17 +799,38 @@ class private_adaptive_node_pool_impl
466
799
  }
467
800
  }
468
801
  BOOST_CATCH(...){
469
- this->deallocate_nodes(chain);
802
+ this->priv_deallocate_nodes(chain, max_free_blocks, real_num_node, num_subblocks, real_block_alignment);
803
+ this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
470
804
  BOOST_RETHROW
471
805
  }
472
806
  BOOST_CATCH_END
473
- this->priv_invariants();
807
+ this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
474
808
  }
475
809
 
476
- //!Deallocates a linked list of nodes. Never throws
477
- void deallocate_nodes(multiallocation_chain &nodes)
810
+ //!Deallocates an array pointed by ptr. Never throws
811
+ void priv_deallocate_node( void *pElem
812
+ , const size_type max_free_blocks, const size_type real_num_node
813
+ , const size_type num_subblocks, const size_type real_block_alignment)
814
+ {
815
+ this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
816
+ block_info_t &block_info = *this->priv_block_from_node(pElem, real_block_alignment);
817
+ const size_type prev_free_nodes = block_info.free_nodes.size();
818
+ BOOST_ASSERT(block_info.free_nodes.size() < real_num_node);
819
+
820
+ //We put the node at the beginning of the free node list
821
+ block_info.free_nodes.push_back(void_pointer(pElem));
822
+
823
+ //The loop reinserts all blocks except the last one
824
+ this->priv_reinsert_block(block_info, prev_free_nodes == 0, real_num_node);
825
+ this->priv_deallocate_free_blocks(max_free_blocks, real_num_node, num_subblocks, real_block_alignment);
826
+ this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
827
+ }
828
+
829
+ void priv_deallocate_nodes( multiallocation_chain &nodes
830
+ , const size_type max_free_blocks, const size_type real_num_node
831
+ , const size_type num_subblocks, const size_type real_block_alignment)
478
832
  {
479
- this->priv_invariants();
833
+ this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
480
834
  //To take advantage of node locality, wait until two
481
835
  //nodes belong to different blocks. Only then reinsert
482
836
  //the block of the first node in the block tree.
@@ -493,8 +847,8 @@ class private_adaptive_node_pool_impl
493
847
  size_type splice_node_count = size_type(-1);
494
848
  while(itf != ite){
495
849
  void *pElem = boost::movelib::to_raw_pointer(boost::movelib::iterator_to_raw_pointer(itf));
496
- block_info_t &block_info = *this->priv_block_from_node(pElem);
497
- BOOST_ASSERT(block_info.free_nodes.size() < m_real_num_node);
850
+ block_info_t &block_info = *this->priv_block_from_node(pElem, real_block_alignment);
851
+ BOOST_ASSERT(block_info.free_nodes.size() < real_num_node);
498
852
  ++splice_node_count;
499
853
 
500
854
  //If block change is detected calculate the cached block position in the tree
@@ -503,7 +857,7 @@ class private_adaptive_node_pool_impl
503
857
  free_nodes_iterator it(itbb); ++it;
504
858
  nodes.erase_after(itbb, itf, splice_node_count);
505
859
  prev_block_info->free_nodes.incorporate_after(prev_block_info->free_nodes.last(), &*it, &*itbf, splice_node_count);
506
- this->priv_reinsert_block(*prev_block_info, prev_block_was_empty);
860
+ this->priv_reinsert_block(*prev_block_info, prev_block_was_empty, real_num_node);
507
861
  splice_node_count = 0;
508
862
  }
509
863
  //Update cache with new data
@@ -520,183 +874,50 @@ class private_adaptive_node_pool_impl
520
874
  const size_type splice_node_count = nodes.size();
521
875
  nodes.clear();
522
876
  prev_block_info->free_nodes.incorporate_after(prev_block_info->free_nodes.last(), &*itfirst, &*itlast, splice_node_count);
523
- this->priv_reinsert_block(*prev_block_info, prev_block_was_empty);
524
- this->priv_invariants();
525
- this->priv_deallocate_free_blocks(m_max_free_blocks);
877
+ this->priv_reinsert_block(*prev_block_info, prev_block_was_empty, real_num_node);
878
+ this->priv_deallocate_free_blocks(max_free_blocks, real_num_node, num_subblocks, real_block_alignment);
526
879
  }
880
+ this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
527
881
  }
528
882
 
529
- void deallocate_free_blocks()
530
- { this->priv_deallocate_free_blocks(0); }
531
-
532
- size_type num_free_nodes()
883
+ void priv_reinsert_block(block_info_t &prev_block_info, const bool prev_block_was_empty, const size_type real_num_node)
533
884
  {
534
- typedef typename block_container_t::const_iterator citerator;
535
- size_type count = 0;
536
- citerator it (m_block_container.begin()), itend(m_block_container.end());
537
- for(; it != itend; ++it){
538
- count += it->free_nodes.size();
885
+ //Cache the free nodes from the block
886
+ const size_type this_block_free_nodes = prev_block_info.free_nodes.size();
887
+ const bool is_full = this_block_free_nodes == real_num_node;
888
+
889
+ //Update free block count
890
+ m_totally_free_blocks += static_cast<size_type>(is_full);
891
+ if(prev_block_was_empty){
892
+ block_container_traits_t::insert_was_empty(m_block_container, prev_block_info, is_full);
893
+ }
894
+ else{
895
+ block_container_traits_t::reinsert_was_used(m_block_container, prev_block_info, is_full);
539
896
  }
540
- return count;
541
897
  }
542
898
 
543
- void swap(private_adaptive_node_pool_impl &other)
899
+ block_info_t *priv_block_from_node(void *node, const size_type real_block_alignment, AlignOnlyFalse) const
544
900
  {
545
- BOOST_ASSERT(m_max_free_blocks == other.m_max_free_blocks);
546
- BOOST_ASSERT(m_real_node_size == other.m_real_node_size);
547
- BOOST_ASSERT(m_real_block_alignment == other.m_real_block_alignment);
548
- BOOST_ASSERT(m_real_num_node == other.m_real_num_node);
549
- std::swap(mp_segment_mngr_base, other.mp_segment_mngr_base);
550
- std::swap(m_totally_free_blocks, other.m_totally_free_blocks);
551
- m_block_container.swap(other.m_block_container);
901
+ hdr_offset_holder *hdr_off_holder =
902
+ reinterpret_cast<hdr_offset_holder*>((std::size_t)node & size_type(~(real_block_alignment - 1)));
903
+ BOOST_ASSERT(0 == ((std::size_t)hdr_off_holder & (real_block_alignment - 1)));
904
+ BOOST_ASSERT(0 == (hdr_off_holder->hdr_offset & (real_block_alignment - 1)));
905
+ block_info_t *block = reinterpret_cast<block_info_t *>
906
+ (reinterpret_cast<char*>(hdr_off_holder) + hdr_off_holder->hdr_offset);
907
+ BOOST_ASSERT(block->hdr_offset == 0);
908
+ return block;
552
909
  }
553
910
 
554
- //Deprecated, use deallocate_free_blocks
555
- void deallocate_free_chunks()
556
- { this->priv_deallocate_free_blocks(0); }
911
+ block_info_t *priv_block_from_node(void *node, const size_type real_block_alignment, AlignOnlyTrue) const
912
+ {
913
+ return (block_info_t *)((std::size_t)node & std::size_t(~(real_block_alignment - 1)));
914
+ }
557
915
 
558
- private:
559
-
560
- void priv_deallocate_free_blocks(size_type max_free_blocks)
561
- { //Trampoline function to ease inlining
562
- if(m_totally_free_blocks > max_free_blocks){
563
- this->priv_deallocate_free_blocks_impl(max_free_blocks);
564
- }
565
- }
566
-
567
- void priv_deallocate_free_blocks_impl(size_type max_free_blocks)
568
- {
569
- this->priv_invariants();
570
- //Now check if we've reached the free nodes limit
571
- //and check if we have free blocks. If so, deallocate as much
572
- //as we can to stay below the limit
573
- multiallocation_chain chain;
574
- {
575
- const const_block_iterator itend = m_block_container.cend();
576
- const_block_iterator it = itend;
577
- --it;
578
- size_type totally_free_blocks = m_totally_free_blocks;
579
-
580
- for( ; totally_free_blocks > max_free_blocks; --totally_free_blocks){
581
- BOOST_ASSERT(it->free_nodes.size() == m_real_num_node);
582
- void *addr = priv_first_subblock_from_block(const_cast<block_info_t*>(&*it));
583
- --it;
584
- block_container_traits_t::erase_last(m_block_container);
585
- chain.push_front(void_pointer(addr));
586
- }
587
- BOOST_ASSERT((m_totally_free_blocks - max_free_blocks) == chain.size());
588
- m_totally_free_blocks = max_free_blocks;
589
- }
590
- this->mp_segment_mngr_base->deallocate_many(chain);
591
- }
592
-
593
- void priv_reinsert_block(block_info_t &prev_block_info, const bool prev_block_was_empty)
594
- {
595
- //Cache the free nodes from the block
596
- const size_type this_block_free_nodes = prev_block_info.free_nodes.size();
597
- const bool is_full = this_block_free_nodes == m_real_num_node;
598
-
599
- //Update free block count
600
- m_totally_free_blocks += static_cast<size_type>(is_full);
601
- if(prev_block_was_empty){
602
- block_container_traits_t::insert_was_empty(m_block_container, prev_block_info, is_full);
603
- }
604
- else{
605
- block_container_traits_t::reinsert_was_used(m_block_container, prev_block_info, is_full);
606
- }
607
- }
608
-
609
- class block_destroyer;
610
- friend class block_destroyer;
611
-
612
- class block_destroyer
613
- {
614
- public:
615
- block_destroyer(const this_type *impl, multiallocation_chain &chain)
616
- : mp_impl(impl), m_chain(chain)
617
- {}
618
-
619
- void operator()(typename block_container_t::pointer to_deallocate)
620
- { return this->do_destroy(to_deallocate, IsAlignOnly()); }
621
-
622
- private:
623
- void do_destroy(typename block_container_t::pointer to_deallocate, AlignOnlyTrue)
624
- {
625
- BOOST_ASSERT(to_deallocate->free_nodes.size() == mp_impl->m_real_num_node);
626
- m_chain.push_back(to_deallocate);
627
- }
628
-
629
- void do_destroy(typename block_container_t::pointer to_deallocate, AlignOnlyFalse)
630
- {
631
- BOOST_ASSERT(to_deallocate->free_nodes.size() == mp_impl->m_real_num_node);
632
- BOOST_ASSERT(0 == to_deallocate->hdr_offset);
633
- hdr_offset_holder *hdr_off_holder =
634
- mp_impl->priv_first_subblock_from_block(boost::movelib::to_raw_pointer(to_deallocate));
635
- m_chain.push_back(hdr_off_holder);
636
- }
637
-
638
- const this_type *mp_impl;
639
- multiallocation_chain &m_chain;
640
- };
641
-
642
- //This macro will activate invariant checking. Slow, but helpful for debugging the code.
643
- //#define BOOST_CONTAINER_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS
644
- void priv_invariants()
645
- #ifdef BOOST_CONTAINER_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS
646
- #undef BOOST_CONTAINER_ADAPTIVE_NODE_POOL_CHECK_INVARIANTS
647
- {
648
- const const_block_iterator itend(m_block_container.end());
649
-
650
- { //We iterate through the block tree to free the memory
651
- const_block_iterator it(m_block_container.begin());
652
-
653
- if(it != itend){
654
- for(++it; it != itend; ++it){
655
- const_block_iterator prev(it);
656
- --prev;
657
- BOOST_ASSERT(*prev < *it);
658
- (void)prev; (void)it;
659
- }
660
- }
661
- }
662
- { //Check that the total free nodes are correct
663
- const_block_iterator it(m_block_container.cbegin());
664
- size_type total_free_nodes = 0;
665
- for(; it != itend; ++it){
666
- total_free_nodes += it->free_nodes.size();
667
- }
668
- BOOST_ASSERT(total_free_nodes >= m_totally_free_blocks*m_real_num_node);
669
- }
670
- { //Check that the total totally free blocks are correct
671
- BOOST_ASSERT(m_block_container.size() >= m_totally_free_blocks);
672
- const_block_iterator it = m_block_container.cend();
673
- size_type total_free_blocks = m_totally_free_blocks;
674
- while(total_free_blocks--){
675
- BOOST_ASSERT((--it)->free_nodes.size() == m_real_num_node);
676
- }
677
- }
678
-
679
- if(!AlignOnly){
680
- //Check that header offsets are correct
681
- const_block_iterator it = m_block_container.begin();
682
- for(; it != itend; ++it){
683
- hdr_offset_holder *hdr_off_holder = this->priv_first_subblock_from_block(const_cast<block_info_t *>(&*it));
684
- for(size_type i = 0, max = m_num_subblocks; i < max; ++i){
685
- const size_type offset = reinterpret_cast<char*>(const_cast<block_info_t *>(&*it)) - reinterpret_cast<char*>(hdr_off_holder);
686
- BOOST_ASSERT(hdr_off_holder->hdr_offset == offset);
687
- BOOST_ASSERT(0 == ((size_type)hdr_off_holder & (m_real_block_alignment - 1)));
688
- BOOST_ASSERT(0 == (hdr_off_holder->hdr_offset & (m_real_block_alignment - 1)));
689
- hdr_off_holder = reinterpret_cast<hdr_offset_holder *>(reinterpret_cast<char*>(hdr_off_holder) + m_real_block_alignment);
690
- }
691
- }
692
- }
693
- }
694
- #else
695
- {} //empty
696
- #endif
916
+ block_info_t *priv_block_from_node(void *node, const size_type real_block_alignment) const
917
+ { return this->priv_block_from_node(node, real_block_alignment, IsAlignOnly()); }
697
918
 
698
919
  //!Deallocates all used memory. Never throws
699
- void priv_clear()
920
+ void priv_clear(const size_type num_subblocks, const size_type real_block_alignment, const size_type real_num_node)
700
921
  {
701
922
  #ifndef NDEBUG
702
923
  block_iterator it = m_block_container.begin();
@@ -704,176 +925,329 @@ class private_adaptive_node_pool_impl
704
925
  size_type n_free_nodes = 0;
705
926
  for(; it != itend; ++it){
706
927
  //Check for memory leak
707
- BOOST_ASSERT(it->free_nodes.size() == m_real_num_node);
928
+ BOOST_ASSERT(it->free_nodes.size() == real_num_node);
708
929
  ++n_free_nodes;
709
930
  }
710
931
  BOOST_ASSERT(n_free_nodes == m_totally_free_blocks);
711
932
  #endif
712
933
  //Check for memory leaks
713
- this->priv_invariants();
934
+ this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
714
935
  multiallocation_chain chain;
715
- m_block_container.clear_and_dispose(block_destroyer(this, chain));
936
+ m_block_container.clear_and_dispose(block_destroyer(this, chain, num_subblocks, real_block_alignment, real_num_node));
716
937
  this->mp_segment_mngr_base->deallocate_many(chain);
717
938
  m_totally_free_blocks = 0;
939
+ this->priv_invariants(real_num_node, num_subblocks, real_block_alignment);
718
940
  }
719
941
 
720
- block_info_t *priv_block_from_node(void *node, AlignOnlyFalse) const
942
+ public:
943
+ private_adaptive_node_pool_impl_common(segment_manager_base_type *segment_mngr_base)
944
+ //General purpose allocator
945
+ : mp_segment_mngr_base(segment_mngr_base)
946
+ , m_block_container()
947
+ , m_totally_free_blocks(0)
948
+ {}
949
+
950
+ size_type num_free_nodes()
721
951
  {
722
- hdr_offset_holder *hdr_off_holder =
723
- reinterpret_cast<hdr_offset_holder*>((std::size_t)node & size_type(~(m_real_block_alignment - 1)));
724
- BOOST_ASSERT(0 == ((std::size_t)hdr_off_holder & (m_real_block_alignment - 1)));
725
- BOOST_ASSERT(0 == (hdr_off_holder->hdr_offset & (m_real_block_alignment - 1)));
726
- block_info_t *block = reinterpret_cast<block_info_t *>
727
- (reinterpret_cast<char*>(hdr_off_holder) + hdr_off_holder->hdr_offset);
728
- BOOST_ASSERT(block->hdr_offset == 0);
729
- return block;
952
+ typedef typename block_container_t::const_iterator citerator;
953
+ size_type count = 0;
954
+ citerator it (m_block_container.begin()), itend(m_block_container.end());
955
+ for(; it != itend; ++it){
956
+ count += it->free_nodes.size();
957
+ }
958
+ return count;
730
959
  }
731
960
 
732
- block_info_t *priv_block_from_node(void *node, AlignOnlyTrue) const
961
+ void swap(private_adaptive_node_pool_impl_common &other)
733
962
  {
734
- return (block_info_t *)((std::size_t)node & std::size_t(~(m_real_block_alignment - 1)));
963
+ std::swap(mp_segment_mngr_base, other.mp_segment_mngr_base);
964
+ std::swap(m_totally_free_blocks, other.m_totally_free_blocks);
965
+ m_block_container.swap(other.m_block_container);
735
966
  }
736
967
 
737
- block_info_t *priv_block_from_node(void *node) const
738
- { return this->priv_block_from_node(node, IsAlignOnly()); }
968
+ //!Returns the segment manager. Never throws
969
+ segment_manager_base_type* get_segment_manager_base()const
970
+ { return boost::movelib::to_raw_pointer(mp_segment_mngr_base); }
971
+ };
972
+
973
+ template< class SizeType
974
+ , std::size_t HdrSize
975
+ , std::size_t PayloadPerAllocation
976
+ , std::size_t RealNodeSize
977
+ , std::size_t NodesPerBlock
978
+ , std::size_t HdrOffsetSize
979
+ , std::size_t OverheadPercent
980
+ , bool AlignOnly>
981
+ struct calculate_alignment_ct
982
+ {
983
+ static const std::size_t alignment = upper_power_of_2_ct<SizeType, HdrSize + RealNodeSize*NodesPerBlock>::value;
984
+ static const std::size_t num_subblocks = 0;
985
+ static const std::size_t real_num_node = (alignment - PayloadPerAllocation - HdrSize)/RealNodeSize;
986
+ };
987
+
988
+ template< class SizeType
989
+ , std::size_t HdrSize
990
+ , std::size_t PayloadPerAllocation
991
+ , std::size_t RealNodeSize
992
+ , std::size_t NodesPerBlock
993
+ , std::size_t HdrOffsetSize
994
+ , std::size_t OverheadPercent>
995
+ struct calculate_alignment_ct
996
+ < SizeType
997
+ , HdrSize
998
+ , PayloadPerAllocation
999
+ , RealNodeSize
1000
+ , NodesPerBlock
1001
+ , HdrOffsetSize
1002
+ , OverheadPercent
1003
+ , false>
1004
+ {
1005
+ typedef typename candidate_power_of_2_ct
1006
+ < upper_power_of_2_ct<SizeType, HdrSize + PayloadPerAllocation + RealNodeSize>::value
1007
+ , RealNodeSize
1008
+ , PayloadPerAllocation
1009
+ , NodesPerBlock
1010
+ , HdrSize
1011
+ , HdrOffsetSize
1012
+ , OverheadPercent
1013
+ >::type type;
1014
+
1015
+ static const std::size_t alignment = type::alignment;
1016
+ static const std::size_t num_subblocks = type::num_subblocks;
1017
+ static const std::size_t real_num_node = type::real_num_node;
1018
+ };
1019
+
1020
+
1021
+ /////////////////////////////////////////////
1022
+ //
1023
+ // private_adaptive_node_pool_impl_ct
1024
+ //
1025
+ /////////////////////////////////////////////
1026
+ template< class SegmentManagerBase
1027
+ , std::size_t MaxFreeBlocks
1028
+ , std::size_t NodeSize
1029
+ , std::size_t NodesPerBlock
1030
+ , std::size_t OverheadPercent
1031
+ , unsigned int Flags>
1032
+ class private_adaptive_node_pool_impl_ct
1033
+ : public private_adaptive_node_pool_impl_common<SegmentManagerBase, Flags>
1034
+ {
1035
+ typedef private_adaptive_node_pool_impl_common<SegmentManagerBase, Flags> base_t;
1036
+
1037
+ //Non-copyable
1038
+ private_adaptive_node_pool_impl_ct();
1039
+ private_adaptive_node_pool_impl_ct(const private_adaptive_node_pool_impl_ct &);
1040
+ private_adaptive_node_pool_impl_ct &operator=(const private_adaptive_node_pool_impl_ct &);
1041
+
1042
+ public:
1043
+ typedef typename base_t::void_pointer void_pointer;
1044
+ typedef typename base_t::size_type size_type;
1045
+ typedef typename base_t::multiallocation_chain multiallocation_chain;
1046
+ typedef typename base_t::segment_manager_base_type segment_manager_base_type;
1047
+
1048
+ static const typename base_t::size_type PayloadPerAllocation = base_t::PayloadPerAllocation;
1049
+
1050
+ //align_only
1051
+ static const bool AlignOnly = base_t::AlignOnly;
1052
+
1053
+ private:
1054
+ static const size_type MaxAlign = base_t::MaxAlign;
1055
+ static const size_type HdrSize = base_t::HdrSize;
1056
+ static const size_type HdrOffsetSize = base_t::HdrOffsetSize;
1057
+
1058
+ static const size_type RealNodeSize = lcm_ct<NodeSize, alignment_of<void_pointer>::value>::value;
1059
+
1060
+ typedef calculate_alignment_ct
1061
+ < size_type, HdrSize, PayloadPerAllocation
1062
+ , RealNodeSize, NodesPerBlock, HdrOffsetSize, OverheadPercent, AlignOnly> data_t;
1063
+
1064
+ //Round the size to a power of two value.
1065
+ //This is the total memory size (including payload) that we want to
1066
+ //allocate from the general-purpose allocator
1067
+ static const size_type NumSubBlocks = data_t::num_subblocks;
1068
+ static const size_type RealNumNode = data_t::real_num_node;
1069
+ static const size_type RealBlockAlignment = data_t::alignment;
739
1070
 
740
- hdr_offset_holder *priv_first_subblock_from_block(block_info_t *block) const
741
- { return this->priv_first_subblock_from_block(block, IsAlignOnly()); }
1071
+ public:
742
1072
 
743
- hdr_offset_holder *priv_first_subblock_from_block(block_info_t *block, AlignOnlyFalse) const
1073
+ //!Constructor from a segment manager. Never throws
1074
+ private_adaptive_node_pool_impl_ct(typename base_t::segment_manager_base_type *segment_mngr_base)
1075
+ //General purpose allocator
1076
+ : base_t(segment_mngr_base)
1077
+ {}
1078
+
1079
+ //!Destructor. Deallocates all allocated blocks. Never throws
1080
+ ~private_adaptive_node_pool_impl_ct()
1081
+ { this->priv_clear(NumSubBlocks, data_t::alignment, RealNumNode); }
1082
+
1083
+ size_type get_real_num_node() const
1084
+ { return RealNumNode; }
1085
+
1086
+ //!Allocates array of count elements. Can throw
1087
+ void *allocate_node()
744
1088
  {
745
- hdr_offset_holder *const hdr_off_holder = reinterpret_cast<hdr_offset_holder*>
746
- (reinterpret_cast<char*>(block) - (m_num_subblocks-1)*m_real_block_alignment);
747
- BOOST_ASSERT(hdr_off_holder->hdr_offset == size_type(reinterpret_cast<char*>(block) - reinterpret_cast<char*>(hdr_off_holder)));
748
- BOOST_ASSERT(0 == ((std::size_t)hdr_off_holder & (m_real_block_alignment - 1)));
749
- BOOST_ASSERT(0 == (hdr_off_holder->hdr_offset & (m_real_block_alignment - 1)));
750
- return hdr_off_holder;
1089
+ return this->priv_allocate_node
1090
+ (MaxFreeBlocks, data_t::alignment, RealNodeSize, RealNumNode, NumSubBlocks);
751
1091
  }
752
1092
 
753
- hdr_offset_holder *priv_first_subblock_from_block(block_info_t *block, AlignOnlyTrue) const
1093
+ //!Allocates n nodes.
1094
+ //!Can throw
1095
+ void allocate_nodes(const size_type n, multiallocation_chain &chain)
754
1096
  {
755
- return reinterpret_cast<hdr_offset_holder*>(block);
1097
+ this->priv_allocate_nodes
1098
+ (n, chain, MaxFreeBlocks, data_t::alignment, RealNodeSize, RealNumNode, NumSubBlocks);
756
1099
  }
757
1100
 
758
- void priv_dispatch_block_chain_or_free
759
- ( multiallocation_chain &chain, block_info_t &c_info, size_type num_node
760
- , char *mem_address, size_type total_elements, bool insert_block_if_free)
1101
+ //!Deallocates an array pointed by ptr. Never throws
1102
+ void deallocate_node(void *pElem)
761
1103
  {
762
- BOOST_ASSERT(chain.size() <= total_elements);
763
- //First add all possible nodes to the chain
764
- const size_type left = total_elements - chain.size();
765
- const size_type max_chain = (num_node < left) ? num_node : left;
766
- mem_address = static_cast<char *>(boost::movelib::to_raw_pointer
767
- (chain.incorporate_after(chain.last(), void_pointer(mem_address), m_real_node_size, max_chain)));
768
- //Now store remaining nodes in the free list
769
- if(const size_type max_free = num_node - max_chain){
770
- free_nodes_t & free_nodes = c_info.free_nodes;
771
- free_nodes.incorporate_after(free_nodes.last(), void_pointer(mem_address), m_real_node_size, max_free);
772
- if(insert_block_if_free){
773
- m_block_container.push_front(c_info);
774
- }
775
- }
1104
+ this->priv_deallocate_node(pElem, MaxFreeBlocks, RealNumNode, NumSubBlocks, RealBlockAlignment);
776
1105
  }
777
1106
 
778
- //!Allocates a several blocks of nodes. Can throw
779
- void priv_append_from_new_blocks(size_type min_elements, multiallocation_chain &chain, AlignOnlyTrue)
1107
+ //!Deallocates a linked list of nodes. Never throws
1108
+ void deallocate_nodes(multiallocation_chain &nodes)
780
1109
  {
781
- BOOST_ASSERT(m_block_container.empty());
782
- BOOST_ASSERT(min_elements > 0);
783
- const size_type n = (min_elements - 1)/m_real_num_node + 1;
784
- const size_type real_block_size = m_real_block_alignment - PayloadPerAllocation;
785
- const size_type total_elements = chain.size() + min_elements;
786
- for(size_type i = 0; i != n; ++i){
787
- //We allocate a new NodeBlock and put it the last
788
- //element of the tree
789
- char *mem_address = static_cast<char*>
790
- (mp_segment_mngr_base->allocate_aligned(real_block_size, m_real_block_alignment));
791
- if(!mem_address){
792
- //In case of error, free memory deallocating all nodes (the new ones allocated
793
- //in this function plus previously stored nodes in chain).
794
- this->deallocate_nodes(chain);
795
- throw_bad_alloc();
796
- }
797
- block_info_t &c_info = *new(mem_address)block_info_t();
798
- mem_address += HdrSize;
799
- if(i != (n-1)){
800
- chain.incorporate_after(chain.last(), void_pointer(mem_address), m_real_node_size, m_real_num_node);
801
- }
802
- else{
803
- this->priv_dispatch_block_chain_or_free(chain, c_info, m_real_num_node, mem_address, total_elements, true);
804
- }
805
- }
1110
+ this->priv_deallocate_nodes(nodes, MaxFreeBlocks, RealNumNode, NumSubBlocks, data_t::alignment);
806
1111
  }
807
1112
 
808
- void priv_append_from_new_blocks(size_type min_elements, multiallocation_chain &chain, AlignOnlyFalse)
809
- {
810
- BOOST_ASSERT(m_block_container.empty());
811
- BOOST_ASSERT(min_elements > 0);
812
- const size_type n = (min_elements - 1)/m_real_num_node + 1;
813
- const size_type real_block_size = m_real_block_alignment*m_num_subblocks - PayloadPerAllocation;
814
- const size_type elements_per_subblock = (m_real_block_alignment - HdrOffsetSize)/m_real_node_size;
815
- const size_type hdr_subblock_elements = (m_real_block_alignment - HdrSize - PayloadPerAllocation)/m_real_node_size;
816
- const size_type total_elements = chain.size() + min_elements;
1113
+ void deallocate_free_blocks()
1114
+ { this->priv_deallocate_free_blocks(0, RealNumNode, NumSubBlocks, data_t::alignment); }
817
1115
 
818
- for(size_type i = 0; i != n; ++i){
819
- //We allocate a new NodeBlock and put it the last
820
- //element of the tree
821
- char *mem_address = static_cast<char*>
822
- (mp_segment_mngr_base->allocate_aligned(real_block_size, m_real_block_alignment));
823
- if(!mem_address){
824
- //In case of error, free memory deallocating all nodes (the new ones allocated
825
- //in this function plus previously stored nodes in chain).
826
- this->deallocate_nodes(chain);
827
- throw_bad_alloc();
828
- }
829
- //First initialize header information on the last subblock
830
- char *hdr_addr = mem_address + m_real_block_alignment*(m_num_subblocks-1);
831
- block_info_t &c_info = *new(hdr_addr)block_info_t();
832
- //Some structural checks
833
- BOOST_ASSERT(static_cast<void*>(&static_cast<hdr_offset_holder&>(c_info).hdr_offset) ==
834
- static_cast<void*>(&c_info)); (void)c_info;
835
- if(i != (n-1)){
836
- for( size_type subblock = 0, maxsubblock = m_num_subblocks - 1
837
- ; subblock < maxsubblock
838
- ; ++subblock, mem_address += m_real_block_alignment){
839
- //Initialize header offset mark
840
- new(mem_address) hdr_offset_holder(size_type(hdr_addr - mem_address));
841
- chain.incorporate_after
842
- (chain.last(), void_pointer(mem_address + HdrOffsetSize), m_real_node_size, elements_per_subblock);
843
- }
844
- chain.incorporate_after(chain.last(), void_pointer(hdr_addr + HdrSize), m_real_node_size, hdr_subblock_elements);
845
- }
846
- else{
847
- for( size_type subblock = 0, maxsubblock = m_num_subblocks - 1
848
- ; subblock < maxsubblock
849
- ; ++subblock, mem_address += m_real_block_alignment){
850
- //Initialize header offset mark
851
- new(mem_address) hdr_offset_holder(size_type(hdr_addr - mem_address));
852
- this->priv_dispatch_block_chain_or_free
853
- (chain, c_info, elements_per_subblock, mem_address + HdrOffsetSize, total_elements, false);
854
- }
855
- this->priv_dispatch_block_chain_or_free
856
- (chain, c_info, hdr_subblock_elements, hdr_addr + HdrSize, total_elements, true);
857
- }
858
- }
859
- }
1116
+ //Deprecated, use deallocate_free_blocks
1117
+ void deallocate_free_chunks()
1118
+ { this->priv_deallocate_free_blocks(0, RealNumNode, NumSubBlocks, data_t::alignment); }
1119
+ };
1120
+
1121
+ /////////////////////////////////////////////
1122
+ //
1123
+ // private_adaptive_node_pool_impl_rt
1124
+ //
1125
+ /////////////////////////////////////////////
1126
+ template<class SizeType>
1127
+ struct private_adaptive_node_pool_impl_rt_data
1128
+ {
1129
+ typedef SizeType size_type;
1130
+
1131
+ private_adaptive_node_pool_impl_rt_data(size_type max_free_blocks, size_type real_node_size)
1132
+ : m_max_free_blocks(max_free_blocks), m_real_node_size(real_node_size)
1133
+ , m_real_block_alignment(), m_num_subblocks(), m_real_num_node()
1134
+ {}
860
1135
 
861
- private:
862
- typedef typename boost::intrusive::pointer_traits
863
- <void_pointer>::template rebind_pointer<segment_manager_base_type>::type segment_mngr_base_ptr_t;
864
1136
  const size_type m_max_free_blocks;
865
1137
  const size_type m_real_node_size;
866
1138
  //Round the size to a power of two value.
867
1139
  //This is the total memory size (including payload) that we want to
868
1140
  //allocate from the general-purpose allocator
869
- const size_type m_real_block_alignment;
1141
+ size_type m_real_block_alignment;
870
1142
  size_type m_num_subblocks;
871
1143
  //This is the real number of nodes per block
872
- //const
873
1144
  size_type m_real_num_node;
874
- segment_mngr_base_ptr_t mp_segment_mngr_base; //Segment manager
875
- block_container_t m_block_container; //Intrusive block list
876
- size_type m_totally_free_blocks; //Free blocks
1145
+ };
1146
+
1147
+
1148
+ template<class SegmentManagerBase, unsigned int Flags>
1149
+ class private_adaptive_node_pool_impl_rt
1150
+ : private private_adaptive_node_pool_impl_rt_data<typename SegmentManagerBase::size_type>
1151
+ , public private_adaptive_node_pool_impl_common<SegmentManagerBase, Flags>
1152
+ {
1153
+ typedef private_adaptive_node_pool_impl_common<SegmentManagerBase, Flags> impl_t;
1154
+ typedef private_adaptive_node_pool_impl_rt_data<typename SegmentManagerBase::size_type> data_t;
1155
+
1156
+ //Non-copyable
1157
+ private_adaptive_node_pool_impl_rt();
1158
+ private_adaptive_node_pool_impl_rt(const private_adaptive_node_pool_impl_rt &);
1159
+ private_adaptive_node_pool_impl_rt &operator=(const private_adaptive_node_pool_impl_rt &);
1160
+
1161
+ protected:
1162
+
1163
+ typedef typename impl_t::void_pointer void_pointer;
1164
+ typedef typename impl_t::size_type size_type;
1165
+ typedef typename impl_t::multiallocation_chain multiallocation_chain;
1166
+
1167
+ static const typename impl_t::size_type PayloadPerAllocation = impl_t::PayloadPerAllocation;
1168
+
1169
+ //Flags
1170
+ //align_only
1171
+ static const bool AlignOnly = impl_t::AlignOnly;
1172
+
1173
+ static const size_type HdrSize = impl_t::HdrSize;
1174
+ static const size_type HdrOffsetSize = impl_t::HdrOffsetSize;
1175
+
1176
+ public:
1177
+
1178
+ //!Segment manager typedef
1179
+ typedef SegmentManagerBase segment_manager_base_type;
1180
+
1181
+ //!Constructor from a segment manager. Never throws
1182
+ private_adaptive_node_pool_impl_rt
1183
+ ( segment_manager_base_type *segment_mngr_base
1184
+ , size_type node_size
1185
+ , size_type nodes_per_block
1186
+ , size_type max_free_blocks
1187
+ , unsigned char overhead_percent
1188
+ )
1189
+ : data_t(max_free_blocks, lcm(node_size, size_type(alignment_of<void_pointer>::value)))
1190
+ , impl_t(segment_mngr_base)
1191
+ {
1192
+ if(AlignOnly){
1193
+ this->m_real_block_alignment = upper_power_of_2(HdrSize + this->m_real_node_size*nodes_per_block);
1194
+ this->m_real_num_node = (this->m_real_block_alignment - PayloadPerAllocation - HdrSize)/this->m_real_node_size;
1195
+ }
1196
+ else{
1197
+ candidate_power_of_2_rt ( upper_power_of_2(HdrSize + PayloadPerAllocation + this->m_real_node_size)
1198
+ , this->m_real_node_size
1199
+ , PayloadPerAllocation
1200
+ , nodes_per_block
1201
+ , HdrSize
1202
+ , HdrOffsetSize
1203
+ , overhead_percent
1204
+ , this->m_real_block_alignment
1205
+ , this->m_num_subblocks
1206
+ , this->m_real_num_node);
1207
+ }
1208
+ }
1209
+
1210
+ //!Destructor. Deallocates all allocated blocks. Never throws
1211
+ ~private_adaptive_node_pool_impl_rt()
1212
+ { this->priv_clear(this->m_num_subblocks, this->m_real_block_alignment, this->m_real_num_node); }
1213
+
1214
+ size_type get_real_num_node() const
1215
+ { return this->m_real_num_node; }
1216
+
1217
+ //!Allocates array of count elements. Can throw
1218
+ void *allocate_node()
1219
+ {
1220
+ return this->priv_allocate_node
1221
+ (this->m_max_free_blocks, this->m_real_block_alignment, this->m_real_node_size, this->m_real_num_node, this->m_num_subblocks);
1222
+ }
1223
+
1224
+ //!Allocates n nodes.
1225
+ //!Can throw
1226
+ void allocate_nodes(const size_type n, multiallocation_chain &chain)
1227
+ {
1228
+
1229
+ this->priv_allocate_nodes
1230
+ (n, chain, this->m_max_free_blocks, this->m_real_block_alignment, this->m_real_node_size, this->m_real_num_node, this->m_num_subblocks);
1231
+ }
1232
+
1233
+ //!Deallocates an array pointed by ptr. Never throws
1234
+ void deallocate_node(void *pElem)
1235
+ {
1236
+ this->priv_deallocate_node(pElem, this->m_max_free_blocks, this->m_real_num_node, this->m_num_subblocks, this->m_real_block_alignment);
1237
+ }
1238
+
1239
+ //!Deallocates a linked list of nodes. Never throws
1240
+ void deallocate_nodes(multiallocation_chain &nodes)
1241
+ {
1242
+ this->priv_deallocate_nodes(nodes, this->m_max_free_blocks, this->m_real_num_node, this->m_num_subblocks, this->m_real_block_alignment);
1243
+ }
1244
+
1245
+ void deallocate_free_blocks()
1246
+ { this->priv_deallocate_free_blocks(0, this->m_real_num_node, this->m_num_subblocks, this->m_real_block_alignment); }
1247
+
1248
+ //Deprecated, use deallocate_free_blocks
1249
+ void deallocate_free_chunks()
1250
+ { this->priv_deallocate_free_blocks(0, this->m_real_num_node, this->m_num_subblocks, this->m_real_block_alignment); }
877
1251
  };
878
1252
 
879
1253
  } //namespace dtl {