passenger 3.0.21 → 3.9.1.beta

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of passenger might be problematic. Click here for more details.

Files changed (835) hide show
  1. data/DEVELOPERS.TXT +4 -10
  2. data/NEWS +19 -27
  3. data/Rakefile +20 -19
  4. data/bin/passenger +3 -2
  5. data/bin/passenger-config +35 -5
  6. data/bin/passenger-install-apache2-module +12 -12
  7. data/bin/passenger-install-nginx-module +55 -38
  8. data/bin/passenger-memory-stats +3 -1
  9. data/bin/passenger-status +7 -35
  10. data/build/agents.rb +107 -21
  11. data/build/apache2.rb +11 -46
  12. data/build/basics.rb +61 -9
  13. data/build/common_library.rb +59 -142
  14. data/build/cxx_tests.rb +111 -110
  15. data/build/documentation.rb +33 -0
  16. data/build/misc.rb +30 -12
  17. data/build/nginx.rb +10 -39
  18. data/build/oxt_tests.rb +1 -0
  19. data/build/ruby_extension.rb +1 -5
  20. data/build/test_basics.rb +3 -2
  21. data/dev/copy_boost_headers.rb +2 -1
  22. data/doc/Architectural overview.html +49 -90
  23. data/doc/DebuggingAndStressTesting.txt.md +49 -0
  24. data/doc/Packaging.txt.md +254 -0
  25. data/doc/Security of user switching support.html +35 -66
  26. data/doc/Users guide Apache.html +588 -758
  27. data/doc/Users guide Apache.idmap.txt +253 -136
  28. data/doc/Users guide Apache.txt +154 -109
  29. data/doc/Users guide Nginx.html +544 -660
  30. data/doc/Users guide Nginx.idmap.txt +179 -91
  31. data/doc/Users guide Nginx.txt +192 -118
  32. data/doc/Users guide Standalone.html +65 -48
  33. data/doc/Users guide Standalone.idmap.txt +10 -2
  34. data/doc/Users guide Standalone.txt +4 -0
  35. data/doc/images/glyphicons-halflings-white.png +0 -0
  36. data/doc/images/glyphicons-halflings.png +0 -0
  37. data/doc/images/phusion_banner_small.png +0 -0
  38. data/doc/images/{smart-lv2.png → smart.png} +0 -0
  39. data/doc/images/{smart-lv2.svg → smart.svg} +0 -0
  40. data/doc/templates/bootstrap.min.css +397 -0
  41. data/doc/templates/markdown.html.erb +117 -0
  42. data/doc/users_guide_snippets/analysis_and_system_maintenance.txt +2 -1
  43. data/doc/users_guide_snippets/appendix_c_spawning_methods.txt +26 -48
  44. data/doc/users_guide_snippets/passenger_spawn_method.txt +18 -30
  45. data/doc/users_guide_snippets/support_information.txt +30 -0
  46. data/ext/apache2/Bucket.cpp +9 -26
  47. data/ext/apache2/Bucket.h +13 -10
  48. data/ext/apache2/Configuration.cpp +70 -58
  49. data/ext/apache2/Configuration.hpp +19 -47
  50. data/ext/apache2/DirectoryMapper.h +7 -7
  51. data/ext/apache2/Hooks.cpp +150 -313
  52. data/ext/boost/algorithm/string/detail/case_conv.hpp +4 -2
  53. data/ext/boost/algorithm/string/detail/find_format.hpp +20 -20
  54. data/ext/boost/algorithm/string/detail/find_format_all.hpp +23 -23
  55. data/ext/boost/algorithm/string/detail/find_format_store.hpp +2 -2
  56. data/ext/boost/algorithm/string/detail/formatter.hpp +25 -0
  57. data/ext/boost/algorithm/string/formatter.hpp +20 -3
  58. data/ext/boost/assert.hpp +85 -4
  59. data/ext/boost/bind/bind.hpp +1 -1
  60. data/ext/boost/concept/detail/backward_compatibility.hpp +1 -1
  61. data/ext/boost/concept_check.hpp +140 -64
  62. data/ext/boost/config.hpp +1 -1
  63. data/ext/boost/config/auto_link.hpp +8 -6
  64. data/ext/boost/config/compiler/borland.hpp +12 -2
  65. data/ext/boost/config/compiler/clang.hpp +89 -30
  66. data/ext/boost/config/compiler/codegear.hpp +3 -2
  67. data/ext/boost/config/compiler/common_edg.hpp +7 -5
  68. data/ext/boost/config/compiler/cray.hpp +61 -0
  69. data/ext/boost/config/compiler/digitalmars.hpp +9 -1
  70. data/ext/boost/config/compiler/gcc.hpp +33 -24
  71. data/ext/boost/config/compiler/gcc_xml.hpp +4 -0
  72. data/ext/boost/config/compiler/hp_acc.hpp +12 -1
  73. data/ext/boost/config/compiler/intel.hpp +78 -4
  74. data/ext/boost/config/compiler/metrowerks.hpp +4 -1
  75. data/ext/boost/config/compiler/mpw.hpp +4 -1
  76. data/ext/boost/config/compiler/nvcc.hpp +8 -66
  77. data/ext/boost/config/compiler/pathscale.hpp +80 -0
  78. data/ext/boost/config/compiler/pgi.hpp +5 -5
  79. data/ext/boost/config/compiler/sunpro_cc.hpp +4 -1
  80. data/ext/boost/config/compiler/vacpp.hpp +37 -13
  81. data/ext/boost/config/compiler/visualc.hpp +24 -11
  82. data/ext/boost/config/platform/bsd.hpp +1 -1
  83. data/ext/boost/config/platform/cray.hpp +18 -0
  84. data/ext/boost/config/platform/cygwin.hpp +10 -0
  85. data/ext/boost/config/platform/linux.hpp +5 -0
  86. data/ext/boost/config/platform/macos.hpp +5 -4
  87. data/ext/boost/config/platform/symbian.hpp +5 -2
  88. data/ext/boost/config/platform/vms.hpp +25 -0
  89. data/ext/boost/config/platform/win32.hpp +7 -1
  90. data/ext/boost/config/select_compiler_config.hpp +8 -25
  91. data/ext/boost/config/select_platform_config.hpp +8 -1
  92. data/ext/boost/config/select_stdlib_config.hpp +9 -1
  93. data/ext/boost/config/stdlib/dinkumware.hpp +6 -9
  94. data/ext/boost/config/stdlib/libcomo.hpp +1 -4
  95. data/ext/boost/config/stdlib/libcpp.hpp +36 -0
  96. data/ext/boost/config/stdlib/libstdcpp3.hpp +37 -11
  97. data/ext/boost/config/stdlib/modena.hpp +1 -4
  98. data/ext/boost/config/stdlib/msl.hpp +1 -4
  99. data/ext/boost/config/stdlib/roguewave.hpp +9 -6
  100. data/ext/boost/config/stdlib/sgi.hpp +12 -4
  101. data/ext/boost/config/stdlib/stlport.hpp +11 -4
  102. data/ext/boost/config/stdlib/vacpp.hpp +11 -4
  103. data/ext/boost/config/suffix.hpp +71 -6
  104. data/ext/boost/config/warning_disable.hpp +1 -1
  105. data/ext/boost/container/container_fwd.hpp +177 -0
  106. data/ext/boost/cstdint.hpp +17 -12
  107. data/ext/boost/current_function.hpp +2 -1
  108. data/ext/boost/date_time/c_time.hpp +17 -1
  109. data/ext/boost/date_time/compiler_config.hpp +13 -15
  110. data/ext/boost/date_time/date_formatting.hpp +7 -1
  111. data/ext/boost/date_time/filetime_functions.hpp +4 -4
  112. data/ext/boost/date_time/gregorian_calendar.ipp +2 -2
  113. data/ext/boost/date_time/strings_from_facet.hpp +3 -3
  114. data/ext/boost/date_time/time_facet.hpp +101 -101
  115. data/ext/boost/detail/endian.hpp +4 -2
  116. data/ext/boost/detail/fenv.hpp +74 -0
  117. data/ext/boost/detail/sp_typeinfo.hpp +6 -0
  118. data/ext/boost/exception/detail/clone_current_exception.hpp +47 -0
  119. data/ext/boost/exception/detail/exception_ptr.hpp +194 -122
  120. data/ext/boost/exception/detail/type_info.hpp +3 -3
  121. data/ext/boost/exception/diagnostic_information.hpp +37 -21
  122. data/ext/boost/exception/exception.hpp +21 -1
  123. data/ext/boost/exception/info.hpp +0 -1
  124. data/ext/boost/function.hpp +2 -2
  125. data/ext/boost/function/function_base.hpp +15 -9
  126. data/ext/boost/function/function_template.hpp +26 -48
  127. data/ext/boost/integer_fwd.hpp +0 -16
  128. data/ext/boost/integer_traits.hpp +2 -2
  129. data/ext/boost/iterator.hpp +1 -1
  130. data/ext/boost/iterator/iterator_adaptor.hpp +1 -7
  131. data/ext/boost/iterator/iterator_facade.hpp +13 -13
  132. data/ext/boost/iterator/transform_iterator.hpp +5 -20
  133. data/ext/boost/lexical_cast.hpp +1655 -673
  134. data/ext/boost/math/policies/policy.hpp +982 -0
  135. data/ext/boost/math/special_functions/detail/fp_traits.hpp +570 -0
  136. data/ext/boost/math/special_functions/detail/round_fwd.hpp +80 -0
  137. data/ext/boost/math/special_functions/fpclassify.hpp +533 -0
  138. data/ext/boost/math/special_functions/math_fwd.hpp +1070 -0
  139. data/ext/boost/math/special_functions/sign.hpp +145 -0
  140. data/ext/boost/math/tools/config.hpp +321 -0
  141. data/ext/boost/math/tools/promotion.hpp +150 -0
  142. data/ext/boost/math/tools/real_cast.hpp +29 -0
  143. data/ext/boost/math/tools/user.hpp +97 -0
  144. data/ext/boost/move/move.hpp +1222 -0
  145. data/ext/boost/mpl/O1_size.hpp +40 -0
  146. data/ext/boost/mpl/O1_size_fwd.hpp +24 -0
  147. data/ext/boost/mpl/advance.hpp +76 -0
  148. data/ext/boost/mpl/advance_fwd.hpp +28 -0
  149. data/ext/boost/mpl/at.hpp +52 -0
  150. data/ext/boost/mpl/at_fwd.hpp +24 -0
  151. data/ext/boost/mpl/aux_/O1_size_impl.hpp +87 -0
  152. data/ext/boost/mpl/aux_/advance_backward.hpp +128 -0
  153. data/ext/boost/mpl/aux_/advance_forward.hpp +127 -0
  154. data/ext/boost/mpl/aux_/arithmetic_op.hpp +92 -0
  155. data/ext/boost/mpl/aux_/at_impl.hpp +45 -0
  156. data/ext/boost/mpl/aux_/begin_end_impl.hpp +101 -0
  157. data/ext/boost/mpl/aux_/clear_impl.hpp +35 -0
  158. data/ext/boost/mpl/aux_/comparison_op.hpp +83 -0
  159. data/ext/boost/mpl/aux_/config/forwarding.hpp +27 -0
  160. data/ext/boost/mpl/aux_/config/typeof.hpp +38 -0
  161. data/ext/boost/mpl/aux_/contains_impl.hpp +61 -0
  162. data/ext/boost/mpl/aux_/find_if_pred.hpp +31 -0
  163. data/ext/boost/mpl/aux_/fold_impl.hpp +43 -0
  164. data/ext/boost/mpl/aux_/has_begin.hpp +23 -0
  165. data/ext/boost/mpl/aux_/has_size.hpp +23 -0
  166. data/ext/boost/mpl/aux_/has_tag.hpp +23 -0
  167. data/ext/boost/mpl/aux_/inserter_algorithm.hpp +159 -0
  168. data/ext/boost/mpl/aux_/is_msvc_eti_arg.hpp +64 -0
  169. data/ext/boost/mpl/aux_/iter_apply.hpp +47 -0
  170. data/ext/boost/mpl/aux_/iter_fold_if_impl.hpp +210 -0
  171. data/ext/boost/mpl/aux_/iter_fold_impl.hpp +42 -0
  172. data/ext/boost/mpl/aux_/lambda_spec.hpp +49 -0
  173. data/ext/boost/mpl/aux_/largest_int.hpp +63 -0
  174. data/ext/boost/mpl/aux_/msvc_eti_base.hpp +77 -0
  175. data/ext/boost/mpl/aux_/msvc_type.hpp +62 -0
  176. data/ext/boost/mpl/aux_/numeric_cast_utils.hpp +77 -0
  177. data/ext/boost/mpl/aux_/numeric_op.hpp +315 -0
  178. data/ext/boost/mpl/aux_/preprocessed/gcc/advance_backward.hpp +97 -0
  179. data/ext/boost/mpl/aux_/preprocessed/gcc/advance_forward.hpp +97 -0
  180. data/ext/boost/mpl/aux_/preprocessed/gcc/equal_to.hpp +94 -0
  181. data/ext/boost/mpl/aux_/preprocessed/gcc/fold_impl.hpp +180 -0
  182. data/ext/boost/mpl/aux_/preprocessed/gcc/greater.hpp +94 -0
  183. data/ext/boost/mpl/aux_/preprocessed/gcc/greater_equal.hpp +94 -0
  184. data/ext/boost/mpl/aux_/preprocessed/gcc/iter_fold_if_impl.hpp +133 -0
  185. data/ext/boost/mpl/aux_/preprocessed/gcc/iter_fold_impl.hpp +180 -0
  186. data/ext/boost/mpl/aux_/preprocessed/gcc/less.hpp +94 -0
  187. data/ext/boost/mpl/aux_/preprocessed/gcc/less_equal.hpp +94 -0
  188. data/ext/boost/mpl/aux_/preprocessed/gcc/list.hpp +323 -0
  189. data/ext/boost/mpl/aux_/preprocessed/gcc/minus.hpp +146 -0
  190. data/ext/boost/mpl/aux_/preprocessed/gcc/not_equal_to.hpp +94 -0
  191. data/ext/boost/mpl/aux_/preprocessed/gcc/plus.hpp +146 -0
  192. data/ext/boost/mpl/aux_/preprocessed/gcc/reverse_fold_impl.hpp +231 -0
  193. data/ext/boost/mpl/aux_/preprocessed/gcc/times.hpp +146 -0
  194. data/ext/boost/mpl/aux_/preprocessed/gcc/vector.hpp +323 -0
  195. data/ext/boost/mpl/aux_/preprocessor/default_params.hpp +67 -0
  196. data/ext/boost/mpl/aux_/push_back_impl.hpp +70 -0
  197. data/ext/boost/mpl/aux_/push_front_impl.hpp +71 -0
  198. data/ext/boost/mpl/aux_/reverse_fold_impl.hpp +44 -0
  199. data/ext/boost/mpl/aux_/size_impl.hpp +52 -0
  200. data/ext/boost/mpl/aux_/traits_lambda_spec.hpp +63 -0
  201. data/ext/boost/mpl/back_fwd.hpp +24 -0
  202. data/ext/boost/mpl/back_inserter.hpp +34 -0
  203. data/ext/boost/mpl/begin_end.hpp +57 -0
  204. data/ext/boost/mpl/begin_end_fwd.hpp +27 -0
  205. data/ext/boost/mpl/clear.hpp +39 -0
  206. data/ext/boost/mpl/clear_fwd.hpp +24 -0
  207. data/ext/boost/mpl/comparison.hpp +24 -0
  208. data/ext/boost/mpl/contains.hpp +41 -0
  209. data/ext/boost/mpl/contains_fwd.hpp +25 -0
  210. data/ext/boost/mpl/deref.hpp +41 -0
  211. data/ext/boost/mpl/distance.hpp +78 -0
  212. data/ext/boost/mpl/distance_fwd.hpp +28 -0
  213. data/ext/boost/mpl/empty_fwd.hpp +24 -0
  214. data/ext/boost/mpl/equal_to.hpp +21 -0
  215. data/ext/boost/mpl/find.hpp +38 -0
  216. data/ext/boost/mpl/find_if.hpp +50 -0
  217. data/ext/boost/mpl/fold.hpp +48 -0
  218. data/ext/boost/mpl/front_fwd.hpp +24 -0
  219. data/ext/boost/mpl/front_inserter.hpp +33 -0
  220. data/ext/boost/mpl/greater.hpp +21 -0
  221. data/ext/boost/mpl/greater_equal.hpp +21 -0
  222. data/ext/boost/mpl/inserter.hpp +32 -0
  223. data/ext/boost/mpl/iter_fold.hpp +49 -0
  224. data/ext/boost/mpl/iter_fold_if.hpp +117 -0
  225. data/ext/boost/mpl/iterator_range.hpp +42 -0
  226. data/ext/boost/mpl/iterator_tags.hpp +27 -0
  227. data/ext/boost/mpl/less.hpp +21 -0
  228. data/ext/boost/mpl/less_equal.hpp +21 -0
  229. data/ext/boost/mpl/limits/list.hpp +21 -0
  230. data/ext/boost/mpl/limits/vector.hpp +21 -0
  231. data/ext/boost/mpl/list.hpp +57 -0
  232. data/ext/boost/mpl/list/aux_/O1_size.hpp +33 -0
  233. data/ext/boost/mpl/list/aux_/begin_end.hpp +44 -0
  234. data/ext/boost/mpl/list/aux_/clear.hpp +34 -0
  235. data/ext/boost/mpl/list/aux_/empty.hpp +34 -0
  236. data/ext/boost/mpl/list/aux_/front.hpp +33 -0
  237. data/ext/boost/mpl/list/aux_/include_preprocessed.hpp +35 -0
  238. data/ext/boost/mpl/list/aux_/item.hpp +55 -0
  239. data/ext/boost/mpl/list/aux_/iterator.hpp +76 -0
  240. data/ext/boost/mpl/list/aux_/pop_front.hpp +34 -0
  241. data/ext/boost/mpl/list/aux_/preprocessed/plain/list10.hpp +149 -0
  242. data/ext/boost/mpl/list/aux_/preprocessed/plain/list20.hpp +169 -0
  243. data/ext/boost/mpl/list/aux_/push_back.hpp +36 -0
  244. data/ext/boost/mpl/list/aux_/push_front.hpp +39 -0
  245. data/ext/boost/mpl/list/aux_/size.hpp +33 -0
  246. data/ext/boost/mpl/list/aux_/tag.hpp +24 -0
  247. data/ext/boost/mpl/list/list0.hpp +42 -0
  248. data/ext/boost/mpl/list/list10.hpp +43 -0
  249. data/ext/boost/mpl/list/list20.hpp +43 -0
  250. data/ext/boost/mpl/long.hpp +22 -0
  251. data/ext/boost/mpl/long_fwd.hpp +27 -0
  252. data/ext/boost/mpl/minus.hpp +21 -0
  253. data/ext/boost/mpl/multiplies.hpp +53 -0
  254. data/ext/boost/mpl/negate.hpp +81 -0
  255. data/ext/boost/mpl/not_equal_to.hpp +21 -0
  256. data/ext/boost/mpl/numeric_cast.hpp +41 -0
  257. data/ext/boost/mpl/pair.hpp +70 -0
  258. data/ext/boost/mpl/plus.hpp +21 -0
  259. data/ext/boost/mpl/pop_back_fwd.hpp +24 -0
  260. data/ext/boost/mpl/pop_front_fwd.hpp +24 -0
  261. data/ext/boost/mpl/prior.hpp +19 -0
  262. data/ext/boost/mpl/push_back.hpp +53 -0
  263. data/ext/boost/mpl/push_back_fwd.hpp +24 -0
  264. data/ext/boost/mpl/push_front.hpp +52 -0
  265. data/ext/boost/mpl/push_front_fwd.hpp +24 -0
  266. data/ext/boost/mpl/remove_if.hpp +83 -0
  267. data/ext/boost/mpl/reverse_fold.hpp +50 -0
  268. data/ext/boost/mpl/same_as.hpp +55 -0
  269. data/ext/boost/mpl/sequence_tag.hpp +124 -0
  270. data/ext/boost/mpl/sequence_tag_fwd.hpp +26 -0
  271. data/ext/boost/mpl/size.hpp +42 -0
  272. data/ext/boost/mpl/size_fwd.hpp +24 -0
  273. data/ext/boost/mpl/tag.hpp +52 -0
  274. data/ext/boost/mpl/times.hpp +21 -0
  275. data/ext/boost/mpl/vector.hpp +57 -0
  276. data/ext/boost/mpl/vector/aux_/O1_size.hpp +56 -0
  277. data/ext/boost/mpl/vector/aux_/at.hpp +116 -0
  278. data/ext/boost/mpl/vector/aux_/back.hpp +59 -0
  279. data/ext/boost/mpl/vector/aux_/begin_end.hpp +49 -0
  280. data/ext/boost/mpl/vector/aux_/clear.hpp +55 -0
  281. data/ext/boost/mpl/vector/aux_/empty.hpp +68 -0
  282. data/ext/boost/mpl/vector/aux_/front.hpp +56 -0
  283. data/ext/boost/mpl/vector/aux_/include_preprocessed.hpp +55 -0
  284. data/ext/boost/mpl/vector/aux_/item.hpp +103 -0
  285. data/ext/boost/mpl/vector/aux_/iterator.hpp +130 -0
  286. data/ext/boost/mpl/vector/aux_/pop_back.hpp +40 -0
  287. data/ext/boost/mpl/vector/aux_/pop_front.hpp +40 -0
  288. data/ext/boost/mpl/vector/aux_/preprocessed/plain/vector10.hpp +829 -0
  289. data/ext/boost/mpl/vector/aux_/preprocessed/plain/vector20.hpp +1144 -0
  290. data/ext/boost/mpl/vector/aux_/preprocessed/typeof_based/vector10.hpp +139 -0
  291. data/ext/boost/mpl/vector/aux_/preprocessed/typeof_based/vector20.hpp +159 -0
  292. data/ext/boost/mpl/vector/aux_/push_back.hpp +40 -0
  293. data/ext/boost/mpl/vector/aux_/push_front.hpp +40 -0
  294. data/ext/boost/mpl/vector/aux_/size.hpp +49 -0
  295. data/ext/boost/mpl/vector/aux_/tag.hpp +32 -0
  296. data/ext/boost/mpl/vector/aux_/vector0.hpp +52 -0
  297. data/ext/boost/mpl/vector/vector0.hpp +34 -0
  298. data/ext/boost/mpl/vector/vector10.hpp +45 -0
  299. data/ext/boost/mpl/vector/vector20.hpp +45 -0
  300. data/ext/boost/none.hpp +1 -1
  301. data/ext/boost/numeric/conversion/bounds.hpp +24 -0
  302. data/ext/boost/numeric/conversion/cast.hpp +61 -0
  303. data/ext/boost/numeric/conversion/conversion_traits.hpp +39 -0
  304. data/ext/boost/numeric/conversion/converter.hpp +68 -0
  305. data/ext/boost/numeric/conversion/converter_policies.hpp +186 -0
  306. data/ext/boost/numeric/conversion/detail/bounds.hpp +58 -0
  307. data/ext/boost/numeric/conversion/detail/conversion_traits.hpp +97 -0
  308. data/ext/boost/numeric/conversion/detail/converter.hpp +602 -0
  309. data/ext/boost/numeric/conversion/detail/int_float_mixture.hpp +72 -0
  310. data/ext/boost/numeric/conversion/detail/is_subranged.hpp +234 -0
  311. data/ext/boost/numeric/conversion/detail/meta.hpp +120 -0
  312. data/ext/boost/numeric/conversion/detail/numeric_cast_traits.hpp +138 -0
  313. data/ext/boost/numeric/conversion/detail/preprocessed/numeric_cast_traits_common.hpp +1741 -0
  314. data/ext/boost/numeric/conversion/detail/preprocessed/numeric_cast_traits_long_long.hpp +347 -0
  315. data/ext/boost/numeric/conversion/detail/sign_mixture.hpp +72 -0
  316. data/ext/boost/numeric/conversion/detail/udt_builtin_mixture.hpp +69 -0
  317. data/ext/boost/numeric/conversion/int_float_mixture_enum.hpp +29 -0
  318. data/ext/boost/numeric/conversion/numeric_cast_traits.hpp +31 -0
  319. data/ext/boost/numeric/conversion/sign_mixture_enum.hpp +29 -0
  320. data/ext/boost/numeric/conversion/udt_builtin_mixture_enum.hpp +26 -0
  321. data/ext/boost/operators.hpp +3 -1
  322. data/ext/boost/optional/optional.hpp +146 -79
  323. data/ext/boost/optional/optional_fwd.hpp +8 -1
  324. data/ext/boost/preprocessor/cat.hpp +2 -2
  325. data/ext/boost/preprocessor/config/config.hpp +39 -4
  326. data/ext/boost/preprocessor/facilities/intercept.hpp +277 -0
  327. data/ext/boost/preprocessor/facilities/overload.hpp +25 -0
  328. data/ext/boost/preprocessor/iteration/detail/iter/forward1.hpp +3 -3
  329. data/ext/boost/preprocessor/iteration/iterate.hpp +3 -3
  330. data/ext/boost/preprocessor/punctuation/paren.hpp +23 -0
  331. data/ext/boost/preprocessor/repetition/enum_shifted_params.hpp +44 -0
  332. data/ext/boost/preprocessor/seq/cat.hpp +5 -4
  333. data/ext/boost/preprocessor/seq/size.hpp +0 -1
  334. data/ext/boost/preprocessor/tuple/eat.hpp +83 -34
  335. data/ext/boost/preprocessor/tuple/elem.hpp +161 -355
  336. data/ext/boost/preprocessor/tuple/rem.hpp +110 -48
  337. data/ext/boost/preprocessor/tuple/to_list.hpp +90 -36
  338. data/ext/boost/preprocessor/variadic/elem.hpp +94 -0
  339. data/ext/boost/preprocessor/variadic/size.hpp +30 -0
  340. data/ext/boost/range/begin.hpp +17 -6
  341. data/ext/boost/range/concepts.hpp +37 -2
  342. data/ext/boost/range/detail/safe_bool.hpp +72 -0
  343. data/ext/boost/range/end.hpp +14 -9
  344. data/ext/boost/range/iterator_range_core.hpp +120 -12
  345. data/ext/boost/range/size.hpp +21 -5
  346. data/ext/boost/smart_ptr/detail/shared_count.hpp +88 -0
  347. data/ext/boost/smart_ptr/detail/sp_counted_base.hpp +3 -0
  348. data/ext/boost/smart_ptr/detail/sp_counted_base_aix.hpp +142 -0
  349. data/ext/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp +9 -0
  350. data/ext/boost/smart_ptr/detail/sp_counted_impl.hpp +10 -2
  351. data/ext/boost/smart_ptr/detail/sp_has_sync.hpp +5 -1
  352. data/ext/boost/smart_ptr/detail/spinlock.hpp +4 -1
  353. data/ext/boost/smart_ptr/detail/spinlock_gcc_arm.hpp +20 -3
  354. data/ext/boost/smart_ptr/detail/spinlock_pool.hpp +4 -0
  355. data/ext/boost/smart_ptr/make_shared.hpp +591 -22
  356. data/ext/boost/smart_ptr/shared_array.hpp +29 -1
  357. data/ext/boost/smart_ptr/shared_ptr.hpp +29 -13
  358. data/ext/boost/smart_ptr/weak_ptr.hpp +24 -12
  359. data/ext/boost/src/pthread/once.cpp +9 -7
  360. data/ext/boost/src/pthread/thread.cpp +32 -28
  361. data/ext/boost/src/pthread/timeconv.inl +4 -5
  362. data/ext/boost/src/tss_null.cpp +5 -1
  363. data/ext/boost/static_assert.hpp +8 -2
  364. data/ext/boost/thread/detail/config.hpp +19 -4
  365. data/ext/boost/thread/detail/move.hpp +11 -5
  366. data/ext/boost/thread/detail/thread.hpp +59 -43
  367. data/ext/boost/thread/exceptions.hpp +9 -9
  368. data/ext/boost/thread/future.hpp +150 -82
  369. data/ext/boost/thread/locks.hpp +101 -60
  370. data/ext/boost/thread/pthread/condition_variable.hpp +79 -32
  371. data/ext/boost/thread/pthread/condition_variable_fwd.hpp +12 -3
  372. data/ext/boost/thread/pthread/mutex.hpp +17 -14
  373. data/ext/boost/thread/pthread/once.hpp +3 -4
  374. data/ext/boost/thread/pthread/pthread_mutex_scoped_lock.hpp +12 -2
  375. data/ext/boost/thread/pthread/recursive_mutex.hpp +19 -19
  376. data/ext/boost/thread/pthread/shared_mutex.hpp +13 -13
  377. data/ext/boost/thread/pthread/thread_data.hpp +40 -12
  378. data/ext/boost/thread/thread_time.hpp +5 -0
  379. data/ext/boost/throw_exception.hpp +1 -1
  380. data/ext/boost/token_functions.hpp +34 -10
  381. data/ext/boost/type_traits/add_rvalue_reference.hpp +66 -0
  382. data/ext/boost/type_traits/alignment_of.hpp +1 -1
  383. data/ext/boost/type_traits/detail/bool_trait_def.hpp +26 -3
  384. data/ext/boost/type_traits/detail/bool_trait_undef.hpp +3 -2
  385. data/ext/boost/type_traits/detail/cv_traits_impl.hpp +1 -1
  386. data/ext/boost/type_traits/detail/size_t_trait_def.hpp +6 -4
  387. data/ext/boost/type_traits/detail/type_trait_def.hpp +8 -2
  388. data/ext/boost/type_traits/function_traits.hpp +1 -1
  389. data/ext/boost/type_traits/has_nothrow_constructor.hpp +53 -0
  390. data/ext/boost/type_traits/has_nothrow_copy.hpp +19 -5
  391. data/ext/boost/type_traits/has_trivial_constructor.hpp +51 -0
  392. data/ext/boost/type_traits/has_trivial_copy.hpp +20 -5
  393. data/ext/boost/type_traits/has_trivial_destructor.hpp +12 -5
  394. data/ext/boost/type_traits/intrinsics.hpp +119 -71
  395. data/ext/boost/type_traits/is_const.hpp +5 -5
  396. data/ext/boost/type_traits/is_convertible.hpp +14 -13
  397. data/ext/boost/type_traits/is_enum.hpp +1 -1
  398. data/ext/boost/type_traits/is_floating_point.hpp +27 -0
  399. data/ext/boost/type_traits/is_function.hpp +3 -3
  400. data/ext/boost/type_traits/is_fundamental.hpp +1 -1
  401. data/ext/boost/type_traits/is_member_function_pointer.hpp +2 -2
  402. data/ext/boost/type_traits/is_member_pointer.hpp +2 -2
  403. data/ext/boost/type_traits/is_pod.hpp +11 -3
  404. data/ext/boost/type_traits/is_pointer.hpp +2 -2
  405. data/ext/boost/type_traits/is_signed.hpp +8 -3
  406. data/ext/boost/type_traits/is_union.hpp +8 -0
  407. data/ext/boost/type_traits/is_unsigned.hpp +9 -4
  408. data/ext/boost/type_traits/is_volatile.hpp +5 -5
  409. data/ext/boost/type_traits/remove_cv.hpp +4 -3
  410. data/ext/boost/type_traits/remove_pointer.hpp +51 -2
  411. data/ext/boost/type_traits/remove_reference.hpp +2 -2
  412. data/ext/boost/type_traits/type_with_alignment.hpp +8 -2
  413. data/ext/boost/utility/declval.hpp +44 -0
  414. data/ext/boost/utility/detail/in_place_factory_prefix.hpp +36 -0
  415. data/ext/boost/utility/detail/in_place_factory_suffix.hpp +23 -0
  416. data/ext/boost/utility/detail/result_of_iterate.hpp +142 -0
  417. data/ext/boost/utility/in_place_factory.hpp +88 -0
  418. data/ext/boost/utility/result_of.hpp +103 -0
  419. data/ext/boost/utility/swap.hpp +55 -0
  420. data/ext/common/AnsiColorConstants.h +36 -0
  421. data/ext/common/ApplicationPool2/Common.h +87 -0
  422. data/ext/common/ApplicationPool2/ComponentInfo.h +53 -0
  423. data/ext/common/ApplicationPool2/Group.h +648 -0
  424. data/ext/common/ApplicationPool2/Implementation.cpp +580 -0
  425. data/ext/common/ApplicationPool2/Options.h +576 -0
  426. data/ext/common/ApplicationPool2/PipeWatcher.h +61 -0
  427. data/ext/common/ApplicationPool2/Pool.h +1181 -0
  428. data/ext/common/ApplicationPool2/Process.h +425 -0
  429. data/ext/common/ApplicationPool2/README.md +96 -0
  430. data/ext/common/ApplicationPool2/Session.h +158 -0
  431. data/ext/common/ApplicationPool2/Socket.h +246 -0
  432. data/ext/common/ApplicationPool2/Spawner.h +2212 -0
  433. data/ext/common/ApplicationPool2/SuperGroup.h +749 -0
  434. data/ext/common/BackgroundEventLoop.cpp +129 -0
  435. data/ext/common/BackgroundEventLoop.h +61 -0
  436. data/ext/common/Constants.h +3 -1
  437. data/ext/common/EventedBufferedInput.h +331 -0
  438. data/ext/common/EventedMessageServer.h +17 -34
  439. data/ext/common/EventedServer.h +2 -2
  440. data/ext/common/Exceptions.h +71 -19
  441. data/ext/common/FileDescriptor.h +8 -6
  442. data/ext/common/HttpConstants.h +167 -0
  443. data/ext/common/IniFile.h +24 -0
  444. data/ext/common/Logging.h +62 -849
  445. data/ext/common/MessageReadersWriters.h +19 -0
  446. data/ext/common/MessageServer.h +11 -14
  447. data/ext/common/MultiLibeio.cpp +198 -0
  448. data/ext/common/MultiLibeio.h +67 -0
  449. data/ext/common/ResourceLocator.h +24 -41
  450. data/ext/common/SafeLibev.h +186 -14
  451. data/ext/common/StaticString.h +23 -3
  452. data/ext/common/UnionStation.h +972 -0
  453. data/ext/common/Utils.cpp +168 -24
  454. data/ext/common/Utils.h +25 -3
  455. data/ext/common/Utils/CachedFileStat.hpp +4 -3
  456. data/ext/common/Utils/FileChangeChecker.h +2 -2
  457. data/ext/common/Utils/HashMap.h +50 -0
  458. data/ext/common/Utils/IOUtils.cpp +229 -68
  459. data/ext/common/Utils/IOUtils.h +134 -3
  460. data/ext/common/Utils/Lock.h +28 -0
  461. data/ext/common/Utils/MemoryBarrier.h +52 -0
  462. data/ext/common/Utils/PriorityQueue.h +54 -0
  463. data/ext/common/Utils/ProcessMetricsCollector.h +9 -11
  464. data/ext/common/Utils/ScopeGuard.h +50 -1
  465. data/ext/common/Utils/SmallVector.h +653 -0
  466. data/ext/common/Utils/StrIntUtils.cpp +26 -2
  467. data/ext/common/Utils/StrIntUtils.h +18 -2
  468. data/ext/common/Utils/StringMap.h +125 -8
  469. data/ext/common/Utils/Template.h +212 -0
  470. data/ext/common/Utils/fib.c +699 -0
  471. data/ext/common/Utils/fib.h +101 -0
  472. data/ext/common/Utils/fibpriv.h +67 -0
  473. data/ext/common/Utils/json-forwards.h +249 -0
  474. data/ext/common/Utils/json.h +1855 -0
  475. data/ext/common/Utils/jsoncpp.cpp +4230 -0
  476. data/ext/common/agents/Base.cpp +1126 -0
  477. data/ext/common/{AgentBase.h → agents/Base.h} +5 -1
  478. data/ext/common/agents/EnvPrinter.c +16 -0
  479. data/ext/common/agents/HelperAgent/AgentOptions.h +81 -0
  480. data/ext/common/{HelperAgent → agents/HelperAgent}/BacktracesServer.h +3 -2
  481. data/ext/common/agents/HelperAgent/FileBackedPipe.h +732 -0
  482. data/ext/common/agents/HelperAgent/Main.cpp +497 -0
  483. data/ext/common/agents/HelperAgent/RequestHandler.cpp +283 -0
  484. data/ext/common/agents/HelperAgent/RequestHandler.h +2139 -0
  485. data/ext/common/agents/HelperAgent/ScgiRequestParser.h +451 -0
  486. data/ext/common/{LoggingAgent → agents/LoggingAgent}/DataStoreId.h +1 -1
  487. data/ext/common/{LoggingAgent → agents/LoggingAgent}/FilterSupport.cpp +1 -1
  488. data/ext/common/{LoggingAgent → agents/LoggingAgent}/FilterSupport.h +0 -0
  489. data/ext/common/{LoggingAgent → agents/LoggingAgent}/LoggingServer.h +18 -16
  490. data/ext/common/{LoggingAgent → agents/LoggingAgent}/Main.cpp +15 -13
  491. data/ext/common/{LoggingAgent → agents/LoggingAgent}/RemoteSender.h +6 -6
  492. data/ext/common/agents/SpawnPreparer.cpp +127 -0
  493. data/ext/common/{Watchdog.cpp → agents/Watchdog/Main.cpp} +63 -25
  494. data/ext/libeio/Changes +72 -0
  495. data/ext/{google/COPYING → libeio/LICENSE} +17 -9
  496. data/ext/libeio/Makefile.am +15 -0
  497. data/ext/libeio/Makefile.in +694 -0
  498. data/ext/libeio/aclocal.m4 +9418 -0
  499. data/ext/libeio/autogen.sh +3 -0
  500. data/ext/libeio/config.guess +1501 -0
  501. data/ext/libeio/config.h.in +136 -0
  502. data/ext/libeio/config.sub +1705 -0
  503. data/ext/libeio/configure +14822 -0
  504. data/ext/libeio/configure.ac +22 -0
  505. data/ext/libeio/demo.c +194 -0
  506. data/ext/libeio/ecb.h +457 -0
  507. data/ext/libeio/eio.c +2816 -0
  508. data/ext/libeio/eio.h +411 -0
  509. data/ext/libeio/install-sh +520 -0
  510. data/ext/libeio/libeio.m4 +211 -0
  511. data/ext/libeio/ltmain.sh +9636 -0
  512. data/ext/libeio/missing +376 -0
  513. data/ext/libeio/xthread.h +166 -0
  514. data/ext/libev/Changes +125 -7
  515. data/ext/libev/Makefile.am +5 -3
  516. data/ext/libev/Makefile.in +209 -120
  517. data/ext/libev/aclocal.m4 +6027 -4619
  518. data/ext/libev/autogen.sh +1 -4
  519. data/ext/libev/config.h.in +11 -7
  520. data/ext/libev/configure +7312 -14993
  521. data/ext/libev/configure.ac +12 -5
  522. data/ext/libev/depcomp +630 -0
  523. data/ext/libev/ev++.h +48 -32
  524. data/ext/libev/ev.c +1173 -391
  525. data/ext/libev/ev.h +315 -181
  526. data/ext/libev/ev_epoll.c +66 -15
  527. data/ext/libev/ev_kqueue.c +20 -18
  528. data/ext/libev/ev_poll.c +27 -23
  529. data/ext/libev/ev_port.c +39 -19
  530. data/ext/libev/ev_select.c +23 -17
  531. data/ext/libev/ev_vars.h +25 -8
  532. data/ext/libev/ev_win32.c +6 -6
  533. data/ext/libev/ev_wrap.h +22 -2
  534. data/ext/libev/event.c +18 -17
  535. data/ext/libev/event.h +16 -4
  536. data/ext/libev/libev.m4 +10 -6
  537. data/ext/libev/ltmain.sh +7353 -5811
  538. data/ext/nginx/Configuration.c +74 -42
  539. data/ext/nginx/Configuration.h +3 -5
  540. data/ext/nginx/ContentHandler.c +26 -83
  541. data/ext/nginx/ContentHandler.h +1 -1
  542. data/ext/nginx/config +13 -9
  543. data/ext/nginx/ngx_http_passenger_module.c +3 -7
  544. data/ext/oxt/detail/backtrace_enabled.hpp +5 -102
  545. data/ext/oxt/detail/context.hpp +90 -0
  546. data/ext/oxt/detail/spin_lock_darwin.hpp +4 -0
  547. data/ext/oxt/detail/spin_lock_gcc_x86.hpp +4 -0
  548. data/ext/oxt/detail/spin_lock_pthreads.hpp +14 -0
  549. data/ext/oxt/detail/tracable_exception_enabled.hpp +2 -2
  550. data/ext/oxt/dynamic_thread_group.hpp +27 -1
  551. data/ext/oxt/implementation.cpp +415 -0
  552. data/ext/oxt/{thread.cpp → initialize.hpp} +13 -6
  553. data/ext/oxt/macros.hpp +32 -1
  554. data/ext/oxt/spin_lock.hpp +6 -11
  555. data/ext/oxt/system_calls.cpp +204 -16
  556. data/ext/oxt/system_calls.hpp +85 -45
  557. data/ext/oxt/thread.hpp +13 -117
  558. data/ext/ruby/passenger_native_support.c +82 -237
  559. data/helper-scripts/backtrace-sanitizer.rb +114 -0
  560. data/helper-scripts/classic-rails-loader.rb +135 -0
  561. data/helper-scripts/classic-rails-preloader.rb +161 -0
  562. data/helper-scripts/node-loader.js +314 -0
  563. data/helper-scripts/rack-loader.rb +104 -0
  564. data/helper-scripts/rack-preloader.rb +132 -0
  565. data/helper-scripts/wsgi-loader.py +231 -0
  566. data/helper-scripts/wsgi-preloader.py +1 -0
  567. data/lib/phusion_passenger.rb +159 -61
  568. data/lib/phusion_passenger/abstract_installer.rb +182 -87
  569. data/lib/phusion_passenger/admin_tools/server_instance.rb +25 -19
  570. data/lib/phusion_passenger/analytics_logger.rb +5 -4
  571. data/lib/phusion_passenger/classic_rails/{request_handler.rb → thread_handler_extension.rb} +4 -40
  572. data/lib/phusion_passenger/classic_rails_extensions/init.rb +5 -3
  573. data/lib/phusion_passenger/common_library.rb +441 -0
  574. data/lib/phusion_passenger/console_text_template.rb +4 -16
  575. data/lib/phusion_passenger/constants.rb +1 -8
  576. data/lib/phusion_passenger/debug_logging.rb +5 -2
  577. data/lib/phusion_passenger/dependencies.rb +51 -13
  578. data/lib/phusion_passenger/loader_shared_helpers.rb +318 -0
  579. data/lib/phusion_passenger/message_channel.rb +3 -47
  580. data/lib/phusion_passenger/message_client.rb +2 -2
  581. data/lib/phusion_passenger/native_support.rb +36 -15
  582. data/lib/phusion_passenger/packaging.rb +8 -11
  583. data/lib/phusion_passenger/platform_info.rb +25 -17
  584. data/lib/phusion_passenger/platform_info/apache.rb +10 -7
  585. data/lib/phusion_passenger/platform_info/binary_compatibility.rb +10 -30
  586. data/lib/phusion_passenger/platform_info/compiler.rb +93 -34
  587. data/lib/phusion_passenger/platform_info/ruby.rb +37 -97
  588. data/lib/phusion_passenger/preloader_shared_helpers.rb +121 -0
  589. data/lib/phusion_passenger/public_api.rb +1 -4
  590. data/lib/phusion_passenger/rack/{request_handler.rb → thread_handler_extension.rb} +14 -63
  591. data/lib/phusion_passenger/rails3_extensions/init.rb +9 -8
  592. data/lib/phusion_passenger/request_handler.rb +500 -0
  593. data/lib/phusion_passenger/request_handler/thread_handler.rb +360 -0
  594. data/lib/phusion_passenger/ruby_core_enhancements.rb +142 -0
  595. data/lib/phusion_passenger/standalone/command.rb +36 -15
  596. data/lib/phusion_passenger/standalone/package_runtime_command.rb +16 -8
  597. data/lib/phusion_passenger/standalone/runtime_installer.rb +169 -72
  598. data/lib/phusion_passenger/standalone/start_command.rb +44 -39
  599. data/lib/phusion_passenger/standalone/utils.rb +5 -5
  600. data/lib/phusion_passenger/utils.rb +35 -914
  601. data/lib/phusion_passenger/utils/ansi_colors.rb +59 -0
  602. data/lib/phusion_passenger/utils/file_system_watcher.rb +1 -1
  603. data/lib/phusion_passenger/utils/robust_interruption.rb +134 -0
  604. data/lib/phusion_passenger/utils/tee_input.rb +174 -0
  605. data/lib/phusion_passenger/utils/tmpio.rb +33 -0
  606. data/lib/phusion_passenger/utils/unseekable_socket.rb +6 -0
  607. data/resources/mime.types +5 -1
  608. data/{lib/phusion_passenger/templates → resources}/standalone_default_root/index.html +0 -0
  609. data/{lib/phusion_passenger → resources}/templates/apache2/apache_must_be_compiled_with_compatible_mpm.txt.erb +0 -0
  610. data/{lib/phusion_passenger → resources}/templates/apache2/config_snippets.txt.erb +0 -0
  611. data/{lib/phusion_passenger → resources}/templates/apache2/deployment_example.txt.erb +0 -0
  612. data/{lib/phusion_passenger → resources}/templates/apache2/no_write_permission_to_passenger_root.txt.erb +0 -0
  613. data/{lib/phusion_passenger → resources}/templates/apache2/possible_solutions_for_compilation_and_installation_problems.txt.erb +0 -0
  614. data/{lib/phusion_passenger → resources}/templates/apache2/run_installer_as_root.txt.erb +0 -0
  615. data/{lib/phusion_passenger → resources}/templates/apache2/welcome.txt.erb +0 -0
  616. data/{lib/phusion_passenger → resources}/templates/error_layout.css +6 -0
  617. data/resources/templates/error_layout.html.template +89 -0
  618. data/resources/templates/general_error.html.template +1 -0
  619. data/resources/templates/general_error_with_html.html.template +1 -0
  620. data/{lib/phusion_passenger → resources}/templates/nginx/ask_for_extra_configure_flags.txt.erb +0 -0
  621. data/{lib/phusion_passenger → resources}/templates/nginx/cannot_write_to_dir.txt.erb +0 -0
  622. data/{lib/phusion_passenger → resources}/templates/nginx/config_snippets.txt.erb +0 -0
  623. data/{lib/phusion_passenger → resources}/templates/nginx/config_snippets_inserted.txt.erb +0 -0
  624. data/{lib/phusion_passenger → resources}/templates/nginx/confirm_extra_configure_flags.txt.erb +0 -0
  625. data/{lib/phusion_passenger → resources}/templates/nginx/deployment_example.txt.erb +0 -0
  626. data/resources/templates/nginx/not_available_when_natively_packaged.txt.erb +8 -0
  627. data/{lib/phusion_passenger → resources}/templates/nginx/pcre_could_not_be_downloaded.txt.erb +0 -0
  628. data/{lib/phusion_passenger → resources}/templates/nginx/pcre_could_not_be_extracted.txt.erb +0 -0
  629. data/{lib/phusion_passenger → resources}/templates/nginx/possible_solutions_for_compilation_and_installation_problems.txt.erb +0 -0
  630. data/{lib/phusion_passenger → resources}/templates/nginx/possible_solutions_for_download_and_extraction_problems.txt.erb +0 -0
  631. data/{lib/phusion_passenger → resources}/templates/nginx/query_download_and_install.txt.erb +0 -0
  632. data/{lib/phusion_passenger → resources}/templates/nginx/run_installer_as_root.txt.erb +0 -0
  633. data/{lib/phusion_passenger → resources}/templates/nginx/welcome.txt.erb +0 -0
  634. data/{lib/phusion_passenger → resources}/templates/standalone/cannot_write_to_dir.txt.erb +0 -0
  635. data/{lib/phusion_passenger → resources}/templates/standalone/config.erb +26 -5
  636. data/{lib/phusion_passenger → resources}/templates/standalone/possible_solutions_for_download_and_extraction_problems.txt.erb +0 -0
  637. data/{lib/phusion_passenger → resources}/templates/standalone/run_installer_as_root.txt.erb +0 -0
  638. data/{lib/phusion_passenger → resources}/templates/standalone/welcome.txt.erb +0 -0
  639. data/resources/templates/undisclosed_error.html.template +25 -0
  640. data/test/config.json.example +42 -0
  641. data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +86 -0
  642. data/test/cxx/ApplicationPool2/OptionsTest.cpp +44 -0
  643. data/test/cxx/ApplicationPool2/PoolTest.cpp +1234 -0
  644. data/test/cxx/ApplicationPool2/ProcessTest.cpp +131 -0
  645. data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +229 -0
  646. data/test/cxx/ApplicationPool2/SpawnerTestCases.cpp +744 -0
  647. data/test/cxx/BufferedIOTest.cpp +7 -7
  648. data/test/cxx/CxxTestMain.cpp +65 -2
  649. data/test/cxx/FileBackedPipeTest.cpp +626 -0
  650. data/test/cxx/FileChangeCheckerTest.cpp +20 -18
  651. data/test/cxx/FilterSupportTest.cpp +5 -5
  652. data/test/cxx/IOUtilsTest.cpp +11 -4
  653. data/test/cxx/MessageReadersWritersTest.cpp +1 -1
  654. data/test/cxx/MessageServerTest.cpp +31 -30
  655. data/test/cxx/RequestHandlerTest.cpp +777 -0
  656. data/test/cxx/ScgiRequestParserTest.cpp +36 -16
  657. data/test/cxx/ServerInstanceDirTest.cpp +1 -1
  658. data/test/cxx/StringMapTest.cpp +61 -0
  659. data/test/cxx/TemplateTest.cpp +118 -0
  660. data/test/cxx/TestSupport.cpp +25 -68
  661. data/test/cxx/TestSupport.h +81 -41
  662. data/test/cxx/{LoggingTest.cpp → UnionStationTest.cpp} +79 -74
  663. data/test/cxx/UtilsTest.cpp +59 -5
  664. data/test/integration_tests/apache2_tests.rb +2 -2
  665. data/test/integration_tests/nginx_tests.rb +1 -1
  666. data/test/integration_tests/spec_helper.rb +7 -5
  667. data/test/oxt/oxt_test_main.cpp +2 -0
  668. data/test/oxt/syscall_interruption_test.cpp +1 -0
  669. data/test/ruby/classic_rails/loader_spec.rb +48 -0
  670. data/test/ruby/classic_rails/preloader_spec.rb +54 -0
  671. data/test/ruby/rack/loader_spec.rb +62 -0
  672. data/test/ruby/rack/preloader_spec.rb +74 -0
  673. data/test/ruby/{abstract_request_handler_spec.rb → request_handler_spec.rb} +31 -68
  674. data/test/ruby/shared/loader_spec.rb +241 -0
  675. data/test/ruby/shared/rails/analytics_logging_extensions_spec.rb +141 -182
  676. data/test/ruby/shared/ruby_loader_spec.rb +55 -0
  677. data/test/ruby/spec_helper.rb +8 -53
  678. data/test/ruby/utils/file_system_watcher_spec.rb +9 -1
  679. data/test/ruby/utils_spec.rb +10 -683
  680. data/test/stub/rack/config.ru +28 -3
  681. data/test/stub/rack/start.rb +47 -0
  682. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/Rakefile +0 -0
  683. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/controllers/application_controller.rb +0 -2
  684. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/controllers/bar_controller_1.rb +0 -0
  685. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/controllers/bar_controller_2.rb +0 -0
  686. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/controllers/foo_controller.rb +0 -0
  687. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/app/helpers/application_helper.rb +0 -0
  688. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/boot.rb +0 -0
  689. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/database.yml +3 -3
  690. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/environment.rb +5 -2
  691. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/environments/development.rb +0 -0
  692. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/environments/production.rb +0 -0
  693. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/environments/staging.rb +0 -0
  694. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/initializers/inflections.rb +0 -0
  695. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/initializers/mime_types.rb +0 -0
  696. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/config/routes.rb +1 -0
  697. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/about +0 -0
  698. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/console +0 -0
  699. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/dbconsole +0 -0
  700. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/destroy +0 -0
  701. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/generate +0 -0
  702. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/performance/benchmarker +0 -0
  703. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/performance/profiler +0 -0
  704. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/performance/request +0 -0
  705. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/plugin +0 -0
  706. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/process/inspector +0 -0
  707. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/process/reaper +0 -0
  708. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/process/spawner +0 -0
  709. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/runner +0 -0
  710. data/test/stub/{rails_apps/2.3/foobar → rails2.3}/script/server +0 -0
  711. data/test/stub/{rails_apps/3.0/empty → rails3.0}/Gemfile +0 -0
  712. data/test/stub/rails3.0/Gemfile.lock +80 -0
  713. data/test/stub/{rails_apps/3.0/empty → rails3.0}/Rakefile +0 -0
  714. data/test/stub/{rails_apps/3.0/empty → rails3.0}/app/controllers/application_controller.rb +0 -0
  715. data/test/stub/{rails_apps/3.0/empty → rails3.0}/app/helpers/application_helper.rb +0 -0
  716. data/test/stub/{rails_apps/3.0/empty → rails3.0}/app/views/layouts/application.html.erb +0 -0
  717. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config.ru +0 -0
  718. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/application.rb +0 -0
  719. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/boot.rb +0 -0
  720. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/database.yml +0 -0
  721. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/environment.rb +0 -0
  722. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/environments/development.rb +0 -0
  723. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/environments/production.rb +0 -0
  724. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/environments/test.rb +0 -0
  725. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/backtrace_silencers.rb +0 -0
  726. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/inflections.rb +0 -0
  727. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/mime_types.rb +0 -0
  728. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/passenger.rb +0 -0
  729. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/secret_token.rb +0 -0
  730. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/initializers/session_store.rb +0 -0
  731. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/locales/en.yml +0 -0
  732. data/test/stub/{rails_apps/3.0/empty → rails3.0}/config/routes.rb +0 -0
  733. data/test/stub/{rails_apps/3.0/empty → rails3.0}/db/seeds.rb +0 -0
  734. data/test/stub/{rails_apps/3.0/empty → rails3.0}/doc/README_FOR_APP +0 -0
  735. data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/404.html +0 -0
  736. data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/422.html +0 -0
  737. data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/500.html +0 -0
  738. data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/favicon.ico +0 -0
  739. data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/index.html +0 -0
  740. data/test/stub/{rails_apps/3.0/empty → rails3.0}/public/robots.txt +0 -0
  741. data/test/stub/{rails_apps/3.0/empty → rails3.0}/script/rails +0 -0
  742. data/test/stub/{rails_apps/3.0/empty → rails3.0}/test/performance/browsing_test.rb +0 -0
  743. data/test/stub/{rails_apps/3.0/empty → rails3.0}/test/test_helper.rb +0 -0
  744. data/test/stub/start_error.pl +24 -0
  745. data/test/stub/wsgi/passenger_wsgi.py +71 -3
  746. data/test/support/apache2_controller.rb +2 -2
  747. data/test/support/placebo-preloader.rb +88 -0
  748. data/test/support/test_helper.rb +1 -14
  749. data/test/tut/tut.h +11 -4
  750. metadata +590 -326
  751. data.tar.gz.asc +0 -12
  752. data/PACKAGING.TXT +0 -25
  753. data/build/config.rb +0 -46
  754. data/ext/apache2/HelperAgent.cpp +0 -364
  755. data/ext/boost/call_traits.hpp +0 -24
  756. data/ext/boost/detail/call_traits.hpp +0 -164
  757. data/ext/common/AbstractSpawnManager.h +0 -110
  758. data/ext/common/AgentBase.cpp +0 -432
  759. data/ext/common/ApplicationPool/Client.h +0 -788
  760. data/ext/common/ApplicationPool/Interface.h +0 -295
  761. data/ext/common/ApplicationPool/Pool.h +0 -1327
  762. data/ext/common/ApplicationPool/Server.h +0 -479
  763. data/ext/common/MessageChannel.h +0 -494
  764. data/ext/common/PoolOptions.h +0 -518
  765. data/ext/common/Process.h +0 -253
  766. data/ext/common/Session.h +0 -436
  767. data/ext/common/SpawnManager.h +0 -611
  768. data/ext/google/ChangeLog +0 -167
  769. data/ext/google/dense_hash_map +0 -310
  770. data/ext/google/dense_hash_set +0 -287
  771. data/ext/google/sparse_hash_map +0 -294
  772. data/ext/google/sparse_hash_set +0 -275
  773. data/ext/google/sparsehash/densehashtable.h +0 -1062
  774. data/ext/google/sparsehash/sparseconfig.h +0 -55
  775. data/ext/google/sparsehash/sparsehashtable.h +0 -1015
  776. data/ext/google/sparsetable +0 -1468
  777. data/ext/google/type_traits.h +0 -250
  778. data/ext/nginx/HelperAgent.cpp +0 -1355
  779. data/ext/nginx/ScgiRequestParser.h +0 -375
  780. data/ext/oxt/backtrace.cpp +0 -185
  781. data/ext/oxt/tracable_exception.cpp +0 -89
  782. data/helper-scripts/passenger-spawn-server +0 -106
  783. data/lib/phusion_passenger/abstract_request_handler.rb +0 -766
  784. data/lib/phusion_passenger/abstract_server.rb +0 -372
  785. data/lib/phusion_passenger/abstract_server_collection.rb +0 -335
  786. data/lib/phusion_passenger/app_process.rb +0 -174
  787. data/lib/phusion_passenger/classic_rails/application_spawner.rb +0 -344
  788. data/lib/phusion_passenger/classic_rails/framework_spawner.rb +0 -311
  789. data/lib/phusion_passenger/exceptions.rb +0 -103
  790. data/lib/phusion_passenger/html_template.rb +0 -107
  791. data/lib/phusion_passenger/rack/application_spawner.rb +0 -231
  792. data/lib/phusion_passenger/spawn_manager.rb +0 -359
  793. data/lib/phusion_passenger/templates/app_exited_during_initialization.html.erb +0 -38
  794. data/lib/phusion_passenger/templates/app_init_error.html.erb +0 -64
  795. data/lib/phusion_passenger/templates/database_error.html.erb +0 -66
  796. data/lib/phusion_passenger/templates/error_layout.html.erb +0 -39
  797. data/lib/phusion_passenger/templates/framework_init_error.html.erb +0 -39
  798. data/lib/phusion_passenger/templates/general_error.html.erb +0 -22
  799. data/lib/phusion_passenger/templates/load_error.html.erb +0 -46
  800. data/lib/phusion_passenger/templates/version_not_found.html.erb +0 -34
  801. data/lib/phusion_passenger/utils/rewindable_input.rb +0 -125
  802. data/lib/phusion_passenger/wsgi/application_spawner.rb +0 -108
  803. data/test/config.yml.example +0 -41
  804. data/test/cxx/ApplicationPool_PoolTest.cpp +0 -33
  805. data/test/cxx/ApplicationPool_PoolTestCases.cpp +0 -1029
  806. data/test/cxx/ApplicationPool_ServerTest.cpp +0 -308
  807. data/test/cxx/ApplicationPool_Server_PoolTest.cpp +0 -80
  808. data/test/cxx/MessageChannelTest.cpp +0 -557
  809. data/test/cxx/PoolOptionsTest.cpp +0 -116
  810. data/test/cxx/SpawnManagerTest.cpp +0 -161
  811. data/test/ruby/abstract_server_collection_spec.rb +0 -247
  812. data/test/ruby/abstract_server_spec.rb +0 -61
  813. data/test/ruby/app_process_spec.rb +0 -43
  814. data/test/ruby/classic_rails/application_spawner_spec.rb +0 -89
  815. data/test/ruby/classic_rails/framework_spawner_spec.rb +0 -92
  816. data/test/ruby/rack/application_spawner_spec.rb +0 -116
  817. data/test/ruby/shared/abstract_server_spec.rb +0 -23
  818. data/test/ruby/shared/spawners/classic_rails/framework_spawner_spec.rb +0 -38
  819. data/test/ruby/shared/spawners/classic_rails/lack_of_rails_gem_version_spec.rb +0 -19
  820. data/test/ruby/shared/spawners/classic_rails/spawner_spec.rb +0 -15
  821. data/test/ruby/shared/spawners/non_preloading_spawner_spec.rb +0 -27
  822. data/test/ruby/shared/spawners/preloading_spawner_spec.rb +0 -29
  823. data/test/ruby/shared/spawners/reload_all_spec.rb +0 -36
  824. data/test/ruby/shared/spawners/reload_single_spec.rb +0 -52
  825. data/test/ruby/shared/spawners/spawn_server_spec.rb +0 -28
  826. data/test/ruby/shared/spawners/spawner_spec.rb +0 -273
  827. data/test/ruby/shared/utils/pseudo_io_spec.rb +0 -60
  828. data/test/ruby/spawn_manager_spec.rb +0 -134
  829. data/test/ruby/wsgi/application_spawner_spec.rb +0 -50
  830. data/test/stub/message_channel.rb +0 -11
  831. data/test/stub/message_channel_2.rb +0 -12
  832. data/test/stub/message_channel_3.rb +0 -19
  833. data/test/stub/rails_apps/3.0/empty/Gemfile.lock +0 -73
  834. data/test/stub/spawn_server.rb +0 -22
  835. metadata.gz.asc +0 -12
@@ -1,1468 +0,0 @@
1
- // Copyright (c) 2005, Google Inc.
2
- // All rights reserved.
3
- //
4
- // Redistribution and use in source and binary forms, with or without
5
- // modification, are permitted provided that the following conditions are
6
- // met:
7
- //
8
- // * Redistributions of source code must retain the above copyright
9
- // notice, this list of conditions and the following disclaimer.
10
- // * Redistributions in binary form must reproduce the above
11
- // copyright notice, this list of conditions and the following disclaimer
12
- // in the documentation and/or other materials provided with the
13
- // distribution.
14
- // * Neither the name of Google Inc. nor the names of its
15
- // contributors may be used to endorse or promote products derived from
16
- // this software without specific prior written permission.
17
- //
18
- // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
- // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
- // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
- // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
- // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
- // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
- // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
- // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
- // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
- // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
- // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
-
30
- // ---
31
- // Author: Craig Silverstein
32
- //
33
- // A sparsetable is a random container that implements a sparse array,
34
- // that is, an array that uses very little memory to store unassigned
35
- // indices (in this case, between 1-2 bits per unassigned index). For
36
- // instance, if you allocate an array of size 5 and assign a[2] = <big
37
- // struct>, then a[2] will take up a lot of memory but a[0], a[1],
38
- // a[3], and a[4] will not. Array elements that have a value are
39
- // called "assigned". Array elements that have no value yet, or have
40
- // had their value cleared using erase() or clear(), are called
41
- // "unassigned".
42
- //
43
- // Unassigned values seem to have the default value of T (see below).
44
- // Nevertheless, there is a difference between an unassigned index and
45
- // one explicitly assigned the value of T(). The latter is considered
46
- // assigned.
47
- //
48
- // Access to an array element is constant time, as is insertion and
49
- // deletion. Insertion and deletion may be fairly slow, however:
50
- // because of this container's memory economy, each insert and delete
51
- // causes a memory reallocation.
52
- //
53
- // See /usr/(local/)?doc/sparsehash-0.1/sparsetable.html
54
- // for information about how to use this class.
55
-
56
- #ifndef _SPARSETABLE_H_
57
- #define _SPARSETABLE_H_
58
-
59
- #include <google/sparsehash/sparseconfig.h>
60
- #include <stdlib.h> // for malloc/free
61
- #include <stdio.h> // to read/write tables
62
- #ifdef HAVE_STDINT_H
63
- #include <stdint.h> // the normal place uint16_t is defined
64
- #endif
65
- #ifdef HAVE_SYS_TYPES_H
66
- #include <sys/types.h> // the normal place u_int16_t is defined
67
- #endif
68
- #ifdef HAVE_INTTYPES_H
69
- #include <inttypes.h> // a third place for uint16_t or u_int16_t
70
- #endif
71
- #include <assert.h> // for bounds checking
72
- #include <iterator> // to define reverse_iterator for me
73
- #include <algorithm> // equal, lexicographical_compare, swap,...
74
- #include <memory> // uninitialized_copy
75
- #include <vector> // a sparsetable is a vector of groups
76
- #include <google/type_traits.h> // for true_type, integral_constant, etc.
77
-
78
- #if STDC_HEADERS
79
- #include <string.h> // for memcpy
80
- #else
81
- #if !HAVE_MEMCPY
82
- #define memcpy(d, s, n) bcopy ((s), (d), (n))
83
- #endif
84
- #endif
85
-
86
- _START_GOOGLE_NAMESPACE_
87
-
88
- #ifndef HAVE_U_INT16_T
89
- # if defined HAVE_UINT16_T
90
- typedef uint16_t u_int16_t; // true on solaris, possibly other C99 libc's
91
- # elif defined HAVE___UINT16
92
- typedef __int16 int16_t; // true on vc++7
93
- typedef unsigned __int16 u_int16_t;
94
- # else
95
- // Cannot find a 16-bit integer type. Hoping for the best with "short"...
96
- typedef short int int16_t;
97
- typedef unsigned short int u_int16_t;
98
- # endif
99
- #endif
100
-
101
- using STL_NAMESPACE::vector;
102
- using STL_NAMESPACE::uninitialized_copy;
103
-
104
- // The smaller this is, the faster lookup is (because the group bitmap is
105
- // smaller) and the faster insert is, because there's less to move.
106
- // On the other hand, there are more groups. Since group::size_type is
107
- // a short, this number should be of the form 32*x + 16 to avoid waste.
108
- static const u_int16_t DEFAULT_SPARSEGROUP_SIZE = 48; // fits in 1.5 words
109
-
110
-
111
- // A NOTE ON ASSIGNING:
112
- // A sparse table does not actually allocate memory for entries
113
- // that are not filled. Because of this, it becomes complicated
114
- // to have a non-const iterator: we don't know, if the iterator points
115
- // to a not-filled bucket, whether you plan to fill it with something
116
- // or whether you plan to read its value (in which case you'll get
117
- // the default bucket value). Therefore, while we can define const
118
- // operations in a pretty 'normal' way, for non-const operations, we
119
- // define something that returns a helper object with operator= and
120
- // operator& that allocate a bucket lazily. We use this for table[]
121
- // and also for regular table iterators.
122
-
123
- template <class tabletype>
124
- class table_element_adaptor {
125
- public:
126
- typedef typename tabletype::value_type value_type;
127
- typedef typename tabletype::size_type size_type;
128
- typedef typename tabletype::reference reference;
129
- typedef typename tabletype::pointer pointer;
130
-
131
- table_element_adaptor(tabletype *tbl, size_type p)
132
- : table(tbl), pos(p) { }
133
- table_element_adaptor& operator= (const value_type &val) {
134
- table->set(pos, val);
135
- return *this;
136
- }
137
- operator value_type() { return table->get(pos); } // we look like a value
138
- pointer operator& () { return &table->mutating_get(pos); }
139
-
140
- private:
141
- tabletype* table;
142
- size_type pos;
143
- };
144
-
145
- // Our iterator as simple as iterators can be: basically it's just
146
- // the index into our table. Dereference, the only complicated
147
- // thing, we punt to the table class. This just goes to show how
148
- // much machinery STL requires to do even the most trivial tasks.
149
- //
150
- // By templatizing over tabletype, we have one iterator type which
151
- // we can use for both sparsetables and sparsebins. In fact it
152
- // works on any class that allows size() and operator[] (eg vector),
153
- // as long as it does the standard STL typedefs too (eg value_type).
154
-
155
- template <class tabletype>
156
- class table_iterator {
157
- public:
158
- typedef table_iterator iterator;
159
-
160
- typedef STL_NAMESPACE::random_access_iterator_tag iterator_category;
161
- typedef typename tabletype::value_type value_type;
162
- typedef typename tabletype::difference_type difference_type;
163
- typedef typename tabletype::size_type size_type;
164
- typedef table_element_adaptor<tabletype> reference;
165
- typedef table_element_adaptor<tabletype>* pointer;
166
-
167
- // The "real" constructor
168
- table_iterator(tabletype *tbl, size_type p)
169
- : table(tbl), pos(p) { }
170
- // The default constructor, used when I define vars of type table::iterator
171
- table_iterator() : table(NULL), pos(0) { }
172
- // The copy constructor, for when I say table::iterator foo = tbl.begin()
173
- // The default destructor is fine; we don't define one
174
- // The default operator= is fine; we don't define one
175
-
176
- // The main thing our iterator does is dereference. If the table entry
177
- // we point to is empty, we return the default value type.
178
- // This is the big different function from the const iterator.
179
- reference operator*() {
180
- return table_element_adaptor<tabletype>(table, pos);
181
- }
182
- pointer operator->() { return &(operator*()); }
183
-
184
- // Helper function to assert things are ok; eg pos is still in range
185
- void check() const {
186
- assert(table);
187
- assert(pos <= table->size());
188
- }
189
-
190
- // Arithmetic: we just do arithmetic on pos. We don't even need to
191
- // do bounds checking, since STL doesn't consider that it's job. :-)
192
- iterator& operator+=(size_type t) { pos += t; check(); return *this; }
193
- iterator& operator-=(size_type t) { pos -= t; check(); return *this; }
194
- iterator& operator++() { ++pos; check(); return *this; }
195
- iterator& operator--() { --pos; check(); return *this; }
196
- iterator operator++(int) { iterator tmp(*this); // for x++
197
- ++pos; check(); return tmp; }
198
- iterator operator--(int) { iterator tmp(*this); // for x--
199
- --pos; check(); return tmp; }
200
- iterator operator+(difference_type i) const { iterator tmp(*this);
201
- tmp += i; return tmp; }
202
- iterator operator-(difference_type i) const { iterator tmp(*this);
203
- tmp -= i; return tmp; }
204
- difference_type operator-(iterator it) const { // for "x = it2 - it"
205
- assert(table == it.table);
206
- return pos - it.pos;
207
- }
208
- reference operator[](difference_type n) const {
209
- return *(*this + n); // simple though not totally efficient
210
- }
211
-
212
- // Comparisons.
213
- bool operator==(const iterator& it) const {
214
- return table == it.table && pos == it.pos;
215
- }
216
- bool operator<(const iterator& it) const {
217
- assert(table == it.table); // life is bad bad bad otherwise
218
- return pos < it.pos;
219
- }
220
- bool operator!=(const iterator& it) const { return !(*this == it); }
221
- bool operator<=(const iterator& it) const { return !(it < *this); }
222
- bool operator>(const iterator& it) const { return it < *this; }
223
- bool operator>=(const iterator& it) const { return !(*this < it); }
224
-
225
- // Here's the info we actually need to be an iterator
226
- tabletype *table; // so we can dereference and bounds-check
227
- size_type pos; // index into the table
228
- };
229
-
230
- // support for "3 + iterator" has to be defined outside the class, alas
231
- template<class T>
232
- table_iterator<T> operator+(typename table_iterator<T>::difference_type i,
233
- table_iterator<T> it) {
234
- return it + i; // so people can say it2 = 3 + it
235
- }
236
-
237
- template <class tabletype>
238
- class const_table_iterator {
239
- public:
240
- typedef table_iterator<tabletype> iterator;
241
- typedef const_table_iterator const_iterator;
242
-
243
- typedef STL_NAMESPACE::random_access_iterator_tag iterator_category;
244
- typedef typename tabletype::value_type value_type;
245
- typedef typename tabletype::difference_type difference_type;
246
- typedef typename tabletype::size_type size_type;
247
- typedef typename tabletype::const_reference reference; // we're const-only
248
- typedef typename tabletype::const_pointer pointer;
249
-
250
- // The "real" constructor
251
- const_table_iterator(const tabletype *tbl, size_type p)
252
- : table(tbl), pos(p) { }
253
- // The default constructor, used when I define vars of type table::iterator
254
- const_table_iterator() : table(NULL), pos(0) { }
255
- // The copy constructor, for when I say table::iterator foo = tbl.begin()
256
- // Also converts normal iterators to const iterators
257
- const_table_iterator(const iterator &from)
258
- : table(from.table), pos(from.pos) { }
259
- // The default destructor is fine; we don't define one
260
- // The default operator= is fine; we don't define one
261
-
262
- // The main thing our iterator does is dereference. If the table entry
263
- // we point to is empty, we return the default value type.
264
- reference operator*() const { return (*table)[pos]; }
265
- pointer operator->() const { return &(operator*()); }
266
-
267
- // Helper function to assert things are ok; eg pos is still in range
268
- void check() const {
269
- assert(table);
270
- assert(pos <= table->size());
271
- }
272
-
273
- // Arithmetic: we just do arithmetic on pos. We don't even need to
274
- // do bounds checking, since STL doesn't consider that it's job. :-)
275
- const_iterator& operator+=(size_type t) { pos += t; check(); return *this; }
276
- const_iterator& operator-=(size_type t) { pos -= t; check(); return *this; }
277
- const_iterator& operator++() { ++pos; check(); return *this; }
278
- const_iterator& operator--() { --pos; check(); return *this; }
279
- const_iterator operator++(int) { const_iterator tmp(*this); // for x++
280
- ++pos; check(); return tmp; }
281
- const_iterator operator--(int) { const_iterator tmp(*this); // for x--
282
- --pos; check(); return tmp; }
283
- const_iterator operator+(difference_type i) const { const_iterator tmp(*this);
284
- tmp += i; return tmp; }
285
- const_iterator operator-(difference_type i) const { const_iterator tmp(*this);
286
- tmp -= i; return tmp; }
287
- difference_type operator-(const_iterator it) const { // for "x = it2 - it"
288
- assert(table == it.table);
289
- return pos - it.pos;
290
- }
291
- reference operator[](difference_type n) const {
292
- return *(*this + n); // simple though not totally efficient
293
- }
294
-
295
- // Comparisons.
296
- bool operator==(const const_iterator& it) const {
297
- return table == it.table && pos == it.pos;
298
- }
299
- bool operator<(const const_iterator& it) const {
300
- assert(table == it.table); // life is bad bad bad otherwise
301
- return pos < it.pos;
302
- }
303
- bool operator!=(const const_iterator& it) const { return !(*this == it); }
304
- bool operator<=(const const_iterator& it) const { return !(it < *this); }
305
- bool operator>(const const_iterator& it) const { return it < *this; }
306
- bool operator>=(const const_iterator& it) const { return !(*this < it); }
307
-
308
- // Here's the info we actually need to be an iterator
309
- const tabletype *table; // so we can dereference and bounds-check
310
- size_type pos; // index into the table
311
- };
312
-
313
- // support for "3 + iterator" has to be defined outside the class, alas
314
- template<class T>
315
- const_table_iterator<T> operator+(typename
316
- const_table_iterator<T>::difference_type i,
317
- const_table_iterator<T> it) {
318
- return it + i; // so people can say it2 = 3 + it
319
- }
320
-
321
-
322
- // ---------------------------------------------------------------------------
323
-
324
-
325
- /*
326
- // This is a 2-D iterator. You specify a begin and end over a list
327
- // of *containers*. We iterate over each container by iterating over
328
- // it. It's actually simple:
329
- // VECTOR.begin() VECTOR[0].begin() --------> VECTOR[0].end() ---,
330
- // | ________________________________________________/
331
- // | \_> VECTOR[1].begin() --------> VECTOR[1].end() -,
332
- // | ___________________________________________________/
333
- // v \_> ......
334
- // VECTOR.end()
335
- //
336
- // It's impossible to do random access on one of these things in constant
337
- // time, so it's just a bidirectional iterator.
338
- //
339
- // Unfortunately, because we need to use this for a non-empty iterator,
340
- // we use nonempty_begin() and nonempty_end() instead of begin() and end()
341
- // (though only going across, not down).
342
- */
343
-
344
- #define TWOD_BEGIN_ nonempty_begin
345
- #define TWOD_END_ nonempty_end
346
- #define TWOD_ITER_ nonempty_iterator
347
- #define TWOD_CONST_ITER_ const_nonempty_iterator
348
-
349
- template <class containertype>
350
- class two_d_iterator {
351
- public:
352
- typedef two_d_iterator iterator;
353
-
354
- typedef STL_NAMESPACE::bidirectional_iterator_tag iterator_category;
355
- // apparently some versions of VC++ have trouble with two ::'s in a typename
356
- typedef typename containertype::value_type _tmp_vt;
357
- typedef typename _tmp_vt::value_type value_type;
358
- typedef typename _tmp_vt::difference_type difference_type;
359
- typedef typename _tmp_vt::reference reference;
360
- typedef typename _tmp_vt::pointer pointer;
361
-
362
- // The "real" constructor. begin and end specify how many rows we have
363
- // (in the diagram above); we always iterate over each row completely.
364
- two_d_iterator(typename containertype::iterator begin,
365
- typename containertype::iterator end,
366
- typename containertype::iterator curr)
367
- : row_begin(begin), row_end(end), row_current(curr), col_current() {
368
- if ( row_current != row_end ) {
369
- col_current = row_current->TWOD_BEGIN_();
370
- advance_past_end(); // in case cur->begin() == cur->end()
371
- }
372
- }
373
- // If you want to start at an arbitrary place, you can, I guess
374
- two_d_iterator(typename containertype::iterator begin,
375
- typename containertype::iterator end,
376
- typename containertype::iterator curr,
377
- typename containertype::value_type::TWOD_ITER_ col)
378
- : row_begin(begin), row_end(end), row_current(curr), col_current(col) {
379
- advance_past_end(); // in case cur->begin() == cur->end()
380
- }
381
- // The default constructor, used when I define vars of type table::iterator
382
- two_d_iterator() : row_begin(), row_end(), row_current(), col_current() { }
383
- // The default destructor is fine; we don't define one
384
- // The default operator= is fine; we don't define one
385
-
386
- // Happy dereferencer
387
- reference operator*() const { return *col_current; }
388
- pointer operator->() const { return &(operator*()); }
389
-
390
- // Arithmetic: we just do arithmetic on pos. We don't even need to
391
- // do bounds checking, since STL doesn't consider that it's job. :-)
392
- // NOTE: this is not amortized constant time! What do we do about it?
393
- void advance_past_end() { // used when col_current points to end()
394
- while ( col_current == row_current->TWOD_END_() ) { // end of current row
395
- ++row_current; // go to beginning of next
396
- if ( row_current != row_end ) // col is irrelevant at end
397
- col_current = row_current->TWOD_BEGIN_();
398
- else
399
- break; // don't go past row_end
400
- }
401
- }
402
-
403
- iterator& operator++() {
404
- assert(row_current != row_end); // how to ++ from there?
405
- ++col_current;
406
- advance_past_end(); // in case col_current is at end()
407
- return *this;
408
- }
409
- iterator& operator--() {
410
- while ( row_current == row_end ||
411
- col_current == row_current->TWOD_BEGIN_() ) {
412
- assert(row_current != row_begin);
413
- --row_current;
414
- col_current = row_current->TWOD_END_(); // this is 1 too far
415
- }
416
- --col_current;
417
- return *this;
418
- }
419
- iterator operator++(int) { iterator tmp(*this); ++*this; return tmp; }
420
- iterator operator--(int) { iterator tmp(*this); --*this; return tmp; }
421
-
422
-
423
- // Comparisons.
424
- bool operator==(const iterator& it) const {
425
- return ( row_begin == it.row_begin &&
426
- row_end == it.row_end &&
427
- row_current == it.row_current &&
428
- (row_current == row_end || col_current == it.col_current) );
429
- }
430
- bool operator!=(const iterator& it) const { return !(*this == it); }
431
-
432
-
433
- // Here's the info we actually need to be an iterator
434
- // These need to be public so we convert from iterator to const_iterator
435
- typename containertype::iterator row_begin, row_end, row_current;
436
- typename containertype::value_type::TWOD_ITER_ col_current;
437
- };
438
-
439
- // The same thing again, but this time const. :-(
440
- template <class containertype>
441
- class const_two_d_iterator {
442
- public:
443
- typedef const_two_d_iterator iterator;
444
-
445
- typedef STL_NAMESPACE::bidirectional_iterator_tag iterator_category;
446
- // apparently some versions of VC++ have trouble with two ::'s in a typename
447
- typedef typename containertype::value_type _tmp_vt;
448
- typedef typename _tmp_vt::value_type value_type;
449
- typedef typename _tmp_vt::difference_type difference_type;
450
- typedef typename _tmp_vt::const_reference reference;
451
- typedef typename _tmp_vt::const_pointer pointer;
452
-
453
- const_two_d_iterator(typename containertype::const_iterator begin,
454
- typename containertype::const_iterator end,
455
- typename containertype::const_iterator curr)
456
- : row_begin(begin), row_end(end), row_current(curr), col_current() {
457
- if ( curr != end ) {
458
- col_current = curr->TWOD_BEGIN_();
459
- advance_past_end(); // in case cur->begin() == cur->end()
460
- }
461
- }
462
- const_two_d_iterator(typename containertype::const_iterator begin,
463
- typename containertype::const_iterator end,
464
- typename containertype::const_iterator curr,
465
- typename containertype::value_type::TWOD_CONST_ITER_ col)
466
- : row_begin(begin), row_end(end), row_current(curr), col_current(col) {
467
- advance_past_end(); // in case cur->begin() == cur->end()
468
- }
469
- const_two_d_iterator()
470
- : row_begin(), row_end(), row_current(), col_current() {
471
- }
472
- // Need this explicitly so we can convert normal iterators to const iterators
473
- const_two_d_iterator(const two_d_iterator<containertype>& it) :
474
- row_begin(it.row_begin), row_end(it.row_end), row_current(it.row_current),
475
- col_current(it.col_current) { }
476
-
477
- typename containertype::const_iterator row_begin, row_end, row_current;
478
- typename containertype::value_type::TWOD_CONST_ITER_ col_current;
479
-
480
-
481
- // EVERYTHING FROM HERE DOWN IS THE SAME AS THE NON-CONST ITERATOR
482
- reference operator*() const { return *col_current; }
483
- pointer operator->() const { return &(operator*()); }
484
-
485
- void advance_past_end() { // used when col_current points to end()
486
- while ( col_current == row_current->TWOD_END_() ) { // end of current row
487
- ++row_current; // go to beginning of next
488
- if ( row_current != row_end ) // col is irrelevant at end
489
- col_current = row_current->TWOD_BEGIN_();
490
- else
491
- break; // don't go past row_end
492
- }
493
- }
494
- iterator& operator++() {
495
- assert(row_current != row_end); // how to ++ from there?
496
- ++col_current;
497
- advance_past_end(); // in case col_current is at end()
498
- return *this;
499
- }
500
- iterator& operator--() {
501
- while ( row_current == row_end ||
502
- col_current == row_current->TWOD_BEGIN_() ) {
503
- assert(row_current != row_begin);
504
- --row_current;
505
- col_current = row_current->TWOD_END_(); // this is 1 too far
506
- }
507
- --col_current;
508
- return *this;
509
- }
510
- iterator operator++(int) { iterator tmp(*this); ++*this; return tmp; }
511
- iterator operator--(int) { iterator tmp(*this); --*this; return tmp; }
512
-
513
- bool operator==(const iterator& it) const {
514
- return ( row_begin == it.row_begin &&
515
- row_end == it.row_end &&
516
- row_current == it.row_current &&
517
- (row_current == row_end || col_current == it.col_current) );
518
- }
519
- bool operator!=(const iterator& it) const { return !(*this == it); }
520
- };
521
-
522
- // We provide yet another version, to be as frugal with memory as
523
- // possible. This one frees each block of memory as it finishes
524
- // iterating over it. By the end, the entire table is freed.
525
- // For understandable reasons, you can only iterate over it once,
526
- // which is why it's an input iterator
527
- template <class containertype>
528
- class destructive_two_d_iterator {
529
- public:
530
- typedef destructive_two_d_iterator iterator;
531
-
532
- typedef STL_NAMESPACE::input_iterator_tag iterator_category;
533
- // apparently some versions of VC++ have trouble with two ::'s in a typename
534
- typedef typename containertype::value_type _tmp_vt;
535
- typedef typename _tmp_vt::value_type value_type;
536
- typedef typename _tmp_vt::difference_type difference_type;
537
- typedef typename _tmp_vt::reference reference;
538
- typedef typename _tmp_vt::pointer pointer;
539
-
540
- destructive_two_d_iterator(typename containertype::iterator begin,
541
- typename containertype::iterator end,
542
- typename containertype::iterator curr)
543
- : row_begin(begin), row_end(end), row_current(curr), col_current() {
544
- if ( curr != end ) {
545
- col_current = curr->TWOD_BEGIN_();
546
- advance_past_end(); // in case cur->begin() == cur->end()
547
- }
548
- }
549
- destructive_two_d_iterator(typename containertype::iterator begin,
550
- typename containertype::iterator end,
551
- typename containertype::iterator curr,
552
- typename containertype::value_type::TWOD_ITER_ col)
553
- : row_begin(begin), row_end(end), row_current(curr), col_current(col) {
554
- advance_past_end(); // in case cur->begin() == cur->end()
555
- }
556
- destructive_two_d_iterator()
557
- : row_begin(), row_end(), row_current(), col_current() {
558
- }
559
-
560
- typename containertype::iterator row_begin, row_end, row_current;
561
- typename containertype::value_type::TWOD_ITER_ col_current;
562
-
563
- // This is the part that destroys
564
- void advance_past_end() { // used when col_current points to end()
565
- while ( col_current == row_current->TWOD_END_() ) { // end of current row
566
- row_current->clear(); // the destructive part
567
- // It would be nice if we could decrement sparsetable->num_buckets here
568
- ++row_current; // go to beginning of next
569
- if ( row_current != row_end ) // col is irrelevant at end
570
- col_current = row_current->TWOD_BEGIN_();
571
- else
572
- break; // don't go past row_end
573
- }
574
- }
575
-
576
- // EVERYTHING FROM HERE DOWN IS THE SAME AS THE REGULAR ITERATOR
577
- reference operator*() const { return *col_current; }
578
- pointer operator->() const { return &(operator*()); }
579
-
580
- iterator& operator++() {
581
- assert(row_current != row_end); // how to ++ from there?
582
- ++col_current;
583
- advance_past_end(); // in case col_current is at end()
584
- return *this;
585
- }
586
- iterator operator++(int) { iterator tmp(*this); ++*this; return tmp; }
587
-
588
- bool operator==(const iterator& it) const {
589
- return ( row_begin == it.row_begin &&
590
- row_end == it.row_end &&
591
- row_current == it.row_current &&
592
- (row_current == row_end || col_current == it.col_current) );
593
- }
594
- bool operator!=(const iterator& it) const { return !(*this == it); }
595
- };
596
-
597
- #undef TWOD_BEGIN_
598
- #undef TWOD_END_
599
- #undef TWOD_ITER_
600
- #undef TWOD_CONST_ITER_
601
-
602
-
603
-
604
-
605
- // SPARSE-TABLE
606
- // ------------
607
- // The idea is that a table with (logically) t buckets is divided
608
- // into t/M *groups* of M buckets each. (M is a constant set in
609
- // GROUP_SIZE for efficiency.) Each group is stored sparsely.
610
- // Thus, inserting into the table causes some array to grow, which is
611
- // slow but still constant time. Lookup involves doing a
612
- // logical-position-to-sparse-position lookup, which is also slow but
613
- // constant time. The larger M is, the slower these operations are
614
- // but the less overhead (slightly).
615
- //
616
- // To store the sparse array, we store a bitmap B, where B[i] = 1 iff
617
- // bucket i is non-empty. Then to look up bucket i we really look up
618
- // array[# of 1s before i in B]. This is constant time for fixed M.
619
- //
620
- // Terminology: the position of an item in the overall table (from
621
- // 1 .. t) is called its "location." The logical position in a group
622
- // (from 1 .. M ) is called its "position." The actual location in
623
- // the array (from 1 .. # of non-empty buckets in the group) is
624
- // called its "offset."
625
-
626
- // The weird mod in the offset is entirely to quiet compiler warnings
627
- // as is the cast to int after doing the "x mod 256"
628
- #define PUT_(take_from, offset) do { \
629
- if (putc(static_cast<int>(((take_from) >> ((offset) % (sizeof(take_from)*8)))\
630
- % 256), fp) \
631
- == EOF) \
632
- return false; \
633
- } while (0)
634
-
635
- #define GET_(add_to, offset) do { \
636
- if ((x=getc(fp)) == EOF) \
637
- return false; \
638
- else \
639
- add_to |= (static_cast<size_type>(x) << ((offset) % (sizeof(add_to)*8))); \
640
- } while (0)
641
-
642
- template <class T, u_int16_t GROUP_SIZE>
643
- class sparsegroup {
644
- public:
645
- // Basic types
646
- typedef T value_type;
647
- typedef value_type* pointer;
648
- typedef const value_type* const_pointer;
649
- typedef table_iterator<sparsegroup<T, GROUP_SIZE> > iterator;
650
- typedef const_table_iterator<sparsegroup<T, GROUP_SIZE> > const_iterator;
651
- typedef table_element_adaptor<sparsegroup<T, GROUP_SIZE> > element_adaptor;
652
- typedef value_type &reference;
653
- typedef const value_type &const_reference;
654
- typedef u_int16_t size_type; // max # of buckets
655
- typedef int16_t difference_type;
656
- typedef STL_NAMESPACE::reverse_iterator<const_iterator> const_reverse_iterator;
657
- typedef STL_NAMESPACE::reverse_iterator<iterator> reverse_iterator;
658
-
659
- // These are our special iterators, that go over non-empty buckets in a
660
- // group. These aren't const-only because you can change non-empty bcks.
661
- typedef pointer nonempty_iterator;
662
- typedef const_pointer const_nonempty_iterator;
663
- typedef STL_NAMESPACE::reverse_iterator<nonempty_iterator> reverse_nonempty_iterator;
664
- typedef STL_NAMESPACE::reverse_iterator<const_nonempty_iterator> const_reverse_nonempty_iterator;
665
-
666
- // Iterator functions
667
- iterator begin() { return iterator(this, 0); }
668
- const_iterator begin() const { return const_iterator(this, 0); }
669
- iterator end() { return iterator(this, size()); }
670
- const_iterator end() const { return const_iterator(this, size()); }
671
- reverse_iterator rbegin() { return reverse_iterator(end()); }
672
- const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
673
- reverse_iterator rend() { return reverse_iterator(begin()); }
674
- const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
675
-
676
- // We'll have versions for our special non-empty iterator too
677
- nonempty_iterator nonempty_begin() { return group; }
678
- const_nonempty_iterator nonempty_begin() const { return group; }
679
- nonempty_iterator nonempty_end() { return group + num_buckets; }
680
- const_nonempty_iterator nonempty_end() const { return group + num_buckets; }
681
- reverse_nonempty_iterator nonempty_rbegin() {
682
- return reverse_nonempty_iterator(nonempty_end());
683
- }
684
- const_reverse_nonempty_iterator nonempty_rbegin() const {
685
- return const_reverse_nonempty_iterator(nonempty_end());
686
- }
687
- reverse_nonempty_iterator nonempty_rend() {
688
- return reverse_nonempty_iterator(nonempty_begin());
689
- }
690
- const_reverse_nonempty_iterator nonempty_rend() const {
691
- return const_reverse_nonempty_iterator(nonempty_begin());
692
- }
693
-
694
-
695
- // This gives us the "default" value to return for an empty bucket.
696
- // We just use the default constructor on T, the template type
697
- const_reference default_value() const {
698
- static value_type defaultval = value_type();
699
- return defaultval;
700
- }
701
-
702
-
703
- private:
704
- // We need to do all this bit manipulation, of course. ick
705
- static size_type charbit(size_type i) { return i >> 3; }
706
- static size_type modbit(size_type i) { return 1 << (i&7); }
707
- int bmtest(size_type i) const { return bitmap[charbit(i)] & modbit(i); }
708
- void bmset(size_type i) { bitmap[charbit(i)] |= modbit(i); }
709
- void bmclear(size_type i) { bitmap[charbit(i)] &= ~modbit(i); }
710
-
711
- void* realloc_or_die(void* ptr, size_t num_bytes) {
712
- void* retval = realloc(ptr, num_bytes);
713
- if (retval == NULL) {
714
- // We really should use PRIuS here, but I don't want to have to add
715
- // a whole new configure option, with concomitant macro namespace
716
- // pollution, just to print this (unlikely) error message. So I cast.
717
- fprintf(stderr, "FATAL ERROR: failed to allocate %lu bytes for ptr %p",
718
- static_cast<unsigned long>(num_bytes), ptr);
719
- exit(1);
720
- }
721
- return retval;
722
- }
723
-
724
- value_type* allocate_group(size_t n) {
725
- return static_cast<value_type*>(realloc_or_die(NULL,
726
- n * sizeof(value_type)));
727
- }
728
-
729
- void free_group() {
730
- // Valid even for empty group, because NULL+0 is defined to be NULL
731
- value_type* end_it = group + num_buckets;
732
- for (value_type* p = group; p != end_it; ++p)
733
- p->~value_type();
734
- free(group);
735
- group = NULL;
736
- }
737
-
738
- public: // get_iter() in sparsetable needs it
739
- // We need a small function that tells us how many set bits there are
740
- // in positions 0..i-1 of the bitmap. It uses a big table.
741
- // We make it static so templates don't allocate lots of these tables
742
- static size_type pos_to_offset(const unsigned char *bm, size_type pos) {
743
- // We could make these ints. The tradeoff is size (eg does it overwhelm
744
- // the cache?) vs efficiency in referencing sub-word-sized array elements
745
- static const char bits_in[256] = { // # of bits set in one char
746
- 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
747
- 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
748
- 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
749
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
750
- 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
751
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
752
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
753
- 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
754
- 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
755
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
756
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
757
- 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
758
- 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
759
- 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
760
- 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
761
- 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
762
- };
763
- size_type retval = 0;
764
-
765
- // [Note: condition pos > 8 is an optimization; convince yourself we
766
- // give exactly the same result as if we had pos >= 8 here instead.]
767
- for ( ; pos > 8; pos -= 8 ) // bm[0..pos/8-1]
768
- retval += bits_in[*bm++]; // chars we want *all* bits in
769
- return retval + bits_in[*bm & ((1 << pos)-1)]; // the char that includes pos
770
- }
771
-
772
- size_type pos_to_offset(size_type pos) const { // not static but still const
773
- return pos_to_offset(bitmap, pos);
774
- }
775
-
776
-
777
- public:
778
- // Constructors -- default and copy -- and destructor
779
- sparsegroup() : group(0), num_buckets(0) { memset(bitmap, 0, sizeof(bitmap)); }
780
- sparsegroup(const sparsegroup& x) : group(0), num_buckets(x.num_buckets) {
781
- if ( num_buckets ) {
782
- group = allocate_group(x.num_buckets);
783
- uninitialized_copy(x.group, x.group + x.num_buckets, group);
784
- }
785
- memcpy(bitmap, x.bitmap, sizeof(bitmap));
786
- }
787
- ~sparsegroup() { free_group(); }
788
-
789
- // Operator= is just like the copy constructor, I guess
790
- // TODO(austern): Make this exception safe. Handle exceptions in value_type's
791
- // copy constructor.
792
- sparsegroup &operator=(const sparsegroup& x) {
793
- if ( &x == this ) return *this; // x = x
794
- if ( x.num_buckets == 0 ) {
795
- free_group();
796
- } else {
797
- value_type* p = allocate_group(x.num_buckets);
798
- uninitialized_copy(x.group, x.group + x.num_buckets, p);
799
- free_group();
800
- group = p;
801
- }
802
- memcpy(bitmap, x.bitmap, sizeof(bitmap));
803
- num_buckets = x.num_buckets;
804
- return *this;
805
- }
806
-
807
- // Many STL algorithms use swap instead of copy constructors
808
- void swap(sparsegroup& x) {
809
- STL_NAMESPACE::swap(group, x.group);
810
- for ( int i = 0; i < sizeof(bitmap) / sizeof(*bitmap); ++i )
811
- STL_NAMESPACE::swap(bitmap[i], x.bitmap[i]); // swap not defined on arrays
812
- STL_NAMESPACE::swap(num_buckets, x.num_buckets);
813
- }
814
-
815
- // It's always nice to be able to clear a table without deallocating it
816
- void clear() {
817
- free_group();
818
- memset(bitmap, 0, sizeof(bitmap));
819
- num_buckets = 0;
820
- }
821
-
822
- // Functions that tell you about size. Alas, these aren't so useful
823
- // because our table is always fixed size.
824
- size_type size() const { return GROUP_SIZE; }
825
- size_type max_size() const { return GROUP_SIZE; }
826
- bool empty() const { return false; }
827
- // We also may want to know how many *used* buckets there are
828
- size_type num_nonempty() const { return num_buckets; }
829
-
830
-
831
- // get()/set() are explicitly const/non-const. You can use [] if
832
- // you want something that can be either (potentially more expensive).
833
- const_reference get(size_type i) const {
834
- if ( bmtest(i) ) // bucket i is occupied
835
- return group[pos_to_offset(bitmap, i)];
836
- else
837
- return default_value(); // return the default reference
838
- }
839
-
840
- // TODO(csilvers): make protected + friend
841
- // This is used by sparse_hashtable to get an element from the table
842
- // when we know it exists.
843
- const_reference unsafe_get(size_type i) const {
844
- assert(bmtest(i));
845
- return group[pos_to_offset(bitmap, i)];
846
- }
847
-
848
- // TODO(csilvers): make protected + friend
849
- reference mutating_get(size_type i) { // fills bucket i before getting
850
- if ( !bmtest(i) )
851
- set(i, default_value());
852
- return group[pos_to_offset(bitmap, i)];
853
- }
854
-
855
- // Syntactic sugar. It's easy to return a const reference. To
856
- // return a non-const reference, we need to use the assigner adaptor.
857
- const_reference operator[](size_type i) const {
858
- return get(i);
859
- }
860
-
861
- element_adaptor operator[](size_type i) {
862
- return element_adaptor(this, i);
863
- }
864
-
865
- private:
866
- // Create space at group[offset], assuming value_type has trivial
867
- // copy constructor and destructor. (Really, we want it to have
868
- // "trivial move", because that's what realloc and memmove both do.
869
- // But there's no way to capture that using type_traits, so we
870
- // pretend that move(x, y) is equivalent to "x.~T(); new(x) T(y);"
871
- // which is pretty much correct, if a bit conservative.)
872
- void set_aux(size_type offset, true_type) {
873
- group = (value_type *)
874
- realloc_or_die(group, sizeof(*group) * (num_buckets+1));
875
- // This is equivalent to memmove(), but faster on my Intel P4,
876
- // at least with gcc4.1 -O2 / glibc 2.3.6.
877
- for (size_type i = num_buckets; i > offset; --i)
878
- memcpy(group + i, group + i-1, sizeof(*group));
879
- }
880
-
881
- // Create space at group[offset], without special assumptions about value_type
882
- void set_aux(size_type offset, false_type) {
883
- // This is valid because 0 <= offset <= num_buckets
884
- value_type* p = allocate_group(num_buckets + 1);
885
- uninitialized_copy(group, group + offset, p);
886
- uninitialized_copy(group + offset, group + num_buckets, p + offset + 1);
887
- free_group();
888
- group = p;
889
- }
890
-
891
- public:
892
- // This returns a reference to the inserted item (which is a copy of val).
893
- // TODO(austern): Make this exception safe: handle exceptions from
894
- // value_type's copy constructor.
895
- reference set(size_type i, const_reference val) {
896
- size_type offset = pos_to_offset(bitmap, i); // where we'll find (or insert)
897
- if ( bmtest(i) ) {
898
- // Delete the old value, which we're replacing with the new one
899
- group[offset].~value_type();
900
- } else {
901
- typedef integral_constant<bool,
902
- (has_trivial_copy<value_type>::value &&
903
- has_trivial_destructor<value_type>::value)>
904
- realloc_and_memmove_ok; // we pretend mv(x,y) == "x.~T(); new(x) T(y)"
905
- set_aux(offset, realloc_and_memmove_ok());
906
- ++num_buckets;
907
- bmset(i);
908
- }
909
- // This does the actual inserting. Since we made the array using
910
- // malloc, we use "placement new" to just call the constructor.
911
- new(&group[offset]) value_type(val);
912
- return group[offset];
913
- }
914
-
915
- // We let you see if a bucket is non-empty without retrieving it
916
- bool test(size_type i) const {
917
- return bmtest(i) ? true : false; // cast an int to a bool
918
- }
919
- bool test(iterator pos) const {
920
- return bmtest(pos.pos) ? true : false;
921
- }
922
-
923
- private:
924
- // Shrink the array, assuming value_type has trivial copy
925
- // constructor and destructor. (Really, we want it to have "trivial
926
- // move", because that's what realloc and memmove both do. But
927
- // there's no way to capture that using type_traits, so we pretend
928
- // that move(x, y) is equivalent to ""x.~T(); new(x) T(y);"
929
- // which is pretty much correct, if a bit conservative.)
930
- void erase_aux(size_type offset, true_type) {
931
- // This isn't technically necessary, since we know we have a
932
- // trivial destructor, but is a cheap way to get a bit more safety.
933
- group[offset].~value_type();
934
- // This is equivalent to memmove(), but faster on my Intel P4,
935
- // at lesat with gcc4.1 -O2 / glibc 2.3.6.
936
- assert(num_buckets > 0);
937
- for (size_type i = offset; i < num_buckets-1; ++i)
938
- memcpy(group + i, group + i+1, sizeof(*group)); // hopefully inlined!
939
- group = (value_type *)
940
- realloc_or_die(group, sizeof(*group) * (num_buckets-1));
941
- }
942
-
943
- // Shrink the array, without any special assumptions about value_type.
944
- void erase_aux(size_type offset, false_type) {
945
- // This is valid because 0 <= offset < num_buckets. Note the inequality.
946
- value_type* p = allocate_group(num_buckets - 1);
947
- uninitialized_copy(group, group + offset, p);
948
- uninitialized_copy(group + offset + 1, group + num_buckets, p + offset);
949
- free_group();
950
- group = p;
951
- }
952
-
953
- public:
954
- // This takes the specified elements out of the group. This is
955
- // "undefining", rather than "clearing".
956
- // TODO(austern): Make this exception safe: handle exceptions from
957
- // value_type's copy constructor.
958
- void erase(size_type i) {
959
- if ( bmtest(i) ) { // trivial to erase empty bucket
960
- size_type offset = pos_to_offset(bitmap,i); // where we'll find (or insert)
961
- if ( num_buckets == 1 ) {
962
- free_group();
963
- group = NULL;
964
- } else {
965
- typedef integral_constant<bool,
966
- (has_trivial_copy<value_type>::value &&
967
- has_trivial_destructor<value_type>::value)>
968
- realloc_and_memmove_ok; // pretend mv(x,y) == "x.~T(); new(x) T(y)"
969
- erase_aux(offset, realloc_and_memmove_ok());
970
- }
971
- --num_buckets;
972
- bmclear(i);
973
- }
974
- }
975
-
976
- void erase(iterator pos) {
977
- erase(pos.pos);
978
- }
979
-
980
- void erase(iterator start_it, iterator end_it) {
981
- // This could be more efficient, but to do so we'd need to make
982
- // bmclear() clear a range of indices. Doesn't seem worth it.
983
- for ( ; start_it != end_it; ++start_it )
984
- erase(start_it);
985
- }
986
-
987
-
988
- // I/O
989
- // We support reading and writing groups to disk. We don't store
990
- // the actual array contents (which we don't know how to store),
991
- // just the bitmap and size. Meant to be used with table I/O.
992
- // Returns true if all was ok
993
- bool write_metadata(FILE *fp) const {
994
- assert(sizeof(num_buckets) == 2); // we explicitly set to u_int16_t
995
- PUT_(num_buckets, 8);
996
- PUT_(num_buckets, 0);
997
- if ( !fwrite(bitmap, sizeof(bitmap), 1, fp) ) return false;
998
- return true;
999
- }
1000
-
1001
- // Reading destroys the old group contents! Returns true if all was ok
1002
- bool read_metadata(FILE *fp) {
1003
- clear();
1004
-
1005
- int x; // the GET_ macro requires an 'int x' to be defined
1006
- GET_(num_buckets, 8);
1007
- GET_(num_buckets, 0);
1008
-
1009
- if ( !fread(bitmap, sizeof(bitmap), 1, fp) ) return false;
1010
-
1011
- // We'll allocate the space, but we won't fill it: it will be
1012
- // left as uninitialized raw memory.
1013
- group = allocate_group(num_buckets);
1014
- return true;
1015
- }
1016
-
1017
- // If your keys and values are simple enough, we can write them
1018
- // to disk for you. "simple enough" means POD and no pointers.
1019
- // However, we don't try to normalize endianness
1020
- bool write_nopointer_data(FILE *fp) const {
1021
- for ( const_nonempty_iterator it = nonempty_begin();
1022
- it != nonempty_end(); ++it ) {
1023
- if ( !fwrite(&*it, sizeof(*it), 1, fp) ) return false;
1024
- }
1025
- return true;
1026
- }
1027
-
1028
- // When reading, we have to override the potential const-ness of *it.
1029
- // Again, only meaningful if value_type is a POD.
1030
- bool read_nopointer_data(FILE *fp) {
1031
- for ( nonempty_iterator it = nonempty_begin();
1032
- it != nonempty_end(); ++it ) {
1033
- if ( !fread(reinterpret_cast<void*>(&(*it)), sizeof(*it), 1, fp) )
1034
- return false;
1035
- }
1036
- return true;
1037
- }
1038
-
1039
- // Comparisons. Note the comparisons are pretty arbitrary: we
1040
- // compare values of the first index that isn't equal (using default
1041
- // value for empty buckets).
1042
- bool operator==(const sparsegroup& x) const {
1043
- return ( num_buckets == x.num_buckets &&
1044
- memcmp(bitmap, x.bitmap, sizeof(bitmap)) == 0 &&
1045
- STL_NAMESPACE::equal(begin(), end(), x.begin()) ); // from algorithm
1046
- }
1047
- bool operator<(const sparsegroup& x) const { // also from algorithm
1048
- return STL_NAMESPACE::lexicographical_compare(begin(), end(),
1049
- x.begin(), x.end());
1050
- }
1051
- bool operator!=(const sparsegroup& x) const { return !(*this == x); }
1052
- bool operator<=(const sparsegroup& x) const { return !(x < *this); }
1053
- bool operator>(const sparsegroup& x) const { return x < *this; }
1054
- bool operator>=(const sparsegroup& x) const { return !(*this < x); }
1055
-
1056
- private:
1057
- // The actual data
1058
- value_type *group; // (small) array of T's
1059
- unsigned char bitmap[(GROUP_SIZE-1)/8 + 1]; // fancy math is so we round up
1060
- size_type num_buckets; // limits GROUP_SIZE to 64K
1061
- };
1062
-
1063
- // We need a global swap as well
1064
- template <class T, u_int16_t GROUP_SIZE>
1065
- inline void swap(sparsegroup<T,GROUP_SIZE> &x, sparsegroup<T,GROUP_SIZE> &y) {
1066
- x.swap(y);
1067
- }
1068
-
1069
- // ---------------------------------------------------------------------------
1070
-
1071
-
1072
- template <class T, u_int16_t GROUP_SIZE = DEFAULT_SPARSEGROUP_SIZE>
1073
- class sparsetable {
1074
- public:
1075
- // Basic types
1076
- typedef T value_type; // stolen from stl_vector.h
1077
- typedef value_type* pointer;
1078
- typedef const value_type* const_pointer;
1079
- typedef table_iterator<sparsetable<T, GROUP_SIZE> > iterator;
1080
- typedef const_table_iterator<sparsetable<T, GROUP_SIZE> > const_iterator;
1081
- typedef table_element_adaptor<sparsetable<T, GROUP_SIZE> > element_adaptor;
1082
- typedef value_type &reference;
1083
- typedef const value_type &const_reference;
1084
- typedef size_t size_type;
1085
- typedef ptrdiff_t difference_type;
1086
- typedef STL_NAMESPACE::reverse_iterator<const_iterator> const_reverse_iterator;
1087
- typedef STL_NAMESPACE::reverse_iterator<iterator> reverse_iterator;
1088
-
1089
- // These are our special iterators, that go over non-empty buckets in a
1090
- // table. These aren't const only because you can change non-empty bcks.
1091
- typedef two_d_iterator< vector< sparsegroup<value_type, GROUP_SIZE> > >
1092
- nonempty_iterator;
1093
- typedef const_two_d_iterator< vector< sparsegroup<value_type, GROUP_SIZE> > >
1094
- const_nonempty_iterator;
1095
- typedef STL_NAMESPACE::reverse_iterator<nonempty_iterator> reverse_nonempty_iterator;
1096
- typedef STL_NAMESPACE::reverse_iterator<const_nonempty_iterator> const_reverse_nonempty_iterator;
1097
- // Another special iterator: it frees memory as it iterates (used to resize)
1098
- typedef destructive_two_d_iterator< vector< sparsegroup<value_type, GROUP_SIZE> > >
1099
- destructive_iterator;
1100
-
1101
- // Iterator functions
1102
- iterator begin() { return iterator(this, 0); }
1103
- const_iterator begin() const { return const_iterator(this, 0); }
1104
- iterator end() { return iterator(this, size()); }
1105
- const_iterator end() const { return const_iterator(this, size()); }
1106
- reverse_iterator rbegin() { return reverse_iterator(end()); }
1107
- const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
1108
- reverse_iterator rend() { return reverse_iterator(begin()); }
1109
- const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
1110
-
1111
- // Versions for our special non-empty iterator
1112
- nonempty_iterator nonempty_begin() {
1113
- return nonempty_iterator(groups.begin(), groups.end(), groups.begin());
1114
- }
1115
- const_nonempty_iterator nonempty_begin() const {
1116
- return const_nonempty_iterator(groups.begin(),groups.end(), groups.begin());
1117
- }
1118
- nonempty_iterator nonempty_end() {
1119
- return nonempty_iterator(groups.begin(), groups.end(), groups.end());
1120
- }
1121
- const_nonempty_iterator nonempty_end() const {
1122
- return const_nonempty_iterator(groups.begin(), groups.end(), groups.end());
1123
- }
1124
- reverse_nonempty_iterator nonempty_rbegin() {
1125
- return reverse_nonempty_iterator(nonempty_end());
1126
- }
1127
- const_reverse_nonempty_iterator nonempty_rbegin() const {
1128
- return const_reverse_nonempty_iterator(nonempty_end());
1129
- }
1130
- reverse_nonempty_iterator nonempty_rend() {
1131
- return reverse_nonempty_iterator(nonempty_begin());
1132
- }
1133
- const_reverse_nonempty_iterator nonempty_rend() const {
1134
- return const_reverse_nonempty_iterator(nonempty_begin());
1135
- }
1136
- destructive_iterator destructive_begin() {
1137
- return destructive_iterator(groups.begin(), groups.end(), groups.begin());
1138
- }
1139
- destructive_iterator destructive_end() {
1140
- return destructive_iterator(groups.begin(), groups.end(), groups.end());
1141
- }
1142
-
1143
- private:
1144
- typedef typename vector< sparsegroup<value_type, GROUP_SIZE> >::reference
1145
- GroupsReference;
1146
- typedef typename
1147
- vector< sparsegroup<value_type, GROUP_SIZE> >::const_reference
1148
- GroupsConstReference;
1149
- typedef typename vector< sparsegroup<value_type, GROUP_SIZE> >::iterator
1150
- GroupsIterator;
1151
- typedef typename vector< sparsegroup<value_type, GROUP_SIZE> >::const_iterator
1152
- GroupsConstIterator;
1153
-
1154
- // How to deal with the proper group
1155
- static size_type num_groups(size_type num) { // how many to hold num buckets
1156
- return num == 0 ? 0 : ((num-1) / GROUP_SIZE) + 1;
1157
- }
1158
-
1159
- u_int16_t pos_in_group(size_type i) const {
1160
- return static_cast<u_int16_t>(i % GROUP_SIZE);
1161
- }
1162
- size_type group_num(size_type i) const {
1163
- return i / GROUP_SIZE;
1164
- }
1165
- GroupsReference which_group(size_type i) {
1166
- return groups[group_num(i)];
1167
- }
1168
- GroupsConstReference which_group(size_type i) const {
1169
- return groups[group_num(i)];
1170
- }
1171
-
1172
- public:
1173
- // Constructors -- default, normal (when you specify size), and copy
1174
- sparsetable(size_type sz = 0)
1175
- : groups(num_groups(sz)), table_size(sz), num_buckets(0) { }
1176
- // We'll can get away with using the default copy constructor,
1177
- // and default destructor, and hence the default operator=. Huzzah!
1178
-
1179
- // Many STL algorithms use swap instead of copy constructors
1180
- void swap(sparsetable& x) {
1181
- STL_NAMESPACE::swap(groups, x.groups);
1182
- STL_NAMESPACE::swap(table_size, x.table_size);
1183
- STL_NAMESPACE::swap(num_buckets, x.num_buckets);
1184
- }
1185
-
1186
- // It's always nice to be able to clear a table without deallocating it
1187
- void clear() {
1188
- GroupsIterator group;
1189
- for ( group = groups.begin(); group != groups.end(); ++group ) {
1190
- group->clear();
1191
- }
1192
- num_buckets = 0;
1193
- }
1194
-
1195
- // Functions that tell you about size.
1196
- // NOTE: empty() is non-intuitive! It does not tell you the number
1197
- // of not-empty buckets (use num_nonempty() for that). Instead
1198
- // it says whether you've allocated any buckets or not.
1199
- size_type size() const { return table_size; }
1200
- size_type max_size() const { return size_type(-1); }
1201
- bool empty() const { return table_size == 0; }
1202
- // We also may want to know how many *used* buckets there are
1203
- size_type num_nonempty() const { return num_buckets; }
1204
-
1205
- // OK, we'll let you resize one of these puppies
1206
- void resize(size_type new_size) {
1207
- groups.resize(num_groups(new_size));
1208
- if ( new_size < table_size) { // lower num_buckets, clear last group
1209
- if ( pos_in_group(new_size) > 0 ) // need to clear inside last group
1210
- groups.back().erase(groups.back().begin() + pos_in_group(new_size),
1211
- groups.back().end());
1212
- num_buckets = 0; // refigure # of used buckets
1213
- GroupsConstIterator group;
1214
- for ( group = groups.begin(); group != groups.end(); ++group )
1215
- num_buckets += group->num_nonempty();
1216
- }
1217
- table_size = new_size;
1218
- }
1219
-
1220
-
1221
- // We let you see if a bucket is non-empty without retrieving it
1222
- bool test(size_type i) const {
1223
- return which_group(i).test(pos_in_group(i));
1224
- }
1225
- bool test(iterator pos) const {
1226
- return which_group(pos.pos).test(pos_in_group(pos.pos));
1227
- }
1228
- bool test(const_iterator pos) const {
1229
- return which_group(pos.pos).test(pos_in_group(pos.pos));
1230
- }
1231
-
1232
- // We only return const_references because it's really hard to
1233
- // return something settable for empty buckets. Use set() instead.
1234
- const_reference get(size_type i) const {
1235
- assert(i < table_size);
1236
- return which_group(i).get(pos_in_group(i));
1237
- }
1238
-
1239
- // TODO(csilvers): make protected + friend
1240
- // This is used by sparse_hashtable to get an element from the table
1241
- // when we know it exists (because the caller has called test(i)).
1242
- const_reference unsafe_get(size_type i) const {
1243
- assert(i < table_size);
1244
- assert(test(i));
1245
- return which_group(i).unsafe_get(pos_in_group(i));
1246
- }
1247
-
1248
- // TODO(csilvers): make protected + friend element_adaptor
1249
- reference mutating_get(size_type i) { // fills bucket i before getting
1250
- assert(i < table_size);
1251
- size_type old_numbuckets = which_group(i).num_nonempty();
1252
- reference retval = which_group(i).mutating_get(pos_in_group(i));
1253
- num_buckets += which_group(i).num_nonempty() - old_numbuckets;
1254
- return retval;
1255
- }
1256
-
1257
- // Syntactic sugar. As in sparsegroup, the non-const version is harder
1258
- const_reference operator[](size_type i) const {
1259
- return get(i);
1260
- }
1261
-
1262
- element_adaptor operator[](size_type i) {
1263
- return element_adaptor(this, i);
1264
- }
1265
-
1266
- // Needed for hashtables, gets as a nonempty_iterator. Crashes for empty bcks
1267
- const_nonempty_iterator get_iter(size_type i) const {
1268
- assert(test(i)); // how can a nonempty_iterator point to an empty bucket?
1269
- return const_nonempty_iterator(
1270
- groups.begin(), groups.end(),
1271
- groups.begin() + group_num(i),
1272
- (groups[group_num(i)].nonempty_begin() +
1273
- groups[group_num(i)].pos_to_offset(pos_in_group(i))));
1274
- }
1275
- // For nonempty we can return a non-const version
1276
- nonempty_iterator get_iter(size_type i) {
1277
- assert(test(i)); // how can a nonempty_iterator point to an empty bucket?
1278
- return nonempty_iterator(
1279
- groups.begin(), groups.end(),
1280
- groups.begin() + group_num(i),
1281
- (groups[group_num(i)].nonempty_begin() +
1282
- groups[group_num(i)].pos_to_offset(pos_in_group(i))));
1283
- }
1284
-
1285
-
1286
- // This returns a reference to the inserted item (which is a copy of val)
1287
- // The trick is to figure out whether we're replacing or inserting anew
1288
- reference set(size_type i, const_reference val) {
1289
- assert(i < table_size);
1290
- size_type old_numbuckets = which_group(i).num_nonempty();
1291
- reference retval = which_group(i).set(pos_in_group(i), val);
1292
- num_buckets += which_group(i).num_nonempty() - old_numbuckets;
1293
- return retval;
1294
- }
1295
-
1296
- // This takes the specified elements out of the table. This is
1297
- // "undefining", rather than "clearing".
1298
- void erase(size_type i) {
1299
- assert(i < table_size);
1300
- size_type old_numbuckets = which_group(i).num_nonempty();
1301
- which_group(i).erase(pos_in_group(i));
1302
- num_buckets += which_group(i).num_nonempty() - old_numbuckets;
1303
- }
1304
-
1305
- void erase(iterator pos) {
1306
- erase(pos.pos);
1307
- }
1308
-
1309
- void erase(iterator start_it, iterator end_it) {
1310
- // This could be more efficient, but then we'd need to figure
1311
- // out if we spanned groups or not. Doesn't seem worth it.
1312
- for ( ; start_it != end_it; ++start_it )
1313
- erase(start_it);
1314
- }
1315
-
1316
-
1317
- // We support reading and writing tables to disk. We don't store
1318
- // the actual array contents (which we don't know how to store),
1319
- // just the groups and sizes. Returns true if all went ok.
1320
-
1321
- private:
1322
- // Every time the disk format changes, this should probably change too
1323
- static const unsigned long MAGIC_NUMBER = 0x24687531;
1324
-
1325
- // Old versions of this code write all data in 32 bits. We need to
1326
- // support these files as well as having support for 64-bit systems.
1327
- // So we use the following encoding scheme: for values < 2^32-1, we
1328
- // store in 4 bytes in big-endian order. For values > 2^32, we
1329
- // store 0xFFFFFFF followed by 8 bytes in big-endian order. This
1330
- // causes us to mis-read old-version code that stores exactly
1331
- // 0xFFFFFFF, but I don't think that is likely to have happened for
1332
- // these particular values.
1333
- static bool write_32_or_64(FILE* fp, size_type value) {
1334
- if ( value < 0xFFFFFFFFULL ) { // fits in 4 bytes
1335
- PUT_(value, 24);
1336
- PUT_(value, 16);
1337
- PUT_(value, 8);
1338
- PUT_(value, 0);
1339
- } else if ( value == 0xFFFFFFFFUL ) { // special case in 32bit systems
1340
- PUT_(0xFF, 0); PUT_(0xFF, 0); PUT_(0xFF, 0); PUT_(0xFF, 0); // marker
1341
- PUT_(0, 0); PUT_(0, 0); PUT_(0, 0); PUT_(0, 0);
1342
- PUT_(0xFF, 0); PUT_(0xFF, 0); PUT_(0xFF, 0); PUT_(0xFF, 0);
1343
- } else {
1344
- PUT_(0xFF, 0); PUT_(0xFF, 0); PUT_(0xFF, 0); PUT_(0xFF, 0); // marker
1345
- PUT_(value, 56);
1346
- PUT_(value, 48);
1347
- PUT_(value, 40);
1348
- PUT_(value, 32);
1349
- PUT_(value, 24);
1350
- PUT_(value, 16);
1351
- PUT_(value, 8);
1352
- PUT_(value, 0);
1353
- }
1354
- return true;
1355
- }
1356
-
1357
- static bool read_32_or_64(FILE* fp, size_type *value) { // reads into value
1358
- size_type first4 = 0;
1359
- int x;
1360
- GET_(first4, 24);
1361
- GET_(first4, 16);
1362
- GET_(first4, 8);
1363
- GET_(first4, 0);
1364
- if ( first4 < 0xFFFFFFFFULL ) {
1365
- *value = first4;
1366
- } else {
1367
- GET_(*value, 56);
1368
- GET_(*value, 48);
1369
- GET_(*value, 40);
1370
- GET_(*value, 32);
1371
- GET_(*value, 24);
1372
- GET_(*value, 16);
1373
- GET_(*value, 8);
1374
- GET_(*value, 0);
1375
- }
1376
- return true;
1377
- }
1378
-
1379
- public:
1380
- bool write_metadata(FILE *fp) const {
1381
- if ( !write_32_or_64(fp, MAGIC_NUMBER) ) return false;
1382
- if ( !write_32_or_64(fp, table_size) ) return false;
1383
- if ( !write_32_or_64(fp, num_buckets) ) return false;
1384
-
1385
- GroupsConstIterator group;
1386
- for ( group = groups.begin(); group != groups.end(); ++group )
1387
- if ( group->write_metadata(fp) == false ) return false;
1388
- return true;
1389
- }
1390
-
1391
- // Reading destroys the old table contents! Returns true if read ok.
1392
- bool read_metadata(FILE *fp) {
1393
- size_type magic_read = 0;
1394
- if ( !read_32_or_64(fp, &magic_read) ) return false;
1395
- if ( magic_read != MAGIC_NUMBER ) {
1396
- clear(); // just to be consistent
1397
- return false;
1398
- }
1399
-
1400
- if ( !read_32_or_64(fp, &table_size) ) return false;
1401
- if ( !read_32_or_64(fp, &num_buckets) ) return false;
1402
-
1403
- resize(table_size); // so the vector's sized ok
1404
- GroupsIterator group;
1405
- for ( group = groups.begin(); group != groups.end(); ++group )
1406
- if ( group->read_metadata(fp) == false ) return false;
1407
- return true;
1408
- }
1409
-
1410
- // This code is identical to that for SparseGroup
1411
- // If your keys and values are simple enough, we can write them
1412
- // to disk for you. "simple enough" means no pointers.
1413
- // However, we don't try to normalize endianness
1414
- bool write_nopointer_data(FILE *fp) const {
1415
- for ( const_nonempty_iterator it = nonempty_begin();
1416
- it != nonempty_end(); ++it ) {
1417
- if ( !fwrite(&*it, sizeof(*it), 1, fp) ) return false;
1418
- }
1419
- return true;
1420
- }
1421
-
1422
- // When reading, we have to override the potential const-ness of *it
1423
- bool read_nopointer_data(FILE *fp) {
1424
- for ( nonempty_iterator it = nonempty_begin();
1425
- it != nonempty_end(); ++it ) {
1426
- if ( !fread(reinterpret_cast<void*>(&(*it)), sizeof(*it), 1, fp) )
1427
- return false;
1428
- }
1429
- return true;
1430
- }
1431
-
1432
- // Comparisons. Note the comparisons are pretty arbitrary: we
1433
- // compare values of the first index that isn't equal (using default
1434
- // value for empty buckets).
1435
- bool operator==(const sparsetable& x) const {
1436
- return ( table_size == x.table_size &&
1437
- num_buckets == x.num_buckets &&
1438
- groups == x.groups );
1439
- }
1440
- bool operator<(const sparsetable& x) const { // also from algobase.h
1441
- return STL_NAMESPACE::lexicographical_compare(begin(), end(),
1442
- x.begin(), x.end());
1443
- }
1444
- bool operator!=(const sparsetable& x) const { return !(*this == x); }
1445
- bool operator<=(const sparsetable& x) const { return !(x < *this); }
1446
- bool operator>(const sparsetable& x) const { return x < *this; }
1447
- bool operator>=(const sparsetable& x) const { return !(*this < x); }
1448
-
1449
-
1450
- private:
1451
- // The actual data
1452
- vector< sparsegroup<value_type, GROUP_SIZE> > groups; // our list of groups
1453
- size_type table_size; // how many buckets they want
1454
- size_type num_buckets; // number of non-empty buckets
1455
- };
1456
-
1457
- // We need a global swap as well
1458
- template <class T, u_int16_t GROUP_SIZE>
1459
- inline void swap(sparsetable<T,GROUP_SIZE> &x, sparsetable<T,GROUP_SIZE> &y) {
1460
- x.swap(y);
1461
- }
1462
-
1463
- #undef GET_
1464
- #undef PUT_
1465
-
1466
- _END_GOOGLE_NAMESPACE_
1467
-
1468
- #endif