passenger 4.0.20 → 4.0.21

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 (496) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.asc +7 -7
  3. data.tar.gz.asc +7 -7
  4. data/.gitignore +1 -0
  5. data/.travis.yml +1 -1
  6. data/NEWS +15 -0
  7. data/README.md +5 -3
  8. data/Rakefile +1 -0
  9. data/bin/passenger-config +1 -5
  10. data/bin/passenger-install-apache2-module +53 -5
  11. data/bin/passenger-install-nginx-module +19 -6
  12. data/bin/passenger-memory-stats +3 -3
  13. data/build/agents.rb +11 -8
  14. data/build/apache2.rb +9 -5
  15. data/build/basics.rb +15 -21
  16. data/build/common_library.rb +16 -6
  17. data/build/cplusplus_support.rb +5 -5
  18. data/build/cxx_tests.rb +3 -3
  19. data/build/documentation.rb +1 -1
  20. data/build/misc.rb +4 -37
  21. data/build/node_tests.rb +29 -0
  22. data/build/oxt_tests.rb +1 -1
  23. data/build/packaging.rb +29 -10
  24. data/build/preprocessor.rb +2 -1
  25. data/build/test_basics.rb +15 -6
  26. data/debian.template/locations.ini.template +1 -0
  27. data/debian.template/passenger.install.template +1 -0
  28. data/dev/copy_boost_headers.rb +7 -3
  29. data/dev/run_travis.sh +32 -16
  30. data/doc/Users guide Apache.idmap.txt +22 -34
  31. data/doc/Users guide Apache.txt +20 -234
  32. data/doc/Users guide Nginx.idmap.txt +84 -66
  33. data/doc/Users guide Nginx.txt +50 -1
  34. data/doc/Users guide Standalone.idmap.txt +74 -0
  35. data/doc/Users guide Standalone.txt +22 -9
  36. data/doc/Users guide.txt +51 -0
  37. data/doc/users_guide_snippets/environment_variables.txt +0 -3
  38. data/doc/users_guide_snippets/installation.txt +337 -380
  39. data/doc/users_guide_snippets/installation/run_installer.txt +58 -0
  40. data/doc/users_guide_snippets/installation/verify_running_epilogue.txt +6 -0
  41. data/doc/users_guide_snippets/support_information.txt +2 -9
  42. data/doc/users_guide_snippets/troubleshooting/default.txt +112 -0
  43. data/doc/users_guide_snippets/troubleshooting/rails.txt +56 -0
  44. data/doc/users_guide_snippets/where_to_get_support.txt +9 -0
  45. data/ext/apache2/Bucket.h +1 -1
  46. data/ext/apache2/Configuration.hpp +0 -44
  47. data/ext/apache2/CreateDirConfig.cpp +1 -1
  48. data/ext/apache2/CreateDirConfig.cpp.erb +1 -1
  49. data/ext/apache2/Hooks.cpp +28 -21
  50. data/ext/apache2/MergeDirConfig.cpp +1 -0
  51. data/ext/apache2/MergeDirConfig.cpp.erb +1 -1
  52. data/ext/apache2/SetHeaders.cpp +73 -0
  53. data/ext/apache2/SetHeaders.cpp.erb +88 -0
  54. data/ext/boost/algorithm/string/detail/find_format.hpp +5 -5
  55. data/ext/boost/algorithm/string/detail/find_format_all.hpp +5 -5
  56. data/ext/boost/algorithm/string/detail/finder.hpp +1 -1
  57. data/ext/boost/algorithm/string/formatter.hpp +2 -2
  58. data/ext/boost/assert.hpp +6 -1
  59. data/ext/boost/atomic.hpp +18 -0
  60. data/ext/boost/atomic/atomic.hpp +241 -0
  61. data/ext/boost/atomic/detail/base.hpp +585 -0
  62. data/ext/boost/atomic/detail/cas32strong.hpp +885 -0
  63. data/ext/boost/atomic/detail/cas32weak.hpp +947 -0
  64. data/ext/boost/atomic/detail/cas64strong.hpp +443 -0
  65. data/ext/boost/atomic/detail/config.hpp +54 -0
  66. data/ext/boost/atomic/detail/gcc-alpha.hpp +368 -0
  67. data/ext/boost/atomic/detail/gcc-armv6plus.hpp +252 -0
  68. data/ext/boost/atomic/detail/gcc-cas.hpp +157 -0
  69. data/ext/boost/atomic/detail/gcc-ppc.hpp +2850 -0
  70. data/ext/boost/atomic/detail/gcc-sparcv9.hpp +1259 -0
  71. data/ext/boost/atomic/detail/gcc-x86.hpp +1766 -0
  72. data/ext/boost/atomic/detail/generic-cas.hpp +206 -0
  73. data/ext/boost/atomic/detail/interlocked.hpp +200 -0
  74. data/ext/boost/atomic/detail/linux-arm.hpp +189 -0
  75. data/ext/boost/atomic/detail/lockpool.hpp +97 -0
  76. data/ext/boost/atomic/detail/platform.hpp +62 -0
  77. data/ext/boost/atomic/detail/type-classification.hpp +45 -0
  78. data/ext/boost/chrono/config.hpp +8 -3
  79. data/ext/boost/chrono/duration.hpp +9 -10
  80. data/ext/boost/chrono/system_clocks.hpp +1 -1
  81. data/ext/boost/chrono/time_point.hpp +4 -3
  82. data/ext/boost/config/auto_link.hpp +53 -52
  83. data/ext/boost/config/compiler/borland.hpp +1 -0
  84. data/ext/boost/config/compiler/clang.hpp +24 -1
  85. data/ext/boost/config/compiler/codegear.hpp +1 -0
  86. data/ext/boost/config/compiler/common_edg.hpp +1 -0
  87. data/ext/boost/config/compiler/cray.hpp +1 -0
  88. data/ext/boost/config/compiler/digitalmars.hpp +1 -0
  89. data/ext/boost/config/compiler/gcc.hpp +29 -3
  90. data/ext/boost/config/compiler/gcc_xml.hpp +2 -1
  91. data/ext/boost/config/compiler/hp_acc.hpp +1 -0
  92. data/ext/boost/config/compiler/intel.hpp +1 -1
  93. data/ext/boost/config/compiler/metrowerks.hpp +1 -0
  94. data/ext/boost/config/compiler/mpw.hpp +1 -0
  95. data/ext/boost/config/compiler/pathscale.hpp +1 -0
  96. data/ext/boost/config/compiler/pgi.hpp +1 -0
  97. data/ext/boost/config/compiler/sunpro_cc.hpp +1 -0
  98. data/ext/boost/config/compiler/vacpp.hpp +3 -2
  99. data/ext/boost/config/compiler/visualc.hpp +25 -11
  100. data/ext/boost/config/platform/vxworks.hpp +353 -15
  101. data/ext/boost/config/select_compiler_config.hpp +4 -4
  102. data/ext/boost/config/stdlib/dinkumware.hpp +10 -3
  103. data/ext/boost/config/stdlib/libstdcpp3.hpp +2 -1
  104. data/ext/boost/config/suffix.hpp +45 -19
  105. data/ext/boost/date_time/format_date_parser.hpp +1 -11
  106. data/ext/boost/date_time/strings_from_facet.hpp +5 -3
  107. data/ext/boost/detail/atomic_redef_macros.hpp +19 -0
  108. data/ext/boost/detail/atomic_undef_macros.hpp +39 -0
  109. data/ext/boost/detail/endian.hpp +52 -4
  110. data/ext/boost/detail/scoped_enum_emulation.hpp +10 -10
  111. data/ext/boost/detail/select_type.hpp +36 -0
  112. data/ext/boost/exception/current_exception_cast.hpp +1 -1
  113. data/ext/boost/exception/detail/error_info_impl.hpp +3 -5
  114. data/ext/boost/exception/detail/exception_ptr.hpp +3 -3
  115. data/ext/boost/exception/detail/is_output_streamable.hpp +1 -1
  116. data/ext/boost/exception/detail/object_hex_dump.hpp +1 -1
  117. data/ext/boost/exception/detail/type_info.hpp +1 -1
  118. data/ext/boost/exception/diagnostic_information.hpp +15 -14
  119. data/ext/boost/exception/exception.hpp +1 -1
  120. data/ext/boost/exception/get_error_info.hpp +1 -1
  121. data/ext/boost/exception/info.hpp +12 -13
  122. data/ext/boost/exception/to_string.hpp +6 -1
  123. data/ext/boost/exception/to_string_stub.hpp +9 -1
  124. data/ext/boost/foreach.hpp +5 -5
  125. data/ext/boost/function/function_template.hpp +6 -6
  126. data/ext/boost/functional/hash/detail/float_functions.hpp +90 -0
  127. data/ext/boost/functional/hash/detail/hash_float.hpp +11 -2
  128. data/ext/boost/functional/hash/extensions.hpp +14 -2
  129. data/ext/boost/functional/hash/hash.hpp +26 -5
  130. data/ext/boost/get_pointer.hpp +17 -2
  131. data/ext/boost/integer_traits.hpp +1 -1
  132. data/ext/boost/lexical_cast.hpp +615 -395
  133. data/ext/boost/libs/atomic/lockpool.cpp +24 -0
  134. data/ext/boost/libs/system/src/error_code.cpp +25 -18
  135. data/ext/boost/libs/thread/src/future.cpp +7 -5
  136. data/ext/boost/libs/thread/src/pthread/once.cpp +9 -3
  137. data/ext/boost/libs/thread/src/pthread/once_atomic.cpp +90 -0
  138. data/ext/boost/libs/thread/src/pthread/thread.cpp +129 -95
  139. data/ext/boost/libs/thread/src/pthread/timeconv.inl +20 -1
  140. data/ext/boost/limits.hpp +1 -1
  141. data/ext/boost/math/policies/policy.hpp +10 -0
  142. data/ext/boost/math/special_functions/detail/round_fwd.hpp +17 -4
  143. data/ext/boost/math/special_functions/fpclassify.hpp +114 -45
  144. data/ext/boost/math/special_functions/math_fwd.hpp +195 -83
  145. data/ext/boost/math/special_functions/sign.hpp +13 -8
  146. data/ext/boost/math/tools/config.hpp +38 -16
  147. data/ext/boost/move/algorithm.hpp +275 -0
  148. data/ext/boost/move/core.hpp +332 -0
  149. data/ext/boost/move/detail/config_begin.hpp +23 -0
  150. data/ext/boost/move/detail/config_end.hpp +20 -0
  151. data/ext/boost/move/detail/meta_utils.hpp +158 -0
  152. data/ext/boost/move/iterator.hpp +298 -0
  153. data/ext/boost/move/move.hpp +10 -1256
  154. data/ext/boost/move/traits.hpp +142 -0
  155. data/ext/boost/move/utility.hpp +194 -0
  156. data/ext/boost/mpl/assert.hpp +72 -4
  157. data/ext/boost/noncopyable.hpp +15 -3
  158. data/ext/boost/pointer_to_other.hpp +55 -0
  159. data/ext/boost/range/concepts.hpp +4 -4
  160. data/ext/boost/range/detail/extract_optional_type.hpp +1 -1
  161. data/ext/boost/range/empty.hpp +1 -1
  162. data/ext/boost/range/iterator_range_core.hpp +4 -1
  163. data/ext/boost/range/iterator_range_io.hpp +2 -2
  164. data/ext/boost/ratio/config.hpp +6 -0
  165. data/ext/boost/ratio/detail/overflow_helpers.hpp +2 -2
  166. data/ext/boost/smart_ptr/allocate_shared_array.hpp +250 -0
  167. data/ext/boost/smart_ptr/detail/allocate_array_helper.hpp +169 -0
  168. data/ext/boost/smart_ptr/detail/array_deleter.hpp +124 -0
  169. data/ext/boost/smart_ptr/detail/array_traits.hpp +53 -0
  170. data/ext/boost/smart_ptr/detail/array_utility.hpp +178 -0
  171. data/ext/boost/smart_ptr/detail/make_array_helper.hpp +157 -0
  172. data/ext/boost/smart_ptr/detail/operator_bool.hpp +16 -9
  173. data/ext/boost/smart_ptr/detail/shared_count.hpp +78 -7
  174. data/ext/boost/smart_ptr/detail/sp_convertible.hpp +15 -0
  175. data/ext/boost/smart_ptr/detail/sp_counted_base.hpp +12 -6
  176. data/ext/boost/smart_ptr/detail/sp_counted_base_acc_ia64.hpp +1 -0
  177. data/ext/boost/smart_ptr/detail/sp_counted_base_aix.hpp +1 -0
  178. data/ext/boost/smart_ptr/detail/sp_counted_base_cw_ppc.hpp +1 -0
  179. data/ext/boost/smart_ptr/detail/sp_counted_base_cw_x86.hpp +1 -0
  180. data/ext/boost/smart_ptr/detail/sp_counted_base_gcc_ia64.hpp +1 -0
  181. data/ext/boost/smart_ptr/detail/sp_counted_base_gcc_mips.hpp +1 -0
  182. data/ext/boost/smart_ptr/detail/sp_counted_base_gcc_ppc.hpp +1 -0
  183. data/ext/boost/smart_ptr/detail/sp_counted_base_gcc_sparc.hpp +1 -0
  184. data/ext/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp +1 -0
  185. data/ext/boost/smart_ptr/detail/sp_counted_base_nt.hpp +1 -0
  186. data/ext/boost/smart_ptr/detail/sp_counted_base_pt.hpp +1 -0
  187. data/ext/boost/smart_ptr/detail/sp_counted_base_snc_ps3.hpp +162 -0
  188. data/ext/boost/smart_ptr/detail/sp_counted_base_solaris.hpp +1 -0
  189. data/ext/boost/smart_ptr/detail/sp_counted_base_spin.hpp +1 -0
  190. data/ext/boost/smart_ptr/detail/sp_counted_base_sync.hpp +1 -0
  191. data/ext/boost/smart_ptr/detail/sp_counted_base_vacpp_ppc.hpp +1 -0
  192. data/ext/boost/smart_ptr/detail/sp_counted_impl.hpp +15 -0
  193. data/ext/boost/smart_ptr/detail/sp_forward.hpp +39 -0
  194. data/ext/boost/smart_ptr/detail/sp_has_sync.hpp +19 -3
  195. data/ext/boost/smart_ptr/detail/sp_if_array.hpp +31 -0
  196. data/ext/boost/smart_ptr/detail/sp_nullptr_t.hpp +45 -0
  197. data/ext/boost/smart_ptr/detail/spinlock_gcc_arm.hpp +5 -12
  198. data/ext/boost/smart_ptr/enable_shared_from_this.hpp +4 -4
  199. data/ext/boost/smart_ptr/make_shared.hpp +5 -1060
  200. data/ext/boost/smart_ptr/make_shared_array.hpp +247 -0
  201. data/ext/boost/smart_ptr/make_shared_object.hpp +1128 -0
  202. data/ext/boost/smart_ptr/scoped_array.hpp +32 -7
  203. data/ext/boost/smart_ptr/scoped_ptr.hpp +31 -5
  204. data/ext/boost/smart_ptr/shared_array.hpp +135 -20
  205. data/ext/boost/smart_ptr/shared_ptr.hpp +444 -126
  206. data/ext/boost/smart_ptr/weak_ptr.hpp +39 -28
  207. data/ext/boost/static_assert.hpp +74 -17
  208. data/ext/boost/system/error_code.hpp +76 -68
  209. data/ext/boost/system/system_error.hpp +5 -1
  210. data/ext/boost/thread/barrier.hpp +6 -2
  211. data/ext/boost/thread/completion_latch.hpp +233 -0
  212. data/ext/boost/thread/condition.hpp +6 -1
  213. data/ext/boost/thread/detail/async_func.hpp +571 -0
  214. data/ext/boost/thread/detail/config.hpp +248 -40
  215. data/ext/boost/thread/detail/counter.hpp +93 -0
  216. data/ext/boost/thread/detail/delete.hpp +12 -0
  217. data/ext/boost/thread/detail/invoke.hpp +1351 -0
  218. data/ext/boost/thread/detail/is_convertible.hpp +48 -0
  219. data/ext/boost/thread/detail/lockable_wrapper.hpp +45 -0
  220. data/ext/boost/thread/detail/log.hpp +83 -0
  221. data/ext/boost/thread/detail/make_tuple_indices.hpp +224 -0
  222. data/ext/boost/thread/detail/move.hpp +32 -16
  223. data/ext/boost/thread/detail/thread.hpp +236 -41
  224. data/ext/boost/thread/detail/thread_group.hpp +55 -9
  225. data/ext/boost/thread/detail/thread_interruption.hpp +4 -1
  226. data/ext/boost/thread/exceptions.hpp +2 -0
  227. data/ext/boost/thread/externally_locked.hpp +351 -0
  228. data/ext/boost/thread/externally_locked_stream.hpp +170 -0
  229. data/ext/boost/thread/future.hpp +2517 -455
  230. data/ext/boost/thread/future_error_code.hpp +61 -0
  231. data/ext/boost/thread/is_locked_by_this_thread.hpp +39 -0
  232. data/ext/boost/thread/latch.hpp +142 -0
  233. data/ext/boost/thread/lock_algorithms.hpp +468 -0
  234. data/ext/boost/thread/lock_concepts.hpp +197 -0
  235. data/ext/boost/thread/lock_factories.hpp +78 -0
  236. data/ext/boost/thread/lock_guard.hpp +88 -0
  237. data/ext/boost/thread/lock_options.hpp +31 -0
  238. data/ext/boost/thread/lock_traits.hpp +45 -0
  239. data/ext/boost/thread/lock_types.hpp +1226 -0
  240. data/ext/boost/thread/lockable_adapter.hpp +226 -0
  241. data/ext/boost/thread/lockable_concepts.hpp +157 -0
  242. data/ext/boost/thread/lockable_traits.hpp +207 -0
  243. data/ext/boost/thread/locks.hpp +5 -1816
  244. data/ext/boost/thread/mutex.hpp +33 -1
  245. data/ext/boost/thread/null_mutex.hpp +243 -0
  246. data/ext/boost/thread/once.hpp +10 -1
  247. data/ext/boost/thread/poly_lockable.hpp +68 -0
  248. data/ext/boost/thread/poly_lockable_adapter.hpp +89 -0
  249. data/ext/boost/thread/poly_shared_lockable.hpp +135 -0
  250. data/ext/boost/thread/poly_shared_lockable_adapter.hpp +170 -0
  251. data/ext/boost/thread/pthread/condition_variable.hpp +74 -26
  252. data/ext/boost/thread/pthread/condition_variable_fwd.hpp +54 -27
  253. data/ext/boost/thread/pthread/mutex.hpp +101 -38
  254. data/ext/boost/thread/pthread/once.hpp +459 -44
  255. data/ext/boost/thread/pthread/once_atomic.hpp +313 -0
  256. data/ext/boost/thread/pthread/recursive_mutex.hpp +19 -10
  257. data/ext/boost/thread/pthread/shared_mutex.hpp +226 -61
  258. data/ext/boost/thread/pthread/shared_mutex_assert.hpp +724 -0
  259. data/ext/boost/thread/pthread/thread_data.hpp +53 -50
  260. data/ext/boost/thread/pthread/timespec.hpp +96 -12
  261. data/ext/boost/thread/recursive_mutex.hpp +44 -1
  262. data/ext/boost/thread/reverse_lock.hpp +3 -2
  263. data/ext/boost/thread/scoped_thread.hpp +285 -0
  264. data/ext/boost/thread/shared_lock_guard.hpp +2 -1
  265. data/ext/boost/thread/shared_mutex.hpp +23 -0
  266. data/ext/boost/thread/strict_lock.hpp +235 -0
  267. data/ext/boost/thread/sync_bounded_queue.hpp +594 -0
  268. data/ext/boost/thread/sync_queue.hpp +516 -0
  269. data/ext/boost/thread/synchronized_value.hpp +1001 -0
  270. data/ext/boost/thread/testable_mutex.hpp +148 -0
  271. data/ext/boost/thread/thread.hpp +1 -13
  272. data/ext/boost/thread/thread_functors.hpp +57 -0
  273. data/ext/boost/thread/thread_guard.hpp +46 -0
  274. data/ext/boost/thread/thread_only.hpp +29 -0
  275. data/ext/boost/thread/v2/shared_mutex.hpp +1062 -0
  276. data/ext/boost/thread/v2/thread.hpp +37 -10
  277. data/ext/boost/thread/xtime.hpp +2 -1
  278. data/ext/boost/token_functions.hpp +16 -16
  279. data/ext/boost/type_traits/add_lvalue_reference.hpp +26 -0
  280. data/ext/boost/type_traits/add_reference.hpp +1 -1
  281. data/ext/boost/type_traits/add_rvalue_reference.hpp +4 -4
  282. data/ext/boost/type_traits/aligned_storage.hpp +13 -0
  283. data/ext/boost/type_traits/common_type.hpp +11 -12
  284. data/ext/boost/type_traits/config.hpp +1 -1
  285. data/ext/boost/type_traits/detail/common_type_imp.hpp +1 -1
  286. data/ext/boost/type_traits/detail/has_binary_operator.hpp +1 -1
  287. data/ext/boost/type_traits/detail/is_function_ptr_tester.hpp +1 -1
  288. data/ext/boost/type_traits/has_left_shift.hpp +49 -0
  289. data/ext/boost/type_traits/has_right_shift.hpp +49 -0
  290. data/ext/boost/type_traits/has_trivial_move_assign.hpp +57 -0
  291. data/ext/boost/type_traits/has_trivial_move_constructor.hpp +57 -0
  292. data/ext/boost/type_traits/intrinsics.hpp +18 -2
  293. data/ext/boost/type_traits/is_abstract.hpp +1 -1
  294. data/ext/boost/type_traits/is_array.hpp +1 -1
  295. data/ext/boost/type_traits/is_const.hpp +1 -1
  296. data/ext/boost/type_traits/is_convertible.hpp +78 -17
  297. data/ext/boost/type_traits/is_function.hpp +6 -1
  298. data/ext/boost/type_traits/is_integral.hpp +6 -1
  299. data/ext/boost/type_traits/is_nothrow_move_assignable.hpp +84 -0
  300. data/ext/boost/type_traits/is_nothrow_move_constructible.hpp +84 -0
  301. data/ext/boost/type_traits/is_pod.hpp +3 -1
  302. data/ext/boost/type_traits/is_rvalue_reference.hpp +1 -1
  303. data/ext/boost/type_traits/is_volatile.hpp +1 -1
  304. data/ext/boost/type_traits/make_signed.hpp +153 -0
  305. data/ext/boost/type_traits/make_unsigned.hpp +16 -0
  306. data/ext/boost/type_traits/remove_const.hpp +1 -1
  307. data/ext/boost/type_traits/remove_cv.hpp +1 -1
  308. data/ext/boost/type_traits/remove_reference.hpp +1 -1
  309. data/ext/boost/type_traits/remove_volatile.hpp +1 -1
  310. data/ext/boost/unordered/detail/allocate.hpp +1120 -0
  311. data/ext/boost/unordered/detail/buckets.hpp +876 -0
  312. data/ext/boost/unordered/detail/equivalent.hpp +680 -0
  313. data/ext/boost/unordered/detail/extract_key.hpp +183 -0
  314. data/ext/boost/unordered/detail/fwd.hpp +23 -0
  315. data/ext/boost/unordered/detail/table.hpp +861 -0
  316. data/ext/boost/unordered/detail/unique.hpp +622 -0
  317. data/ext/boost/unordered/detail/util.hpp +260 -0
  318. data/ext/boost/unordered/unordered_map.hpp +1652 -0
  319. data/ext/boost/unordered/unordered_map_fwd.hpp +65 -0
  320. data/ext/boost/unordered/unordered_set.hpp +1549 -0
  321. data/ext/boost/unordered/unordered_set_fwd.hpp +63 -0
  322. data/ext/boost/unordered_map.hpp +18 -0
  323. data/ext/boost/unordered_set.hpp +18 -0
  324. data/ext/boost/utility/addressof.hpp +2 -2
  325. data/ext/boost/utility/result_of.hpp +8 -1
  326. data/ext/boost/version.hpp +2 -2
  327. data/ext/common/Account.h +1 -1
  328. data/ext/common/AccountsDatabase.h +1 -1
  329. data/ext/common/AgentsStarter.cpp +3 -1
  330. data/ext/common/AgentsStarter.h +2 -2
  331. data/ext/common/ApplicationPool2/AppTypes.cpp +24 -6
  332. data/ext/common/ApplicationPool2/AppTypes.h +17 -8
  333. data/ext/common/ApplicationPool2/Common.h +12 -12
  334. data/ext/common/ApplicationPool2/DirectSpawner.h +2 -2
  335. data/ext/common/ApplicationPool2/DummySpawner.h +3 -3
  336. data/ext/common/ApplicationPool2/Group.h +6 -6
  337. data/ext/common/ApplicationPool2/Implementation.cpp +19 -19
  338. data/ext/common/ApplicationPool2/PipeWatcher.h +5 -5
  339. data/ext/common/ApplicationPool2/Pool.h +21 -21
  340. data/ext/common/ApplicationPool2/Process.h +6 -6
  341. data/ext/common/ApplicationPool2/Session.h +1 -1
  342. data/ext/common/ApplicationPool2/SmartSpawner.h +24 -12
  343. data/ext/common/ApplicationPool2/Socket.h +2 -2
  344. data/ext/common/ApplicationPool2/Spawner.h +64 -14
  345. data/ext/common/ApplicationPool2/SpawnerFactory.h +7 -7
  346. data/ext/common/ApplicationPool2/SuperGroup.h +5 -5
  347. data/ext/common/BackgroundEventLoop.cpp +4 -4
  348. data/ext/common/BackgroundEventLoop.h +1 -1
  349. data/ext/common/Constants.h +13 -1
  350. data/ext/common/EventedBufferedInput.h +8 -8
  351. data/ext/common/Exceptions.cpp +71 -0
  352. data/ext/common/Exceptions.h +60 -7
  353. data/ext/common/FileDescriptor.h +4 -4
  354. data/ext/common/MessageClient.h +1 -1
  355. data/ext/common/MessageServer.h +5 -5
  356. data/ext/common/MultiLibeio.cpp +3 -3
  357. data/ext/common/MultiLibeio.h +2 -2
  358. data/ext/common/RandomGenerator.h +11 -11
  359. data/ext/common/ResourceLocator.h +8 -1
  360. data/ext/common/SafeLibev.h +12 -12
  361. data/ext/common/ServerInstanceDir.h +11 -3
  362. data/ext/common/UnionStation.h +10 -10
  363. data/ext/common/Utils.cpp +11 -13
  364. data/ext/common/Utils.h +9 -9
  365. data/ext/common/Utils/BlockingQueue.h +10 -10
  366. data/ext/common/Utils/BufferedIO.h +1 -1
  367. data/ext/common/Utils/CachedFileStat.hpp +2 -2
  368. data/ext/common/Utils/FileChangeChecker.h +1 -1
  369. data/ext/common/Utils/HashMap.h +13 -4
  370. data/ext/common/Utils/IOUtils.cpp +33 -10
  371. data/ext/common/Utils/IniFile.h +3 -3
  372. data/ext/common/Utils/Lock.h +2 -2
  373. data/ext/common/Utils/MessagePassing.h +10 -10
  374. data/ext/common/Utils/ProcessMetricsCollector.h +24 -6
  375. data/ext/common/Utils/ScopeGuard.h +5 -5
  376. data/ext/common/Utils/jsoncpp.cpp +2 -0
  377. data/ext/common/agents/HelperAgent/FileBackedPipe.h +26 -26
  378. data/ext/common/agents/HelperAgent/Main.cpp +18 -18
  379. data/ext/common/agents/HelperAgent/RequestHandler.cpp +4 -4
  380. data/ext/common/agents/HelperAgent/RequestHandler.h +30 -21
  381. data/ext/common/agents/LoggingAgent/AdminController.h +1 -1
  382. data/ext/common/agents/LoggingAgent/FilterSupport.h +13 -11
  383. data/ext/common/agents/LoggingAgent/LoggingServer.h +11 -11
  384. data/ext/common/agents/LoggingAgent/Main.cpp +9 -9
  385. data/ext/common/agents/LoggingAgent/RemoteSender.h +3 -3
  386. data/ext/common/agents/SpawnPreparer.cpp +1 -0
  387. data/ext/common/agents/Watchdog/AgentWatcher.cpp +8 -7
  388. data/ext/common/agents/Watchdog/Main.cpp +81 -73
  389. data/ext/common/agents/Watchdog/ServerInstanceDirToucher.cpp +1 -1
  390. data/ext/libev/Changes +57 -0
  391. data/ext/libev/LICENSE +2 -1
  392. data/ext/libev/Makefile.in +110 -50
  393. data/ext/libev/README +8 -8
  394. data/ext/libev/aclocal.m4 +1503 -861
  395. data/ext/libev/config.guess +290 -304
  396. data/ext/libev/config.sub +77 -198
  397. data/ext/libev/configure +1735 -890
  398. data/ext/libev/configure.ac +3 -2
  399. data/ext/libev/ev++.h +6 -6
  400. data/ext/libev/ev.c +541 -214
  401. data/ext/libev/ev.h +106 -100
  402. data/ext/libev/ev_epoll.c +1 -1
  403. data/ext/libev/ev_kqueue.c +20 -4
  404. data/ext/libev/ev_vars.h +15 -16
  405. data/ext/libev/ev_win32.c +12 -2
  406. data/ext/libev/ev_wrap.h +162 -160
  407. data/ext/libev/event.c +29 -6
  408. data/ext/libev/event.h +9 -2
  409. data/ext/libev/ltmain.sh +2632 -1384
  410. data/ext/nginx/ConfigurationCommands.c +1 -1
  411. data/ext/nginx/ConfigurationCommands.c.erb +3 -1
  412. data/ext/nginx/ContentHandler.c +25 -2
  413. data/ext/nginx/CreateLocationConfig.c +1 -0
  414. data/ext/nginx/CreateLocationConfig.c.erb +1 -1
  415. data/ext/nginx/MergeLocationConfig.c +1 -0
  416. data/ext/nginx/MergeLocationConfig.c.erb +1 -1
  417. data/ext/nginx/config +12 -0
  418. data/ext/oxt/dynamic_thread_group.hpp +7 -4
  419. data/ext/oxt/system_calls.cpp +5 -1
  420. data/ext/oxt/system_calls.hpp +3 -0
  421. data/helper-scripts/node-loader.js +117 -249
  422. data/lib/phusion_passenger.rb +27 -5
  423. data/lib/phusion_passenger/abstract_installer.rb +104 -9
  424. data/lib/phusion_passenger/admin_tools/memory_stats.rb +10 -9
  425. data/lib/phusion_passenger/apache2/config_options.rb +6 -3
  426. data/lib/phusion_passenger/common_library.rb +7 -1
  427. data/lib/phusion_passenger/constants.rb +6 -0
  428. data/lib/phusion_passenger/loader_shared_helpers.rb +7 -4
  429. data/lib/phusion_passenger/nginx/config_options.rb +2 -1
  430. data/lib/phusion_passenger/packaging.rb +3 -0
  431. data/lib/phusion_passenger/platform_info/apache.rb +43 -6
  432. data/lib/phusion_passenger/platform_info/apache_detector.rb +15 -5
  433. data/lib/phusion_passenger/platform_info/compiler.rb +167 -32
  434. data/lib/phusion_passenger/platform_info/cxx_portability.rb +133 -77
  435. data/lib/phusion_passenger/platform_info/depcheck.rb +17 -7
  436. data/lib/phusion_passenger/platform_info/depcheck_specs/apache2.rb +3 -3
  437. data/lib/phusion_passenger/platform_info/depcheck_specs/compiler_toolchain.rb +4 -4
  438. data/lib/phusion_passenger/platform_info/depcheck_specs/ruby.rb +5 -6
  439. data/lib/phusion_passenger/platform_info/linux.rb +2 -1
  440. data/lib/phusion_passenger/platform_info/operating_system.rb +1 -1
  441. data/lib/phusion_passenger/platform_info/ruby.rb +18 -3
  442. data/lib/phusion_passenger/standalone/runtime_installer.rb +6 -2
  443. data/lib/phusion_passenger/standalone/start_command.rb +8 -2
  444. data/lib/phusion_passenger/utils/ansi_colors.rb +9 -0
  445. data/lib/phusion_passenger/utils/hosts_file_parser.rb +4 -2
  446. data/node_lib/phusion_passenger/httplib_emulation.js +141 -0
  447. data/node_lib/phusion_passenger/line_reader.js +154 -0
  448. data/node_lib/phusion_passenger/request_handler.js +65 -0
  449. data/node_lib/phusion_passenger/session_protocol_parser.js +113 -0
  450. data/resources/templates/apache2/deployment_example.txt.erb +2 -1
  451. data/resources/templates/apache2/installing_against_a_different_apache.txt.erb +14 -0
  452. data/resources/templates/apache2/multiple_apache_installations_detected.txt.erb +15 -0
  453. data/resources/templates/apache2/possible_solutions_for_compilation_and_installation_problems.txt.erb +4 -5
  454. data/resources/templates/general_error_with_html.html.template +1 -1
  455. data/resources/templates/installer_common/gem_install_permission_problems.txt.erb +17 -0
  456. data/resources/templates/installer_common/low_amount_of_memory_warning.txt.erb +6 -4
  457. data/resources/templates/installer_common/world_inaccessible_directories.txt.erb +16 -0
  458. data/resources/templates/nginx/deployment_example.txt.erb +2 -1
  459. data/resources/templates/nginx/possible_solutions_for_compilation_and_installation_problems.txt.erb +4 -5
  460. data/resources/templates/standalone/config.erb +1 -0
  461. data/test/cxx/ApplicationPool2/DirectSpawnerTest.cpp +3 -3
  462. data/test/cxx/ApplicationPool2/PoolTest.cpp +4 -4
  463. data/test/cxx/ApplicationPool2/ProcessTest.cpp +5 -5
  464. data/test/cxx/ApplicationPool2/SmartSpawnerTest.cpp +5 -5
  465. data/test/cxx/ApplicationPool2/SpawnerTestCases.cpp +1 -1
  466. data/test/cxx/EventedBufferedInputTest.cpp +6 -6
  467. data/test/cxx/FileBackedPipeTest.cpp +1 -1
  468. data/test/cxx/MessagePassingTest.cpp +1 -1
  469. data/test/cxx/MessageServerTest.cpp +4 -4
  470. data/test/cxx/RequestHandlerTest.cpp +7 -7
  471. data/test/cxx/UnionStationTest.cpp +2 -2
  472. data/test/node/line_reader_spec.js +338 -0
  473. data/test/node/spec_helper.js +27 -0
  474. data/test/ruby/standalone/runtime_installer_spec.rb +2 -1
  475. metadata +131 -22
  476. metadata.gz.asc +7 -7
  477. data/ext/boost/functional/hash/detail/container_fwd_0x.hpp +0 -29
  478. data/ext/boost/lambda/core.hpp +0 -79
  479. data/ext/boost/lambda/detail/actions.hpp +0 -174
  480. data/ext/boost/lambda/detail/arity_code.hpp +0 -110
  481. data/ext/boost/lambda/detail/function_adaptors.hpp +0 -789
  482. data/ext/boost/lambda/detail/is_instance_of.hpp +0 -104
  483. data/ext/boost/lambda/detail/lambda_config.hpp +0 -48
  484. data/ext/boost/lambda/detail/lambda_functor_base.hpp +0 -615
  485. data/ext/boost/lambda/detail/lambda_functors.hpp +0 -324
  486. data/ext/boost/lambda/detail/lambda_fwd.hpp +0 -74
  487. data/ext/boost/lambda/detail/lambda_traits.hpp +0 -578
  488. data/ext/boost/lambda/detail/member_ptr.hpp +0 -737
  489. data/ext/boost/lambda/detail/operator_actions.hpp +0 -139
  490. data/ext/boost/lambda/detail/operator_lambda_func_base.hpp +0 -271
  491. data/ext/boost/lambda/detail/operator_return_type_traits.hpp +0 -917
  492. data/ext/boost/lambda/detail/operators.hpp +0 -370
  493. data/ext/boost/lambda/detail/ret.hpp +0 -325
  494. data/ext/boost/lambda/detail/return_type_traits.hpp +0 -282
  495. data/ext/boost/lambda/detail/select_functions.hpp +0 -74
  496. data/ext/boost/lambda/lambda.hpp +0 -34
@@ -0,0 +1,148 @@
1
+ // (C) Copyright 2012 Vicente J. Botet Escriba
2
+ // Distributed under the Boost Software License, Version 1.0. (See
3
+ // accompanying file LICENSE_1_0.txt or copy at
4
+ // http://www.boost.org/LICENSE_1_0.txt)
5
+
6
+
7
+ #ifndef BOOST_THREAD_TESTABLE_LOCKABLE_HPP
8
+ #define BOOST_THREAD_TESTABLE_LOCKABLE_HPP
9
+
10
+ #include <boost/thread/detail/config.hpp>
11
+
12
+ #include <boost/thread/thread_only.hpp>
13
+
14
+ #include <boost/atomic.hpp>
15
+ #include <boost/assert.hpp>
16
+
17
+ #include <boost/config/abi_prefix.hpp>
18
+
19
+ namespace boost
20
+ {
21
+ /**
22
+ * Based on Associate Mutexes with Data to Prevent Races, By Herb Sutter, May 13, 2010
23
+ * http://www.drdobbs.com/windows/associate-mutexes-with-data-to-prevent-r/224701827?pgno=3
24
+ *
25
+ * Make our mutex testable if it isn't already.
26
+ *
27
+ * Many mutex services (including boost::mutex) don't provide a way to ask,
28
+ * "Do I already hold a lock on this mutex?"
29
+ * Sometimes it is needed to know if a method like is_locked to be available.
30
+ * This wrapper associates an arbitrary lockable type with a thread id that stores the ID of the thread that
31
+ * currently holds the lockable. The thread id initially holds an invalid value that means no threads own the mutex.
32
+ * When we acquire a lock, we set the thread id; and when we release a lock, we reset it back to its default no id state.
33
+ *
34
+ */
35
+ template <typename Lockable>
36
+ class testable_mutex
37
+ {
38
+ Lockable mtx_;
39
+ atomic<thread::id> id_;
40
+ public:
41
+ /// the type of the wrapped lockable
42
+ typedef Lockable lockable_type;
43
+
44
+ /// Non copyable
45
+ BOOST_THREAD_NO_COPYABLE(testable_mutex)
46
+
47
+ testable_mutex() : id_(thread::id()) {}
48
+
49
+ void lock()
50
+ {
51
+ mtx_.lock();
52
+ id_ = this_thread::get_id();
53
+ }
54
+
55
+ void unlock()
56
+ {
57
+ BOOST_ASSERT(is_locked_by_this_thread());
58
+ id_ = thread::id();
59
+ mtx_.unlock();
60
+ }
61
+
62
+ bool try_lock()
63
+ {
64
+ if (mtx_.try_lock())
65
+ {
66
+ id_ = this_thread::get_id();
67
+ return true;
68
+ }
69
+ else
70
+ {
71
+ return false;
72
+ }
73
+ }
74
+ #ifdef BOOST_THREAD_USES_CHRONO
75
+ template <class Rep, class Period>
76
+ bool try_lock_for(const chrono::duration<Rep, Period>& rel_time)
77
+ {
78
+ if (mtx_.try_lock_for(rel_time))
79
+ {
80
+ id_ = this_thread::get_id();
81
+ return true;
82
+ }
83
+ else
84
+ {
85
+ return false;
86
+ }
87
+ }
88
+ template <class Clock, class Duration>
89
+ bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time)
90
+ {
91
+ if (mtx_.try_lock_until(abs_time))
92
+ {
93
+ id_ = this_thread::get_id();
94
+ return true;
95
+ }
96
+ else
97
+ {
98
+ return false;
99
+ }
100
+ }
101
+ #endif
102
+
103
+ bool is_locked_by_this_thread() const
104
+ {
105
+ return this_thread::get_id() == id_;
106
+ }
107
+ bool is_locked() const
108
+ {
109
+ return ! (thread::id() == id_);
110
+ }
111
+
112
+ thread::id get_id() const
113
+ {
114
+ return id_;
115
+ }
116
+
117
+ // todo add the shared and upgrade mutex functions
118
+ };
119
+
120
+ template <typename Lockable>
121
+ struct is_testable_lockable : false_type
122
+ {};
123
+
124
+ template <typename Lockable>
125
+ struct is_testable_lockable<testable_mutex<Lockable> > : true_type
126
+ {};
127
+
128
+ // /**
129
+ // * Overloaded function used to check if the mutex is locked when it is testable and do nothing otherwise.
130
+ // *
131
+ // * This function is used usually to assert the pre-condition when the function can only be called when the mutex
132
+ // * must be locked by the current thread.
133
+ // */
134
+ // template <typename Lockable>
135
+ // bool is_locked_by_this_thread(testable_mutex<Lockable> const& mtx)
136
+ // {
137
+ // return mtx.is_locked();
138
+ // }
139
+ // template <typename Lockable>
140
+ // bool is_locked_by_this_thread(Lockable const&)
141
+ // {
142
+ // return true;
143
+ // }
144
+ }
145
+
146
+ #include <boost/config/abi_suffix.hpp>
147
+
148
+ #endif // header
@@ -9,20 +9,8 @@
9
9
  // accompanying file LICENSE_1_0.txt or copy at
10
10
  // http://www.boost.org/LICENSE_1_0.txt)
11
11
 
12
- #include <boost/thread/detail/platform.hpp>
13
-
14
- #if defined(BOOST_THREAD_PLATFORM_WIN32)
15
- #include <boost/thread/win32/thread_data.hpp>
16
- #elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
17
- #include <boost/thread/pthread/thread_data.hpp>
18
- #else
19
- #error "Boost threads unavailable on this platform"
20
- #endif
21
-
22
- #include <boost/thread/detail/thread.hpp>
23
- #include <boost/thread/detail/thread_interruption.hpp>
12
+ #include <boost/thread/thread_only.hpp>
24
13
  #include <boost/thread/detail/thread_group.hpp>
25
- #include <boost/thread/v2/thread.hpp>
26
14
 
27
15
 
28
16
  #endif
@@ -0,0 +1,57 @@
1
+ // Distributed under the Boost Software License, Version 1.0. (See
2
+ // accompanying file LICENSE_1_0.txt or copy at
3
+ // http://www.boost.org/LICENSE_1_0.txt)
4
+ // (C) Copyright 2009-2012 Anthony Williams
5
+ // (C) Copyright 2012 Vicente J. Botet Escriba
6
+
7
+ // Based on the Anthony's idea of scoped_thread in CCiA
8
+
9
+ #ifndef BOOST_THREAD_THREAD_FUNCTORS_HPP
10
+ #define BOOST_THREAD_THREAD_FUNCTORS_HPP
11
+
12
+ #include <boost/thread/detail/config.hpp>
13
+ #include <boost/thread/detail/delete.hpp>
14
+ #include <boost/thread/detail/move.hpp>
15
+ #include <boost/thread/thread_only.hpp>
16
+
17
+ #include <boost/config/abi_prefix.hpp>
18
+
19
+ namespace boost
20
+ {
21
+
22
+ struct detach
23
+ {
24
+ void operator()(thread& t)
25
+ {
26
+ t.detach();
27
+ }
28
+ };
29
+
30
+ struct join_if_joinable
31
+ {
32
+ void operator()(thread& t)
33
+ {
34
+ if (t.joinable())
35
+ {
36
+ t.join();
37
+ }
38
+ }
39
+ };
40
+
41
+ #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
42
+ struct interrupt_and_join_if_joinable
43
+ {
44
+ void operator()(thread& t)
45
+ {
46
+ t.interrupt();
47
+ if (t.joinable())
48
+ {
49
+ t.join();
50
+ }
51
+ }
52
+ };
53
+ #endif
54
+ }
55
+ #include <boost/config/abi_suffix.hpp>
56
+
57
+ #endif
@@ -0,0 +1,46 @@
1
+ // Distributed under the Boost Software License, Version 1.0. (See
2
+ // accompanying file LICENSE_1_0.txt or copy at
3
+ // http://www.boost.org/LICENSE_1_0.txt)
4
+ // (C) Copyright 2009-2012 Anthony Williams
5
+ // (C) Copyright 2012 Vicente J. Botet Escriba
6
+
7
+ // Based on the Anthony's idea of thread_joiner in CCiA
8
+
9
+ #ifndef BOOST_THREAD_THREAD_GUARD_HPP
10
+ #define BOOST_THREAD_THREAD_GUARD_HPP
11
+
12
+ #include <boost/thread/detail/delete.hpp>
13
+ #include <boost/thread/detail/move.hpp>
14
+ #include <boost/thread/thread_functors.hpp>
15
+
16
+ #include <boost/config/abi_prefix.hpp>
17
+
18
+ namespace boost
19
+ {
20
+
21
+ /**
22
+ * Non-copyable RAII scoped thread guard joiner which join the thread if joinable when destroyed.
23
+ */
24
+ template <class CallableThread = join_if_joinable>
25
+ class thread_guard
26
+ {
27
+ thread& t_;
28
+ public:
29
+ BOOST_THREAD_NO_COPYABLE( thread_guard)
30
+
31
+ explicit thread_guard(thread& t) :
32
+ t_(t)
33
+ {
34
+ }
35
+ ~thread_guard()
36
+ {
37
+ CallableThread on_destructor;
38
+
39
+ on_destructor(t_);
40
+ }
41
+ };
42
+
43
+ }
44
+ #include <boost/config/abi_suffix.hpp>
45
+
46
+ #endif
@@ -0,0 +1,29 @@
1
+ #ifndef BOOST_THREAD_THREAD_ONLY_HPP
2
+ #define BOOST_THREAD_THREAD_ONLY_HPP
3
+
4
+ // thread.hpp
5
+ //
6
+ // (C) Copyright 2013 Vicente J. Botet Escriba
7
+ //
8
+ // Distributed under the Boost Software License, Version 1.0. (See
9
+ // accompanying file LICENSE_1_0.txt or copy at
10
+ // http://www.boost.org/LICENSE_1_0.txt)
11
+
12
+ #include <boost/thread/detail/platform.hpp>
13
+
14
+ #if defined(BOOST_THREAD_PLATFORM_WIN32)
15
+ #include <boost/thread/win32/thread_data.hpp>
16
+ #elif defined(BOOST_THREAD_PLATFORM_PTHREAD)
17
+ #include <boost/thread/pthread/thread_data.hpp>
18
+ #else
19
+ #error "Boost threads unavailable on this platform"
20
+ #endif
21
+
22
+ #include <boost/thread/detail/thread.hpp>
23
+ #if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS
24
+ #include <boost/thread/detail/thread_interruption.hpp>
25
+ #endif
26
+ #include <boost/thread/v2/thread.hpp>
27
+
28
+
29
+ #endif
@@ -0,0 +1,1062 @@
1
+ #ifndef BOOST_THREAD_V2_SHARED_MUTEX_HPP
2
+ #define BOOST_THREAD_V2_SHARED_MUTEX_HPP
3
+
4
+ // shared_mutex.hpp
5
+ //
6
+ // Copyright Howard Hinnant 2007-2010.
7
+ // Copyright Vicente J. Botet Escriba 2012.
8
+ //
9
+ // Distributed under the Boost Software License, Version 1.0. (See
10
+ // accompanying file LICENSE_1_0.txt or copy at
11
+ // http://www.boost.org/LICENSE_1_0.txt)
12
+
13
+ /*
14
+ <shared_mutex> synopsis
15
+
16
+ namespace boost
17
+ {
18
+ namespace thread_v2
19
+ {
20
+
21
+ class shared_mutex
22
+ {
23
+ public:
24
+
25
+ shared_mutex();
26
+ ~shared_mutex();
27
+
28
+ shared_mutex(const shared_mutex&) = delete;
29
+ shared_mutex& operator=(const shared_mutex&) = delete;
30
+
31
+ // Exclusive ownership
32
+
33
+ void lock();
34
+ bool try_lock();
35
+ template <class Rep, class Period>
36
+ bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time);
37
+ template <class Clock, class Duration>
38
+ bool
39
+ try_lock_until(
40
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
41
+ void unlock();
42
+
43
+ // Shared ownership
44
+
45
+ void lock_shared();
46
+ bool try_lock_shared();
47
+ template <class Rep, class Period>
48
+ bool
49
+ try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time);
50
+ template <class Clock, class Duration>
51
+ bool
52
+ try_lock_shared_until(
53
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
54
+ void unlock_shared();
55
+ };
56
+
57
+ class upgrade_mutex
58
+ {
59
+ public:
60
+
61
+ upgrade_mutex();
62
+ ~upgrade_mutex();
63
+
64
+ upgrade_mutex(const upgrade_mutex&) = delete;
65
+ upgrade_mutex& operator=(const upgrade_mutex&) = delete;
66
+
67
+ // Exclusive ownership
68
+
69
+ void lock();
70
+ bool try_lock();
71
+ template <class Rep, class Period>
72
+ bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time);
73
+ template <class Clock, class Duration>
74
+ bool
75
+ try_lock_until(
76
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
77
+ void unlock();
78
+
79
+ // Shared ownership
80
+
81
+ void lock_shared();
82
+ bool try_lock_shared();
83
+ template <class Rep, class Period>
84
+ bool
85
+ try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time);
86
+ template <class Clock, class Duration>
87
+ bool
88
+ try_lock_shared_until(
89
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
90
+ void unlock_shared();
91
+
92
+ // Upgrade ownership
93
+
94
+ void lock_upgrade();
95
+ bool try_lock_upgrade();
96
+ template <class Rep, class Period>
97
+ bool
98
+ try_lock_upgrade_for(
99
+ const boost::chrono::duration<Rep, Period>& rel_time);
100
+ template <class Clock, class Duration>
101
+ bool
102
+ try_lock_upgrade_until(
103
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
104
+ void unlock_upgrade();
105
+
106
+ // Shared <-> Exclusive
107
+
108
+ bool try_unlock_shared_and_lock();
109
+ template <class Rep, class Period>
110
+ bool
111
+ try_unlock_shared_and_lock_for(
112
+ const boost::chrono::duration<Rep, Period>& rel_time);
113
+ template <class Clock, class Duration>
114
+ bool
115
+ try_unlock_shared_and_lock_until(
116
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
117
+ void unlock_and_lock_shared();
118
+
119
+ // Shared <-> Upgrade
120
+
121
+ bool try_unlock_shared_and_lock_upgrade();
122
+ template <class Rep, class Period>
123
+ bool
124
+ try_unlock_shared_and_lock_upgrade_for(
125
+ const boost::chrono::duration<Rep, Period>& rel_time);
126
+ template <class Clock, class Duration>
127
+ bool
128
+ try_unlock_shared_and_lock_upgrade_until(
129
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
130
+ void unlock_upgrade_and_lock_shared();
131
+
132
+ // Upgrade <-> Exclusive
133
+
134
+ void unlock_upgrade_and_lock();
135
+ bool try_unlock_upgrade_and_lock();
136
+ template <class Rep, class Period>
137
+ bool
138
+ try_unlock_upgrade_and_lock_for(
139
+ const boost::chrono::duration<Rep, Period>& rel_time);
140
+ template <class Clock, class Duration>
141
+ bool
142
+ try_unlock_upgrade_and_lock_until(
143
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
144
+ void unlock_and_lock_upgrade();
145
+ };
146
+
147
+ } // thread_v2
148
+ } // boost
149
+
150
+ */
151
+
152
+ #include <boost/thread/detail/config.hpp>
153
+ #include <boost/thread/mutex.hpp>
154
+ #include <boost/thread/condition_variable.hpp>
155
+ #include <boost/thread/mutex.hpp>
156
+ #include <boost/chrono.hpp>
157
+ #include <climits>
158
+ #include <boost/system/system_error.hpp>
159
+ #define BOOST_THREAD_INLINE inline
160
+
161
+ namespace boost {
162
+ namespace thread_v2 {
163
+
164
+ class shared_mutex
165
+ {
166
+ typedef ::boost::mutex mutex_t;
167
+ typedef ::boost::condition_variable cond_t;
168
+ typedef unsigned count_t;
169
+
170
+ mutex_t mut_;
171
+ cond_t gate1_;
172
+ cond_t gate2_;
173
+ count_t state_;
174
+
175
+ static const count_t write_entered_ = 1U << (sizeof(count_t)*CHAR_BIT - 1);
176
+ static const count_t n_readers_ = ~write_entered_;
177
+
178
+ public:
179
+ BOOST_THREAD_INLINE shared_mutex();
180
+ BOOST_THREAD_INLINE ~shared_mutex();
181
+
182
+ #ifndef BOOST_NO_DELETED_FUNCTIONS
183
+ shared_mutex(shared_mutex const&) = delete;
184
+ shared_mutex& operator=(shared_mutex const&) = delete;
185
+ #else // BOOST_NO_DELETED_FUNCTIONS
186
+ private:
187
+ shared_mutex(shared_mutex const&);
188
+ shared_mutex& operator=(shared_mutex const&);
189
+ public:
190
+ #endif // BOOST_NO_DELETED_FUNCTIONS
191
+
192
+ // Exclusive ownership
193
+
194
+ BOOST_THREAD_INLINE void lock();
195
+ BOOST_THREAD_INLINE bool try_lock();
196
+ template <class Rep, class Period>
197
+ bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time)
198
+ {
199
+ return try_lock_until(boost::chrono::steady_clock::now() + rel_time);
200
+ }
201
+ template <class Clock, class Duration>
202
+ bool
203
+ try_lock_until(
204
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
205
+ BOOST_THREAD_INLINE void unlock();
206
+
207
+
208
+ // Shared ownership
209
+
210
+ BOOST_THREAD_INLINE void lock_shared();
211
+ BOOST_THREAD_INLINE bool try_lock_shared();
212
+ template <class Rep, class Period>
213
+ bool
214
+ try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time)
215
+ {
216
+ return try_lock_shared_until(boost::chrono::steady_clock::now() +
217
+ rel_time);
218
+ }
219
+ template <class Clock, class Duration>
220
+ bool
221
+ try_lock_shared_until(
222
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
223
+ BOOST_THREAD_INLINE void unlock_shared();
224
+
225
+ #if defined BOOST_THREAD_USES_DATETIME
226
+ bool timed_lock(system_time const& timeout);
227
+ template<typename TimeDuration>
228
+ bool timed_lock(TimeDuration const & relative_time)
229
+ {
230
+ return timed_lock(get_system_time()+relative_time);
231
+ }
232
+ bool timed_lock_shared(system_time const& timeout);
233
+ template<typename TimeDuration>
234
+ bool timed_lock_shared(TimeDuration const & relative_time)
235
+ {
236
+ return timed_lock_shared(get_system_time()+relative_time);
237
+ }
238
+ #endif
239
+ };
240
+
241
+ template <class Clock, class Duration>
242
+ bool
243
+ shared_mutex::try_lock_until(
244
+ const boost::chrono::time_point<Clock, Duration>& abs_time)
245
+ {
246
+ boost::unique_lock<mutex_t> lk(mut_);
247
+ if (state_ & write_entered_)
248
+ {
249
+ while (true)
250
+ {
251
+ boost::cv_status status = gate1_.wait_until(lk, abs_time);
252
+ if ((state_ & write_entered_) == 0)
253
+ break;
254
+ if (status == boost::cv_status::timeout)
255
+ return false;
256
+ }
257
+ }
258
+ state_ |= write_entered_;
259
+ if (state_ & n_readers_)
260
+ {
261
+ while (true)
262
+ {
263
+ boost::cv_status status = gate2_.wait_until(lk, abs_time);
264
+ if ((state_ & n_readers_) == 0)
265
+ break;
266
+ if (status == boost::cv_status::timeout)
267
+ {
268
+ state_ &= ~write_entered_;
269
+ return false;
270
+ }
271
+ }
272
+ }
273
+ return true;
274
+ }
275
+
276
+ template <class Clock, class Duration>
277
+ bool
278
+ shared_mutex::try_lock_shared_until(
279
+ const boost::chrono::time_point<Clock, Duration>& abs_time)
280
+ {
281
+ boost::unique_lock<mutex_t> lk(mut_);
282
+ if ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
283
+ {
284
+ while (true)
285
+ {
286
+ boost::cv_status status = gate1_.wait_until(lk, abs_time);
287
+ if ((state_ & write_entered_) == 0 &&
288
+ (state_ & n_readers_) < n_readers_)
289
+ break;
290
+ if (status == boost::cv_status::timeout)
291
+ return false;
292
+ }
293
+ }
294
+ count_t num_readers = (state_ & n_readers_) + 1;
295
+ state_ &= ~n_readers_;
296
+ state_ |= num_readers;
297
+ return true;
298
+ }
299
+
300
+ #if defined BOOST_THREAD_USES_DATETIME
301
+ bool shared_mutex::timed_lock(system_time const& abs_time)
302
+ {
303
+ boost::unique_lock<mutex_t> lk(mut_);
304
+ if (state_ & write_entered_)
305
+ {
306
+ while (true)
307
+ {
308
+ bool status = gate1_.timed_wait(lk, abs_time);
309
+ if ((state_ & write_entered_) == 0)
310
+ break;
311
+ if (!status)
312
+ return false;
313
+ }
314
+ }
315
+ state_ |= write_entered_;
316
+ if (state_ & n_readers_)
317
+ {
318
+ while (true)
319
+ {
320
+ bool status = gate2_.timed_wait(lk, abs_time);
321
+ if ((state_ & n_readers_) == 0)
322
+ break;
323
+ if (!status)
324
+ {
325
+ state_ &= ~write_entered_;
326
+ return false;
327
+ }
328
+ }
329
+ }
330
+ return true;
331
+ }
332
+ bool shared_mutex::timed_lock_shared(system_time const& abs_time)
333
+ {
334
+ boost::unique_lock<mutex_t> lk(mut_);
335
+ if (state_ & write_entered_)
336
+ {
337
+ while (true)
338
+ {
339
+ bool status = gate1_.timed_wait(lk, abs_time);
340
+ if ((state_ & write_entered_) == 0)
341
+ break;
342
+ if (!status )
343
+ return false;
344
+ }
345
+ }
346
+ state_ |= write_entered_;
347
+ if (state_ & n_readers_)
348
+ {
349
+ while (true)
350
+ {
351
+ bool status = gate2_.timed_wait(lk, abs_time);
352
+ if ((state_ & n_readers_) == 0)
353
+ break;
354
+ if (!status)
355
+ {
356
+ state_ &= ~write_entered_;
357
+ return false;
358
+ }
359
+ }
360
+ }
361
+ return true;
362
+ }
363
+ #endif
364
+ class upgrade_mutex
365
+ {
366
+ typedef boost::mutex mutex_t;
367
+ typedef boost::condition_variable cond_t;
368
+ typedef unsigned count_t;
369
+
370
+ mutex_t mut_;
371
+ cond_t gate1_;
372
+ cond_t gate2_;
373
+ count_t state_;
374
+
375
+ static const unsigned write_entered_ = 1U << (sizeof(count_t)*CHAR_BIT - 1);
376
+ static const unsigned upgradable_entered_ = write_entered_ >> 1;
377
+ static const unsigned n_readers_ = ~(write_entered_ | upgradable_entered_);
378
+
379
+ public:
380
+
381
+ BOOST_THREAD_INLINE upgrade_mutex();
382
+ BOOST_THREAD_INLINE ~upgrade_mutex();
383
+
384
+ #ifndef BOOST_NO_DELETED_FUNCTIONS
385
+ upgrade_mutex(const upgrade_mutex&) = delete;
386
+ upgrade_mutex& operator=(const upgrade_mutex&) = delete;
387
+ #else // BOOST_NO_DELETED_FUNCTIONS
388
+ private:
389
+ upgrade_mutex(const upgrade_mutex&);
390
+ upgrade_mutex& operator=(const upgrade_mutex&);
391
+ public:
392
+ #endif // BOOST_NO_DELETED_FUNCTIONS
393
+
394
+ // Exclusive ownership
395
+
396
+ BOOST_THREAD_INLINE void lock();
397
+ BOOST_THREAD_INLINE bool try_lock();
398
+ template <class Rep, class Period>
399
+ bool try_lock_for(const boost::chrono::duration<Rep, Period>& rel_time)
400
+ {
401
+ return try_lock_until(boost::chrono::steady_clock::now() + rel_time);
402
+ }
403
+ template <class Clock, class Duration>
404
+ bool
405
+ try_lock_until(
406
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
407
+ BOOST_THREAD_INLINE void unlock();
408
+
409
+ // Shared ownership
410
+
411
+ BOOST_THREAD_INLINE void lock_shared();
412
+ BOOST_THREAD_INLINE bool try_lock_shared();
413
+ template <class Rep, class Period>
414
+ bool
415
+ try_lock_shared_for(const boost::chrono::duration<Rep, Period>& rel_time)
416
+ {
417
+ return try_lock_shared_until(boost::chrono::steady_clock::now() +
418
+ rel_time);
419
+ }
420
+ template <class Clock, class Duration>
421
+ bool
422
+ try_lock_shared_until(
423
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
424
+ BOOST_THREAD_INLINE void unlock_shared();
425
+
426
+ // Upgrade ownership
427
+
428
+ BOOST_THREAD_INLINE void lock_upgrade();
429
+ BOOST_THREAD_INLINE bool try_lock_upgrade();
430
+ template <class Rep, class Period>
431
+ bool
432
+ try_lock_upgrade_for(
433
+ const boost::chrono::duration<Rep, Period>& rel_time)
434
+ {
435
+ return try_lock_upgrade_until(boost::chrono::steady_clock::now() +
436
+ rel_time);
437
+ }
438
+ template <class Clock, class Duration>
439
+ bool
440
+ try_lock_upgrade_until(
441
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
442
+ BOOST_THREAD_INLINE void unlock_upgrade();
443
+
444
+ // Shared <-> Exclusive
445
+
446
+ BOOST_THREAD_INLINE bool try_unlock_shared_and_lock();
447
+ template <class Rep, class Period>
448
+ bool
449
+ try_unlock_shared_and_lock_for(
450
+ const boost::chrono::duration<Rep, Period>& rel_time)
451
+ {
452
+ return try_unlock_shared_and_lock_until(
453
+ boost::chrono::steady_clock::now() + rel_time);
454
+ }
455
+ template <class Clock, class Duration>
456
+ bool
457
+ try_unlock_shared_and_lock_until(
458
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
459
+ BOOST_THREAD_INLINE void unlock_and_lock_shared();
460
+
461
+ // Shared <-> Upgrade
462
+
463
+ BOOST_THREAD_INLINE bool try_unlock_shared_and_lock_upgrade();
464
+ template <class Rep, class Period>
465
+ bool
466
+ try_unlock_shared_and_lock_upgrade_for(
467
+ const boost::chrono::duration<Rep, Period>& rel_time)
468
+ {
469
+ return try_unlock_shared_and_lock_upgrade_until(
470
+ boost::chrono::steady_clock::now() + rel_time);
471
+ }
472
+ template <class Clock, class Duration>
473
+ bool
474
+ try_unlock_shared_and_lock_upgrade_until(
475
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
476
+ BOOST_THREAD_INLINE void unlock_upgrade_and_lock_shared();
477
+
478
+ // Upgrade <-> Exclusive
479
+
480
+ BOOST_THREAD_INLINE void unlock_upgrade_and_lock();
481
+ BOOST_THREAD_INLINE bool try_unlock_upgrade_and_lock();
482
+ template <class Rep, class Period>
483
+ bool
484
+ try_unlock_upgrade_and_lock_for(
485
+ const boost::chrono::duration<Rep, Period>& rel_time)
486
+ {
487
+ return try_unlock_upgrade_and_lock_until(
488
+ boost::chrono::steady_clock::now() + rel_time);
489
+ }
490
+ template <class Clock, class Duration>
491
+ bool
492
+ try_unlock_upgrade_and_lock_until(
493
+ const boost::chrono::time_point<Clock, Duration>& abs_time);
494
+ BOOST_THREAD_INLINE void unlock_and_lock_upgrade();
495
+
496
+ #if defined BOOST_THREAD_USES_DATETIME
497
+ inline bool timed_lock(system_time const& abs_time);
498
+ template<typename TimeDuration>
499
+ bool timed_lock(TimeDuration const & relative_time)
500
+ {
501
+ return timed_lock(get_system_time()+relative_time);
502
+ }
503
+ inline bool timed_lock_shared(system_time const& abs_time);
504
+ template<typename TimeDuration>
505
+ bool timed_lock_shared(TimeDuration const & relative_time)
506
+ {
507
+ return timed_lock_shared(get_system_time()+relative_time);
508
+ }
509
+ inline bool timed_lock_upgrade(system_time const& abs_time);
510
+ template<typename TimeDuration>
511
+ bool timed_lock_upgrade(TimeDuration const & relative_time)
512
+ {
513
+ return timed_lock_upgrade(get_system_time()+relative_time);
514
+ }
515
+ #endif
516
+
517
+ };
518
+
519
+ template <class Clock, class Duration>
520
+ bool
521
+ upgrade_mutex::try_lock_until(
522
+ const boost::chrono::time_point<Clock, Duration>& abs_time)
523
+ {
524
+ boost::unique_lock<mutex_t> lk(mut_);
525
+ if (state_ & (write_entered_ | upgradable_entered_))
526
+ {
527
+ while (true)
528
+ {
529
+ boost::cv_status status = gate1_.wait_until(lk, abs_time);
530
+ if ((state_ & (write_entered_ | upgradable_entered_)) == 0)
531
+ break;
532
+ if (status == boost::cv_status::timeout)
533
+ return false;
534
+ }
535
+ }
536
+ state_ |= write_entered_;
537
+ if (state_ & n_readers_)
538
+ {
539
+ while (true)
540
+ {
541
+ boost::cv_status status = gate2_.wait_until(lk, abs_time);
542
+ if ((state_ & n_readers_) == 0)
543
+ break;
544
+ if (status == boost::cv_status::timeout)
545
+ {
546
+ state_ &= ~write_entered_;
547
+ return false;
548
+ }
549
+ }
550
+ }
551
+ return true;
552
+ }
553
+
554
+ template <class Clock, class Duration>
555
+ bool
556
+ upgrade_mutex::try_lock_shared_until(
557
+ const boost::chrono::time_point<Clock, Duration>& abs_time)
558
+ {
559
+ boost::unique_lock<mutex_t> lk(mut_);
560
+ if ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
561
+ {
562
+ while (true)
563
+ {
564
+ boost::cv_status status = gate1_.wait_until(lk, abs_time);
565
+ if ((state_ & write_entered_) == 0 &&
566
+ (state_ & n_readers_) < n_readers_)
567
+ break;
568
+ if (status == boost::cv_status::timeout)
569
+ return false;
570
+ }
571
+ }
572
+ count_t num_readers = (state_ & n_readers_) + 1;
573
+ state_ &= ~n_readers_;
574
+ state_ |= num_readers;
575
+ return true;
576
+ }
577
+
578
+ template <class Clock, class Duration>
579
+ bool
580
+ upgrade_mutex::try_lock_upgrade_until(
581
+ const boost::chrono::time_point<Clock, Duration>& abs_time)
582
+ {
583
+ boost::unique_lock<mutex_t> lk(mut_);
584
+ if ((state_ & (write_entered_ | upgradable_entered_)) ||
585
+ (state_ & n_readers_) == n_readers_)
586
+ {
587
+ while (true)
588
+ {
589
+ boost::cv_status status = gate1_.wait_until(lk, abs_time);
590
+ if ((state_ & (write_entered_ | upgradable_entered_)) == 0 &&
591
+ (state_ & n_readers_) < n_readers_)
592
+ break;
593
+ if (status == boost::cv_status::timeout)
594
+ return false;
595
+ }
596
+ }
597
+ count_t num_readers = (state_ & n_readers_) + 1;
598
+ state_ &= ~n_readers_;
599
+ state_ |= upgradable_entered_ | num_readers;
600
+ return true;
601
+ }
602
+
603
+ #if defined BOOST_THREAD_USES_DATETIME
604
+ bool upgrade_mutex::timed_lock(system_time const& abs_time)
605
+ {
606
+ boost::unique_lock<mutex_t> lk(mut_);
607
+ if (state_ & (write_entered_ | upgradable_entered_))
608
+ {
609
+ while (true)
610
+ {
611
+ bool status = gate1_.timed_wait(lk, abs_time);
612
+ if ((state_ & (write_entered_ | upgradable_entered_)) == 0)
613
+ break;
614
+ if (!status)
615
+ return false;
616
+ }
617
+ }
618
+ state_ |= write_entered_;
619
+ if (state_ & n_readers_)
620
+ {
621
+ while (true)
622
+ {
623
+ bool status = gate2_.timed_wait(lk, abs_time);
624
+ if ((state_ & n_readers_) == 0)
625
+ break;
626
+ if (!status)
627
+ {
628
+ state_ &= ~write_entered_;
629
+ return false;
630
+ }
631
+ }
632
+ }
633
+ return true;
634
+ }
635
+ bool upgrade_mutex::timed_lock_shared(system_time const& abs_time)
636
+ {
637
+ boost::unique_lock<mutex_t> lk(mut_);
638
+ if ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
639
+ {
640
+ while (true)
641
+ {
642
+ bool status = gate1_.timed_wait(lk, abs_time);
643
+ if ((state_ & write_entered_) == 0 &&
644
+ (state_ & n_readers_) < n_readers_)
645
+ break;
646
+ if (!status)
647
+ return false;
648
+ }
649
+ }
650
+ count_t num_readers = (state_ & n_readers_) + 1;
651
+ state_ &= ~n_readers_;
652
+ state_ |= num_readers;
653
+ return true;
654
+ }
655
+ bool upgrade_mutex::timed_lock_upgrade(system_time const& abs_time)
656
+ {
657
+ boost::unique_lock<mutex_t> lk(mut_);
658
+ if ((state_ & (write_entered_ | upgradable_entered_)) ||
659
+ (state_ & n_readers_) == n_readers_)
660
+ {
661
+ while (true)
662
+ {
663
+ bool status = gate1_.timed_wait(lk, abs_time);
664
+ if ((state_ & (write_entered_ | upgradable_entered_)) == 0 &&
665
+ (state_ & n_readers_) < n_readers_)
666
+ break;
667
+ if (!status)
668
+ return false;
669
+ }
670
+ }
671
+ count_t num_readers = (state_ & n_readers_) + 1;
672
+ state_ &= ~n_readers_;
673
+ state_ |= upgradable_entered_ | num_readers;
674
+ return true;
675
+ }
676
+
677
+ #endif
678
+ template <class Clock, class Duration>
679
+ bool
680
+ upgrade_mutex::try_unlock_shared_and_lock_until(
681
+ const boost::chrono::time_point<Clock, Duration>& abs_time)
682
+ {
683
+ boost::unique_lock<mutex_t> lk(mut_);
684
+ if (state_ != 1)
685
+ {
686
+ while (true)
687
+ {
688
+ boost::cv_status status = gate2_.wait_until(lk, abs_time);
689
+ if (state_ == 1)
690
+ break;
691
+ if (status == boost::cv_status::timeout)
692
+ return false;
693
+ }
694
+ }
695
+ state_ = write_entered_;
696
+ return true;
697
+ }
698
+
699
+ template <class Clock, class Duration>
700
+ bool
701
+ upgrade_mutex::try_unlock_shared_and_lock_upgrade_until(
702
+ const boost::chrono::time_point<Clock, Duration>& abs_time)
703
+ {
704
+ boost::unique_lock<mutex_t> lk(mut_);
705
+ if ((state_ & (write_entered_ | upgradable_entered_)) != 0)
706
+ {
707
+ while (true)
708
+ {
709
+ boost::cv_status status = gate2_.wait_until(lk, abs_time);
710
+ if ((state_ & (write_entered_ | upgradable_entered_)) == 0)
711
+ break;
712
+ if (status == boost::cv_status::timeout)
713
+ return false;
714
+ }
715
+ }
716
+ state_ |= upgradable_entered_;
717
+ return true;
718
+ }
719
+
720
+ template <class Clock, class Duration>
721
+ bool
722
+ upgrade_mutex::try_unlock_upgrade_and_lock_until(
723
+ const boost::chrono::time_point<Clock, Duration>& abs_time)
724
+ {
725
+ boost::unique_lock<mutex_t> lk(mut_);
726
+ if ((state_ & n_readers_) != 1)
727
+ {
728
+ while (true)
729
+ {
730
+ boost::cv_status status = gate2_.wait_until(lk, abs_time);
731
+ if ((state_ & n_readers_) == 1)
732
+ break;
733
+ if (status == boost::cv_status::timeout)
734
+ return false;
735
+ }
736
+ }
737
+ state_ = write_entered_;
738
+ return true;
739
+ }
740
+
741
+ //////
742
+ // shared_mutex
743
+
744
+ shared_mutex::shared_mutex()
745
+ : state_(0)
746
+ {
747
+ }
748
+
749
+ shared_mutex::~shared_mutex()
750
+ {
751
+ boost::lock_guard<mutex_t> _(mut_);
752
+ }
753
+
754
+ // Exclusive ownership
755
+
756
+ void
757
+ shared_mutex::lock()
758
+ {
759
+ boost::unique_lock<mutex_t> lk(mut_);
760
+ while (state_ & write_entered_)
761
+ gate1_.wait(lk);
762
+ state_ |= write_entered_;
763
+ while (state_ & n_readers_)
764
+ gate2_.wait(lk);
765
+ }
766
+
767
+ bool
768
+ shared_mutex::try_lock()
769
+ {
770
+ boost::unique_lock<mutex_t> lk(mut_);
771
+ if (state_ == 0)
772
+ {
773
+ state_ = write_entered_;
774
+ return true;
775
+ }
776
+ return false;
777
+ }
778
+
779
+ void
780
+ shared_mutex::unlock()
781
+ {
782
+ boost::lock_guard<mutex_t> _(mut_);
783
+ state_ = 0;
784
+ gate1_.notify_all();
785
+ }
786
+
787
+ // Shared ownership
788
+
789
+ void
790
+ shared_mutex::lock_shared()
791
+ {
792
+ boost::unique_lock<mutex_t> lk(mut_);
793
+ while ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
794
+ gate1_.wait(lk);
795
+ count_t num_readers = (state_ & n_readers_) + 1;
796
+ state_ &= ~n_readers_;
797
+ state_ |= num_readers;
798
+ }
799
+
800
+ bool
801
+ shared_mutex::try_lock_shared()
802
+ {
803
+ boost::unique_lock<mutex_t> lk(mut_);
804
+ count_t num_readers = state_ & n_readers_;
805
+ if (!(state_ & write_entered_) && num_readers != n_readers_)
806
+ {
807
+ ++num_readers;
808
+ state_ &= ~n_readers_;
809
+ state_ |= num_readers;
810
+ return true;
811
+ }
812
+ return false;
813
+ }
814
+
815
+ void
816
+ shared_mutex::unlock_shared()
817
+ {
818
+ boost::lock_guard<mutex_t> _(mut_);
819
+ count_t num_readers = (state_ & n_readers_) - 1;
820
+ state_ &= ~n_readers_;
821
+ state_ |= num_readers;
822
+ if (state_ & write_entered_)
823
+ {
824
+ if (num_readers == 0)
825
+ gate2_.notify_one();
826
+ }
827
+ else
828
+ {
829
+ if (num_readers == n_readers_ - 1)
830
+ gate1_.notify_one();
831
+ }
832
+ }
833
+
834
+ // upgrade_mutex
835
+
836
+ upgrade_mutex::upgrade_mutex()
837
+ : gate1_(),
838
+ gate2_(),
839
+ state_(0)
840
+ {
841
+ }
842
+
843
+ upgrade_mutex::~upgrade_mutex()
844
+ {
845
+ boost::lock_guard<mutex_t> _(mut_);
846
+ }
847
+
848
+ // Exclusive ownership
849
+
850
+ void
851
+ upgrade_mutex::lock()
852
+ {
853
+ boost::unique_lock<mutex_t> lk(mut_);
854
+ while (state_ & (write_entered_ | upgradable_entered_))
855
+ gate1_.wait(lk);
856
+ state_ |= write_entered_;
857
+ while (state_ & n_readers_)
858
+ gate2_.wait(lk);
859
+ }
860
+
861
+ bool
862
+ upgrade_mutex::try_lock()
863
+ {
864
+ boost::unique_lock<mutex_t> lk(mut_);
865
+ if (state_ == 0)
866
+ {
867
+ state_ = write_entered_;
868
+ return true;
869
+ }
870
+ return false;
871
+ }
872
+
873
+ void
874
+ upgrade_mutex::unlock()
875
+ {
876
+ boost::lock_guard<mutex_t> _(mut_);
877
+ state_ = 0;
878
+ gate1_.notify_all();
879
+ }
880
+
881
+ // Shared ownership
882
+
883
+ void
884
+ upgrade_mutex::lock_shared()
885
+ {
886
+ boost::unique_lock<mutex_t> lk(mut_);
887
+ while ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_)
888
+ gate1_.wait(lk);
889
+ count_t num_readers = (state_ & n_readers_) + 1;
890
+ state_ &= ~n_readers_;
891
+ state_ |= num_readers;
892
+ }
893
+
894
+ bool
895
+ upgrade_mutex::try_lock_shared()
896
+ {
897
+ boost::unique_lock<mutex_t> lk(mut_);
898
+ count_t num_readers = state_ & n_readers_;
899
+ if (!(state_ & write_entered_) && num_readers != n_readers_)
900
+ {
901
+ ++num_readers;
902
+ state_ &= ~n_readers_;
903
+ state_ |= num_readers;
904
+ return true;
905
+ }
906
+ return false;
907
+ }
908
+
909
+ void
910
+ upgrade_mutex::unlock_shared()
911
+ {
912
+ boost::lock_guard<mutex_t> _(mut_);
913
+ count_t num_readers = (state_ & n_readers_) - 1;
914
+ state_ &= ~n_readers_;
915
+ state_ |= num_readers;
916
+ if (state_ & write_entered_)
917
+ {
918
+ if (num_readers == 0)
919
+ gate2_.notify_one();
920
+ }
921
+ else
922
+ {
923
+ if (num_readers == n_readers_ - 1)
924
+ gate1_.notify_one();
925
+ }
926
+ }
927
+
928
+ // Upgrade ownership
929
+
930
+ void
931
+ upgrade_mutex::lock_upgrade()
932
+ {
933
+ boost::unique_lock<mutex_t> lk(mut_);
934
+ while ((state_ & (write_entered_ | upgradable_entered_)) ||
935
+ (state_ & n_readers_) == n_readers_)
936
+ gate1_.wait(lk);
937
+ count_t num_readers = (state_ & n_readers_) + 1;
938
+ state_ &= ~n_readers_;
939
+ state_ |= upgradable_entered_ | num_readers;
940
+ }
941
+
942
+ bool
943
+ upgrade_mutex::try_lock_upgrade()
944
+ {
945
+ boost::unique_lock<mutex_t> lk(mut_);
946
+ count_t num_readers = state_ & n_readers_;
947
+ if (!(state_ & (write_entered_ | upgradable_entered_))
948
+ && num_readers != n_readers_)
949
+ {
950
+ ++num_readers;
951
+ state_ &= ~n_readers_;
952
+ state_ |= upgradable_entered_ | num_readers;
953
+ return true;
954
+ }
955
+ return false;
956
+ }
957
+
958
+ void
959
+ upgrade_mutex::unlock_upgrade()
960
+ {
961
+ {
962
+ boost::lock_guard<mutex_t> _(mut_);
963
+ count_t num_readers = (state_ & n_readers_) - 1;
964
+ state_ &= ~(upgradable_entered_ | n_readers_);
965
+ state_ |= num_readers;
966
+ }
967
+ gate1_.notify_all();
968
+ }
969
+
970
+ // Shared <-> Exclusive
971
+
972
+ bool
973
+ upgrade_mutex::try_unlock_shared_and_lock()
974
+ {
975
+ boost::unique_lock<mutex_t> lk(mut_);
976
+ if (state_ == 1)
977
+ {
978
+ state_ = write_entered_;
979
+ return true;
980
+ }
981
+ return false;
982
+ }
983
+
984
+ void
985
+ upgrade_mutex::unlock_and_lock_shared()
986
+ {
987
+ {
988
+ boost::lock_guard<mutex_t> _(mut_);
989
+ state_ = 1;
990
+ }
991
+ gate1_.notify_all();
992
+ }
993
+
994
+ // Shared <-> Upgrade
995
+
996
+ bool
997
+ upgrade_mutex::try_unlock_shared_and_lock_upgrade()
998
+ {
999
+ boost::unique_lock<mutex_t> lk(mut_);
1000
+ if (!(state_ & (write_entered_ | upgradable_entered_)))
1001
+ {
1002
+ state_ |= upgradable_entered_;
1003
+ return true;
1004
+ }
1005
+ return false;
1006
+ }
1007
+
1008
+ void
1009
+ upgrade_mutex::unlock_upgrade_and_lock_shared()
1010
+ {
1011
+ {
1012
+ boost::lock_guard<mutex_t> _(mut_);
1013
+ state_ &= ~upgradable_entered_;
1014
+ }
1015
+ gate1_.notify_all();
1016
+ }
1017
+
1018
+ // Upgrade <-> Exclusive
1019
+
1020
+ void
1021
+ upgrade_mutex::unlock_upgrade_and_lock()
1022
+ {
1023
+ boost::unique_lock<mutex_t> lk(mut_);
1024
+ count_t num_readers = (state_ & n_readers_) - 1;
1025
+ state_ &= ~(upgradable_entered_ | n_readers_);
1026
+ state_ |= write_entered_ | num_readers;
1027
+ while (state_ & n_readers_)
1028
+ gate2_.wait(lk);
1029
+ }
1030
+
1031
+ bool
1032
+ upgrade_mutex::try_unlock_upgrade_and_lock()
1033
+ {
1034
+ boost::unique_lock<mutex_t> lk(mut_);
1035
+ if (state_ == (upgradable_entered_ | 1))
1036
+ {
1037
+ state_ = write_entered_;
1038
+ return true;
1039
+ }
1040
+ return false;
1041
+ }
1042
+
1043
+ void
1044
+ upgrade_mutex::unlock_and_lock_upgrade()
1045
+ {
1046
+ {
1047
+ boost::lock_guard<mutex_t> _(mut_);
1048
+ state_ = upgradable_entered_ | 1;
1049
+ }
1050
+ gate1_.notify_all();
1051
+ }
1052
+
1053
+ } // thread_v2
1054
+ } // boost
1055
+
1056
+ namespace boost {
1057
+ //using thread_v2::shared_mutex;
1058
+ using thread_v2::upgrade_mutex;
1059
+ typedef thread_v2::upgrade_mutex shared_mutex;
1060
+ }
1061
+
1062
+ #endif