passenger 6.0.1 → 6.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 {