From 869912de45bfec53f8fd15c4f716b49ac2ca7aa4 Mon Sep 17 00:00:00 2001 From: Mark Benvenuto Date: Thu, 31 Mar 2016 15:09:29 -0400 Subject: SERVER-17294 Boost 1.60 --- .../boost-1.60.0/boost/thread/barrier.hpp | 254 + .../boost-1.60.0/boost/thread/caller_context.hpp | 59 + .../boost-1.60.0/boost/thread/completion_latch.hpp | 226 + .../thread/concurrent_queues/deque_adaptor.hpp | 209 + .../boost/thread/concurrent_queues/deque_base.hpp | 202 + .../boost/thread/concurrent_queues/deque_views.hpp | 165 + .../concurrent_queues/detail/sync_deque_base.hpp | 223 + .../concurrent_queues/detail/sync_queue_base.hpp | 223 + .../thread/concurrent_queues/queue_adaptor.hpp | 209 + .../boost/thread/concurrent_queues/queue_base.hpp | 202 + .../thread/concurrent_queues/queue_op_status.hpp | 46 + .../boost/thread/concurrent_queues/queue_views.hpp | 155 + .../concurrent_queues/sync_bounded_queue.hpp | 725 +++ .../boost/thread/concurrent_queues/sync_deque.hpp | 327 ++ .../concurrent_queues/sync_priority_queue.hpp | 369 ++ .../boost/thread/concurrent_queues/sync_queue.hpp | 335 ++ .../thread/concurrent_queues/sync_timed_queue.hpp | 466 ++ .../boost-1.60.0/boost/thread/condition.hpp | 21 + .../boost/thread/condition_variable.hpp | 21 + .../boost-1.60.0/boost/thread/csbl/deque.hpp | 45 + .../boost-1.60.0/boost/thread/csbl/devector.hpp | 102 + .../boost-1.60.0/boost/thread/csbl/functional.hpp | 49 + .../boost-1.60.0/boost/thread/csbl/list.hpp | 35 + .../boost-1.60.0/boost/thread/csbl/memory.hpp | 61 + .../boost/thread/csbl/memory/allocator_arg.hpp | 41 + .../boost/thread/csbl/memory/allocator_traits.hpp | 35 + .../boost/thread/csbl/memory/config.hpp | 16 + .../boost/thread/csbl/memory/default_delete.hpp | 41 + .../boost/thread/csbl/memory/pointer_traits.hpp | 35 + .../boost/thread/csbl/memory/scoped_allocator.hpp | 35 + .../boost/thread/csbl/memory/shared_ptr.hpp | 42 + .../boost/thread/csbl/memory/unique_ptr.hpp | 28 + .../boost-1.60.0/boost/thread/csbl/queue.hpp | 45 + .../boost-1.60.0/boost/thread/csbl/tuple.hpp | 49 + .../boost-1.60.0/boost/thread/csbl/vector.hpp | 35 + .../boost-1.60.0/boost/thread/cv_status.hpp | 26 + .../boost-1.60.0/boost/thread/detail/config.hpp | 465 ++ .../boost-1.60.0/boost/thread/detail/counter.hpp | 106 + .../boost-1.60.0/boost/thread/detail/delete.hpp | 58 + .../boost/thread/detail/force_cast.hpp | 39 + .../boost/thread/detail/function_wrapper.hpp | 93 + .../boost-1.60.0/boost/thread/detail/invoke.hpp | 1604 ++++++ .../boost-1.60.0/boost/thread/detail/invoker.hpp | 762 +++ .../boost/thread/detail/is_convertible.hpp | 49 + .../boost/thread/detail/lockable_wrapper.hpp | 45 + .../boost-1.60.0/boost/thread/detail/log.hpp | 83 + .../boost/thread/detail/make_tuple_indices.hpp | 224 + .../boost-1.60.0/boost/thread/detail/memory.hpp | 48 + .../boost-1.60.0/boost/thread/detail/move.hpp | 374 ++ .../boost/thread/detail/nullary_function.hpp | 234 + .../boost-1.60.0/boost/thread/detail/platform.hpp | 73 + .../boost-1.60.0/boost/thread/detail/singleton.hpp | 59 + .../boost-1.60.0/boost/thread/detail/thread.hpp | 873 +++ .../boost/thread/detail/thread_group.hpp | 155 + .../boost/thread/detail/thread_heap_alloc.hpp | 23 + .../boost/thread/detail/thread_interruption.hpp | 39 + .../boost-1.60.0/boost/thread/detail/tss_hooks.hpp | 65 + .../boost/thread/detail/variadic_footer.hpp | 10 + .../boost/thread/detail/variadic_header.hpp | 19 + .../boost-1.60.0/boost/thread/exceptional_ptr.hpp | 44 + .../boost-1.60.0/boost/thread/exceptions.hpp | 225 + .../boost-1.60.0/boost/thread/executor.hpp | 15 + .../boost/thread/executors/basic_thread_pool.hpp | 318 ++ .../executors/detail/priority_executor_base.hpp | 77 + .../executors/detail/scheduled_executor_base.hpp | 66 + .../boost/thread/executors/executor.hpp | 148 + .../boost/thread/executors/executor_adaptor.hpp | 136 + .../thread/executors/generic_executor_ref.hpp | 213 + .../boost/thread/executors/inline_executor.hpp | 171 + .../boost/thread/executors/loop_executor.hpp | 205 + .../thread/executors/scheduled_thread_pool.hpp | 48 + .../boost/thread/executors/scheduler.hpp | 271 + .../boost/thread/executors/scheduling_adaptor.hpp | 51 + .../boost/thread/executors/serial_executor.hpp | 216 + .../thread/executors/serial_executor_cont.hpp | 170 + .../boost/thread/executors/thread_executor.hpp | 157 + .../boost-1.60.0/boost/thread/executors/work.hpp | 30 + .../experimental/config/inline_namespace.hpp | 23 + .../boost/thread/experimental/exception_list.hpp | 16 + .../experimental/parallel/v1/exception_list.hpp | 70 + .../experimental/parallel/v1/inline_namespace.hpp | 28 + .../experimental/parallel/v2/inline_namespace.hpp | 29 + .../experimental/parallel/v2/task_region.hpp | 316 ++ .../boost/thread/experimental/task_region.hpp | 16 + .../boost/thread/externally_locked.hpp | 351 ++ .../boost/thread/externally_locked_stream.hpp | 170 + .../boost-1.60.0/boost/thread/future.hpp | 5552 ++++++++++++++++++++ .../boost/thread/futures/future_error.hpp | 98 + .../boost/thread/futures/future_error_code.hpp | 61 + .../boost/thread/futures/future_status.hpp | 30 + .../boost/thread/futures/is_future_type.hpp | 21 + .../boost-1.60.0/boost/thread/futures/launch.hpp | 31 + .../boost/thread/futures/wait_for_all.hpp | 74 + .../boost/thread/futures/wait_for_any.hpp | 161 + .../boost/thread/is_locked_by_this_thread.hpp | 39 + .../boost-1.60.0/boost/thread/latch.hpp | 170 + .../boost-1.60.0/boost/thread/lock_algorithms.hpp | 468 ++ .../boost-1.60.0/boost/thread/lock_concepts.hpp | 197 + .../boost-1.60.0/boost/thread/lock_factories.hpp | 78 + .../boost-1.60.0/boost/thread/lock_guard.hpp | 88 + .../boost-1.60.0/boost/thread/lock_options.hpp | 31 + .../boost-1.60.0/boost/thread/lock_traits.hpp | 45 + .../boost-1.60.0/boost/thread/lock_types.hpp | 1230 +++++ .../boost-1.60.0/boost/thread/lockable_adapter.hpp | 226 + .../boost/thread/lockable_concepts.hpp | 157 + .../boost-1.60.0/boost/thread/lockable_traits.hpp | 207 + .../boost-1.60.0/boost/thread/locks.hpp | 16 + .../boost-1.60.0/boost/thread/mutex.hpp | 53 + .../boost-1.60.0/boost/thread/null_mutex.hpp | 243 + src/third_party/boost-1.60.0/boost/thread/once.hpp | 44 + .../boost-1.60.0/boost/thread/ostream_buffer.hpp | 45 + .../boost-1.60.0/boost/thread/poly_lockable.hpp | 68 + .../boost/thread/poly_lockable_adapter.hpp | 89 + .../boost/thread/poly_shared_lockable.hpp | 135 + .../boost/thread/poly_shared_lockable_adapter.hpp | 170 + .../boost/thread/pthread/condition_variable.hpp | 428 ++ .../thread/pthread/condition_variable_fwd.hpp | 360 ++ .../boost-1.60.0/boost/thread/pthread/mutex.hpp | 361 ++ .../boost-1.60.0/boost/thread/pthread/once.hpp | 540 ++ .../boost/thread/pthread/once_atomic.hpp | 313 ++ .../thread/pthread/pthread_mutex_scoped_lock.hpp | 64 + .../boost/thread/pthread/recursive_mutex.hpp | 404 ++ .../boost/thread/pthread/shared_mutex.hpp | 716 +++ .../boost/thread/pthread/shared_mutex_assert.hpp | 724 +++ .../boost/thread/pthread/thread_data.hpp | 292 + .../boost/thread/pthread/thread_heap_alloc.hpp | 242 + .../boost-1.60.0/boost/thread/pthread/timespec.hpp | 120 + .../boost-1.60.0/boost/thread/recursive_mutex.hpp | 64 + .../boost-1.60.0/boost/thread/reverse_lock.hpp | 59 + .../boost-1.60.0/boost/thread/scoped_thread.hpp | 289 + .../boost/thread/shared_lock_guard.hpp | 53 + .../boost-1.60.0/boost/thread/shared_mutex.hpp | 50 + .../boost-1.60.0/boost/thread/strict_lock.hpp | 235 + .../boost/thread/sync_bounded_queue.hpp | 16 + .../boost-1.60.0/boost/thread/sync_queue.hpp | 16 + .../boost/thread/synchronized_value.hpp | 1068 ++++ .../boost-1.60.0/boost/thread/testable_mutex.hpp | 152 + .../boost-1.60.0/boost/thread/thread.hpp | 16 + .../boost-1.60.0/boost/thread/thread_functors.hpp | 57 + .../boost-1.60.0/boost/thread/thread_guard.hpp | 46 + .../boost-1.60.0/boost/thread/thread_only.hpp | 29 + .../boost-1.60.0/boost/thread/thread_pool.hpp | 15 + .../boost-1.60.0/boost/thread/thread_time.hpp | 55 + src/third_party/boost-1.60.0/boost/thread/tss.hpp | 113 + .../boost-1.60.0/boost/thread/user_scheduler.hpp | 202 + .../boost-1.60.0/boost/thread/v2/shared_mutex.hpp | 1062 ++++ .../boost-1.60.0/boost/thread/v2/thread.hpp | 155 + .../boost/thread/win32/basic_recursive_mutex.hpp | 164 + .../boost/thread/win32/basic_timed_mutex.hpp | 279 + .../boost/thread/win32/condition_variable.hpp | 567 ++ .../boost/thread/win32/interlocked_read.hpp | 77 + .../boost/thread/win32/mfc_thread_init.hpp | 40 + .../boost-1.60.0/boost/thread/win32/mutex.hpp | 72 + .../boost-1.60.0/boost/thread/win32/once.hpp | 1087 ++++ .../boost/thread/win32/recursive_mutex.hpp | 70 + .../boost/thread/win32/shared_mutex.hpp | 903 ++++ .../boost/thread/win32/thread_data.hpp | 328 ++ .../boost/thread/win32/thread_heap_alloc.hpp | 409 ++ .../boost/thread/win32/thread_primitives.hpp | 669 +++ .../boost-1.60.0/boost/thread/with_lock_guard.hpp | 234 + .../boost-1.60.0/boost/thread/xtime.hpp | 93 + 161 files changed, 37372 insertions(+) create mode 100644 src/third_party/boost-1.60.0/boost/thread/barrier.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/caller_context.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/completion_latch.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/concurrent_queues/deque_adaptor.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/concurrent_queues/deque_base.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/concurrent_queues/deque_views.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/concurrent_queues/detail/sync_deque_base.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/concurrent_queues/detail/sync_queue_base.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/concurrent_queues/queue_adaptor.hpp create mode 100755 src/third_party/boost-1.60.0/boost/thread/concurrent_queues/queue_base.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/concurrent_queues/queue_op_status.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/concurrent_queues/queue_views.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_bounded_queue.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_deque.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_priority_queue.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_queue.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_timed_queue.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/condition.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/condition_variable.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/csbl/deque.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/csbl/devector.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/csbl/functional.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/csbl/list.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/csbl/memory.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/csbl/memory/allocator_arg.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/csbl/memory/allocator_traits.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/csbl/memory/config.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/csbl/memory/default_delete.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/csbl/memory/pointer_traits.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/csbl/memory/scoped_allocator.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/csbl/memory/shared_ptr.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/csbl/memory/unique_ptr.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/csbl/queue.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/csbl/tuple.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/csbl/vector.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/cv_status.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/detail/config.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/detail/counter.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/detail/delete.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/detail/force_cast.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/detail/function_wrapper.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/detail/invoke.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/detail/invoker.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/detail/is_convertible.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/detail/lockable_wrapper.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/detail/log.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/detail/make_tuple_indices.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/detail/memory.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/detail/move.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/detail/nullary_function.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/detail/platform.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/detail/singleton.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/detail/thread.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/detail/thread_group.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/detail/thread_heap_alloc.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/detail/thread_interruption.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/detail/tss_hooks.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/detail/variadic_footer.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/detail/variadic_header.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/exceptional_ptr.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/exceptions.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/executor.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/executors/basic_thread_pool.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/executors/detail/priority_executor_base.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/executors/detail/scheduled_executor_base.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/executors/executor.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/executors/executor_adaptor.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/executors/generic_executor_ref.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/executors/inline_executor.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/executors/loop_executor.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/executors/scheduled_thread_pool.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/executors/scheduler.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/executors/scheduling_adaptor.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/executors/serial_executor.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/executors/serial_executor_cont.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/executors/thread_executor.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/executors/work.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/experimental/config/inline_namespace.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/experimental/exception_list.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/experimental/parallel/v1/exception_list.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/experimental/parallel/v1/inline_namespace.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/experimental/parallel/v2/inline_namespace.hpp create mode 100755 src/third_party/boost-1.60.0/boost/thread/experimental/parallel/v2/task_region.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/experimental/task_region.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/externally_locked.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/externally_locked_stream.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/future.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/futures/future_error.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/futures/future_error_code.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/futures/future_status.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/futures/is_future_type.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/futures/launch.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/futures/wait_for_all.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/futures/wait_for_any.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/is_locked_by_this_thread.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/latch.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/lock_algorithms.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/lock_concepts.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/lock_factories.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/lock_guard.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/lock_options.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/lock_traits.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/lock_types.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/lockable_adapter.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/lockable_concepts.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/lockable_traits.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/locks.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/mutex.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/null_mutex.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/once.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/ostream_buffer.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/poly_lockable.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/poly_lockable_adapter.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/poly_shared_lockable.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/poly_shared_lockable_adapter.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/pthread/condition_variable.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/pthread/condition_variable_fwd.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/pthread/mutex.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/pthread/once.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/pthread/once_atomic.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/pthread/pthread_mutex_scoped_lock.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/pthread/recursive_mutex.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/pthread/shared_mutex.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/pthread/shared_mutex_assert.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/pthread/thread_data.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/pthread/thread_heap_alloc.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/pthread/timespec.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/recursive_mutex.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/reverse_lock.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/scoped_thread.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/shared_lock_guard.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/shared_mutex.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/strict_lock.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/sync_bounded_queue.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/sync_queue.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/synchronized_value.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/testable_mutex.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/thread.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/thread_functors.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/thread_guard.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/thread_only.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/thread_pool.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/thread_time.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/tss.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/user_scheduler.hpp create mode 100755 src/third_party/boost-1.60.0/boost/thread/v2/shared_mutex.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/v2/thread.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/win32/basic_recursive_mutex.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/win32/basic_timed_mutex.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/win32/condition_variable.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/win32/interlocked_read.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/win32/mfc_thread_init.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/win32/mutex.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/win32/once.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/win32/recursive_mutex.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/win32/shared_mutex.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/win32/thread_data.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/win32/thread_heap_alloc.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/win32/thread_primitives.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/with_lock_guard.hpp create mode 100644 src/third_party/boost-1.60.0/boost/thread/xtime.hpp (limited to 'src/third_party/boost-1.60.0/boost/thread') diff --git a/src/third_party/boost-1.60.0/boost/thread/barrier.hpp b/src/third_party/boost-1.60.0/boost/thread/barrier.hpp new file mode 100644 index 00000000000..47daf07b352 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/barrier.hpp @@ -0,0 +1,254 @@ +// Copyright (C) 2002-2003 +// David Moore, William E. Kempf +// Copyright (C) 2007-8 Anthony Williams +// (C) Copyright 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_BARRIER_JDM030602_HPP +#define BOOST_BARRIER_JDM030602_HPP + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost +{ + namespace thread_detail + { + typedef detail::nullary_function void_completion_function; + typedef detail::nullary_function size_completion_function; + + struct default_barrier_reseter + { + unsigned int size_; + default_barrier_reseter(unsigned int size) : + size_(size) + { + } + BOOST_THREAD_MOVABLE(default_barrier_reseter) + //BOOST_THREAD_COPYABLE_AND_MOVABLE(default_barrier_reseter) + + default_barrier_reseter(default_barrier_reseter const& other) BOOST_NOEXCEPT : + size_(other.size_) + { + } + default_barrier_reseter(BOOST_THREAD_RV_REF(default_barrier_reseter) other) BOOST_NOEXCEPT : + size_(BOOST_THREAD_RV(other).size_) + { + } + + unsigned int operator()() + { + return size_; + } + }; + + struct void_functor_barrier_reseter + { + unsigned int size_; + void_completion_function fct_; + template + void_functor_barrier_reseter(unsigned int size, BOOST_THREAD_RV_REF(F) funct) + : size_(size), fct_(boost::move(funct)) + {} + template + void_functor_barrier_reseter(unsigned int size, F& funct) + : size_(size), fct_(funct) + {} + + BOOST_THREAD_MOVABLE(void_functor_barrier_reseter) + //BOOST_THREAD_COPYABLE_AND_MOVABLE(void_functor_barrier_reseter) + + void_functor_barrier_reseter(void_functor_barrier_reseter const& other) BOOST_NOEXCEPT : + size_(other.size_), fct_(other.fct_) + { + } + void_functor_barrier_reseter(BOOST_THREAD_RV_REF(void_functor_barrier_reseter) other) BOOST_NOEXCEPT : + size_(BOOST_THREAD_RV(other).size_), fct_(BOOST_THREAD_RV(other).fct_) + //size_(BOOST_THREAD_RV(other).size_), fct_(boost::move(BOOST_THREAD_RV(other).fct_)) + { + } + + unsigned int operator()() + { + fct_(); + return size_; + } + }; + struct void_fct_ptr_barrier_reseter + { + unsigned int size_; + void(*fct_)(); + void_fct_ptr_barrier_reseter(unsigned int size, void(*funct)()) : + size_(size), fct_(funct) + { + } + BOOST_THREAD_MOVABLE(void_fct_ptr_barrier_reseter) + //BOOST_THREAD_COPYABLE_AND_MOVABLE(void_fct_ptr_barrier_reseter) + + void_fct_ptr_barrier_reseter(void_fct_ptr_barrier_reseter const& other) BOOST_NOEXCEPT : + size_(other.size_), fct_(other.fct_) + { + } + void_fct_ptr_barrier_reseter(BOOST_THREAD_RV_REF(void_fct_ptr_barrier_reseter) other) BOOST_NOEXCEPT : + size_(BOOST_THREAD_RV(other).size_), fct_(BOOST_THREAD_RV(other).fct_) + { + } + unsigned int operator()() + { + fct_(); + return size_; + } + }; + } + //BOOST_THREAD_DCL_MOVABLE(thread_detail::default_barrier_reseter) + //BOOST_THREAD_DCL_MOVABLE(thread_detail::void_functor_barrier_reseter) + //BOOST_THREAD_DCL_MOVABLE(thread_detail::void_fct_ptr_barrier_reseter) + + class barrier + { + static inline unsigned int check_counter(unsigned int count) + { + if (count == 0) boost::throw_exception( + thread_exception(system::errc::invalid_argument, "barrier constructor: count cannot be zero.")); + return count; + } + struct dummy + { + }; + + public: + BOOST_THREAD_NO_COPYABLE( barrier) + + explicit barrier(unsigned int count) : + m_count(check_counter(count)), m_generation(0), fct_(BOOST_THREAD_MAKE_RV_REF(thread_detail::default_barrier_reseter(count))) + { + } + + template + barrier( + unsigned int count, + BOOST_THREAD_RV_REF(F) funct, + typename enable_if< + typename is_void::type>::type, dummy* + >::type=0 + ) + : m_count(check_counter(count)), + m_generation(0), + fct_(BOOST_THREAD_MAKE_RV_REF(thread_detail::void_functor_barrier_reseter(count, + boost::move(funct))) + ) + { + } + template + barrier( + unsigned int count, + F &funct, + typename enable_if< + typename is_void::type>::type, dummy* + >::type=0 + ) + : m_count(check_counter(count)), + m_generation(0), + fct_(BOOST_THREAD_MAKE_RV_REF(thread_detail::void_functor_barrier_reseter(count, + funct)) + ) + { + } + + template + barrier( + unsigned int count, + BOOST_THREAD_RV_REF(F) funct, + typename enable_if< + typename is_same::type, unsigned int>::type, dummy* + >::type=0 + ) + : m_count(check_counter(count)), + m_generation(0), + fct_(boost::move(funct)) + { + } + template + barrier( + unsigned int count, + F& funct, + typename enable_if< + typename is_same::type, unsigned int>::type, dummy* + >::type=0 + ) + : m_count(check_counter(count)), + m_generation(0), + fct_(funct) + { + } + + barrier(unsigned int count, void(*funct)()) : + m_count(check_counter(count)), m_generation(0), + fct_(funct + ? BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(BOOST_THREAD_MAKE_RV_REF(thread_detail::void_fct_ptr_barrier_reseter(count, funct)))) + : BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(BOOST_THREAD_MAKE_RV_REF(thread_detail::default_barrier_reseter(count)))) + ) + { + } + barrier(unsigned int count, unsigned int(*funct)()) : + m_count(check_counter(count)), m_generation(0), + fct_(funct + ? BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(funct)) + : BOOST_THREAD_MAKE_RV_REF(thread_detail::size_completion_function(BOOST_THREAD_MAKE_RV_REF(thread_detail::default_barrier_reseter(count)))) + ) + { + } + + bool wait() + { + boost::unique_lock < boost::mutex > lock(m_mutex); + unsigned int gen = m_generation; + + if (--m_count == 0) + { + m_generation++; + m_count = static_cast(fct_()); + BOOST_ASSERT(m_count != 0); + m_cond.notify_all(); + return true; + } + + while (gen == m_generation) + m_cond.wait(lock); + return false; + } + + void count_down_and_wait() + { + wait(); + } + + private: + mutex m_mutex; + condition_variable m_cond; + unsigned int m_count; + unsigned int m_generation; + thread_detail::size_completion_function fct_; + }; + +} // namespace boost + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/caller_context.hpp b/src/third_party/boost-1.60.0/boost/thread/caller_context.hpp new file mode 100644 index 00000000000..dc50a05f975 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/caller_context.hpp @@ -0,0 +1,59 @@ +// (C) Copyright 2013,2015 Vicente J. Botet Escriba +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#ifndef BOOST_THREAD_CALL_CONTEXT_HPP +#define BOOST_THREAD_CALL_CONTEXT_HPP + +#include +#if defined BOOST_THREAD_USES_LOG_THREAD_ID +#include +#endif +#include +#include +#include + +#include + +namespace boost +{ + + struct caller_context_t + { + const char * filename; + unsigned lineno; + const char * func; + caller_context_t(const char * filename, unsigned lineno, const char * func) : + filename(filename), lineno(lineno), func(func) + { + } + }; + +#define BOOST_CONTEXTOF boost::caller_context_t(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION) + + template + OStream& operator<<(OStream& os, caller_context_t const& ctx) + { +#if defined BOOST_THREAD_USES_LOG_THREAD_ID + { + io::ios_flags_saver ifs( os ); + os << std::left << std::setw(14) << boost::this_thread::get_id() << " "; + } +#endif + { + io::ios_flags_saver ifs(os); + os << std::setw(50) << ctx.filename << "[" + << std::setw(4) << std::right << std::dec<< ctx.lineno << "] "; +#if defined BOOST_THREAD_USES_LOG_CURRENT_FUNCTION + os << ctx.func << " " ; +#endif + } + return os; + } +} + +#include + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/completion_latch.hpp b/src/third_party/boost-1.60.0/boost/thread/completion_latch.hpp new file mode 100644 index 00000000000..ea76474276c --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/completion_latch.hpp @@ -0,0 +1,226 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2013 Vicente J. Botet Escriba + +#ifndef BOOST_THREAD_COMPLETION_LATCH_HPP +#define BOOST_THREAD_COMPLETION_LATCH_HPP + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +//#include +#include + +#include + +namespace boost +{ + namespace thread_detail + { + void noop() + { + } + } + class completion_latch + { + public: + /// the implementation defined completion function type + //typedef detail::nullary_function completion_function; + typedef csbl::function completion_function; + /// noop completion function factory + static completion_function noop() + { + return completion_function(&thread_detail::noop); + } + + private: + struct around_wait; + friend struct around_wait; + struct around_wait + { + completion_latch &that_; + boost::unique_lock &lk_; + around_wait(completion_latch &that, boost::unique_lock &lk) + : that_(that), lk_(lk) + { + that_.leavers_.cond_.wait(lk, detail::counter_is_zero(that_.leavers_)); + that_.waiters_.inc_and_notify_all(); + that_.leavers_.cond_.wait(lk, detail::counter_is_not_zero(that_.leavers_)); + } + ~around_wait() + { + that_.waiters_.dec_and_notify_all(); + } + }; + + bool count_down(unique_lock &lk) + { + BOOST_ASSERT(count_ > 0); + if (--count_ == 0) + { + waiters_.cond_.wait(lk, detail::counter_is_not_zero(waiters_)); + leavers_.assign_and_notify_all(waiters_); + count_.cond_.notify_all(); + waiters_.cond_.wait(lk, detail::counter_is_zero(waiters_)); + leavers_.assign_and_notify_all(0); + lk.unlock(); + funct_(); + return true; + } + return false; + } + + public: + BOOST_THREAD_NO_COPYABLE( completion_latch ) + + /// Constructs a latch with a given count. + completion_latch(std::size_t count) : + count_(count), funct_(noop()), waiters_(0), leavers_(0) + { + } + + /// Constructs a latch with a given count and a completion function. + template + completion_latch(std::size_t count, BOOST_THREAD_RV_REF(F) funct) : + count_(count), + funct_(boost::move(funct)), + waiters_(0), + leavers_(0) + { + } + template + completion_latch(std::size_t count, void(*funct)()) : + count_(count), funct_(funct), waiters_(0), leavers_(0) + { + } + + /// + ~completion_latch() + { + } + + /// Blocks until the latch has counted down to zero. + void wait() + { + boost::unique_lock lk(mutex_); + around_wait aw(*this, lk); + count_.cond_.wait(lk, detail::counter_is_zero(count_)); + } + + /// @return true if the internal counter is already 0, false otherwise + bool try_wait() + { + boost::unique_lock lk(mutex_); + around_wait aw(*this, lk); + return (count_ == 0); + } + + /// try to wait for a specified amount of time + /// @return whether there is a timeout or not. + template + cv_status wait_for(const chrono::duration& rel_time) + { + boost::unique_lock lk(mutex_); + around_wait aw(*this, lk); + return count_.cond_.wait_for(lk, rel_time, detail::counter_is_zero(count_)) + ? cv_status::no_timeout + : cv_status::timeout; + } + + /// try to wait until the specified time_point is reached + /// @return whether there is a timeout or not. + template + cv_status wait_until(const chrono::time_point& abs_time) + { + boost::unique_lock lk(mutex_); + around_wait aw(*this, lk); + return count_.cond_.wait_until(lk, abs_time, detail::counter_is_zero(count_)) + ? cv_status::no_timeout + : cv_status::timeout; + } + + /// Decrement the count and notify anyone waiting if we reach zero. + /// @Requires count must be greater than 0 + void count_down() + { + unique_lock lk(mutex_); + count_down(lk); + } + void signal() + { + count_down(); + } + + /// Decrement the count and notify anyone waiting if we reach zero. + /// Blocks until the latch has counted down to zero. + /// @Requires count must be greater than 0 + void count_down_and_wait() + { + boost::unique_lock lk(mutex_); + if (count_down(lk)) + { + return; + } + around_wait aw(*this, lk); + count_.cond_.wait(lk, detail::counter_is_zero(count_)); + } + void sync() + { + count_down_and_wait(); + } + + /// Reset the counter + /// #Requires This method may only be invoked when there are no other threads currently inside the count_down_and_wait() method. + void reset(std::size_t count) + { + boost::lock_guard lk(mutex_); + //BOOST_ASSERT(count_ == 0); + count_ = count; + } + + /// Resets the latch with the new completion function. + /// The next time the internal count reaches 0, this function will be invoked. + /// This completion function may only be invoked when there are no other threads + /// currently inside the count_down and wait related functions. + /// It may also be invoked from within the registered completion function. + /// @Returns the old completion function if any or noop if + +#ifdef BOOST_NO_CXX11_HDR_FUNCTIONAL + template + completion_function then(BOOST_THREAD_RV_REF(F) funct) + { + boost::lock_guard lk(mutex_); + completion_function tmp(funct_); + funct_ = boost::move(funct); + return tmp; + } +#endif + completion_function then(void(*funct)()) + { + boost::lock_guard lk(mutex_); + completion_function tmp(funct_); + funct_ = completion_function(funct); + return tmp; + } + + private: + mutex mutex_; + detail::counter count_; + completion_function funct_; + detail::counter waiters_; + detail::counter leavers_; + }; + +} // namespace boost + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/deque_adaptor.hpp b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/deque_adaptor.hpp new file mode 100644 index 00000000000..a8f45f863f4 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/deque_adaptor.hpp @@ -0,0 +1,209 @@ +#ifndef BOOST_THREAD_CONCURRENT_DEQUE_ADAPTOR_HPP +#define BOOST_THREAD_CONCURRENT_DEQUE_ADAPTOR_HPP + +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Vicente J. Botet Escriba 2014. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +#include + +namespace boost +{ +namespace concurrent +{ +namespace detail +{ + + template + class deque_adaptor_copyable_only : + public boost::deque_base + { + Queue queue; + public: + typedef typename Queue::value_type value_type; + typedef typename Queue::size_type size_type; + + // Constructors/Assignment/Destructors + deque_adaptor_copyable_only() {} + + // Observers + bool empty() const { return queue.empty(); } + bool full() const { return queue.full(); } + size_type size() const { return queue.size(); } + bool closed() const { return queue.closed(); } + + // Modifiers + void close() { queue.close(); } + + void push_back(const value_type& x) { queue.push_back(x); } + + void pull_front(value_type& x) { queue.pull_front(x); }; + value_type pull_front() { return queue.pull_front(); } + + queue_op_status try_push_back(const value_type& x) { return queue.try_push_back(x); } + queue_op_status try_pull_front(value_type& x) { return queue.try_pull_front(x); } + + queue_op_status nonblocking_push_back(const value_type& x) { return queue.nonblocking_push_back(x); } + queue_op_status nonblocking_pull_front(value_type& x) { return queue.nonblocking_pull_front(x); } + + queue_op_status wait_push_back(const value_type& x) { return queue.wait_push_back(x); } + queue_op_status wait_pull_front(value_type& x) { return queue.wait_pull_front(x); } + + }; + template + class deque_adaptor_movable_only : + public boost::deque_base + { + Queue queue; + public: + typedef typename Queue::value_type value_type; + typedef typename Queue::size_type size_type; + + // Constructors/Assignment/Destructors + + deque_adaptor_movable_only() {} + + // Observers + bool empty() const { return queue.empty(); } + bool full() const { return queue.full(); } + size_type size() const { return queue.size(); } + bool closed() const { return queue.closed(); } + + // Modifiers + void close() { queue.close(); } + + + void pull_front(value_type& x) { queue.pull_front(x); }; + // enable_if is_nothrow_copy_movable + value_type pull_front() { return queue.pull_front(); } + + queue_op_status try_pull_front(value_type& x) { return queue.try_pull_front(x); } + + queue_op_status nonblocking_pull_front(value_type& x) { return queue.nonblocking_pull_front(x); } + + queue_op_status wait_pull_front(value_type& x) { return queue.wait_pull_front(x); } + + void push_back(BOOST_THREAD_RV_REF(value_type) x) { queue.push_back(boost::move(x)); } + queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.try_push_back(boost::move(x)); } + queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.nonblocking_push_back(boost::move(x)); } + queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.wait_push_back(boost::move(x)); } + }; + + template + class deque_adaptor_copyable_and_movable : + public boost::deque_base + { + Queue queue; + public: + typedef typename Queue::value_type value_type; + typedef typename Queue::size_type size_type; + + // Constructors/Assignment/Destructors + + deque_adaptor_copyable_and_movable() {} + + // Observers + bool empty() const { return queue.empty(); } + bool full() const { return queue.full(); } + size_type size() const { return queue.size(); } + bool closed() const { return queue.closed(); } + + // Modifiers + void close() { queue.close(); } + + + void push_back(const value_type& x) { queue.push_back(x); } + + void pull_front(value_type& x) { queue.pull_front(x); }; + // enable_if is_nothrow_copy_movable + value_type pull_front() { return queue.pull_front(); } + + queue_op_status try_push_back(const value_type& x) { return queue.try_push_back(x); } + queue_op_status try_pull_front(value_type& x) { return queue.try_pull_front(x); } + + queue_op_status nonblocking_push_back(const value_type& x) { return queue.nonblocking_push_back(x); } + queue_op_status nonblocking_pull_front(value_type& x) { return queue.nonblocking_pull_front(x); } + + queue_op_status wait_push_back(const value_type& x) { return queue.wait_push_back(x); } + queue_op_status wait_pull_front(value_type& x) { return queue.wait_pull_front(x); } + + void push_back(BOOST_THREAD_RV_REF(value_type) x) { queue.push_back(boost::move(x)); } + queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.try_push_back(boost::move(x)); } + queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.nonblocking_push_back(boost::move(x)); } + queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) { return queue.wait_push_back(boost::move(x)); } + }; + + + template ::value, + bool Movable = true +#else + bool Copyable = std::is_copy_constructible::value && std::is_copy_assignable::value, + bool Movable = std::is_move_constructible::value && std::is_move_assignable::value +#endif // __GNUC__ +#elif defined _MSC_VER +#if _MSC_VER < 1700 + bool Copyable = is_copy_constructible::value, + bool Movable = true +#else + bool Copyable = std::is_copy_constructible::value && std::is_copy_assignable::value, + bool Movable = std::is_move_constructible::value && std::is_move_assignable::value +#endif // _MSC_VER +#else + bool Copyable = std::is_copy_constructible::value && std::is_copy_assignable::value, + bool Movable = std::is_move_constructible::value && std::is_move_assignable::value +#endif +#else + bool Copyable = is_copy_constructible::value, + bool Movable = has_move_emulation_enabled::value +#endif + > + struct deque_adaptor; + + template + struct deque_adaptor { + typedef deque_adaptor_copyable_and_movable type; + }; + template + struct deque_adaptor { + typedef deque_adaptor_copyable_only type; + }; + template + struct deque_adaptor { + typedef deque_adaptor_movable_only type; + }; + +} + + template + class deque_adaptor : + public detail::deque_adaptor::type + { + public: + typedef typename Queue::value_type value_type; + typedef typename Queue::size_type size_type; + // Constructors/Assignment/Destructors + virtual ~deque_adaptor() {}; + }; +} +using concurrent::deque_adaptor; + +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/deque_base.hpp b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/deque_base.hpp new file mode 100644 index 00000000000..f76e8a761dd --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/deque_base.hpp @@ -0,0 +1,202 @@ +#ifndef BOOST_THREAD_CONCURRENT_DEQUE_BASE_HPP +#define BOOST_THREAD_CONCURRENT_DEQUE_BASE_HPP + +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Vicente J. Botet Escriba 2014. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include + + +#include + +namespace boost +{ +namespace concurrent +{ +namespace detail +{ + + template + class deque_base_copyable_only + { + public: + typedef ValueType value_type; + typedef SizeType size_type; + + // Constructors/Assignment/Destructors + virtual ~deque_base_copyable_only() {}; + + // Observers + virtual bool empty() const = 0; + virtual bool full() const = 0; + virtual size_type size() const = 0; + virtual bool closed() const = 0; + + // Modifiers + virtual void close() = 0; + + virtual void push_back(const value_type& x) = 0; + + virtual void pull_front(value_type&) = 0; + virtual value_type pull_front() = 0; + + virtual queue_op_status try_push_back(const value_type& x) = 0; + virtual queue_op_status try_pull_front(value_type&) = 0; + + virtual queue_op_status nonblocking_push_back(const value_type& x) = 0; + virtual queue_op_status nonblocking_pull_front(value_type&) = 0; + + virtual queue_op_status wait_push_back(const value_type& x) = 0; + virtual queue_op_status wait_pull_front(value_type& elem) = 0; + + }; + + template + class deque_base_movable_only + { + public: + typedef ValueType value_type; + typedef SizeType size_type; + // Constructors/Assignment/Destructors + virtual ~deque_base_movable_only() {}; + + // Observers + virtual bool empty() const = 0; + virtual bool full() const = 0; + virtual size_type size() const = 0; + virtual bool closed() const = 0; + + // Modifiers + virtual void close() = 0; + + virtual void pull_front(value_type&) = 0; + // enable_if is_nothrow_movable + virtual value_type pull_front() = 0; + + virtual queue_op_status try_pull_front(value_type&) = 0; + + virtual queue_op_status nonblocking_pull_front(value_type&) = 0; + + virtual queue_op_status wait_pull_front(value_type& elem) = 0; + + virtual void push_back(BOOST_THREAD_RV_REF(value_type) x) = 0; + virtual queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0; + virtual queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0; + virtual queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0; + }; + + + template + class deque_base_copyable_and_movable + { + public: + typedef ValueType value_type; + typedef SizeType size_type; + // Constructors/Assignment/Destructors + virtual ~deque_base_copyable_and_movable() {}; + + + // Observers + virtual bool empty() const = 0; + virtual bool full() const = 0; + virtual size_type size() const = 0; + virtual bool closed() const = 0; + + // Modifiers + virtual void close() = 0; + + virtual void push_back(const value_type& x) = 0; + + virtual void pull_front(value_type&) = 0; + // enable_if is_nothrow_copy_movable + virtual value_type pull_front() = 0; + + virtual queue_op_status try_push_back(const value_type& x) = 0; + virtual queue_op_status try_pull_front(value_type&) = 0; + + virtual queue_op_status nonblocking_push_back(const value_type& x) = 0; + virtual queue_op_status nonblocking_pull_front(value_type&) = 0; + + virtual queue_op_status wait_push_back(const value_type& x) = 0; + virtual queue_op_status wait_pull_front(value_type& elem) = 0; + + virtual void push_back(BOOST_THREAD_RV_REF(value_type) x) = 0; + virtual queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0; + virtual queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0; + virtual queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x) = 0; + }; + + template ::value, + bool Movable = true +#else + bool Copyable = std::is_copy_constructible::value && std::is_copy_assignable::value, + bool Movable = std::is_move_constructible::value && std::is_move_assignable::value +#endif // __GNUC__ +#elif defined _MSC_VER +#if _MSC_VER < 1700 + bool Copyable = is_copy_constructible::value, + bool Movable = true +#else + bool Copyable = std::is_copy_constructible::value && std::is_copy_assignable::value, + bool Movable = std::is_move_constructible::value && std::is_move_assignable::value +#endif // _MSC_VER +#else + bool Copyable = std::is_copy_constructible::value && std::is_copy_assignable::value, + bool Movable = std::is_move_constructible::value && std::is_move_assignable::value +#endif +#else + bool Copyable = is_copy_constructible::value, + bool Movable = has_move_emulation_enabled::value +#endif + > + struct deque_base; + + template + struct deque_base { + typedef deque_base_copyable_and_movable type; + }; + template + struct deque_base { + typedef deque_base_copyable_only type; + }; + template + struct deque_base { + typedef deque_base_movable_only type; + }; + +} + + template + class deque_base : + public detail::deque_base::type + { + public: + typedef ValueType value_type; + typedef SizeType size_type; + // Constructors/Assignment/Destructors + virtual ~deque_base() {}; + }; + +} +using concurrent::deque_base; + +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/deque_views.hpp b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/deque_views.hpp new file mode 100644 index 00000000000..5715fb88cff --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/deque_views.hpp @@ -0,0 +1,165 @@ +#ifndef BOOST_THREAD_QUEUE_VIEWS_HPP +#define BOOST_THREAD_QUEUE_VIEWS_HPP + +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Vicente J. Botet Escriba 2014. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +#include + +namespace boost +{ +namespace concurrent +{ + + template + class deque_back_view + { + Queue* queue; + public: + typedef typename Queue::value_type value_type; + typedef typename Queue::size_type size_type; + + // Constructors/Assignment/Destructors + deque_back_view(Queue& q) BOOST_NOEXCEPT : queue(&q) {} + + // Observers + bool empty() const { return queue->empty(); } + bool full() const { return queue->full(); } + size_type size() const { return queue->size(); } + bool closed() const { return queue->closed(); } + + // Modifiers + void close() { queue->close(); } + + void push(const value_type& x) { queue->push_back(x); } + + void pull(value_type& x) { queue->pull_back(x); } + // enable_if is_nothrow_copy_movable + value_type pull() { return queue->pull_back(); } + + queue_op_status try_push(const value_type& x) { return queue->try_push_back(x); } + + queue_op_status try_pull(value_type& x) { return queue->try_pull_back(x); } + + queue_op_status nonblocking_push(const value_type& x) { return queue->nonblocking_push_back(x); } + + queue_op_status nonblocking_pull(value_type& x) { return queue->nonblocking_pull_back(x); } + + queue_op_status wait_push(const value_type& x) { return queue->wait_push_back(x); } + queue_op_status wait_pull(value_type& x) { return queue->wait_pull_back(x); } + + void push(BOOST_THREAD_RV_REF(value_type) x) { queue->push_back(boost::move(x)); } + queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->try_push_back(boost::move(x)); } + queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->nonblocking_push_back(boost::move(x)); } + queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->wait_push_back(boost::move(x)); } + }; + + template + class deque_front_view + { + Queue* queue; + public: + typedef typename Queue::value_type value_type; + typedef typename Queue::size_type size_type; + + // Constructors/Assignment/Destructors + deque_front_view(Queue& q) BOOST_NOEXCEPT : queue(&q) {} + + // Observers + bool empty() const { return queue->empty(); } + bool full() const { return queue->full(); } + size_type size() const { return queue->size(); } + bool closed() const { return queue->closed(); } + + // Modifiers + void close() { queue->close(); } + + void push(const value_type& x) { queue->push_front(x); } + + void pull(value_type& x) { queue->pull_front(x); }; + // enable_if is_nothrow_copy_movable + value_type pull() { return queue->pull_front(); } + + queue_op_status try_push(const value_type& x) { return queue->try_push_front(x); } + + queue_op_status try_pull(value_type& x) { return queue->try_pull_front(x); } + + queue_op_status nonblocking_push(const value_type& x) { return queue->nonblocking_push_front(x); } + + queue_op_status nonblocking_pull(value_type& x) { return queue->nonblocking_pull_front(x); } + + queue_op_status wait_push(const value_type& x) { return queue->wait_push_front(x); } + queue_op_status wait_pull(value_type& x) { return queue->wait_pull_front(x); } + void push(BOOST_THREAD_RV_REF(value_type) x) { queue->push_front(forward(x)); } + queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->try_push_front(forward(x)); } + queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->nonblocking_push_front(forward(x)); } + queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->wait_push_front(forward(x)); } + + }; + +#if ! defined BOOST_NO_CXX11_TEMPLATE_ALIASES + + template + using deque_back = deque_back_view > ; + template + using deque_front = deque_front_view > ; + +#else + + template + struct deque_back : deque_back_view > + { + typedef deque_back_view > base_type; + deque_back(deque_base& q) BOOST_NOEXCEPT : base_type(q) {} + }; + template + struct deque_front : deque_front_view > + { + typedef deque_front_view > base_type; + deque_front(deque_base& q) BOOST_NOEXCEPT : base_type(q) {} + + }; + +#endif + +// template +// deque_back_view back(Queue & q) { return deque_back_view(q); } +// template +// deque_front_view front(Queue & q) { return deque_front_view(q); } +//#if 0 +// template +// deque_back back(deque_base & q) { return deque_back(q); } +// template +// deque_front front(deque_base & q) { return deque_front(q); } +//#else +// template +// typename deque_back::type back(deque_base & q) { return typename deque_back::type(q); } +// template +// typename deque_front::type front(deque_base & q) { return typename deque_front::type(q); } +//#endif +} + +using concurrent::deque_back_view; +using concurrent::deque_front_view; +using concurrent::deque_back; +using concurrent::deque_front; +//using concurrent::back; +//using concurrent::front; + +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/detail/sync_deque_base.hpp b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/detail/sync_deque_base.hpp new file mode 100644 index 00000000000..877e1e2eb40 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/detail/sync_deque_base.hpp @@ -0,0 +1,223 @@ +#ifndef BOOST_THREAD_CONCURRENT_QUEUES_DETAIL_SYNC_DEQUE_BASE_HPP +#define BOOST_THREAD_CONCURRENT_QUEUES_DETAIL_SYNC_DEQUE_BASE_HPP + +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Vicente J. Botet Escriba 2013-2014. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +namespace boost +{ +namespace concurrent +{ +namespace detail +{ + + template + class sync_deque_base + { + public: + typedef ValueType value_type; + typedef Queue underlying_queue_type; + typedef typename Queue::size_type size_type; + typedef queue_op_status op_status; + + typedef typename chrono::steady_clock clock; + typedef typename clock::duration duration; + typedef typename clock::time_point time_point; + + // Constructors/Assignment/Destructors + BOOST_THREAD_NO_COPYABLE(sync_deque_base) + inline sync_deque_base(); + //template + //inline explicit sync_deque(Range range); + inline ~sync_deque_base(); + + // Observers + inline bool empty() const; + inline bool full() const; + inline size_type size() const; + inline bool closed() const; + + // Modifiers + inline void close(); + + inline underlying_queue_type underlying_queue() { + lock_guard lk(mtx_); + return boost::move(data_); + } + + protected: + mutable mutex mtx_; + condition_variable not_empty_; + underlying_queue_type data_; + bool closed_; + + inline bool empty(unique_lock& ) const BOOST_NOEXCEPT + { + return data_.empty(); + } + inline bool empty(lock_guard& ) const BOOST_NOEXCEPT + { + return data_.empty(); + } + + inline size_type size(lock_guard& ) const BOOST_NOEXCEPT + { + return data_.size(); + } + inline bool closed(unique_lock& lk) const; + inline bool closed(lock_guard& lk) const; + + inline void throw_if_closed(unique_lock&); + inline void throw_if_closed(lock_guard&); + + inline void wait_until_not_empty(unique_lock& lk); + inline bool wait_until_not_empty_or_closed(unique_lock& lk); + inline queue_op_status wait_until_not_empty_until(unique_lock& lk, time_point const&); + + inline void notify_not_empty_if_needed(unique_lock& ) + { + not_empty_.notify_one(); + } + inline void notify_not_empty_if_needed(lock_guard& ) + { + not_empty_.notify_one(); + } + + }; + + template + sync_deque_base::sync_deque_base() : + data_(), closed_(false) + { + BOOST_ASSERT(data_.empty()); + } + + template + sync_deque_base::~sync_deque_base() + { + } + + template + void sync_deque_base::close() + { + { + lock_guard lk(mtx_); + closed_ = true; + } + not_empty_.notify_all(); + } + + template + bool sync_deque_base::closed() const + { + lock_guard lk(mtx_); + return closed(lk); + } + template + bool sync_deque_base::closed(unique_lock&) const + { + return closed_; + } + template + bool sync_deque_base::closed(lock_guard&) const + { + return closed_; + } + + template + bool sync_deque_base::empty() const + { + lock_guard lk(mtx_); + return empty(lk); + } + template + bool sync_deque_base::full() const + { + return false; + } + + template + typename sync_deque_base::size_type sync_deque_base::size() const + { + lock_guard lk(mtx_); + return size(lk); + } + + template + void sync_deque_base::throw_if_closed(unique_lock& lk) + { + if (closed(lk)) + { + BOOST_THROW_EXCEPTION( sync_deque_is_closed() ); + } + } + template + void sync_deque_base::throw_if_closed(lock_guard& lk) + { + if (closed(lk)) + { + BOOST_THROW_EXCEPTION( sync_deque_is_closed() ); + } + } + + template + void sync_deque_base::wait_until_not_empty(unique_lock& lk) + { + for (;;) + { + if (! empty(lk)) break; + throw_if_closed(lk); + not_empty_.wait(lk); + } + } + template + bool sync_deque_base::wait_until_not_empty_or_closed(unique_lock& lk) + { + for (;;) + { + if (! empty(lk)) break; + if (closed(lk)) return true; + not_empty_.wait(lk); + } + return false; + } + + template + queue_op_status sync_deque_base::wait_until_not_empty_until(unique_lock& lk, time_point const&tp) + { + for (;;) + { + if (! empty(lk)) return queue_op_status::success; + throw_if_closed(lk); + if (not_empty_.wait_until(lk, tp) == cv_status::timeout ) return queue_op_status::timeout; + } + } + + +} // detail +} // concurrent +} // boost + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/detail/sync_queue_base.hpp b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/detail/sync_queue_base.hpp new file mode 100644 index 00000000000..653e273f8b8 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/detail/sync_queue_base.hpp @@ -0,0 +1,223 @@ +#ifndef BOOST_THREAD_CONCURRENT_QUEUES_DETAIL_SYNC_QUEUE_BASE_HPP +#define BOOST_THREAD_CONCURRENT_QUEUES_DETAIL_SYNC_QUEUE_BASE_HPP + +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Vicente J. Botet Escriba 2013-2014. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +namespace boost +{ +namespace concurrent +{ +namespace detail +{ + + template + class sync_queue_base + { + public: + typedef ValueType value_type; + typedef Queue underlying_queue_type; + typedef typename Queue::size_type size_type; + typedef queue_op_status op_status; + + typedef typename chrono::steady_clock clock; + typedef typename clock::duration duration; + typedef typename clock::time_point time_point; + + // Constructors/Assignment/Destructors + BOOST_THREAD_NO_COPYABLE(sync_queue_base) + inline sync_queue_base(); + //template + //inline explicit sync_queue(Range range); + inline ~sync_queue_base(); + + // Observers + inline bool empty() const; + inline bool full() const; + inline size_type size() const; + inline bool closed() const; + + // Modifiers + inline void close(); + + inline underlying_queue_type underlying_queue() { + lock_guard lk(mtx_); + return boost::move(data_); + } + + protected: + mutable mutex mtx_; + condition_variable not_empty_; + underlying_queue_type data_; + bool closed_; + + inline bool empty(unique_lock& ) const BOOST_NOEXCEPT + { + return data_.empty(); + } + inline bool empty(lock_guard& ) const BOOST_NOEXCEPT + { + return data_.empty(); + } + + inline size_type size(lock_guard& ) const BOOST_NOEXCEPT + { + return data_.size(); + } + inline bool closed(unique_lock& lk) const; + inline bool closed(lock_guard& lk) const; + + inline void throw_if_closed(unique_lock&); + inline void throw_if_closed(lock_guard&); + + inline void wait_until_not_empty(unique_lock& lk); + inline bool wait_until_not_empty_or_closed(unique_lock& lk); + inline queue_op_status wait_until_not_empty_until(unique_lock& lk, time_point const&); + + inline void notify_not_empty_if_needed(unique_lock& ) + { + not_empty_.notify_one(); + } + inline void notify_not_empty_if_needed(lock_guard& ) + { + not_empty_.notify_one(); + } + + }; + + template + sync_queue_base::sync_queue_base() : + data_(), closed_(false) + { + BOOST_ASSERT(data_.empty()); + } + + template + sync_queue_base::~sync_queue_base() + { + } + + template + void sync_queue_base::close() + { + { + lock_guard lk(mtx_); + closed_ = true; + } + not_empty_.notify_all(); + } + + template + bool sync_queue_base::closed() const + { + lock_guard lk(mtx_); + return closed(lk); + } + template + bool sync_queue_base::closed(unique_lock&) const + { + return closed_; + } + template + bool sync_queue_base::closed(lock_guard&) const + { + return closed_; + } + + template + bool sync_queue_base::empty() const + { + lock_guard lk(mtx_); + return empty(lk); + } + template + bool sync_queue_base::full() const + { + return false; + } + + template + typename sync_queue_base::size_type sync_queue_base::size() const + { + lock_guard lk(mtx_); + return size(lk); + } + + template + void sync_queue_base::throw_if_closed(unique_lock& lk) + { + if (closed(lk)) + { + BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); + } + } + template + void sync_queue_base::throw_if_closed(lock_guard& lk) + { + if (closed(lk)) + { + BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); + } + } + + template + void sync_queue_base::wait_until_not_empty(unique_lock& lk) + { + for (;;) + { + if (! empty(lk)) break; + throw_if_closed(lk); + not_empty_.wait(lk); + } + } + template + bool sync_queue_base::wait_until_not_empty_or_closed(unique_lock& lk) + { + for (;;) + { + if (! empty(lk)) break; + if (closed(lk)) return true; + not_empty_.wait(lk); + } + return false; + } + + template + queue_op_status sync_queue_base::wait_until_not_empty_until(unique_lock& lk, time_point const&tp) + { + for (;;) + { + if (! empty(lk)) return queue_op_status::success; + throw_if_closed(lk); + if (not_empty_.wait_until(lk, tp) == cv_status::timeout ) return queue_op_status::timeout; + } + } + + +} // detail +} // concurrent +} // boost + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/queue_adaptor.hpp b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/queue_adaptor.hpp new file mode 100644 index 00000000000..f04e0354f75 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/queue_adaptor.hpp @@ -0,0 +1,209 @@ +#ifndef BOOST_THREAD_QUEUE_ADAPTOR_HPP +#define BOOST_THREAD_QUEUE_ADAPTOR_HPP + +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Vicente J. Botet Escriba 2014. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +#include + +namespace boost +{ +namespace concurrent +{ +namespace detail +{ + + template + class queue_adaptor_copyable_only : + public boost::queue_base + { + Queue queue; + public: + typedef typename Queue::value_type value_type; + typedef typename Queue::size_type size_type; + + // Constructors/Assignment/Destructors + queue_adaptor_copyable_only() {} + + // Observers + bool empty() const { return queue.empty(); } + bool full() const { return queue.full(); } + size_type size() const { return queue.size(); } + bool closed() const { return queue.closed(); } + + // Modifiers + void close() { queue.close(); } + + void push(const value_type& x) { queue.push(x); } + + void pull(value_type& x) { queue.pull(x); }; + value_type pull() { return queue.pull(); } + + queue_op_status try_push(const value_type& x) { return queue.try_push(x); } + queue_op_status try_pull(value_type& x) { return queue.try_pull(x); } + + queue_op_status nonblocking_push(const value_type& x) { return queue.nonblocking_push(x); } + queue_op_status nonblocking_pull(value_type& x) { return queue.nonblocking_pull(x); } + + queue_op_status wait_push(const value_type& x) { return queue.wait_push(x); } + queue_op_status wait_pull(value_type& x) { return queue.wait_pull(x); } + + }; + template + class queue_adaptor_movable_only : + public boost::queue_base + { + Queue queue; + public: + typedef typename Queue::value_type value_type; + typedef typename Queue::size_type size_type; + + // Constructors/Assignment/Destructors + + queue_adaptor_movable_only() {} + + // Observers + bool empty() const { return queue.empty(); } + bool full() const { return queue.full(); } + size_type size() const { return queue.size(); } + bool closed() const { return queue.closed(); } + + // Modifiers + void close() { queue.close(); } + + + void pull(value_type& x) { queue.pull(x); }; + // enable_if is_nothrow_copy_movable + value_type pull() { return queue.pull(); } + + queue_op_status try_pull(value_type& x) { return queue.try_pull(x); } + + queue_op_status nonblocking_pull(value_type& x) { return queue.nonblocking_pull(x); } + + queue_op_status wait_pull(value_type& x) { return queue.wait_pull(x); } + + void push(BOOST_THREAD_RV_REF(value_type) x) { queue.push(boost::move(x)); } + queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue.try_push(boost::move(x)); } + queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue.nonblocking_push(boost::move(x)); } + queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue.wait_push(boost::move(x)); } + }; + + template + class queue_adaptor_copyable_and_movable : + public boost::queue_base + { + Queue queue; + public: + typedef typename Queue::value_type value_type; + typedef typename Queue::size_type size_type; + + // Constructors/Assignment/Destructors + + queue_adaptor_copyable_and_movable() {} + + // Observers + bool empty() const { return queue.empty(); } + bool full() const { return queue.full(); } + size_type size() const { return queue.size(); } + bool closed() const { return queue.closed(); } + + // Modifiers + void close() { queue.close(); } + + + void push(const value_type& x) { queue.push(x); } + + void pull(value_type& x) { queue.pull(x); }; + // enable_if is_nothrow_copy_movable + value_type pull() { return queue.pull(); } + + queue_op_status try_push(const value_type& x) { return queue.try_push(x); } + queue_op_status try_pull(value_type& x) { return queue.try_pull(x); } + + queue_op_status nonblocking_push(const value_type& x) { return queue.nonblocking_push(x); } + queue_op_status nonblocking_pull(value_type& x) { return queue.nonblocking_pull(x); } + + queue_op_status wait_push(const value_type& x) { return queue.wait_push(x); } + queue_op_status wait_pull(value_type& x) { return queue.wait_pull(x); } + + void push(BOOST_THREAD_RV_REF(value_type) x) { queue.push(boost::move(x)); } + queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue.try_push(boost::move(x)); } + queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue.nonblocking_push(boost::move(x)); } + queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue.wait_push(boost::move(x)); } + }; + + + template ::value, + bool Movable = true +#else + bool Copyable = std::is_copy_constructible::value && std::is_copy_assignable::value, + bool Movable = std::is_move_constructible::value && std::is_move_assignable::value +#endif // __GNUC__ +#elif defined _MSC_VER +#if _MSC_VER < 1700 + bool Copyable = is_copy_constructible::value, + bool Movable = true +#else + bool Copyable = std::is_copy_constructible::value && std::is_copy_assignable::value, + bool Movable = std::is_move_constructible::value && std::is_move_assignable::value +#endif // _MSC_VER +#else + bool Copyable = std::is_copy_constructible::value && std::is_copy_assignable::value, + bool Movable = std::is_move_constructible::value && std::is_move_assignable::value +#endif +#else + bool Copyable = is_copy_constructible::value, + bool Movable = has_move_emulation_enabled::value +#endif + > + struct queue_adaptor; + + template + struct queue_adaptor { + typedef queue_adaptor_copyable_and_movable type; + }; + template + struct queue_adaptor { + typedef queue_adaptor_copyable_only type; + }; + template + struct queue_adaptor { + typedef queue_adaptor_movable_only type; + }; + +} + + template + class queue_adaptor : + public detail::queue_adaptor::type + { + public: + typedef typename Queue::value_type value_type; + typedef typename Queue::size_type size_type; + // Constructors/Assignment/Destructors + virtual ~queue_adaptor() {}; + }; +} +using concurrent::queue_adaptor; + +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/queue_base.hpp b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/queue_base.hpp new file mode 100755 index 00000000000..0d42839158e --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/queue_base.hpp @@ -0,0 +1,202 @@ +#ifndef BOOST_THREAD_QUEUE_BASE_HPP +#define BOOST_THREAD_QUEUE_BASE_HPP + +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Vicente J. Botet Escriba 2014. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include + + +#include + +namespace boost +{ +namespace concurrent +{ +namespace detail +{ + + template + class queue_base_copyable_only + { + public: + typedef ValueType value_type; + typedef SizeType size_type; + + // Constructors/Assignment/Destructors + virtual ~queue_base_copyable_only() {}; + + // Observers + virtual bool empty() const = 0; + virtual bool full() const = 0; + virtual size_type size() const = 0; + virtual bool closed() const = 0; + + // Modifiers + virtual void close() = 0; + + virtual void push(const value_type& x) = 0; + + virtual void pull(value_type&) = 0; + virtual value_type pull() = 0; + + virtual queue_op_status try_push(const value_type& x) = 0; + virtual queue_op_status try_pull(value_type&) = 0; + + virtual queue_op_status nonblocking_push(const value_type& x) = 0; + virtual queue_op_status nonblocking_pull(value_type&) = 0; + + virtual queue_op_status wait_push(const value_type& x) = 0; + virtual queue_op_status wait_pull(ValueType& elem) = 0; + + }; + + template + class queue_base_movable_only + { + public: + typedef ValueType value_type; + typedef SizeType size_type; + // Constructors/Assignment/Destructors + virtual ~queue_base_movable_only() {}; + + // Observers + virtual bool empty() const = 0; + virtual bool full() const = 0; + virtual size_type size() const = 0; + virtual bool closed() const = 0; + + // Modifiers + virtual void close() = 0; + + virtual void pull(value_type&) = 0; + // enable_if is_nothrow_movable + virtual value_type pull() = 0; + + virtual queue_op_status try_pull(value_type&) = 0; + + virtual queue_op_status nonblocking_pull(value_type&) = 0; + + virtual queue_op_status wait_pull(value_type& elem) = 0; + + virtual void push(BOOST_THREAD_RV_REF(value_type) x) = 0; + virtual queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) = 0; + virtual queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) = 0; + virtual queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) = 0; + }; + + + template + class queue_base_copyable_and_movable + { + public: + typedef ValueType value_type; + typedef SizeType size_type; + // Constructors/Assignment/Destructors + virtual ~queue_base_copyable_and_movable() {}; + + + // Observers + virtual bool empty() const = 0; + virtual bool full() const = 0; + virtual size_type size() const = 0; + virtual bool closed() const = 0; + + // Modifiers + virtual void close() = 0; + + virtual void push(const value_type& x) = 0; + + virtual void pull(value_type&) = 0; + // enable_if is_nothrow_copy_movable + virtual value_type pull() = 0; + + virtual queue_op_status try_push(const value_type& x) = 0; + virtual queue_op_status try_pull(value_type&) = 0; + + virtual queue_op_status nonblocking_push(const value_type& x) = 0; + virtual queue_op_status nonblocking_pull(value_type&) = 0; + + virtual queue_op_status wait_push(const value_type& x) = 0; + virtual queue_op_status wait_pull(value_type& elem) = 0; + + virtual void push(BOOST_THREAD_RV_REF(value_type) x) = 0; + virtual queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) = 0; + virtual queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) = 0; + virtual queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) = 0; + }; + + template ::value, + bool Movable = true +#else + bool Copyable = std::is_copy_constructible::value && std::is_copy_assignable::value, + bool Movable = std::is_move_constructible::value && std::is_move_assignable::value +#endif // __GNUC__ +#elif defined _MSC_VER +#if _MSC_VER < 1700 + bool Copyable = is_copy_constructible::value, + bool Movable = true +#else + bool Copyable = std::is_copy_constructible::value && std::is_copy_assignable::value, + bool Movable = std::is_move_constructible::value && std::is_move_assignable::value +#endif // _MSC_VER +#else + bool Copyable = std::is_copy_constructible::value && std::is_copy_assignable::value, + bool Movable = std::is_move_constructible::value && std::is_move_assignable::value +#endif +#else + bool Copyable = is_copy_constructible::value, + bool Movable = has_move_emulation_enabled::value +#endif + > + struct queue_base; + + template + struct queue_base { + typedef queue_base_copyable_and_movable type; + }; + template + struct queue_base { + typedef queue_base_copyable_only type; + }; + template + struct queue_base { + typedef queue_base_movable_only type; + }; + +} + + template + class queue_base : + public detail::queue_base::type + { + public: + typedef ValueType value_type; + typedef SizeType size_type; + // Constructors/Assignment/Destructors + virtual ~queue_base() {}; + }; + +} +using concurrent::queue_base; + +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/queue_op_status.hpp b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/queue_op_status.hpp new file mode 100644 index 00000000000..197650d0521 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/queue_op_status.hpp @@ -0,0 +1,46 @@ +#ifndef BOOST_THREAD_QUEUE_OP_STATUS_HPP +#define BOOST_THREAD_QUEUE_OP_STATUS_HPP + +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Vicente J. Botet Escriba 2014. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include + +namespace boost +{ +namespace concurrent +{ + + BOOST_SCOPED_ENUM_DECLARE_BEGIN(queue_op_status) + { success = 0, empty, full, closed, busy, timeout, not_ready } + BOOST_SCOPED_ENUM_DECLARE_END(queue_op_status) + + struct sync_queue_is_closed : std::exception + { + }; + +} + +#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD + struct no_block_tag{}; + BOOST_CONSTEXPR_OR_CONST no_block_tag no_block = {}; +#endif + + using concurrent::queue_op_status; + using concurrent::sync_queue_is_closed; + +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/queue_views.hpp b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/queue_views.hpp new file mode 100644 index 00000000000..5a4512dd6ed --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/queue_views.hpp @@ -0,0 +1,155 @@ +#ifndef BOOST_THREAD_QUEUE_VIEWS_HPP +#define BOOST_THREAD_QUEUE_VIEWS_HPP + +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Vicente J. Botet Escriba 2014. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +#include + +namespace boost +{ +namespace concurrent +{ + + template + class queue_back_view + { + Queue* queue; + public: + typedef typename Queue::value_type value_type; + typedef typename Queue::size_type size_type; + + // Constructors/Assignment/Destructors + queue_back_view(Queue& q) BOOST_NOEXCEPT : queue(&q) {} + + // Observers + bool empty() const { return queue->empty(); } + bool full() const { return queue->full(); } + size_type size() const { return queue->size(); } + bool closed() const { return queue->closed(); } + + // Modifiers + void close() { queue->close(); } + + void push(const value_type& x) { queue->push(x); } + + queue_op_status try_push(const value_type& x) { return queue->try_push(x); } + + queue_op_status nonblocking_push(const value_type& x) { return queue->nonblocking_push(x); } + queue_op_status wait_push(const value_type& x) { return queue->wait_push(x); } + + void push(BOOST_THREAD_RV_REF(value_type) x) { queue->push(boost::move(x)); } + queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->try_push(boost::move(x)); } + queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->nonblocking_push(boost::move(x)); } + queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->wait_push(boost::move(x)); } + }; + + template + class queue_front_view + { + Queue* queue; + public: + typedef typename Queue::value_type value_type; + typedef typename Queue::size_type size_type; + + // Constructors/Assignment/Destructors + queue_front_view(Queue& q) BOOST_NOEXCEPT : queue(&q) {} + + // Observers + bool empty() const { return queue->empty(); } + bool full() const { return queue->full(); } + size_type size() const { return queue->size(); } + bool closed() const { return queue->closed(); } + + // Modifiers + void close() { queue->close(); } + + void push(const value_type& x) { queue->push_front(x); } + + void pull(value_type& x) { queue->pull(x); }; + // enable_if is_nothrow_copy_movable + value_type pull() { return queue->pull(); } + + queue_op_status try_push(const value_type& x) { return queue->try_push_front(x); } + + queue_op_status try_pull(value_type& x) { return queue->try_pull(x); } + + queue_op_status nonblocking_push(const value_type& x) { return queue->nonblocking_push_front(x); } + + queue_op_status nonblocking_pull(value_type& x) { return queue->nonblocking_pull(x); } + + queue_op_status wait_push(const value_type& x) { return queue->wait_push_front(x); } + queue_op_status wait_pull(value_type& x) { return queue->wait_pull(x); } + void push(BOOST_THREAD_RV_REF(value_type) x) { queue->push_front(forward(x)); } + queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->try_push_front(forward(x)); } + queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->nonblocking_push_front(forward(x)); } + queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x) { return queue->wait_push_front(forward(x)); } + + }; + +#if ! defined BOOST_NO_CXX11_TEMPLATE_ALIASES + + template + using queue_back = queue_back_view > ; + template + using queue_front = queue_front_view > ; + +#else + + template + struct queue_back : queue_back_view > + { + typedef queue_back_view > base_type; + queue_back(queue_base& q) BOOST_NOEXCEPT : base_type(q) {} + }; + template + struct queue_front : queue_front_view > + { + typedef queue_front_view > base_type; + queue_front(queue_base& q) BOOST_NOEXCEPT : base_type(q) {} + + }; + +#endif + +// template +// queue_back_view back(Queue & q) { return queue_back_view(q); } +// template +// queue_front_view front(Queue & q) { return queue_front_view(q); } +//#if 0 +// template +// queue_back back(queue_base & q) { return queue_back(q); } +// template +// queue_front front(queue_base & q) { return queue_front(q); } +//#else +// template +// typename queue_back::type back(queue_base & q) { return typename queue_back::type(q); } +// template +// typename queue_front::type front(queue_base & q) { return typename queue_front::type(q); } +//#endif +} + +using concurrent::queue_back_view; +using concurrent::queue_front_view; +using concurrent::queue_back; +using concurrent::queue_front; +//using concurrent::back; +//using concurrent::front; + +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_bounded_queue.hpp b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_bounded_queue.hpp new file mode 100644 index 00000000000..e34fa56f37f --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_bounded_queue.hpp @@ -0,0 +1,725 @@ +#ifndef BOOST_THREAD_CONCURRENT_QUEUES_SYNC_BOUNDED_QUEUE_HPP +#define BOOST_THREAD_CONCURRENT_QUEUES_SYNC_BOUNDED_QUEUE_HPP + +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Vicente J. Botet Escriba 2013-2014. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include + +#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD +#include +#include +#endif +#include + +namespace boost +{ +namespace concurrent +{ + template + class sync_bounded_queue + { + public: + typedef ValueType value_type; + typedef std::size_t size_type; + + // Constructors/Assignment/Destructors + BOOST_THREAD_NO_COPYABLE(sync_bounded_queue) + explicit sync_bounded_queue(size_type max_elems); + template + sync_bounded_queue(size_type max_elems, Range range); + ~sync_bounded_queue(); + + // Observers + inline bool empty() const; + inline bool full() const; + inline size_type capacity() const; + inline size_type size() const; + inline bool closed() const; + + // Modifiers + inline void close(); + +#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD + inline void push(const value_type& x); + inline void push(BOOST_THREAD_RV_REF(value_type) x); + inline bool try_push(const value_type& x); + inline bool try_push(BOOST_THREAD_RV_REF(value_type) x); + inline bool try_push(no_block_tag, const value_type& x); + inline bool try_push(no_block_tag, BOOST_THREAD_RV_REF(value_type) x); +#endif + inline void push_back(const value_type& x); + inline void push_back(BOOST_THREAD_RV_REF(value_type) x); + inline queue_op_status try_push_back(const value_type& x); + inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x); + inline queue_op_status nonblocking_push_back(const value_type& x); + inline queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x); + inline queue_op_status wait_push_back(const value_type& x); + inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x); + + // Observers/Modifiers +#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD + inline void pull(value_type&); + // enable_if is_nothrow_copy_movable + inline value_type pull(); + inline shared_ptr ptr_pull(); + inline bool try_pull(value_type&); + inline bool try_pull(no_block_tag,value_type&); + inline shared_ptr try_pull(); +#endif + inline void pull_front(value_type&); + // enable_if is_nothrow_copy_movable + inline value_type pull_front(); + inline queue_op_status try_pull_front(value_type&); + inline queue_op_status nonblocking_pull_front(value_type&); + + inline queue_op_status wait_pull_front(ValueType& elem); + + private: + mutable mutex mtx_; + condition_variable not_empty_; + condition_variable not_full_; + size_type waiting_full_; + size_type waiting_empty_; + value_type* data_; + size_type in_; + size_type out_; + size_type capacity_; + bool closed_; + + inline size_type inc(size_type idx) const BOOST_NOEXCEPT + { + return (idx + 1) % capacity_; + } + + inline bool empty(unique_lock& ) const BOOST_NOEXCEPT + { + return in_ == out_; + } + inline bool empty(lock_guard& ) const BOOST_NOEXCEPT + { + return in_ == out_; + } + inline bool full(unique_lock& ) const BOOST_NOEXCEPT + { + return (inc(in_) == out_); + } + inline bool full(lock_guard& ) const BOOST_NOEXCEPT + { + return (inc(in_) == out_); + } + inline size_type capacity(lock_guard& ) const BOOST_NOEXCEPT + { + return capacity_-1; + } + inline size_type size(lock_guard& lk) const BOOST_NOEXCEPT + { + if (full(lk)) return capacity(lk); + return ((out_+capacity(lk)-in_) % capacity(lk)); + } + + inline void throw_if_closed(unique_lock&); + inline bool closed(unique_lock&) const; + +#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD + inline bool try_pull(value_type& x, unique_lock& lk); + inline shared_ptr try_pull(unique_lock& lk); + inline bool try_push(const value_type& x, unique_lock& lk); + inline bool try_push(BOOST_THREAD_RV_REF(value_type) x, unique_lock& lk); +#endif + inline queue_op_status try_pull_front(value_type& x, unique_lock& lk); + inline queue_op_status try_push_back(const value_type& x, unique_lock& lk); + inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock& lk); + + inline queue_op_status wait_pull_front(value_type& x, unique_lock& lk); + inline queue_op_status wait_push_back(const value_type& x, unique_lock& lk); + inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock& lk); + + inline void wait_until_not_empty(unique_lock& lk); + inline void wait_until_not_empty(unique_lock& lk, bool&); + inline size_type wait_until_not_full(unique_lock& lk); + inline size_type wait_until_not_full(unique_lock& lk, bool&); + + + inline void notify_not_empty_if_needed(unique_lock& lk) + { + if (waiting_empty_ > 0) + { + --waiting_empty_; + lk.unlock(); + not_empty_.notify_one(); + } + } + inline void notify_not_full_if_needed(unique_lock& lk) + { + if (waiting_full_ > 0) + { + --waiting_full_; + lk.unlock(); + not_full_.notify_one(); + } + } + +#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD + inline void pull(value_type& elem, unique_lock& lk) + { + elem = boost::move(data_[out_]); + out_ = inc(out_); + notify_not_full_if_needed(lk); + } + inline value_type pull(unique_lock& lk) + { + value_type elem = boost::move(data_[out_]); + out_ = inc(out_); + notify_not_full_if_needed(lk); + return boost::move(elem); + } + inline boost::shared_ptr ptr_pull(unique_lock& lk) + { + shared_ptr res = make_shared(boost::move(data_[out_])); + out_ = inc(out_); + notify_not_full_if_needed(lk); + return res; + } +#endif + inline void pull_front(value_type& elem, unique_lock& lk) + { + elem = boost::move(data_[out_]); + out_ = inc(out_); + notify_not_full_if_needed(lk); + } + inline value_type pull_front(unique_lock& lk) + { + value_type elem = boost::move(data_[out_]); + out_ = inc(out_); + notify_not_full_if_needed(lk); + return boost::move(elem); + } + + inline void set_in(size_type in, unique_lock& lk) + { + in_ = in; + notify_not_empty_if_needed(lk); + } + + inline void push_at(const value_type& elem, size_type in_p_1, unique_lock& lk) + { + data_[in_] = elem; + set_in(in_p_1, lk); + } + + inline void push_at(BOOST_THREAD_RV_REF(value_type) elem, size_type in_p_1, unique_lock& lk) + { + data_[in_] = boost::move(elem); + set_in(in_p_1, lk); + } + }; + + template + sync_bounded_queue::sync_bounded_queue(typename sync_bounded_queue::size_type max_elems) : + waiting_full_(0), waiting_empty_(0), data_(new value_type[max_elems + 1]), in_(0), out_(0), capacity_(max_elems + 1), + closed_(false) + { + BOOST_ASSERT_MSG(max_elems >= 1, "number of elements must be > 1"); + } + +// template +// template +// sync_bounded_queue::sync_bounded_queue(size_type max_elems, Range range) : +// waiting_full_(0), waiting_empty_(0), data_(new value_type[max_elems + 1]), in_(0), out_(0), capacity_(max_elems + 1), +// closed_(false) +// { +// BOOST_ASSERT_MSG(max_elems >= 1, "number of elements must be > 1"); +// BOOST_ASSERT_MSG(max_elems == size(range), "number of elements must match range's size"); +// try +// { +// typedef typename Range::iterator iterator_t; +// iterator_t first = boost::begin(range); +// iterator_t end = boost::end(range); +// size_type in = 0; +// for (iterator_t cur = first; cur != end; ++cur, ++in) +// { +// data_[in] = *cur; +// } +// set_in(in); +// } +// catch (...) +// { +// delete[] data_; +// } +// } + + template + sync_bounded_queue::~sync_bounded_queue() + { + delete[] data_; + } + + template + void sync_bounded_queue::close() + { + { + lock_guard lk(mtx_); + closed_ = true; + } + not_empty_.notify_all(); + not_full_.notify_all(); + } + + template + bool sync_bounded_queue::closed() const + { + lock_guard lk(mtx_); + return closed_; + } + template + bool sync_bounded_queue::closed(unique_lock& ) const + { + return closed_; + } + + template + bool sync_bounded_queue::empty() const + { + lock_guard lk(mtx_); + return empty(lk); + } + template + bool sync_bounded_queue::full() const + { + lock_guard lk(mtx_); + return full(lk); + } + + template + typename sync_bounded_queue::size_type sync_bounded_queue::capacity() const + { + lock_guard lk(mtx_); + return capacity(lk); + } + + template + typename sync_bounded_queue::size_type sync_bounded_queue::size() const + { + lock_guard lk(mtx_); + return size(lk); + } + +#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD + template + bool sync_bounded_queue::try_pull(ValueType& elem, unique_lock& lk) + { + if (empty(lk)) + { + throw_if_closed(lk); + return false; + } + pull(elem, lk); + return true; + } + template + shared_ptr sync_bounded_queue::try_pull(unique_lock& lk) + { + if (empty(lk)) + { + throw_if_closed(lk); + return shared_ptr(); + } + return ptr_pull(lk); + } + template + bool sync_bounded_queue::try_pull(ValueType& elem) + { + unique_lock lk(mtx_); + return try_pull(elem, lk); + } +#endif + + template + queue_op_status sync_bounded_queue::try_pull_front(ValueType& elem, unique_lock& lk) + { + if (empty(lk)) + { + if (closed(lk)) return queue_op_status::closed; + return queue_op_status::empty; + } + pull_front(elem, lk); + return queue_op_status::success; + } + + template + queue_op_status sync_bounded_queue::try_pull_front(ValueType& elem) + { + unique_lock lk(mtx_); + return try_pull_front(elem, lk); + } + +#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD + template + bool sync_bounded_queue::try_pull(no_block_tag,ValueType& elem) + { + unique_lock lk(mtx_, try_to_lock); + if (!lk.owns_lock()) + { + return false; + } + return try_pull(elem, lk); + } + template + boost::shared_ptr sync_bounded_queue::try_pull() + { + unique_lock lk(mtx_); + return try_pull(lk); + } +#endif + + template + queue_op_status sync_bounded_queue::nonblocking_pull_front(ValueType& elem) + { + unique_lock lk(mtx_, try_to_lock); + if (!lk.owns_lock()) + { + return queue_op_status::busy; + } + return try_pull_front(elem, lk); + } + + template + void sync_bounded_queue::throw_if_closed(unique_lock&) + { + if (closed_) + { + BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); + } + } + + template + void sync_bounded_queue::wait_until_not_empty(unique_lock& lk) + { + for (;;) + { + if (out_ != in_) break; + throw_if_closed(lk); + ++waiting_empty_; + not_empty_.wait(lk); + } + } + template + void sync_bounded_queue::wait_until_not_empty(unique_lock& lk, bool & closed) + { + for (;;) + { + if (out_ != in_) break; + if (closed_) {closed=true; return;} + ++waiting_empty_; + not_empty_.wait(lk); + } + } + +#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD + template + void sync_bounded_queue::pull(ValueType& elem) + { + unique_lock lk(mtx_); + wait_until_not_empty(lk); + pull(elem, lk); + } +// template +// void sync_bounded_queue::pull(ValueType& elem, bool & closed) +// { +// unique_lock lk(mtx_); +// wait_until_not_empty(lk, closed); +// if (closed) {return;} +// pull(elem, lk); +// } + + // enable if ValueType is nothrow movable + template + ValueType sync_bounded_queue::pull() + { + unique_lock lk(mtx_); + wait_until_not_empty(lk); + return pull(lk); + } + template + boost::shared_ptr sync_bounded_queue::ptr_pull() + { + unique_lock lk(mtx_); + wait_until_not_empty(lk); + return ptr_pull(lk); + } + +#endif + + template + void sync_bounded_queue::pull_front(ValueType& elem) + { + unique_lock lk(mtx_); + wait_until_not_empty(lk); + pull_front(elem, lk); + } + + // enable if ValueType is nothrow movable + template + ValueType sync_bounded_queue::pull_front() + { + unique_lock lk(mtx_); + wait_until_not_empty(lk); + return pull_front(lk); + } + + template + queue_op_status sync_bounded_queue::wait_pull_front(ValueType& elem, unique_lock& lk) + { + if (empty(lk) && closed(lk)) {return queue_op_status::closed;} + wait_until_not_empty(lk); + pull_front(elem, lk); + return queue_op_status::success; + } + template + queue_op_status sync_bounded_queue::wait_pull_front(ValueType& elem) + { + unique_lock lk(mtx_); + return wait_pull_front(elem, lk); + } + +#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD + template + bool sync_bounded_queue::try_push(const ValueType& elem, unique_lock& lk) + { + throw_if_closed(lk); + size_type in_p_1 = inc(in_); + if (in_p_1 == out_) // full() + { + return false; + } + push_at(elem, in_p_1, lk); + return true; + } + template + bool sync_bounded_queue::try_push(const ValueType& elem) + { + unique_lock lk(mtx_); + return try_push(elem, lk); + } + +#endif + + template + queue_op_status sync_bounded_queue::try_push_back(const ValueType& elem, unique_lock& lk) + { + if (closed(lk)) return queue_op_status::closed; + size_type in_p_1 = inc(in_); + if (in_p_1 == out_) // full() + { + return queue_op_status::full; + } + push_at(elem, in_p_1, lk); + return queue_op_status::success; + } + + template + queue_op_status sync_bounded_queue::try_push_back(const ValueType& elem) + { + unique_lock lk(mtx_); + return try_push_back(elem, lk); + } + + template + queue_op_status sync_bounded_queue::wait_push_back(const ValueType& elem, unique_lock& lk) + { + if (closed(lk)) return queue_op_status::closed; + push_at(elem, wait_until_not_full(lk), lk); + return queue_op_status::success; + } + template + queue_op_status sync_bounded_queue::wait_push_back(const ValueType& elem) + { + unique_lock lk(mtx_); + return wait_push_back(elem, lk); + } + + +#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD + template + bool sync_bounded_queue::try_push(no_block_tag, const ValueType& elem) + { + unique_lock lk(mtx_, try_to_lock); + if (!lk.owns_lock()) return false; + return try_push(elem, lk); + } +#endif + + template + queue_op_status sync_bounded_queue::nonblocking_push_back(const ValueType& elem) + { + unique_lock lk(mtx_, try_to_lock); + if (!lk.owns_lock()) return queue_op_status::busy; + return try_push_back(elem, lk); + } + + template + typename sync_bounded_queue::size_type sync_bounded_queue::wait_until_not_full(unique_lock& lk) + { + for (;;) + { + throw_if_closed(lk); + size_type in_p_1 = inc(in_); + if (in_p_1 != out_) // ! full() + { + return in_p_1; + } + ++waiting_full_; + not_full_.wait(lk); + } + } + +#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD + template + void sync_bounded_queue::push(const ValueType& elem) + { + unique_lock lk(mtx_); + push_at(elem, wait_until_not_full(lk), lk); + } +#endif + template + void sync_bounded_queue::push_back(const ValueType& elem) + { + unique_lock lk(mtx_); + push_at(elem, wait_until_not_full(lk), lk); + } + +#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD + template + bool sync_bounded_queue::try_push(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock& lk) + { + throw_if_closed(lk); + size_type in_p_1 = inc(in_); + if (in_p_1 == out_) // full() + { + return false; + } + push_at(boost::move(elem), in_p_1, lk); + return true; + } + + template + bool sync_bounded_queue::try_push(BOOST_THREAD_RV_REF(ValueType) elem) + { + unique_lock lk(mtx_); + return try_push(boost::move(elem), lk); + } +#endif + + template + queue_op_status sync_bounded_queue::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock& lk) + { + if (closed(lk)) return queue_op_status::closed; + size_type in_p_1 = inc(in_); + if (in_p_1 == out_) // full() + { + return queue_op_status::full; + } + push_at(boost::move(elem), in_p_1, lk); + return queue_op_status::success; + } + template + queue_op_status sync_bounded_queue::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem) + { + unique_lock lk(mtx_); + return try_push_back(boost::move(elem), lk); + } + + template + queue_op_status sync_bounded_queue::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock& lk) + { + if (closed(lk)) return queue_op_status::closed; + push_at(boost::move(elem), wait_until_not_full(lk), lk); + return queue_op_status::success; + } + template + queue_op_status sync_bounded_queue::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem) + { + unique_lock lk(mtx_); + return try_push_back(boost::move(elem), lk); + } + + +#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD + template + bool sync_bounded_queue::try_push(no_block_tag, BOOST_THREAD_RV_REF(ValueType) elem) + { + unique_lock lk(mtx_, try_to_lock); + if (!lk.owns_lock()) + { + return false; + } + return try_push(boost::move(elem), lk); + } +#endif + template + queue_op_status sync_bounded_queue::nonblocking_push_back(BOOST_THREAD_RV_REF(ValueType) elem) + { + unique_lock lk(mtx_, try_to_lock); + if (!lk.owns_lock()) + { + return queue_op_status::busy; + } + return try_push_back(boost::move(elem), lk); + } + +#ifndef BOOST_THREAD_QUEUE_DEPRECATE_OLD + template + void sync_bounded_queue::push(BOOST_THREAD_RV_REF(ValueType) elem) + { + unique_lock lk(mtx_); + push_at(boost::move(elem), wait_until_not_full(lk), lk); + } +#endif + template + void sync_bounded_queue::push_back(BOOST_THREAD_RV_REF(ValueType) elem) + { + unique_lock lk(mtx_); + push_at(boost::move(elem), wait_until_not_full(lk), lk); + } + + template + sync_bounded_queue& operator<<(sync_bounded_queue& sbq, BOOST_THREAD_RV_REF(ValueType) elem) + { + sbq.push_back(boost::move(elem)); + return sbq; + } + + template + sync_bounded_queue& operator<<(sync_bounded_queue& sbq, ValueType const&elem) + { + sbq.push_back(elem); + return sbq; + } + + template + sync_bounded_queue& operator>>(sync_bounded_queue& sbq, ValueType &elem) + { + sbq.pull_front(elem); + return sbq; + } +} +using concurrent::sync_bounded_queue; + +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_deque.hpp b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_deque.hpp new file mode 100644 index 00000000000..c84dae022ac --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_deque.hpp @@ -0,0 +1,327 @@ +#ifndef BOOST_THREAD_CONCURRENT_QUEUES_SYNC_DEQUE_HPP +#define BOOST_THREAD_CONCURRENT_QUEUES_SYNC_DEQUE_HPP + +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Vicente J. Botet Escriba 2013-2014. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +namespace boost +{ +namespace concurrent +{ + template > + class sync_deque + : public detail::sync_queue_base + { + typedef detail::sync_queue_base super; + + public: + typedef ValueType value_type; + //typedef typename super::value_type value_type; // fixme + typedef typename super::underlying_queue_type underlying_queue_type; + typedef typename super::size_type size_type; + typedef typename super::op_status op_status; + + // Constructors/Assignment/Destructors + BOOST_THREAD_NO_COPYABLE(sync_deque) + inline sync_deque(); + //template + //inline explicit sync_deque(Range range); + inline ~sync_deque(); + + // Modifiers + inline void push_back(const value_type& x); + inline queue_op_status try_push_back(const value_type& x); + inline queue_op_status nonblocking_push_back(const value_type& x); + inline queue_op_status wait_push_back(const value_type& x); + inline void push_back(BOOST_THREAD_RV_REF(value_type) x); + inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x); + inline queue_op_status nonblocking_push_back(BOOST_THREAD_RV_REF(value_type) x); + inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x); + + // Observers/Modifiers + inline void pull_front(value_type&); + // enable_if is_nothrow_copy_movable + inline value_type pull_front(); + + inline queue_op_status try_pull_front(value_type&); + inline queue_op_status nonblocking_pull_front(value_type&); + inline queue_op_status wait_pull_front(ValueType& elem); + + private: + + inline queue_op_status try_pull_front(value_type& x, unique_lock& lk); + inline queue_op_status wait_pull_front(value_type& x, unique_lock& lk); + inline queue_op_status try_push_back(const value_type& x, unique_lock& lk); + inline queue_op_status wait_push_back(const value_type& x, unique_lock& lk); + inline queue_op_status try_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock& lk); + inline queue_op_status wait_push_back(BOOST_THREAD_RV_REF(value_type) x, unique_lock& lk); + + inline void pull_front(value_type& elem, unique_lock& ) + { + elem = boost::move(super::data_.front()); + super::data_.pop_front(); + } + inline value_type pull_front(unique_lock& ) + { + value_type e = boost::move(super::data_.front()); + super::data_.pop_front(); + return boost::move(e); + } + + inline void push_back(const value_type& elem, unique_lock& lk) + { + super::data_.push_back(elem); + super::notify_not_empty_if_needed(lk); + } + + inline void push_back(BOOST_THREAD_RV_REF(value_type) elem, unique_lock& lk) + { + super::data_.push_back(boost::move(elem)); + super::notify_not_empty_if_needed(lk); + } + }; + + template + sync_deque::sync_deque() : + super() + { + } + +// template +// template +// explicit sync_deque::sync_deque(Range range) : +// data_(), closed_(false) +// { +// try +// { +// typedef typename Range::iterator iterator_t; +// iterator_t first = boost::begin(range); +// iterator_t end = boost::end(range); +// for (iterator_t cur = first; cur != end; ++cur) +// { +// data_.push(boost::move(*cur));; +// } +// notify_not_empty_if_needed(lk); +// } +// catch (...) +// { +// delete[] data_; +// } +// } + + template + sync_deque::~sync_deque() + { + } + + template + queue_op_status sync_deque::try_pull_front(ValueType& elem, unique_lock& lk) + { + if (super::empty(lk)) + { + if (super::closed(lk)) return queue_op_status::closed; + return queue_op_status::empty; + } + pull_front(elem, lk); + return queue_op_status::success; + } + template + queue_op_status sync_deque::wait_pull_front(ValueType& elem, unique_lock& lk) + { + if (super::empty(lk)) + { + if (super::closed(lk)) return queue_op_status::closed; + } + bool has_been_closed = super::wait_until_not_empty_or_closed(lk); + if (has_been_closed) return queue_op_status::closed; + pull_front(elem, lk); + return queue_op_status::success; + } + + template + queue_op_status sync_deque::try_pull_front(ValueType& elem) + { + unique_lock lk(super::mtx_); + return try_pull_front(elem, lk); + } + + template + queue_op_status sync_deque::wait_pull_front(ValueType& elem) + { + unique_lock lk(super::mtx_); + return wait_pull_front(elem, lk); + } + + template + queue_op_status sync_deque::nonblocking_pull_front(ValueType& elem) + { + unique_lock lk(super::mtx_, try_to_lock); + if (!lk.owns_lock()) + { + return queue_op_status::busy; + } + return try_pull_front(elem, lk); + } + + template + void sync_deque::pull_front(ValueType& elem) + { + unique_lock lk(super::mtx_); + super::wait_until_not_empty(lk); + pull_front(elem, lk); + } + + // enable if ValueType is nothrow movable + template + ValueType sync_deque::pull_front() + { + unique_lock lk(super::mtx_); + super::wait_until_not_empty(lk); + return pull_front(lk); + } + + template + queue_op_status sync_deque::try_push_back(const ValueType& elem, unique_lock& lk) + { + if (super::closed(lk)) return queue_op_status::closed; + push_back(elem, lk); + return queue_op_status::success; + } + + template + queue_op_status sync_deque::try_push_back(const ValueType& elem) + { + unique_lock lk(super::mtx_); + return try_push_back(elem, lk); + } + + template + queue_op_status sync_deque::wait_push_back(const ValueType& elem, unique_lock& lk) + { + if (super::closed(lk)) return queue_op_status::closed; + push_back(elem, lk); + return queue_op_status::success; + } + + template + queue_op_status sync_deque::wait_push_back(const ValueType& elem) + { + unique_lock lk(super::mtx_); + return wait_push_back(elem, lk); + } + + template + queue_op_status sync_deque::nonblocking_push_back(const ValueType& elem) + { + unique_lock lk(super::mtx_, try_to_lock); + if (!lk.owns_lock()) return queue_op_status::busy; + return try_push_back(elem, lk); + } + + template + void sync_deque::push_back(const ValueType& elem) + { + unique_lock lk(super::mtx_); + super::throw_if_closed(lk); + push_back(elem, lk); + } + + template + queue_op_status sync_deque::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock& lk) + { + if (super::closed(lk)) return queue_op_status::closed; + push_back(boost::move(elem), lk); + return queue_op_status::success; + } + + template + queue_op_status sync_deque::try_push_back(BOOST_THREAD_RV_REF(ValueType) elem) + { + unique_lock lk(super::mtx_); + return try_push_back(boost::move(elem), lk); + } + + template + queue_op_status sync_deque::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock& lk) + { + if (super::closed(lk)) return queue_op_status::closed; + push_back(boost::move(elem), lk); + return queue_op_status::success; + } + + template + queue_op_status sync_deque::wait_push_back(BOOST_THREAD_RV_REF(ValueType) elem) + { + unique_lock lk(super::mtx_); + return wait_push_back(boost::move(elem), lk); + } + + template + queue_op_status sync_deque::nonblocking_push_back(BOOST_THREAD_RV_REF(ValueType) elem) + { + unique_lock lk(super::mtx_, try_to_lock); + if (!lk.owns_lock()) + { + return queue_op_status::busy; + } + return try_push_back(boost::move(elem), lk); + } + + template + void sync_deque::push_back(BOOST_THREAD_RV_REF(ValueType) elem) + { + unique_lock lk(super::mtx_); + super::throw_if_closed(lk); + push_back(boost::move(elem), lk); + } + + template + sync_deque& operator<<(sync_deque& sbq, BOOST_THREAD_RV_REF(ValueType) elem) + { + sbq.push_back(boost::move(elem)); + return sbq; + } + + template + sync_deque& operator<<(sync_deque& sbq, ValueType const&elem) + { + sbq.push_back(elem); + return sbq; + } + + template + sync_deque& operator>>(sync_deque& sbq, ValueType &elem) + { + sbq.pull_front(elem); + return sbq; + } + +} +using concurrent::sync_deque; + +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_priority_queue.hpp b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_priority_queue.hpp new file mode 100644 index 00000000000..d604faa7423 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_priority_queue.hpp @@ -0,0 +1,369 @@ +// Copyright (C) 2014 Ian Forbed +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_THREAD_SYNC_PRIORITY_QUEUE +#define BOOST_THREAD_SYNC_PRIORITY_QUEUE + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +namespace boost +{ +namespace detail { + + template < + class Type, + class Container = csbl::vector, + class Compare = std::less + > + class priority_queue + { + private: + Container _elements; + Compare _compare; + public: + typedef Type value_type; + typedef typename Container::size_type size_type; + + explicit priority_queue(const Compare& compare = Compare()) + : _elements(), _compare(compare) + { } + + size_type size() const + { + return _elements.size(); + } + + bool empty() const + { + return _elements.empty(); + } + + void push(Type const& element) + { + _elements.push_back(element); + std::push_heap(_elements.begin(), _elements.end(), _compare); + } + void push(BOOST_RV_REF(Type) element) + { + _elements.push_back(boost::move(element)); + std::push_heap(_elements.begin(), _elements.end(), _compare); + } + + void pop() + { + std::pop_heap(_elements.begin(), _elements.end(), _compare); + _elements.pop_back(); + } + Type pull() + { + Type result = boost::move(_elements.front()); + pop(); + return boost::move(result); + } + + Type const& top() + { + return _elements.front(); + } + }; +} + +namespace concurrent +{ + template , + class Compare = std::less > + class sync_priority_queue + : public detail::sync_queue_base > + { + typedef detail::sync_queue_base > super; + + public: + typedef ValueType value_type; + //typedef typename super::value_type value_type; // fixme + typedef typename super::underlying_queue_type underlying_queue_type; + typedef typename super::size_type size_type; + typedef typename super::op_status op_status; + + typedef chrono::steady_clock clock; + protected: + + public: + sync_priority_queue() {} + + ~sync_priority_queue() + { + if(!super::closed()) + { + super::close(); + } + } + + void push(const ValueType& elem); + void push(BOOST_THREAD_RV_REF(ValueType) elem); + + queue_op_status try_push(const ValueType& elem); + queue_op_status try_push(BOOST_THREAD_RV_REF(ValueType) elem); + + ValueType pull(); + + void pull(ValueType&); + + queue_op_status pull_until(const clock::time_point&, ValueType&); + queue_op_status pull_for(const clock::duration&, ValueType&); + + queue_op_status try_pull(ValueType& elem); + queue_op_status wait_pull(ValueType& elem); + queue_op_status nonblocking_pull(ValueType&); + + private: + void push(unique_lock&, const ValueType& elem); + void push(lock_guard&, const ValueType& elem); + void push(unique_lock&, BOOST_THREAD_RV_REF(ValueType) elem); + void push(lock_guard&, BOOST_THREAD_RV_REF(ValueType) elem); + + queue_op_status try_push(unique_lock&, const ValueType& elem); + queue_op_status try_push(unique_lock&, BOOST_THREAD_RV_REF(ValueType) elem); + + ValueType pull(unique_lock&); + ValueType pull(lock_guard&); + + void pull(unique_lock&, ValueType&); + void pull(lock_guard&, ValueType&); + + queue_op_status try_pull(lock_guard& lk, ValueType& elem); + queue_op_status try_pull(unique_lock& lk, ValueType& elem); + + queue_op_status wait_pull(unique_lock& lk, ValueType& elem); + + queue_op_status nonblocking_pull(unique_lock& lk, ValueType&); + + sync_priority_queue(const sync_priority_queue&); + sync_priority_queue& operator= (const sync_priority_queue&); + sync_priority_queue(BOOST_THREAD_RV_REF(sync_priority_queue)); + sync_priority_queue& operator= (BOOST_THREAD_RV_REF(sync_priority_queue)); + }; //end class + + + ////////////////////// + template + void sync_priority_queue::push(unique_lock& lk, const T& elem) + { + super::throw_if_closed(lk); + super::data_.push(elem); + super::notify_not_empty_if_needed(lk); + } + template + void sync_priority_queue::push(lock_guard& lk, const T& elem) + { + super::throw_if_closed(lk); + super::data_.push(elem); + super::notify_not_empty_if_needed(lk); + } + template + void sync_priority_queue::push(const T& elem) + { + lock_guard lk(super::mtx_); + push(lk, elem); + } + + ////////////////////// + template + void sync_priority_queue::push(unique_lock& lk, BOOST_THREAD_RV_REF(T) elem) + { + super::throw_if_closed(lk); + super::data_.push(boost::move(elem)); + super::notify_not_empty_if_needed(lk); + } + template + void sync_priority_queue::push(lock_guard& lk, BOOST_THREAD_RV_REF(T) elem) + { + super::throw_if_closed(lk); + super::data_.push(boost::move(elem)); + super::notify_not_empty_if_needed(lk); + } + template + void sync_priority_queue::push(BOOST_THREAD_RV_REF(T) elem) + { + lock_guard lk(super::mtx_); + push(lk, boost::move(elem)); + } + + ////////////////////// + template + queue_op_status sync_priority_queue::try_push(const T& elem) + { + lock_guard lk(super::mtx_); + if (super::closed(lk)) return queue_op_status::closed; + push(lk, elem); + return queue_op_status::success; + } + + ////////////////////// + template + queue_op_status sync_priority_queue::try_push(BOOST_THREAD_RV_REF(T) elem) + { + lock_guard lk(super::mtx_); + if (super::closed(lk)) return queue_op_status::closed; + push(lk, boost::move(elem)); + + return queue_op_status::success; + } + + ////////////////////// + template + T sync_priority_queue::pull(unique_lock&) + { + return super::data_.pull(); + } + template + T sync_priority_queue::pull(lock_guard&) + { + return super::data_.pull(); + } + + template + T sync_priority_queue::pull() + { + unique_lock lk(super::mtx_); + super::wait_until_not_empty(lk); + return pull(lk); + } + + ////////////////////// + template + void sync_priority_queue::pull(unique_lock&, T& elem) + { + elem = super::data_.pull(); + } + template + void sync_priority_queue::pull(lock_guard&, T& elem) + { + elem = super::data_.pull(); + } + + template + void sync_priority_queue::pull(T& elem) + { + unique_lock lk(super::mtx_); + super::wait_until_not_empty(lk); + pull(lk, elem); + } + + ////////////////////// + template + queue_op_status + sync_priority_queue::pull_until(const clock::time_point& tp, T& elem) + { + unique_lock lk(super::mtx_); + if (queue_op_status::timeout == super::wait_until_not_empty_until(lk, tp)) + return queue_op_status::timeout; + pull(lk, elem); + return queue_op_status::success; + } + + ////////////////////// + template + queue_op_status + sync_priority_queue::pull_for(const clock::duration& dura, T& elem) + { + return pull_until(clock::now() + dura, elem); + } + + ////////////////////// + template + queue_op_status + sync_priority_queue::try_pull(unique_lock& lk, T& elem) + { + if (super::empty(lk)) + { + if (super::closed(lk)) return queue_op_status::closed; + return queue_op_status::empty; + } + pull(lk, elem); + return queue_op_status::success; + } + + template + queue_op_status + sync_priority_queue::try_pull(lock_guard& lk, T& elem) + { + if (super::empty(lk)) + { + if (super::closed(lk)) return queue_op_status::closed; + return queue_op_status::empty; + } + pull(lk, elem); + return queue_op_status::success; + } + + template + queue_op_status + sync_priority_queue::try_pull(T& elem) + { + lock_guard lk(super::mtx_); + return try_pull(lk, elem); + } + + ////////////////////// + template + queue_op_status sync_priority_queue::wait_pull(unique_lock& lk, T& elem) + { + if (super::empty(lk)) + { + if (super::closed(lk)) return queue_op_status::closed; + } + bool has_been_closed = super::wait_until_not_empty_or_closed(lk); + if (has_been_closed) return queue_op_status::closed; + pull(lk, elem); + return queue_op_status::success; + } + + template + queue_op_status sync_priority_queue::wait_pull(T& elem) + { + unique_lock lk(super::mtx_); + return wait_pull(lk, elem); + } + + ////////////////////// + + template + queue_op_status sync_priority_queue::nonblocking_pull(T& elem) + { + unique_lock lk(super::mtx_, try_to_lock); + if (!lk.owns_lock()) return queue_op_status::busy; + return try_pull(lk, elem); + } + + + +} //end concurrent namespace + +using concurrent::sync_priority_queue; + +} //end boost namespace +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_queue.hpp b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_queue.hpp new file mode 100644 index 00000000000..1dbbef05dd3 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_queue.hpp @@ -0,0 +1,335 @@ +#ifndef BOOST_THREAD_CONCURRENT_QUEUES_SYNC_QUEUE_HPP +#define BOOST_THREAD_CONCURRENT_QUEUES_SYNC_QUEUE_HPP + +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Vicente J. Botet Escriba 2013-2014. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +namespace boost +{ +namespace concurrent +{ + template > + class sync_queue + : public detail::sync_queue_base + { + typedef detail::sync_queue_base super; + + public: + typedef ValueType value_type; + //typedef typename super::value_type value_type; // fixme + typedef typename super::underlying_queue_type underlying_queue_type; + typedef typename super::size_type size_type; + typedef typename super::op_status op_status; + + // Constructors/Assignment/Destructors + BOOST_THREAD_NO_COPYABLE(sync_queue) + inline sync_queue(); + //template + //inline explicit sync_queue(Range range); + inline ~sync_queue(); + + // Modifiers + + inline void push(const value_type& x); + inline queue_op_status try_push(const value_type& x); + inline queue_op_status nonblocking_push(const value_type& x); + inline queue_op_status wait_push(const value_type& x); + inline void push(BOOST_THREAD_RV_REF(value_type) x); + inline queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x); + inline queue_op_status nonblocking_push(BOOST_THREAD_RV_REF(value_type) x); + inline queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x); + + // Observers/Modifiers + inline void pull(value_type&); + // enable_if is_nothrow_copy_movable + inline value_type pull(); + + inline queue_op_status try_pull(value_type&); + inline queue_op_status nonblocking_pull(value_type&); + inline queue_op_status wait_pull(ValueType& elem); + + private: + + inline queue_op_status try_pull(value_type& x, unique_lock& lk); + inline queue_op_status wait_pull(value_type& x, unique_lock& lk); + inline queue_op_status try_push(const value_type& x, unique_lock& lk); + inline queue_op_status wait_push(const value_type& x, unique_lock& lk); + inline queue_op_status try_push(BOOST_THREAD_RV_REF(value_type) x, unique_lock& lk); + inline queue_op_status wait_push(BOOST_THREAD_RV_REF(value_type) x, unique_lock& lk); + + inline void pull(value_type& elem, unique_lock& ) + { + elem = boost::move(super::data_.front()); + super::data_.pop_front(); + } + inline value_type pull(unique_lock& ) + { + value_type e = boost::move(super::data_.front()); + super::data_.pop_front(); + return boost::move(e); + } + + inline void push(const value_type& elem, unique_lock& lk) + { + super::data_.push_back(elem); + super::notify_not_empty_if_needed(lk); + } + + inline void push(BOOST_THREAD_RV_REF(value_type) elem, unique_lock& lk) + { + super::data_.push_back(boost::move(elem)); + super::notify_not_empty_if_needed(lk); + } + }; + + template + sync_queue::sync_queue() : + super() + { + } + +// template +// template +// explicit sync_queue::sync_queue(Range range) : +// data_(), closed_(false) +// { +// try +// { +// typedef typename Range::iterator iterator_t; +// iterator_t first = boost::begin(range); +// iterator_t end = boost::end(range); +// for (iterator_t cur = first; cur != end; ++cur) +// { +// data_.push(boost::move(*cur));; +// } +// notify_not_empty_if_needed(lk); +// } +// catch (...) +// { +// delete[] data_; +// } +// } + + template + sync_queue::~sync_queue() + { + } + + template + queue_op_status sync_queue::try_pull(ValueType& elem, unique_lock& lk) + { + if (super::empty(lk)) + { + if (super::closed(lk)) return queue_op_status::closed; + return queue_op_status::empty; + } + pull(elem, lk); + return queue_op_status::success; + } + template + queue_op_status sync_queue::wait_pull(ValueType& elem, unique_lock& lk) + { + //std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + if (super::empty(lk)) + { + //std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + if (super::closed(lk)) return queue_op_status::closed; + } + //std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + bool has_been_closed = super::wait_until_not_empty_or_closed(lk); + //std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + if (has_been_closed) return queue_op_status::closed; + //std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + pull(elem, lk); + //std::cout << __FILE__ << "[" << __LINE__ << "]" << std::endl; + return queue_op_status::success; + } + + template + queue_op_status sync_queue::try_pull(ValueType& elem) + { + unique_lock lk(super::mtx_); + return try_pull(elem, lk); + } + + template + queue_op_status sync_queue::wait_pull(ValueType& elem) + { + unique_lock lk(super::mtx_); + return wait_pull(elem, lk); + } + + template + queue_op_status sync_queue::nonblocking_pull(ValueType& elem) + { + unique_lock lk(super::mtx_, try_to_lock); + if (!lk.owns_lock()) + { + return queue_op_status::busy; + } + return try_pull(elem, lk); + } + + template + void sync_queue::pull(ValueType& elem) + { + unique_lock lk(super::mtx_); + super::wait_until_not_empty(lk); + pull(elem, lk); + } + + // enable if ValueType is nothrow movable + template + ValueType sync_queue::pull() + { + unique_lock lk(super::mtx_); + super::wait_until_not_empty(lk); + return pull(lk); + } + + template + queue_op_status sync_queue::try_push(const ValueType& elem, unique_lock& lk) + { + if (super::closed(lk)) return queue_op_status::closed; + push(elem, lk); + return queue_op_status::success; + } + + template + queue_op_status sync_queue::try_push(const ValueType& elem) + { + unique_lock lk(super::mtx_); + return try_push(elem, lk); + } + + template + queue_op_status sync_queue::wait_push(const ValueType& elem, unique_lock& lk) + { + if (super::closed(lk)) return queue_op_status::closed; + push(elem, lk); + return queue_op_status::success; + } + + template + queue_op_status sync_queue::wait_push(const ValueType& elem) + { + unique_lock lk(super::mtx_); + return wait_push(elem, lk); + } + + template + queue_op_status sync_queue::nonblocking_push(const ValueType& elem) + { + unique_lock lk(super::mtx_, try_to_lock); + if (!lk.owns_lock()) return queue_op_status::busy; + return try_push(elem, lk); + } + + template + void sync_queue::push(const ValueType& elem) + { + unique_lock lk(super::mtx_); + super::throw_if_closed(lk); + push(elem, lk); + } + + template + queue_op_status sync_queue::try_push(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock& lk) + { + if (super::closed(lk)) return queue_op_status::closed; + push(boost::move(elem), lk); + return queue_op_status::success; + } + + template + queue_op_status sync_queue::try_push(BOOST_THREAD_RV_REF(ValueType) elem) + { + unique_lock lk(super::mtx_); + return try_push(boost::move(elem), lk); + } + + template + queue_op_status sync_queue::wait_push(BOOST_THREAD_RV_REF(ValueType) elem, unique_lock& lk) + { + if (super::closed(lk)) return queue_op_status::closed; + push(boost::move(elem), lk); + return queue_op_status::success; + } + + template + queue_op_status sync_queue::wait_push(BOOST_THREAD_RV_REF(ValueType) elem) + { + unique_lock lk(super::mtx_); + return wait_push(boost::move(elem), lk); + } + + template + queue_op_status sync_queue::nonblocking_push(BOOST_THREAD_RV_REF(ValueType) elem) + { + unique_lock lk(super::mtx_, try_to_lock); + if (!lk.owns_lock()) + { + return queue_op_status::busy; + } + return try_push(boost::move(elem), lk); + } + + template + void sync_queue::push(BOOST_THREAD_RV_REF(ValueType) elem) + { + unique_lock lk(super::mtx_); + super::throw_if_closed(lk); + push(boost::move(elem), lk); + } + + template + sync_queue& operator<<(sync_queue& sbq, BOOST_THREAD_RV_REF(ValueType) elem) + { + sbq.push(boost::move(elem)); + return sbq; + } + + template + sync_queue& operator<<(sync_queue& sbq, ValueType const&elem) + { + sbq.push(elem); + return sbq; + } + + template + sync_queue& operator>>(sync_queue& sbq, ValueType &elem) + { + sbq.pull(elem); + return sbq; + } + +} +using concurrent::sync_queue; + +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_timed_queue.hpp b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_timed_queue.hpp new file mode 100644 index 00000000000..36223d87152 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/concurrent_queues/sync_timed_queue.hpp @@ -0,0 +1,466 @@ +// Copyright (C) 2014 Ian Forbed +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_THREAD_SYNC_TIMED_QUEUE_HPP +#define BOOST_THREAD_SYNC_TIMED_QUEUE_HPP + +#include + +#include +#include +#include +#include +#include + +#include + +namespace boost +{ +namespace concurrent +{ +namespace detail +{ + template + struct scheduled_type + { + typedef T value_type; + typedef Clock clock; + typedef typename clock::time_point time_point; + T data; + time_point time; + + BOOST_THREAD_COPYABLE_AND_MOVABLE(scheduled_type) + + scheduled_type(T const& pdata, time_point tp) : data(pdata), time(tp) {} + scheduled_type(BOOST_THREAD_RV_REF(T) pdata, time_point tp) : data(boost::move(pdata)), time(tp) {} + + scheduled_type(scheduled_type const& other) : data(other.data), time(other.time) {} + scheduled_type& operator=(BOOST_THREAD_COPY_ASSIGN_REF(scheduled_type) other) { + data = other.data; + time = other.time; + return *this; + } + + scheduled_type(BOOST_THREAD_RV_REF(scheduled_type) other) : data(boost::move(other.data)), time(other.time) {} + scheduled_type& operator=(BOOST_THREAD_RV_REF(scheduled_type) other) { + data = boost::move(other.data); + time = other.time; + return *this; + } + + bool time_not_reached() const + { + return time > clock::now(); + } + + bool operator <(const scheduled_type other) const + { + return this->time > other.time; + } + }; //end struct + +} //end detail namespace + + template + class sync_timed_queue + : private sync_priority_queue > + { + typedef detail::scheduled_type stype; + typedef sync_priority_queue super; + public: + typedef T value_type; + typedef Clock clock; + typedef typename clock::duration duration; + typedef typename clock::time_point time_point; + typedef typename super::underlying_queue_type underlying_queue_type; + typedef typename super::size_type size_type; + typedef typename super::op_status op_status; + + sync_timed_queue() : super() {}; + ~sync_timed_queue() {} + + using super::size; + using super::empty; + using super::full; + using super::close; + using super::closed; + + T pull(); + void pull(T& elem); + + template + queue_op_status pull_until(chrono::time_point const& tp, T& elem); + template + queue_op_status pull_for(chrono::duration const& dura, T& elem); + + queue_op_status try_pull(T& elem); + queue_op_status wait_pull(T& elem); + queue_op_status nonblocking_pull(T& elem); + + template + void push(const T& elem, chrono::time_point const& tp); + template + void push(const T& elem, chrono::duration const& dura); + + template + void push(BOOST_THREAD_RV_REF(T) elem, chrono::time_point const& tp); + template + void push(BOOST_THREAD_RV_REF(T) elem, chrono::duration const& dura); + + template + queue_op_status try_push(const T& elem, chrono::time_point const& tp); + template + queue_op_status try_push(const T& elem, chrono::duration const& dura); + + template + queue_op_status try_push(BOOST_THREAD_RV_REF(T) elem, chrono::time_point const& tp); + template + queue_op_status try_push(BOOST_THREAD_RV_REF(T) elem, chrono::duration const& dura); + + private: + T pull(unique_lock&); + T pull(lock_guard&); + + void pull(unique_lock&, T& elem); + void pull(lock_guard&, T& elem); + + queue_op_status try_pull(unique_lock&, T& elem); + queue_op_status try_pull(lock_guard&, T& elem); + + queue_op_status wait_pull(unique_lock& lk, T& elem); + + bool wait_until_not_empty_time_reached_or_closed(unique_lock&); + T pull_when_time_reached(unique_lock&); + template + queue_op_status pull_when_time_reached_until(unique_lock&, chrono::time_point const& tp, T& elem); + bool time_not_reached(unique_lock&); + bool time_not_reached(lock_guard&); + bool empty_or_time_not_reached(unique_lock&); + bool empty_or_time_not_reached(lock_guard&); + + sync_timed_queue(const sync_timed_queue&); + sync_timed_queue& operator=(const sync_timed_queue&); + sync_timed_queue(BOOST_THREAD_RV_REF(sync_timed_queue)); + sync_timed_queue& operator=(BOOST_THREAD_RV_REF(sync_timed_queue)); + }; //end class + + + template + template + void sync_timed_queue::push(const T& elem, chrono::time_point const& tp) + { + super::push(stype(elem,tp)); + } + + template + template + void sync_timed_queue::push(const T& elem, chrono::duration const& dura) + { + push(elem, clock::now() + dura); + } + + template + template + void sync_timed_queue::push(BOOST_THREAD_RV_REF(T) elem, chrono::time_point const& tp) + { + super::push(stype(boost::move(elem),tp)); + } + + template + template + void sync_timed_queue::push(BOOST_THREAD_RV_REF(T) elem, chrono::duration const& dura) + { + push(boost::move(elem), clock::now() + dura); + } + + + + template + template + queue_op_status sync_timed_queue::try_push(const T& elem, chrono::time_point const& tp) + { + return super::try_push(stype(elem,tp)); + } + + template + template + queue_op_status sync_timed_queue::try_push(const T& elem, chrono::duration const& dura) + { + return try_push(elem,clock::now() + dura); + } + + template + template + queue_op_status sync_timed_queue::try_push(BOOST_THREAD_RV_REF(T) elem, chrono::time_point const& tp) + { + return super::try_push(stype(boost::move(elem), tp)); + } + + template + template + queue_op_status sync_timed_queue::try_push(BOOST_THREAD_RV_REF(T) elem, chrono::duration const& dura) + { + return try_push(boost::move(elem), clock::now() + dura); + } + + /////////////////////////// + template + bool sync_timed_queue::time_not_reached(unique_lock&) + { + return super::data_.top().time_not_reached(); + } + + template + bool sync_timed_queue::time_not_reached(lock_guard&) + { + return super::data_.top().time_not_reached(); + } + + /////////////////////////// + template + bool sync_timed_queue::wait_until_not_empty_time_reached_or_closed(unique_lock& lk) + { + for (;;) + { + if (super::closed(lk)) return true; + while (! super::empty(lk)) { + if (! time_not_reached(lk)) return false; + super::not_empty_.wait_until(lk, super::data_.top().time); + if (super::closed(lk)) return true; + } + if (super::closed(lk)) return true; + super::not_empty_.wait(lk); + } + //return false; + } + + /////////////////////////// + template + T sync_timed_queue::pull_when_time_reached(unique_lock& lk) + { + while (time_not_reached(lk)) + { + super::throw_if_closed(lk); + super::not_empty_.wait_until(lk,super::data_.top().time); + super::wait_until_not_empty(lk); + } + return pull(lk); + } + + template + template + queue_op_status + sync_timed_queue::pull_when_time_reached_until(unique_lock& lk, chrono::time_point const& tp, T& elem) + { + chrono::time_point tpmin = (tp < super::data_.top().time) ? tp : super::data_.top().time; + while (time_not_reached(lk)) + { + super::throw_if_closed(lk); + if (queue_op_status::timeout == super::not_empty_.wait_until(lk, tpmin)) { + if (time_not_reached(lk)) return queue_op_status::not_ready; + return queue_op_status::timeout; + } + } + pull(lk, elem); + return queue_op_status::success; + } + + /////////////////////////// + template + bool sync_timed_queue::empty_or_time_not_reached(unique_lock& lk) + { + if ( super::empty(lk) ) return true; + if ( time_not_reached(lk) ) return true; + return false; + } + template + bool sync_timed_queue::empty_or_time_not_reached(lock_guard& lk) + { + if ( super::empty(lk) ) return true; + if ( time_not_reached(lk) ) return true; + return false; + } + + /////////////////////////// + template + T sync_timed_queue::pull(unique_lock&) + { +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + return boost::move(super::data_.pull().data); +#else + return super::data_.pull().data; +#endif + } + + template + T sync_timed_queue::pull(lock_guard&) + { +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + return boost::move(super::data_.pull().data); +#else + return super::data_.pull().data; +#endif + } + template + T sync_timed_queue::pull() + { + unique_lock lk(super::mtx_); + super::wait_until_not_empty(lk); + return pull_when_time_reached(lk); + } + + /////////////////////////// + template + void sync_timed_queue::pull(unique_lock&, T& elem) + { +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + elem = boost::move(super::data_.pull().data); +#else + elem = super::data_.pull().data; +#endif + } + + template + void sync_timed_queue::pull(lock_guard&, T& elem) + { +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + elem = boost::move(super::data_.pull().data); +#else + elem = super::data_.pull().data; +#endif + } + + template + void sync_timed_queue::pull(T& elem) + { + unique_lock lk(super::mtx_); + super::wait_until_not_empty(lk); + elem = pull_when_time_reached(lk); + } + + ////////////////////// + template + template + queue_op_status + sync_timed_queue::pull_until(chrono::time_point const& tp, T& elem) + { + unique_lock lk(super::mtx_); + + if (queue_op_status::timeout == super::wait_until_not_empty_until(lk, tp)) + return queue_op_status::timeout; + return pull_when_time_reached_until(lk, tp, elem); + } + + ////////////////////// + template + template + queue_op_status + sync_timed_queue::pull_for(chrono::duration const& dura, T& elem) + { + return pull_until(clock::now() + dura, elem); + } + + /////////////////////////// + template + queue_op_status sync_timed_queue::try_pull(unique_lock& lk, T& elem) + { + if ( super::empty(lk) ) + { + if (super::closed(lk)) return queue_op_status::closed; + return queue_op_status::empty; + } + if ( time_not_reached(lk) ) + { + if (super::closed(lk)) return queue_op_status::closed; + return queue_op_status::not_ready; + } + + pull(lk, elem); + return queue_op_status::success; + } + template + queue_op_status sync_timed_queue::try_pull(lock_guard& lk, T& elem) + { + if ( super::empty(lk) ) + { + if (super::closed(lk)) return queue_op_status::closed; + return queue_op_status::empty; + } + if ( time_not_reached(lk) ) + { + if (super::closed(lk)) return queue_op_status::closed; + return queue_op_status::not_ready; + } + pull(lk, elem); + return queue_op_status::success; + } + + template + queue_op_status sync_timed_queue::try_pull(T& elem) + { + lock_guard lk(super::mtx_); + return try_pull(lk, elem); + } + + /////////////////////////// + template + queue_op_status sync_timed_queue::wait_pull(unique_lock& lk, T& elem) + { + if (super::empty(lk)) + { + if (super::closed(lk)) return queue_op_status::closed; + } + bool has_been_closed = wait_until_not_empty_time_reached_or_closed(lk); + if (has_been_closed) return queue_op_status::closed; + pull(lk, elem); + return queue_op_status::success; + } + + template + queue_op_status sync_timed_queue::wait_pull(T& elem) + { + unique_lock lk(super::mtx_); + return wait_pull(lk, elem); + } + +// /////////////////////////// +// template +// queue_op_status sync_timed_queue::wait_pull(unique_lock &lk, T& elem) +// { +// if (super::empty(lk)) +// { +// if (super::closed(lk)) return queue_op_status::closed; +// } +// bool has_been_closed = super::wait_until_not_empty_or_closed(lk); +// if (has_been_closed) return queue_op_status::closed; +// pull(lk, elem); +// return queue_op_status::success; +// } +// template +// queue_op_status sync_timed_queue::wait_pull(T& elem) +// { +// unique_lock lk(super::mtx_); +// return wait_pull(lk, elem); +// } + + /////////////////////////// + template + queue_op_status sync_timed_queue::nonblocking_pull(T& elem) + { + unique_lock lk(super::mtx_, try_to_lock); + if (! lk.owns_lock()) return queue_op_status::busy; + return try_pull(lk, elem); + } + +} //end concurrent namespace + +using concurrent::sync_timed_queue; + +} //end boost namespace +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/condition.hpp b/src/third_party/boost-1.60.0/boost/thread/condition.hpp new file mode 100644 index 00000000000..9567df98251 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/condition.hpp @@ -0,0 +1,21 @@ +#ifndef BOOST_THREAD_CONDITION_HPP +#define BOOST_THREAD_CONDITION_HPP +// (C) Copyright 2007 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include + +#if defined BOOST_THREAD_PROVIDES_CONDITION + +#include + +namespace boost +{ + typedef condition_variable_any condition; +} + +#endif +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/condition_variable.hpp b/src/third_party/boost-1.60.0/boost/thread/condition_variable.hpp new file mode 100644 index 00000000000..8f8e9f2ed65 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/condition_variable.hpp @@ -0,0 +1,21 @@ +#ifndef BOOST_THREAD_CONDITION_VARIABLE_HPP +#define BOOST_THREAD_CONDITION_VARIABLE_HPP + +// condition_variable.hpp +// +// (C) Copyright 2007 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#if defined(BOOST_THREAD_PLATFORM_WIN32) +#include +#elif defined(BOOST_THREAD_PLATFORM_PTHREAD) +#include +#else +#error "Boost threads unavailable on this platform" +#endif + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/csbl/deque.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/deque.hpp new file mode 100644 index 00000000000..2b26a46e1ac --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/csbl/deque.hpp @@ -0,0 +1,45 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// 2013/10 Vicente J. Botet Escriba +// Creation. + +#ifndef BOOST_CSBL_DEQUE_HPP +#define BOOST_CSBL_DEQUE_HPP + +#include +// MSVC has some trouble instantiating a non_copyable type +//C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xmemory0(606) : error C2248: 'non_copyable::non_copyable' : cannot access private member declared in class 'non_copyable' +// ..\libs\thread\test\sync\mutual_exclusion\queue_views\single_thread_pass.cpp(24) : see declaration of 'non_copyable::non_copyable' +// ..\libs\thread\test\sync\mutual_exclusion\queue_views\single_thread_pass.cpp(23) : see declaration of 'non_copyable' +// C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xmemory0(605) : while compiling class template member function 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)' +// with +// [ +// _Ty=non_copyable +// ] +#if defined BOOST_THREAD_USES_BOOST_DEQUE || defined BOOST_NO_CXX11_RVALUE_REFERENCES || (defined _MSC_VER && _MSC_FULL_VER < 180020827) +#ifndef BOOST_THREAD_USES_BOOST_DEQUE +#define BOOST_THREAD_USES_BOOST_DEQUE +#endif +#include +#else +#include +#endif + +namespace boost +{ + namespace csbl + { +#if defined BOOST_THREAD_USES_BOOST_DEQUE + using ::boost::container::deque; + +#else + using ::std::deque; + +#endif + + } +} +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/csbl/devector.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/devector.hpp new file mode 100644 index 00000000000..c2bc0bbe992 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/csbl/devector.hpp @@ -0,0 +1,102 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// 2013/10 Vicente J. Botet Escriba +// Creation. + +#ifndef BOOST_CSBL_DEVECTOR_HPP +#define BOOST_CSBL_DEVECTOR_HPP + +#include + +#include +#include + +namespace boost +{ + namespace csbl + { + template + class devector + { + typedef csbl::vector vector_type; + vector_type data_; + std::size_t front_index_; + + BOOST_COPYABLE_AND_MOVABLE(devector) + + template + void priv_push_back(BOOST_FWD_REF(U) x) + { data_.push_back(boost::forward(x)); } + + public: + typedef typename vector_type::size_type size_type; + typedef typename vector_type::reference reference; + typedef typename vector_type::const_reference const_reference; + + + devector() : front_index_(0) {} + devector(devector const& x) BOOST_NOEXCEPT + : data_(x.data_), + front_index_(x.front_index_) + {} + devector(BOOST_RV_REF(devector) x) BOOST_NOEXCEPT + : data_(boost::move(x.data_)), + front_index_(x.front_index_) + {} + + devector& operator=(BOOST_COPY_ASSIGN_REF(devector) x) + { + if (&x != this) + { + data_ = x.data_; + front_index_ = x.front_index_; + } + return *this; + } + + devector& operator=(BOOST_RV_REF(devector) x) +#if defined BOOST_THREAD_USES_BOOST_VECTOR + BOOST_NOEXCEPT_IF(vector_type::allocator_traits_type::propagate_on_container_move_assignment::value) +#endif + { + data_ = boost::move(x.data_); + front_index_ = x.front_index_; + return *this; + } + + bool empty() const BOOST_NOEXCEPT + { return data_.size() == front_index_; } + + size_type size() const BOOST_NOEXCEPT + { return data_.size() - front_index_; } + + reference front() BOOST_NOEXCEPT + { return data_[front_index_]; } + + const_reference front() const BOOST_NOEXCEPT + { return data_[front_index_]; } + + reference back() BOOST_NOEXCEPT + { return data_.back(); } + + const_reference back() const BOOST_NOEXCEPT + { return data_.back(); } + + BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back) + + void pop_front() + { + ++front_index_; + if (empty()) { + data_.clear(); + front_index_=0; + } + } + + }; + } +} +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/csbl/functional.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/functional.hpp new file mode 100644 index 00000000000..7a7e928b70f --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/csbl/functional.hpp @@ -0,0 +1,49 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// 2013/10 Vicente J. Botet Escriba +// Creation. + +#ifndef BOOST_CSBL_FUNCTIONAL_HPP +#define BOOST_CSBL_FUNCTIONAL_HPP + +#include + +#include + +#if defined BOOST_THREAD_USES_BOOST_FUNCTIONAL || defined BOOST_NO_CXX11_HDR_FUNCTIONAL || defined BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_THREAD_USES_BOOST_FUNCTIONAL +#define BOOST_THREAD_USES_BOOST_FUNCTIONAL +#endif +#include +#endif + +namespace boost +{ + namespace csbl + { +#if defined BOOST_THREAD_USES_BOOST_FUNCTIONAL + using ::boost::function; +#else + // D.8.1, base (deprecated): + // 20.9.3, reference_wrapper: + // 20.9.4, arithmetic operations: + // 20.9.5, comparisons: + // 20.9.6, logical operations: + // 20.9.7, bitwise operations: + // 20.9.8, negators: + // 20.9.9, bind: + // D.9, binders (deprecated): + // D.8.2.1, adaptors (deprecated): + // D.8.2.2, adaptors (deprecated): + // 20.9.10, member function adaptors: + // 20.9.11 polymorphic function wrappers: + using ::std::function; + // 20.9.12, hash function primary template: +#endif + + } +} +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/csbl/list.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/list.hpp new file mode 100644 index 00000000000..52ff45d3497 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/csbl/list.hpp @@ -0,0 +1,35 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// 2013/10 Vicente J. Botet Escriba +// Creation. + +#ifndef BOOST_CSBL_LIST_HPP +#define BOOST_CSBL_LIST_HPP + +#include + +#if defined BOOST_THREAD_USES_BOOST_LIST || defined BOOST_NO_CXX11_RVALUE_REFERENCES +#ifndef BOOST_THREAD_USES_BOOST_LIST +#define BOOST_THREAD_USES_BOOST_LIST +#endif +#include +#else +#include +#endif + +namespace boost +{ + namespace csbl + { +#if defined BOOST_THREAD_USES_BOOST_LIST + using ::boost::container::list; +#else + using ::std::list; +#endif + + } +} +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/csbl/memory.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/memory.hpp new file mode 100644 index 00000000000..e076f11ad30 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/csbl/memory.hpp @@ -0,0 +1,61 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// 2013/10 Vicente J. Botet Escriba +// Creation. + +#ifndef BOOST_CSBL_MEMORY_HPP +#define BOOST_CSBL_MEMORY_HPP + +// 20.7.2 Header synopsis + +// 20.7.3, pointer traits +#include + +// 20.7.4, pointer safety +// 20.7.5, pointer alignment function + +// 20.7.6, allocator argument tag +#include + +// 20.7.8, allocator traits +#include + +// 20.7.7, uses_allocator +#include + +// 20.7.9, the default allocator: +namespace boost +{ + namespace csbl + { + using ::std::allocator; + } +} +// 20.7.10, raw storage iterator: +// 20.7.11, temporary buffers: +// 20.7.12, specialized algorithms: + +// 20.8.1 class template unique_ptr: +// default_delete +#include +#include + +// 20.8.2.1, class bad_weak_ptr: +// 20.8.2.2, class template shared_ptr: +// 20.8.2.2.6, shared_ptr creation +// 20.8.2.2.7, shared_ptr comparisons: +// 20.8.2.2.8, shared_ptr specialized algorithms: +// 20.8.2.2.9, shared_ptr casts: +// 20.8.2.2.10, shared_ptr get_deleter: +// 20.8.2.2.11, shared_ptr I/O: +// 20.8.2.3, class template weak_ptr: +// 20.8.2.3.6, weak_ptr specialized algorithms: +// 20.8.2.3.7, class template owner_less: +// 20.8.2.4, class template enable_shared_from_this: +// 20.8.2.5, shared_ptr atomic access: +// 20.8.2.6 hash support + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/csbl/memory/allocator_arg.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/memory/allocator_arg.hpp new file mode 100644 index 00000000000..354cdaee885 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/csbl/memory/allocator_arg.hpp @@ -0,0 +1,41 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// 2013/10 Vicente J. Botet Escriba +// Creation. + +#ifndef BOOST_CSBL_MEMORY_ALLOCATOR_ARG_HPP +#define BOOST_CSBL_MEMORY_ALLOCATOR_ARG_HPP + +#include + +// 20.7.6, allocator argument tag +#if defined BOOST_NO_CXX11_ALLOCATOR +#include + +namespace boost +{ + namespace csbl + { + using ::boost::container::allocator_arg_t; + using ::boost::container::allocator_arg; + } +} +#else +namespace boost +{ + namespace csbl + { + using ::std::allocator_arg_t; + using ::std::allocator_arg; + } +} +#endif // BOOST_NO_CXX11_ALLOCATOR +namespace boost +{ + using ::boost::csbl::allocator_arg_t; + using ::boost::csbl::allocator_arg; +} +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/csbl/memory/allocator_traits.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/memory/allocator_traits.hpp new file mode 100644 index 00000000000..3737cd85def --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/csbl/memory/allocator_traits.hpp @@ -0,0 +1,35 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// 2013/10 Vicente J. Botet Escriba +// Creation. + +#ifndef BOOST_CSBL_MEMORY_ALLOCATOR_TRAITS_HPP +#define BOOST_CSBL_MEMORY_ALLOCATOR_TRAITS_HPP + +#include + +// 20.7.8, allocator traits +#if defined BOOST_NO_CXX11_ALLOCATOR +#include + +namespace boost +{ + namespace csbl + { + using ::boost::container::allocator_traits; + } +} +#else +namespace boost +{ + namespace csbl + { + using ::std::allocator_traits; + } +} +#endif // BOOST_NO_CXX11_POINTER_TRAITS + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/csbl/memory/config.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/memory/config.hpp new file mode 100644 index 00000000000..7b0596ac490 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/csbl/memory/config.hpp @@ -0,0 +1,16 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// 2013/10 Vicente J. Botet Escriba +// Creation. + +#ifndef BOOST_CSBL_MEMORY_CONFIG_HPP +#define BOOST_CSBL_MEMORY_CONFIG_HPP + +#include + +#include + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/csbl/memory/default_delete.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/memory/default_delete.hpp new file mode 100644 index 00000000000..d20153b3096 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/csbl/memory/default_delete.hpp @@ -0,0 +1,41 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// 2013/10 Vicente J. Botet Escriba +// Creation. + +#ifndef BOOST_CSBL_MEMORY_DEFAULT_DELETE_HPP +#define BOOST_CSBL_MEMORY_DEFAULT_DELETE_HPP + +#include + +// 20.8.1 class template unique_ptr: +// default_delete + +#if defined BOOST_NO_CXX11_SMART_PTR +#include + +namespace boost +{ + namespace csbl + { + using ::boost::movelib::default_delete; + } +} +#else +namespace boost +{ + namespace csbl + { + using ::std::default_delete; + } +} +#endif // defined BOOST_NO_CXX11_SMART_PTR + +namespace boost +{ + using ::boost::csbl::default_delete; +} +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/csbl/memory/pointer_traits.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/memory/pointer_traits.hpp new file mode 100644 index 00000000000..320f8e9e774 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/csbl/memory/pointer_traits.hpp @@ -0,0 +1,35 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// 2013/10 Vicente J. Botet Escriba +// Creation. + +#ifndef BOOST_CSBL_MEMORY_POINTER_TRAITS_HPP +#define BOOST_CSBL_MEMORY_POINTER_TRAITS_HPP + +#include + +// 20.7.3, pointer traits +#if defined BOOST_NO_CXX11_ALLOCATOR +#include + +namespace boost +{ + namespace csbl + { + using ::boost::intrusive::pointer_traits; + } +} +#else +namespace boost +{ + namespace csbl + { + using ::std::pointer_traits; + } +} +#endif // BOOST_NO_CXX11_ALLOCATOR + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/csbl/memory/scoped_allocator.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/memory/scoped_allocator.hpp new file mode 100644 index 00000000000..a92f3d85146 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/csbl/memory/scoped_allocator.hpp @@ -0,0 +1,35 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// 2013/10 Vicente J. Botet Escriba +// Creation. + +#ifndef BOOST_CSBL_MEMORY_SCOPED_ALLOCATOR_HPP +#define BOOST_CSBL_MEMORY_SCOPED_ALLOCATOR_HPP + +#include + +// 20.7.7, uses_allocator +#if defined BOOST_NO_CXX11_ALLOCATOR +#include + +namespace boost +{ + namespace csbl + { + using ::boost::container::uses_allocator; + } +} +#else +namespace boost +{ + namespace csbl + { + using ::std::uses_allocator; + } +} +#endif // BOOST_NO_CXX11_POINTER_TRAITS + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/csbl/memory/shared_ptr.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/memory/shared_ptr.hpp new file mode 100644 index 00000000000..e9a9383723a --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/csbl/memory/shared_ptr.hpp @@ -0,0 +1,42 @@ +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// 2014/10 Vicente J. Botet Escriba +// Creation. + +#ifndef BOOST_CSBL_MEMORY_SHARED_PTR_HPP +#define BOOST_CSBL_MEMORY_SHARED_PTR_HPP + +#include + +#if defined BOOST_NO_CXX11_SMART_PTR + +#include +#include + +namespace boost +{ + namespace csbl + { + using ::boost::shared_ptr; + using ::boost::make_shared; + } +} + +#else + +#include + +namespace boost +{ + namespace csbl + { + using std::shared_ptr; + using std::make_shared; + } +} + +#endif +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/csbl/memory/unique_ptr.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/memory/unique_ptr.hpp new file mode 100644 index 00000000000..17abf54e92a --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/csbl/memory/unique_ptr.hpp @@ -0,0 +1,28 @@ +// Copyright (C) 2013-2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// 2013/10 Vicente J. Botet Escriba +// Creation using interprocess::unique_ptr. +// 2014/09 Vicente J. Botet Escriba +// Adaptation to movelib::unique_ptr + +#ifndef BOOST_CSBL_MEMORY_UNIQUE_PTR_HPP +#define BOOST_CSBL_MEMORY_UNIQUE_PTR_HPP + +#include + +#include +#include + +namespace boost +{ + namespace csbl + { + using ::boost::movelib::unique_ptr; + using ::boost::movelib::make_unique; + + } +} +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/csbl/queue.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/queue.hpp new file mode 100644 index 00000000000..1aa645d18fb --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/csbl/queue.hpp @@ -0,0 +1,45 @@ +// Copyright (C) 2015 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// 2013/10 Vicente J. Botet Escriba +// Creation. + +#ifndef BOOST_CSBL_QUEUE_HPP +#define BOOST_CSBL_QUEUE_HPP + +#include +// MSVC has some trouble instantiating a non_copyable type +//C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xmemory0(606) : error C2248: 'non_copyable::non_copyable' : cannot access private member declared in class 'non_copyable' +// ..\libs\thread\test\sync\mutual_exclusion\queue_views\single_thread_pass.cpp(24) : see declaration of 'non_copyable::non_copyable' +// ..\libs\thread\test\sync\mutual_exclusion\queue_views\single_thread_pass.cpp(23) : see declaration of 'non_copyable' +// C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE\xmemory0(605) : while compiling class template member function 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)' +// with +// [ +// _Ty=non_copyable +// ] +#if defined BOOST_THREAD_USES_BOOST_QUEUE || defined BOOST_NO_CXX11_RVALUE_REFERENCES || (defined _MSC_VER && _MSC_FULL_VER < 180020827) +#ifndef BOOST_THREAD_USES_BOOST_QUEUE +#define BOOST_THREAD_USES_BOOST_QUEUE +#endif +#include +#else +#include +#endif + +namespace boost +{ + namespace csbl + { +#if defined BOOST_THREAD_USES_BOOST_QUEUE + using ::boost::container::queue; + +#else + using ::std::queue; + +#endif + + } +} +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/csbl/tuple.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/tuple.hpp new file mode 100644 index 00000000000..860229ebe0b --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/csbl/tuple.hpp @@ -0,0 +1,49 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// 2013/10 Vicente J. Botet Escriba +// Creation. + +#ifndef BOOST_CSBL_TUPLE_HPP +#define BOOST_CSBL_TUPLE_HPP + +#include + +#if defined BOOST_THREAD_USES_BOOST_TUPLE || defined BOOST_NO_CXX11_HDR_TUPLE || defined BOOST_NO_CXX11_RVALUE_REFERENCES +#include +#ifndef BOOST_THREAD_USES_BOOST_TUPLE +#define BOOST_THREAD_USES_BOOST_TUPLE +#endif + +#else +#include +#endif + +namespace boost +{ + namespace csbl + { +#if defined BOOST_THREAD_USES_BOOST_TUPLE + using ::boost::tuple; + using ::boost::get; + using ::boost::make_tuple; + //using ::boost::tuple_size; +#else + // 20.4.2, class template tuple: + using ::std::tuple; + using ::std::get; + using ::std::make_tuple; + using ::std::tuple_size; + // 20.4.2.4, tuple creation functions: + // 20.4.2.5, tuple helper classes: + // 20.4.2.6, element access: + // 20.4.2.7, relational operators: + // 20.4.2.8, allocator-related traits + // 20.4.2.9, specialized algorithms: +#endif + + } +} +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/csbl/vector.hpp b/src/third_party/boost-1.60.0/boost/thread/csbl/vector.hpp new file mode 100644 index 00000000000..c77a5b143bb --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/csbl/vector.hpp @@ -0,0 +1,35 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// 2013/10 Vicente J. Botet Escriba +// Creation. + +#ifndef BOOST_CSBL_VECTOR_HPP +#define BOOST_CSBL_VECTOR_HPP + +#include + +#if defined BOOST_THREAD_USES_BOOST_VECTOR || defined BOOST_NO_CXX11_RVALUE_REFERENCES || defined BOOST_MSVC +#ifndef BOOST_THREAD_USES_BOOST_VECTOR +#define BOOST_THREAD_USES_BOOST_VECTOR +#endif +#include +#else +#include +#endif + +namespace boost +{ + namespace csbl + { +#if defined BOOST_THREAD_USES_BOOST_VECTOR + using ::boost::container::vector; +#else + using ::std::vector; +#endif + + } +} +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/cv_status.hpp b/src/third_party/boost-1.60.0/boost/thread/cv_status.hpp new file mode 100644 index 00000000000..e52de4a5220 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/cv_status.hpp @@ -0,0 +1,26 @@ +// cv_status.hpp +// +// Copyright (C) 2011 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_THREAD_CV_STATUS_HPP +#define BOOST_THREAD_CV_STATUS_HPP + +#include + +namespace boost +{ + + // enum class cv_status; + BOOST_SCOPED_ENUM_DECLARE_BEGIN(cv_status) + { + no_timeout, + timeout + } + BOOST_SCOPED_ENUM_DECLARE_END(cv_status) +} + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/config.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/config.hpp new file mode 100644 index 00000000000..475dadbaaa0 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/config.hpp @@ -0,0 +1,465 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// Copyright (C) 2011-2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_THREAD_CONFIG_WEK01032003_HPP +#define BOOST_THREAD_CONFIG_WEK01032003_HPP + +#include +#include +#include + +//#define BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS +// ATTRIBUTE_MAY_ALIAS + +#if defined(__GNUC__) && !defined(__INTEL_COMPILER) + + // GCC since 3.3 has may_alias attribute that helps to alleviate optimizer issues with + // regard to violation of the strict aliasing rules. + + #define BOOST_THREAD_DETAIL_USE_ATTRIBUTE_MAY_ALIAS + #define BOOST_THREAD_ATTRIBUTE_MAY_ALIAS __attribute__((__may_alias__)) +#else + #define BOOST_THREAD_ATTRIBUTE_MAY_ALIAS +#endif + + +#if defined BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED +#define BOOST_THREAD_ASSERT_PRECONDITION(EXPR, EX) \ + if (EXPR) {} else boost::throw_exception(EX) +#define BOOST_THREAD_VERIFY_PRECONDITION(EXPR, EX) \ + if (EXPR) {} else boost::throw_exception(EX) +#define BOOST_THREAD_THROW_ELSE_RETURN(EX, RET) \ + boost::throw_exception(EX) +#else +#define BOOST_THREAD_ASSERT_PRECONDITION(EXPR, EX) +#define BOOST_THREAD_VERIFY_PRECONDITION(EXPR, EX) \ + (void)(EXPR) +#define BOOST_THREAD_THROW_ELSE_RETURN(EX, RET) \ + return (RET) +#endif + +// This compiler doesn't support Boost.Chrono +#if defined __IBMCPP__ && (__IBMCPP__ < 1100) \ + && ! defined BOOST_THREAD_DONT_USE_CHRONO +#define BOOST_THREAD_DONT_USE_CHRONO +#if ! defined BOOST_THREAD_USES_DATETIME +#define BOOST_THREAD_USES_DATETIME +#endif +#endif + +// This compiler doesn't support Boost.Move +#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) \ + && ! defined BOOST_THREAD_DONT_USE_MOVE +#define BOOST_THREAD_DONT_USE_MOVE +#endif + +// This compiler doesn't support Boost.Container Allocators files +#if defined __SUNPRO_CC \ + && ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS +#define BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS +#endif + +#if defined _WIN32_WCE && _WIN32_WCE==0x501 \ + && ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS +#define BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS +#endif + + +#if defined BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX || defined BOOST_NO_CXX11_HDR_INITIALIZER_LIST +#define BOOST_THREAD_NO_CXX11_HDR_INITIALIZER_LIST +#define BOOST_THREAD_NO_MAKE_LOCK_GUARD +#define BOOST_THREAD_NO_MAKE_STRICT_LOCK +#define BOOST_THREAD_NO_MAKE_NESTED_STRICT_LOCK +#endif + +#if defined(BOOST_NO_CXX11_HDR_TUPLE) || defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +#define BOOST_THREAD_NO_MAKE_UNIQUE_LOCKS +#define BOOST_THREAD_NO_SYNCHRONIZE +#elif defined _MSC_VER && _MSC_VER <= 1600 +// C++ features supported by VC++ 10 (aka 2010) +#define BOOST_THREAD_NO_MAKE_UNIQUE_LOCKS +#define BOOST_THREAD_NO_SYNCHRONIZE +#endif + +/// BASIC_THREAD_ID +#if ! defined BOOST_THREAD_DONT_PROVIDE_BASIC_THREAD_ID \ + && ! defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID +#define BOOST_THREAD_PROVIDES_BASIC_THREAD_ID +#endif + +/// RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR +//#if defined BOOST_NO_CXX11_RVALUE_REFERENCES || defined BOOST_MSVC +#define BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR +//#endif + +// Default version +#if !defined BOOST_THREAD_VERSION +#define BOOST_THREAD_VERSION 2 +#else +#if BOOST_THREAD_VERSION!=2 && BOOST_THREAD_VERSION!=3 && BOOST_THREAD_VERSION!=4 +#error "BOOST_THREAD_VERSION must be 2, 3 or 4" +#endif +#endif + +// CHRONO +// Uses Boost.Chrono by default if not stated the opposite defining BOOST_THREAD_DONT_USE_CHRONO +#if ! defined BOOST_THREAD_DONT_USE_CHRONO \ + && ! defined BOOST_THREAD_USES_CHRONO +#define BOOST_THREAD_USES_CHRONO +#endif + +#if ! defined BOOST_THREAD_DONT_USE_ATOMIC \ + && ! defined BOOST_THREAD_USES_ATOMIC +#define BOOST_THREAD_USES_ATOMIC +//#define BOOST_THREAD_DONT_USE_ATOMIC +#endif + +#if defined BOOST_THREAD_USES_ATOMIC +// Andrey Semashev +#define BOOST_THREAD_ONCE_ATOMIC +#else +//#elif ! defined BOOST_NO_CXX11_THREAD_LOCAL && ! defined BOOST_NO_THREAD_LOCAL && ! defined BOOST_THREAD_NO_UINT32_PSEUDO_ATOMIC +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2444.html#Appendix +#define BOOST_THREAD_ONCE_FAST_EPOCH +#endif +#if BOOST_THREAD_VERSION==2 + +// PROVIDE_PROMISE_LAZY +#if ! defined BOOST_THREAD_DONT_PROVIDE_PROMISE_LAZY \ + && ! defined BOOST_THREAD_PROVIDES_PROMISE_LAZY +#define BOOST_THREAD_PROVIDES_PROMISE_LAZY +#endif + +// PROVIDE_THREAD_EQ +#if ! defined BOOST_THREAD_DONT_PROVIDE_THREAD_EQ \ + && ! defined BOOST_THREAD_PROVIDES_THREAD_EQ +#define BOOST_THREAD_PROVIDES_THREAD_EQ +#endif + +#endif + +#if BOOST_THREAD_VERSION>=3 + +// ONCE_CXX11 +// fixme BOOST_THREAD_PROVIDES_ONCE_CXX11 doesn't works when thread.cpp is compiled BOOST_THREAD_VERSION 3 +#if ! defined BOOST_THREAD_DONT_PROVIDE_ONCE_CXX11 \ + && ! defined BOOST_THREAD_PROVIDES_ONCE_CXX11 +#define BOOST_THREAD_DONT_PROVIDE_ONCE_CXX11 +#endif + +// THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE +#if ! defined BOOST_THREAD_DONT_PROVIDE_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE \ + && ! defined BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE +#define BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE +#endif + +// THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE +#if ! defined BOOST_THREAD_DONT_PROVIDE_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE \ + && ! defined BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE +#define BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE +#endif + +// PROVIDE_FUTURE +#if ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE \ + && ! defined BOOST_THREAD_PROVIDES_FUTURE +#define BOOST_THREAD_PROVIDES_FUTURE +#endif + +// FUTURE_CTOR_ALLOCATORS +#if ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_CTOR_ALLOCATORS \ + && ! defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS +#define BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS +#endif + +// SHARED_MUTEX_UPWARDS_CONVERSIONS +#if ! defined BOOST_THREAD_DONT_PROVIDE_SHARED_MUTEX_UPWARDS_CONVERSIONS \ + && ! defined BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS +#define BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS +#endif + +// PROVIDE_EXPLICIT_LOCK_CONVERSION +#if ! defined BOOST_THREAD_DONT_PROVIDE_EXPLICIT_LOCK_CONVERSION \ + && ! defined BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION +#define BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION +#endif + +// GENERIC_SHARED_MUTEX_ON_WIN +#if ! defined BOOST_THREAD_DONT_PROVIDE_GENERIC_SHARED_MUTEX_ON_WIN \ + && ! defined BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN +#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN +#endif + +// USE_MOVE +#if ! defined BOOST_THREAD_DONT_USE_MOVE \ + && ! defined BOOST_THREAD_USES_MOVE +#define BOOST_THREAD_USES_MOVE +#endif + +#endif + +// deprecated since version 4 +#if BOOST_THREAD_VERSION < 4 + +// NESTED_LOCKS +#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS \ + && ! defined BOOST_THREAD_DONT_PROVIDE_NESTED_LOCKS +#define BOOST_THREAD_PROVIDES_NESTED_LOCKS +#endif + +// CONDITION +#if ! defined BOOST_THREAD_PROVIDES_CONDITION \ + && ! defined BOOST_THREAD_DONT_PROVIDE_CONDITION +#define BOOST_THREAD_PROVIDES_CONDITION +#endif + +// USE_DATETIME +#if ! defined BOOST_THREAD_DONT_USE_DATETIME \ + && ! defined BOOST_THREAD_USES_DATETIME +#define BOOST_THREAD_USES_DATETIME +#endif +#endif + +#if BOOST_THREAD_VERSION>=4 + +// SIGNATURE_PACKAGED_TASK +#if ! defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK \ + && ! defined BOOST_THREAD_DONT_PROVIDE_SIGNATURE_PACKAGED_TASK +#define BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK +#endif + +// VARIADIC_THREAD +#if ! defined BOOST_THREAD_PROVIDES_VARIADIC_THREAD \ + && ! defined BOOST_THREAD_DONT_PROVIDE_VARIADIC_THREAD + +#if ! defined(BOOST_NO_SFINAE_EXPR) && \ + ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \ + ! defined(BOOST_NO_CXX11_DECLTYPE) && \ + ! defined(BOOST_NO_CXX11_DECLTYPE_N3276) && \ + ! defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) && \ + ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \ + ! defined(BOOST_NO_CXX11_HDR_TUPLE) + +#define BOOST_THREAD_PROVIDES_VARIADIC_THREAD +#endif +#endif + +#if ! defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY \ + && ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_WHEN_ALL_WHEN_ANY + +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \ + ! defined(BOOST_NO_CXX11_HDR_TUPLE) + +#define BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY +#endif +#endif + +// ! defined(BOOST_NO_SFINAE_EXPR) && +// ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && +// ! defined(BOOST_NO_CXX11_AUTO) && +// ! defined(BOOST_NO_CXX11_DECLTYPE) && +// ! defined(BOOST_NO_CXX11_DECLTYPE_N3276) && + + +// MAKE_READY_AT_THREAD_EXIT +#if ! defined BOOST_THREAD_PROVIDES_MAKE_READY_AT_THREAD_EXIT \ + && ! defined BOOST_THREAD_DONT_PROVIDE_MAKE_READY_AT_THREAD_EXIT + +//#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#define BOOST_THREAD_PROVIDES_MAKE_READY_AT_THREAD_EXIT +//#endif +#endif + +// FUTURE_CONTINUATION +#if ! defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION \ + && ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_CONTINUATION +#define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION +#endif + +#if ! defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP \ + && ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_UNWRAP +#define BOOST_THREAD_PROVIDES_FUTURE_UNWRAP +#endif + +// FUTURE_INVALID_AFTER_GET +#if ! defined BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET \ + && ! defined BOOST_THREAD_DONT_PROVIDE_FUTURE_INVALID_AFTER_GET +#define BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET +#endif + +// NESTED_LOCKS +#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS \ + && ! defined BOOST_THREAD_DONT_PROVIDE_NESTED_LOCKS +#define BOOST_THREAD_DONT_PROVIDE_NESTED_LOCKS +#endif + +// CONDITION +#if ! defined BOOST_THREAD_PROVIDES_CONDITION \ + && ! defined BOOST_THREAD_DONT_PROVIDE_CONDITION +#define BOOST_THREAD_DONT_PROVIDE_CONDITION +#endif + +#endif // BOOST_THREAD_VERSION>=4 + +// INTERRUPTIONS +#if ! defined BOOST_THREAD_PROVIDES_INTERRUPTIONS \ + && ! defined BOOST_THREAD_DONT_PROVIDE_INTERRUPTIONS +#define BOOST_THREAD_PROVIDES_INTERRUPTIONS +#endif + +// CORRELATIONS + +// EXPLICIT_LOCK_CONVERSION. +#if defined BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION +#define BOOST_THREAD_EXPLICIT_LOCK_CONVERSION explicit +#else +#define BOOST_THREAD_EXPLICIT_LOCK_CONVERSION +#endif + +// BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN is defined if BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS +#if defined BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS \ +&& ! defined BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN +#define BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN +#endif + +// For C++11 call_once interface the compiler MUST support constexpr. +// Otherwise once_flag would be initialized during dynamic initialization stage, which is not thread-safe. +#if defined(BOOST_THREAD_PROVIDES_ONCE_CXX11) +#if defined(BOOST_NO_CXX11_CONSTEXPR) +#undef BOOST_THREAD_PROVIDES_ONCE_CXX11 +#endif +#endif + +#if defined(BOOST_THREAD_PLATFORM_WIN32) && defined BOOST_THREAD_DONT_USE_DATETIME +#undef BOOST_THREAD_DONT_USE_DATETIME +#define BOOST_THREAD_USES_DATETIME +#endif + +#if defined(BOOST_THREAD_PLATFORM_WIN32) && defined BOOST_THREAD_DONT_USE_CHRONO +#undef BOOST_THREAD_DONT_USE_CHRONO +#define BOOST_THREAD_USES_CHRONO +#endif + +// BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 defined by default up to Boost 1.55 +// BOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0 defined by default up to Boost 1.55 +#if defined BOOST_THREAD_PROVIDES_DEPRECATED_FEATURES_SINCE_V3_0_0 + +#if ! defined BOOST_THREAD_PROVIDES_THREAD_EQ +#define BOOST_THREAD_PROVIDES_THREAD_EQ +#endif + +#endif + + +//#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES || defined BOOST_THREAD_USES_MOVE +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES +#define BOOST_THREAD_FUTURE_USES_OPTIONAL +#endif + +#if BOOST_WORKAROUND(__BORLANDC__, < 0x600) +# pragma warn -8008 // Condition always true/false +# pragma warn -8080 // Identifier declared but never used +# pragma warn -8057 // Parameter never used +# pragma warn -8066 // Unreachable code +#endif + +#include + +#if defined(BOOST_THREAD_PLATFORM_WIN32) +#else + # if defined(BOOST_HAS_PTHREAD_DELAY_NP) || defined(BOOST_HAS_NANOSLEEP) + # define BOOST_THREAD_SLEEP_FOR_IS_STEADY + # endif +#endif + +// provided for backwards compatibility, since this +// macro was used for several releases by mistake. +#if defined(BOOST_THREAD_DYN_DLL) && ! defined BOOST_THREAD_DYN_LINK +# define BOOST_THREAD_DYN_LINK +#endif + +// compatibility with the rest of Boost's auto-linking code: +#if defined(BOOST_THREAD_DYN_LINK) || defined(BOOST_ALL_DYN_LINK) +# undef BOOST_THREAD_USE_LIB +# if !defined(BOOST_THREAD_USE_DLL) +# define BOOST_THREAD_USE_DLL +# endif +#endif + +#if defined(BOOST_THREAD_BUILD_DLL) //Build dll +#elif defined(BOOST_THREAD_BUILD_LIB) //Build lib +#elif defined(BOOST_THREAD_USE_DLL) //Use dll +#elif defined(BOOST_THREAD_USE_LIB) //Use lib +#else //Use default +# if defined(BOOST_THREAD_PLATFORM_WIN32) +# if defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN) \ + || defined(__MINGW32__) || defined(MINGW32) || defined(BOOST_MINGW32) + //For compilers supporting auto-tss cleanup + //with Boost.Threads lib, use Boost.Threads lib +# define BOOST_THREAD_USE_LIB +# else + //For compilers not yet supporting auto-tss cleanup + //with Boost.Threads lib, use Boost.Threads dll +# define BOOST_THREAD_USE_DLL +# endif +# else +# define BOOST_THREAD_USE_LIB +# endif +#endif + +#if defined(BOOST_HAS_DECLSPEC) +# if defined(BOOST_THREAD_BUILD_DLL) //Build dll +# define BOOST_THREAD_DECL BOOST_SYMBOL_EXPORT +//# define BOOST_THREAD_DECL __declspec(dllexport) + +# elif defined(BOOST_THREAD_USE_DLL) //Use dll +# define BOOST_THREAD_DECL BOOST_SYMBOL_IMPORT +//# define BOOST_THREAD_DECL __declspec(dllimport) +# else +# define BOOST_THREAD_DECL +# endif +#elif (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) +# define BOOST_THREAD_DECL BOOST_SYMBOL_VISIBLE + +#else +# define BOOST_THREAD_DECL +#endif // BOOST_HAS_DECLSPEC + +// +// Automatically link to the correct build variant where possible. +// +#if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_THREAD_NO_LIB) && !defined(BOOST_THREAD_BUILD_DLL) && !defined(BOOST_THREAD_BUILD_LIB) +// +// Tell the autolink to link dynamically, this will get undef'ed by auto_link.hpp +// once it's done with it: +// +#if defined(BOOST_THREAD_USE_DLL) +# define BOOST_DYN_LINK +#endif +// +// Set the name of our library, this will get undef'ed by auto_link.hpp +// once it's done with it: +// +#if defined(BOOST_THREAD_LIB_NAME) +# define BOOST_LIB_NAME BOOST_THREAD_LIB_NAME +#else +# define BOOST_LIB_NAME boost_thread +#endif +// +// If we're importing code from a dll, then tell auto_link.hpp about it: +// +// And include the header that does the work: +// +#include +#endif // auto-linking disabled + +#endif // BOOST_THREAD_CONFIG_WEK1032003_HPP + +// Change Log: +// 22 Jan 05 Roland Schwarz (speedsnail) +// Usage of BOOST_HAS_DECLSPEC macro. +// Default again is static lib usage. +// BOOST_DYN_LINK only defined when autolink included. diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/counter.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/counter.hpp new file mode 100644 index 00000000000..38e1597c574 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/counter.hpp @@ -0,0 +1,106 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2013 Vicente J. Botet Escriba + +#ifndef BOOST_THREAD_COUNTER_HPP +#define BOOST_THREAD_COUNTER_HPP + +#include +#include + +//#include +//#include +#include +#include +#include +#include + +#include + +namespace boost +{ + namespace detail { + struct counter + { + condition_variable cond_; + std::size_t value_; + + counter(std::size_t value) + : value_(value) + { + + } + counter& operator=(counter const& rhs) + { + value_ = rhs.value_; + return *this; + } + counter& operator=(std::size_t value) + { + value_ = value; + return *this; + } + + operator std::size_t() const + { + return value_; + } + operator std::size_t&() + { + return value_; + } + + void inc_and_notify_all() + { + ++value_; + cond_.notify_all(); + } + + void dec_and_notify_all() + { + --value_; + cond_.notify_all(); + } + void assign_and_notify_all(counter const& rhs) + { + value_ = rhs.value_; + cond_.notify_all(); + } + void assign_and_notify_all(std::size_t value) + { + value_ = value; + cond_.notify_all(); + } + }; + struct counter_is_not_zero + { + counter_is_not_zero(counter const& count) : count_(count) {} + bool operator()() const { return count_ != 0; } + counter const& count_; + }; + struct counter_is_zero + { + counter_is_zero(counter const& count) : count_(count) {} + bool operator()() const { return count_ == 0; } + counter const& count_; + }; + struct is_zero + { + is_zero(std::size_t& count) : count_(count) {} + bool operator()() const { return count_ == 0; } + std::size_t& count_; + }; + struct not_equal + { + not_equal(std::size_t& x, std::size_t& y) : x_(x), y_(y) {} + bool operator()() const { return x_ != y_; } + std::size_t& x_; + std::size_t& y_; + }; + } +} // namespace boost + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/delete.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/delete.hpp new file mode 100644 index 00000000000..8f8113f4e87 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/delete.hpp @@ -0,0 +1,58 @@ +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_THREAD_DETAIL_DELETE_HPP +#define BOOST_THREAD_DETAIL_DELETE_HPP + +#include + +/** + * BOOST_THREAD_DELETE_COPY_CTOR deletes the copy constructor when the compiler supports it or + * makes it private. + * + * BOOST_THREAD_DELETE_COPY_ASSIGN deletes the copy assignment when the compiler supports it or + * makes it private. + */ + +#if ! defined BOOST_NO_CXX11_DELETED_FUNCTIONS && ! defined BOOST_NO_CXX11_RVALUE_REFERENCES +#define BOOST_THREAD_DELETE_COPY_CTOR(CLASS) \ + CLASS(CLASS const&) = delete; \ + +#define BOOST_THREAD_DELETE_COPY_ASSIGN(CLASS) \ + CLASS& operator=(CLASS const&) = delete; + +#else // BOOST_NO_CXX11_DELETED_FUNCTIONS +#if defined(BOOST_MSVC) && _MSC_VER >= 1600 +#define BOOST_THREAD_DELETE_COPY_CTOR(CLASS) \ + private: \ + CLASS(CLASS const&); \ + public: + +#define BOOST_THREAD_DELETE_COPY_ASSIGN(CLASS) \ + private: \ + CLASS& operator=(CLASS const&); \ + public: +#else +#define BOOST_THREAD_DELETE_COPY_CTOR(CLASS) \ + private: \ + CLASS(CLASS&); \ + public: + +#define BOOST_THREAD_DELETE_COPY_ASSIGN(CLASS) \ + private: \ + CLASS& operator=(CLASS&); \ + public: +#endif +#endif // BOOST_NO_CXX11_DELETED_FUNCTIONS + +/** + * BOOST_THREAD_NO_COPYABLE deletes the copy constructor and assignment when the compiler supports it or + * makes them private. + */ +#define BOOST_THREAD_NO_COPYABLE(CLASS) \ + BOOST_THREAD_DELETE_COPY_CTOR(CLASS) \ + BOOST_THREAD_DELETE_COPY_ASSIGN(CLASS) + +#endif // BOOST_THREAD_DETAIL_DELETE_HPP diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/force_cast.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/force_cast.hpp new file mode 100644 index 00000000000..d5d15adc1a7 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/force_cast.hpp @@ -0,0 +1,39 @@ +// Copyright (C) 2001-2003 +// Mac Murrett +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org for most recent version including documentation. + +#ifndef BOOST_FORCE_CAST_MJM012402_HPP +#define BOOST_FORCE_CAST_MJM012402_HPP + +#include + +namespace boost { +namespace detail { +namespace thread { + +// force_cast will convert anything to anything. + +// general case +template +inline Return_Type &force_cast(Argument_Type &rSrc) +{ + return(*reinterpret_cast(&rSrc)); +} + +// specialization for const +template +inline const Return_Type &force_cast(const Argument_Type &rSrc) +{ + return(*reinterpret_cast(&rSrc)); +} + +} // namespace thread +} // namespace detail +} // namespace boost + +#endif // BOOST_FORCE_CAST_MJM012402_HPP diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/function_wrapper.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/function_wrapper.hpp new file mode 100644 index 00000000000..355f726762b --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/function_wrapper.hpp @@ -0,0 +1,93 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// 2013/09 Vicente J. Botet Escriba +// Adapt to boost from CCIA C++11 implementation +// Make use of Boost.Move + +#ifndef BOOST_THREAD_DETAIL_FUNCTION_WRAPPER_HPP +#define BOOST_THREAD_DETAIL_FUNCTION_WRAPPER_HPP + +#include +#include +#include + +#include + +#include +#include + +namespace boost +{ + namespace detail + { + class function_wrapper + { + struct impl_base + { + virtual void call()=0; + virtual ~impl_base() + { + } + }; + typedef boost::csbl::unique_ptr impl_base_type; + impl_base_type impl; + template + struct impl_type: impl_base + { + F f; + impl_type(F const &f_) + : f(f_) + {} + impl_type(BOOST_THREAD_RV_REF(F) f_) + : f(boost::move(f_)) + {} + + void call() + { + if (impl) f(); + } + }; + public: + BOOST_THREAD_MOVABLE_ONLY(function_wrapper) + +//#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + template + function_wrapper(F const& f): + impl(new impl_type(f)) + {} +//#endif + template + function_wrapper(BOOST_THREAD_RV_REF(F) f): + impl(new impl_type(boost::forward(f))) + {} + function_wrapper(BOOST_THREAD_RV_REF(function_wrapper) other) BOOST_NOEXCEPT : + impl(other.impl) + { + other.impl = 0; + } + function_wrapper() + : impl(0) + { + } + ~function_wrapper() + { + } + + function_wrapper& operator=(BOOST_THREAD_RV_REF(function_wrapper) other) BOOST_NOEXCEPT + { + impl=other.impl; + other.impl=0; + return *this; + } + + void operator()() + { impl->call();} + + }; + } +} + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/invoke.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/invoke.hpp new file mode 100644 index 00000000000..e772da29ee9 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/invoke.hpp @@ -0,0 +1,1604 @@ +// Copyright (C) 2012-2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// 2013/04 Vicente J. Botet Escriba +// Provide implementation up to 9 parameters when BOOST_NO_CXX11_VARIADIC_TEMPLATES is defined. +// Make use of Boost.Move +// Make use of Boost.Tuple (movable) +// 2012 Vicente J. Botet Escriba +// Provide implementation _RET using bind when BOOST_NO_CXX11_HDR_FUNCTIONAL and BOOST_NO_SFINAE_EXPR are not defined +// 2012 Vicente J. Botet Escriba +// Adapt to boost libc++ implementation + +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// The invoke code is based on the one from libcxx. +//===----------------------------------------------------------------------===// + +#ifndef BOOST_THREAD_DETAIL_INVOKE_HPP +#define BOOST_THREAD_DETAIL_INVOKE_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef BOOST_NO_CXX11_HDR_FUNCTIONAL +#include +#endif + +namespace boost +{ + namespace detail + { + + +#if ! defined(BOOST_NO_SFINAE_EXPR) && \ + ! defined(BOOST_NO_CXX11_DECLTYPE) && \ + ! defined(BOOST_NO_CXX11_DECLTYPE_N3276) && \ + ! defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) + +#define BOOST_THREAD_PROVIDES_INVOKE + +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + // bullets 1 and 2 + + template + inline auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args) + -> decltype((boost::forward(a0).*f)(boost::forward(args)...)) + { + return (boost::forward(a0).*f)(boost::forward(args)...); + } + template + inline auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args) + -> decltype((boost::forward(a0).*f)(boost::forward(args)...)) + { + return (boost::forward(a0).*f)(boost::forward(args)...); + } + + template + inline auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args) + -> decltype(((*boost::forward(a0)).*f)(boost::forward(args)...)) + { + return ((*boost::forward(a0)).*f)(boost::forward(args)...); + } + template + inline auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args) + -> decltype(((*boost::forward(a0)).*f)(boost::forward(args)...)) + { + return ((*boost::forward(a0)).*f)(boost::forward(args)...); + } + + // bullets 3 and 4 + + template + inline auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0) + -> decltype(boost::forward(a0).*f) + { + return boost::forward(a0).*f; + } + + template + inline auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0) + -> decltype((*boost::forward(a0)).*f) + { + return (*boost::forward(a0)).*f; + } + + template + inline auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0) + -> decltype(boost::forward(a0).*f) + { + return boost::forward(a0).*f; + } + + template + inline auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0) + -> decltype((*boost::forward(a0)).*f) + { + return (*boost::forward(a0)).*f; + } + + + // bullet 5 + + template + inline auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args) + -> decltype(boost::forward(f)(boost::forward(args)...)) + { + return boost::forward(f)(boost::forward(args)...); + } + template + inline auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args) + -> decltype(boost::forward(f)(boost::forward(args)...)) + { + return boost::forward(f)(boost::forward(args)...); + } + +#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES + + // bullets 1 and 2 + + template + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0) + -> decltype((boost::forward(a0).*f)()) + { + return (boost::forward(a0).*f)(); + } + template + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0) + -> decltype((boost::forward(a0).*f)()) + { + return (boost::forward(a0).*f)(); + } + template + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1) + -> decltype((boost::forward(a0).*f)(boost::forward(a1))) + { + return (boost::forward(a0).*f)(boost::forward(a1)); + } + template + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1) + -> decltype((boost::forward(a0).*f)(boost::forward(a1))) + { + return (boost::forward(a0).*f)(boost::forward(a1)); + } + template + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + -> decltype((boost::forward(a0).*f)(boost::forward(a1), boost::forward(a2))) + { + return (boost::forward(a0).*f)(boost::forward(a1), boost::forward(a2)); + } + template + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + -> decltype((boost::forward(a0).*f)(boost::forward(a1), boost::forward(a2))) + { + return (boost::forward(a0).*f)(boost::forward(a1), boost::forward(a2)); + } + + template + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0) + -> decltype(((*boost::forward(a0)).*f)()) + { + return ((*boost::forward(a0)).*f)(); + } + template + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0) + -> decltype(((*boost::forward(a0)).*f)()) + { + return ((*boost::forward(a0)).*f)(); + } + template + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1) + -> decltype(((*boost::forward(a0)).*f)(boost::forward(a1))) + { + return ((*boost::forward(a0)).*f)(boost::forward(a1)); + } + template + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1) + -> decltype(((*boost::forward(a0)).*f)(boost::forward(a1))) + { + return ((*boost::forward(a0)).*f)(boost::forward(a1)); + } + template + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + -> decltype(((*boost::forward(a0)).*f)(boost::forward(a1), boost::forward(a2))) + { + return ((*boost::forward(a0)).*f)(boost::forward(a1), boost::forward(a2)); + } + template + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + -> decltype(((*boost::forward(a0)).*f)(boost::forward(a1), boost::forward(a2))) + { + return ((*boost::forward(a0)).*f)(boost::forward(a1), boost::forward(a2)); + } + + // bullets 3 and 4 + + template + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0) + -> decltype(boost::forward(a0).*f) + { + return boost::forward(a0).*f; + } + template + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0) + -> decltype(boost::forward(a0).*f) + { + return boost::forward(a0).*f; + } + + template + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0) + -> decltype((*boost::forward(a0)).*f) + { + return (*boost::forward(a0)).*f; + } + template + inline + auto + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A0) a0) + -> decltype((*boost::forward(a0)).*f) + { + return (*boost::forward(a0)).*f; + } + + // bullet 5 + + template + inline + auto invoke(BOOST_THREAD_RV_REF(Fp) f) + -> decltype(boost::forward(f)()) + { + return boost::forward(f)(); + } + template + inline + auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1) + -> decltype(boost::forward(f)(boost::forward(a1))) + { + return boost::forward(f)(boost::forward(a1)); + } template + inline + auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + -> decltype(boost::forward(f)(boost::forward(a1), boost::forward(a2))) + { + return boost::forward(f)(boost::forward(a1), boost::forward(a2)); + } + template + inline + auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3) + -> decltype(boost::forward(f)(boost::forward(a1), boost::forward(a2), boost::forward(a3))) + { + return boost::forward(f)(boost::forward(a1), boost::forward(a2), boost::forward(a3)); + } + + + template + inline + auto invoke(BOOST_THREAD_RV_REF(Fp) f) + -> decltype(boost::forward(f)()) + { + return boost::forward(f)(); + } + template + inline + auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1) + -> decltype(boost::forward(f)(boost::forward(a1))) + { + return boost::forward(f)(boost::forward(a1)); + } + template + inline + auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + -> decltype(boost::forward(f)(boost::forward(a1), boost::forward(a2))) + { + return boost::forward(f)(boost::forward(a1), boost::forward(a2)); + } + template + inline + auto invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3) + -> decltype(boost::forward(f)(boost::forward(a1), boost::forward(a2), boost::forward(a3))) + { + return boost::forward(f)(boost::forward(a1), boost::forward(a2), boost::forward(a3)); + } + +#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES + +#elif ! defined(BOOST_NO_SFINAE_EXPR) && \ + ! defined BOOST_NO_CXX11_HDR_FUNCTIONAL && \ + defined BOOST_MSVC + + template + inline + Ret invoke(BOOST_THREAD_RV_REF(Fp) f) + { + return f(); + } + template + inline + Ret invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1) + { + return std::bind(boost::forward(f), boost::forward(a1))(); + } + template + inline + Ret invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + { + return std::bind(boost::forward(f), boost::forward(a1), boost::forward(a2))(); + } + template + inline + Ret invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3) + { + return std::bind(boost::forward(f), boost::forward(a1), boost::forward(a2), boost::forward(a3))(); + } + +#define BOOST_THREAD_PROVIDES_INVOKE_RET + +#elif ! defined BOOST_MSVC +//!!!!! WARNING !!!!! THIS DOESN'T WORKS YET +#define BOOST_THREAD_PROVIDES_INVOKE_RET + +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + // bullet 1 + // (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is an object of + // type T or a reference to an object of type T or a reference to an object of a type derived from T + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(Args...), BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args) + { + return (boost::forward(a0).*f)(boost::forward(args)...); + } + + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(Args...) const, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args) + { + return (boost::forward(a0).*f)(boost::forward(args)...); + } + + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(Args...) volatile, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args) + { + return (boost::forward(a0).*f)(boost::forward(args)...); + } + + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(Args...) const volatile, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args) + { + return (boost::forward(a0).*f)(boost::forward(args)...); + } + + // bullet 2 + // ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is not one of + // the types described in the previous item; + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(Args...), BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args) + { + return ((*boost::forward(a0)).*f)(boost::forward(args)...); + } + + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(Args...) const, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args) + { + return ((*boost::forward(a0)).*f)(boost::forward(args)...); + } + + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(Args...) volatile, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args) + { + return ((*boost::forward(a0)).*f)(boost::forward(args)...); + } + + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(Args...) const volatile, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(Args) ...args) + { + return ((*boost::forward(a0)).*f)(boost::forward(args)...); + } + + // bullet 3 + // t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is an object of type T or a + // reference to an object of type T or a reference to an object of a type derived from T; +// template +// inline +// typename enable_if_c +// < +// is_base_of::type>::value, +// typename detail::apply_cv::type& +// >::type +// invoke(Ret A::* f, BOOST_THREAD_RV_REF(A0) a0) +// { +// return boost::forward(a0).*f; +// } + + // bullet 4 + // (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1 is not one of the types + //described in the previous item; + +// template +// struct d4th_helper +// { +// }; +// +// template +// struct d4th_helper +// { +// typedef typename apply_cv()), Ret>::type type; +// }; +// +// template +// inline +// typename detail::4th_helper::type +// >::value +// >::type& +// invoke(Ret A::* f, BOOST_THREAD_RV_REF(A0) a0) +// { +// return (*boost::forward(a0)).*f; +// } + +// template +// inline +// typename enable_if_c +// < +// !is_base_of::type>::value, +// typename detail::ref_return1::type +// >::type +// invoke(Ret A::* f, BOOST_THREAD_RV_REF(A0) a0) +// { +// return (*boost::forward(a0)).*f; +// } + + // bullet 5 + // f(t1, t2, ..., tN) in all other cases. + + template + inline Ret do_invoke(mpl::false_, BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args) + { + return boost::forward(f)(boost::forward(args)...); + } + + template + inline Ret do_invoke(mpl::true_, BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args) + { + return f(boost::forward(args)...); + } + + template + inline + typename disable_if_c + < + is_member_function_pointer::value, + Ret + >::type + invoke(BOOST_THREAD_RV_REF(Fp) f, BOOST_THREAD_RV_REF(Args) ...args) + { + return boost::detail::do_invoke(boost::is_pointer(), boost::forward(f), boost::forward(args)...); + } +#else // BOOST_NO_CXX11_VARIADIC_TEMPLATES + // bullet 1 + // (t1.*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is an object of + // type T or a reference to an object of type T or a reference to an object of a type derived from T + + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(), A0& a0) + { + return (a0.*f)(); + } + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(), A0* a0) + { + return ((*a0).*f)(); + } + + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1), + A0& a0, BOOST_THREAD_RV_REF(A1) a1 + ) + { + return (a0.*f)(boost::forward(a1)); + } + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1), A0& a0, A1 a1) + { + return (a0.*f)(a1); + } + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1), A0* a0, BOOST_THREAD_RV_REF(A1) a1 + ) + { + return (*(a0).*f)(boost::forward(a1)); + } + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1), A0* a0, A1 a1) + { + return (*a0.*f)(a1); + } + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2), + A0& a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2 + ) + { + return (a0.*f)(boost::forward(a1), boost::forward(a2)); + } + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2), A0* a0, A1 a1, A2 a2) + { + return ((*a0).*f)(a1, a2); + } + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2, A3), + A0& a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3) + { + return (a0.*f)(boost::forward(a1), boost::forward(a2), boost::forward(a3)); + } + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2, A3), A0* a0, A1 a1, A2 a2, A3 a3) + { + return ((*a0).*f)(a1, a2, a3); + } + +/// + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)() const, A0 const& a0) + { + return (a0.*f)(); + } + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)() const, A0 const* a0) + { + return ((*a0).*f)(); + } + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1) const, A0 const& a0, BOOST_THREAD_RV_REF(A1) a1) + { + return (a0.*f)(boost::forward(a1)); + } + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1) const, A0 const* a0, BOOST_THREAD_RV_REF(A1) a1) + { + return ((*a0).*f)(boost::forward(a1)); + } + + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1) const, A0 const& a0, A1 a1) + { + return (a0.*f)(a1); + } + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2) const, + A0 const& a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2 + ) + { + return (boost::forward(a0).*f)(boost::forward(a1), boost::forward(a2) + ); + } + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2) const, A0 const& a0, A1 a1, A2 a2) + { + return (a0.*f)(a1, a2); + } + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2, A3) const, + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3 + ) + { + return (boost::forward(a0).*f)(boost::forward(a1), boost::forward(a2), boost::forward(a3)); + } + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2, A3) const, A0 a0, A1 a1, A2 a2, A3 a3) + { + return (a0.*f)(a1, a2, a3); + } + /// + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)() volatile, BOOST_THREAD_RV_REF(A0) a0) + { + return (boost::forward(a0).*f)(); + } + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1) volatile, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1) + { + return (boost::forward(a0).*f)(boost::forward(a1)); + } + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1) volatile, A0 a0, A1 a1) + { + return (a0.*f)(a1); + } + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2) volatile, + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + { + return (boost::forward(a0).*f)(boost::forward(a1), boost::forward(a2)); + } + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2) volatile, A0 a0, A1 a1, A2 a2 ) + { + return (a0.*f)(a1, a2); + } + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2, A3) volatile, + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3 + ) + { + return (boost::forward(a0).*f)(boost::forward(a1), boost::forward(a2), boost::forward(a3)); + } + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2, A3) volatile, A0 a0, A1 a1, A2 a2, A3 a3) + { + return (a0.*f)(a1, a2, a3); + } + /// + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)() const volatile, BOOST_THREAD_RV_REF(A0) a0) + { + return (boost::forward(a0).*f)(); + } + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1) const volatile, BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1) + { + return (boost::forward(a0).*f)(boost::forward(a1)); + } + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1) const volatile, A0 a0, A1 a1) + { + return (a0.*f)(a1); + } + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2) const volatile, + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2 + ) + { + return (boost::forward(a0).*f)(boost::forward(a1), boost::forward(a2)); + } + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2) const volatile, + A0 a0, A1 a1, A2 a2 + ) + { + return (a0.*f)(a1, a2); + } + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2, A3) const volatile, + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3 + ) + { + return (boost::forward(a0).*f)(boost::forward(a1), boost::forward(a2), boost::forward(a3)); + } + template + inline + typename enable_if_c + < + is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2, A3) const volatile, + A0 a0, A1 a1, A2 a2, A3 a3 + ) + { + return (a0.*f)(a1, a2, a3); + } + + // bullet 2 + // ((*t1).*f)(t2, ..., tN) when f is a pointer to a member function of a class T and t1 is not one of + // the types described in the previous item; + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(), BOOST_THREAD_RV_REF(A0) a0) + { + return ((*boost::forward(a0)).*f)(); + } + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1), BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1) + { + return ((*boost::forward(a0)).*f)(boost::forward(a1)); + } + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1), A0 a0, A1 a1) + { + return ((*a0).*f)(a1); + } + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, BOOST_THREAD_RV_REF(A2)), + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + { + return ((*boost::forward(a0)).*f)(boost::forward(a1), boost::forward(a2)); + } + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2), A0 a0, A1 a1, A2 a2) + { + return ((*a0).*f)(a1, a2); + } + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, BOOST_THREAD_RV_REF(A2), BOOST_THREAD_RV_REF(A3)), + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3) + { + return ((*boost::forward(a0)).*f)(boost::forward(a1), boost::forward(a2), boost::forward(a3) + ); + } + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2, A3), A0 a0, A1 a1, A2 a2, A3 a3) + { + return ((*a0).*f)(a1, a2, a3); + } + +/// + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)() const, BOOST_THREAD_RV_REF(A0) a0) + { + return ((*boost::forward(a0)).*f)(); + } + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1) const, + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1) + { + return ((*boost::forward(a0)).*f)(boost::forward(a1)); + } + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1) const, BOOST_THREAD_RV_REF(A0) a0, A1 a1) + { + return ((*boost::forward(a0)).*f)(a1); + } + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1) const, A0 a0, A1 a1) + { + return ((*a0).*f)(a1); + } + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2) const, + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + { + return ((*boost::forward(a0)).*f)(boost::forward(a1), boost::forward(a2)); + } + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2) const, A0 a0, A1 a1, A2 a2) + { + return ((*a0).*f)(a1, a2); + } + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2, A3) const, + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3) + { + return ((*boost::forward(a0)).*f)(boost::forward(a1), boost::forward(a2), boost::forward(a3)); + } + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2, A3) const, + A0 a0, A1 a1, A2 a2, A3 a3) + { + return ((*a0).*f)(a1, a2, a3); + } + /// + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)() volatile, BOOST_THREAD_RV_REF(A0) a0) + { + return ((*boost::forward(a0)).*f)(); + } + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1) volatile, + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1) + { + return ((*boost::forward(a0)).*f)(boost::forward(a1)); + } + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1) volatile, A0 a0, A1 a1) + { + return ((*a0).*f)(a1); + } + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2) volatile, + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + { + return ((*boost::forward(a0)).*f)(boost::forward(a1), boost::forward(a2)); + } + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2) volatile, A0 a0, A1 a1, A2 a2) + { + return ((*a0).*f)(a1, a2); + } + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2, A3) volatile, + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3) + { + return ((*boost::forward(a0)).*f)(boost::forward(a1), boost::forward(a2), boost::forward(a3)); + } + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2, A3) volatile, A0 a0, A1 a1, A2 a2, A3 a3) + { + return ((*a0).*f)(a1, a2, a3); + } + /// + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)() const volatile, BOOST_THREAD_RV_REF(A0) a0) + { + return ((*boost::forward(a0)).*f)(); + } + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)() const volatile, A0 a0) + { + return ((*a0).*f)(); + } + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1) const volatile, + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1) + { + return ((*boost::forward(a0)).*f)(boost::forward(a1)); + } + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1) const volatile, A0 a0, A1 a1) + { + return ((*a0).*f)(a1); + } + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2) const volatile, + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + { + return ((*boost::forward(a0)).*f)(boost::forward(a1), boost::forward(a2)); + } + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2) const volatile, + A0 a0, A1 a1, A2 a2) + { + return ((*a0).*f)(a1, a2); + } + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2, A3) const volatile, + BOOST_THREAD_RV_REF(A0) a0, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3) + { + return ((*boost::forward(a0)).*f)(boost::forward(a1), boost::forward(a2), boost::forward(a3)); + } + template + inline + typename enable_if_c + < + ! is_base_of::type>::value, + Ret + >::type + invoke(Ret (A::*f)(A1, A2, A3) const volatile, + A0 a0, A1 a1, A2 a2, A3 a3) + { + return ((*a0).*f)(a1, a2, a3); + } + // bullet 3 + // t1.*f when N == 1 and f is a pointer to member data of a class T and t1 is an object of type T or a + // reference to an object of type T or a reference to an object of a type derived from T; +// template +// inline +// typename enable_if_c +// < +// is_base_of::type>::value, +// typename detail::apply_cv::type& +// >::type +// invoke(Ret A::* f, BOOST_THREAD_RV_REF(A0) a0) +// { +// return boost::forward(a0).*f; +// } + + // bullet 4 + // (*t1).*f when N == 1 and f is a pointer to member data of a class T and t1 is not one of the types + //described in the previous item; + +// template +// struct d4th_helper +// { +// }; +// +// template +// struct d4th_helper +// { +// typedef typename apply_cv()), Ret>::type type; +// }; +// +// template +// inline +// typename detail::4th_helper::type +// >::value +// >::type& +// invoke(Ret A::* f, BOOST_THREAD_RV_REF(A0) a0) +// { +// return (*boost::forward(a0)).*f; +// } + +// template +// inline +// typename enable_if_c +// < +// !is_base_of::type>::value, +// typename detail::ref_return1::type +// >::type +// invoke(Ret A::* f, BOOST_THREAD_RV_REF(A0) a0) +// { +// return (*boost::forward(a0)).*f; +// } + + // bullet 5 + // f(t1, t2, ..., tN) in all other cases. + + template + inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f) + { + return boost::forward(f)(); + } + template + inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f) + { + return f(); + } + template + inline + typename disable_if_c + < + is_member_function_pointer::value, + Ret + >::type + invoke(BOOST_THREAD_FWD_REF(Fp) f) + { + return boost::detail::do_invoke(boost::is_pointer(), boost::forward(f)); + } + + template + inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1) + { + return boost::forward(f)(boost::forward(a1)); + } + template + inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1) + { + return f(boost::forward(a1)); + } + template + inline + typename disable_if_c + < + is_member_function_pointer::value, + Ret + >::type + invoke(BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1) + { + return boost::detail::do_invoke(boost::is_pointer(), boost::forward(f), boost::forward(a1)); + } + + template + inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + { + return boost::forward(f)(boost::forward(a1), boost::forward(a2)); + } + template + inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + { + return f(boost::forward(a1), boost::forward(a2)); + } + template + inline + typename disable_if_c + < + is_member_function_pointer::value, + Ret + >::type + invoke(BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + { + return boost::detail::do_invoke(boost::is_pointer(), boost::forward(f), boost::forward(a1), boost::forward(a2)); + } + + template + inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3) + { + return boost::forward(f)(boost::forward(a1), boost::forward(a2), boost::forward(a3)); + } + template + inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3) + { + return f(boost::forward(a1), boost::forward(a2), boost::forward(a3)); + } + template + inline + typename disable_if_c + < + is_member_function_pointer::value, + Ret + >::type + invoke(BOOST_THREAD_FWD_REF(Fp) f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3) + { + return boost::detail::do_invoke(boost::is_pointer(), boost::forward(f), boost::forward(a1), boost::forward(a2), boost::forward(a3)); + } + + + template + inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1) + { + return boost::forward(f)(a1); + } + template + inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1) + { + return f(a1); + } + template + inline + typename disable_if_c + < + is_member_function_pointer::value, + Ret + >::type + invoke(BOOST_THREAD_FWD_REF(Fp) f, A1 a1) + { + return boost::detail::do_invoke(boost::is_pointer(), boost::forward(f), a1); + } + + template + inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2) + { + return boost::forward(f)(a1, a2); + } + template + inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2) + { + return f(a1, a2); + } + template + inline + typename disable_if_c + < + is_member_function_pointer::value, + Ret + >::type + invoke(BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2) + { + return boost::detail::do_invoke(boost::is_pointer(), boost::forward(f), a1, a2); + } + + template + inline Ret do_invoke(mpl::false_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2, A3 a3) + { + return boost::forward(f)(a1, a2, a3); + } + template + inline Ret do_invoke(mpl::true_, BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2, A3 a3) + { + return f(a1, a2, a3); + } + template + inline + typename disable_if_c + < + is_member_function_pointer::value, + Ret + >::type + invoke(BOOST_THREAD_FWD_REF(Fp) f, A1 a1, A2 a2, A3 a3) + { + return boost::detail::do_invoke(boost::is_pointer(), boost::forward(f), a1, a2, a3); + } + + + /// + template + inline + typename disable_if_c + < + is_member_function_pointer::value, + Ret + >::type + invoke(Fp &f) + { + return f(); + } + template + inline + typename disable_if_c + < + is_member_function_pointer::value, + Ret + >::type + invoke(Fp &f, BOOST_THREAD_RV_REF(A1) a1) + { + return f(boost::forward(a1)); + } + template + inline + typename disable_if_c + < + is_member_function_pointer::value, + Ret + >::type + invoke(Fp &f, A1 a1) + { + return f(a1); + } + template + inline + typename disable_if_c + < + is_member_function_pointer::value, + Ret + >::type + invoke(Fp &f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2) + { + return f(boost::forward(a1), boost::forward(a2)); + } + template + inline + typename disable_if_c + < + is_member_function_pointer::value, + Ret + >::type + invoke(Fp &f, A1 a1, A2 a2) + { + return f(a1, a2); + } + template + inline + typename disable_if_c + < + is_member_function_pointer::value, + Ret + >::type + invoke(Fp &f, BOOST_THREAD_RV_REF(A1) a1, BOOST_THREAD_RV_REF(A2) a2, BOOST_THREAD_RV_REF(A3) a3) + { + return f(boost::forward(a1), boost::forward(a2), boost::forward(a3)); + } + template + inline + typename disable_if_c + < + is_member_function_pointer::value, + Ret + >::type + invoke(Fp &f, A1 a1, A2 a2, A3 a3) + { + return f(a1, a2, a3); + } + /// + +#endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES + +#endif // all + } + } + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/invoker.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/invoker.hpp new file mode 100644 index 00000000000..9f38e9798dd --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/invoker.hpp @@ -0,0 +1,762 @@ +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// 2013/04 Vicente J. Botet Escriba +// Provide implementation up to 9 parameters when BOOST_NO_CXX11_VARIADIC_TEMPLATES is defined. +// Make use of Boost.Move +// Make use of Boost.Tuple (movable) +// 2012/11 Vicente J. Botet Escriba +// Adapt to boost libc++ implementation + +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// The invoker code is based on the one from libcxx. +//===----------------------------------------------------------------------===// + +#ifndef BOOST_THREAD_DETAIL_INVOKER_HPP +#define BOOST_THREAD_DETAIL_INVOKER_HPP + +#include + +#include +#include +#include +#include +#include +#include + +#include + +namespace boost +{ + namespace detail + { + +#if defined(BOOST_THREAD_PROVIDES_INVOKE) && ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && ! defined(BOOST_NO_CXX11_HDR_TUPLE) + + template + class invoker + { + //typedef typename decay::type Fpd; + //typedef tuple::type...> Argsd; + + //csbl::tuple f_; + csbl::tuple f_; + + public: + BOOST_THREAD_COPYABLE_AND_MOVABLE( invoker) + //typedef typename invoke_of<_Fp, _Args...>::type Rp; + typedef typename result_of::type result_type; + + template + BOOST_SYMBOL_VISIBLE + explicit invoker(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(As)... args) + : f_(boost::forward(f), boost::forward(args)...) + {} + + BOOST_SYMBOL_VISIBLE + invoker(BOOST_THREAD_RV_REF(invoker) f) : f_(boost::move(BOOST_THREAD_RV(f).f_)) + {} + + BOOST_SYMBOL_VISIBLE + invoker( const invoker& f) : f_(f.f_) + {} + + BOOST_SYMBOL_VISIBLE + invoker& operator=(BOOST_THREAD_RV_REF(invoker) f) + { + if (this != &f) + { + f_ = boost::move(BOOST_THREAD_RV(f).f_); + } + return *this; + } + + BOOST_SYMBOL_VISIBLE + invoker& operator=( BOOST_THREAD_COPY_ASSIGN_REF(invoker) f) + { + if (this != &f) + { + f_ = f.f_; + } + return *this; + } + + result_type operator()() + { + typedef typename make_tuple_indices<1+sizeof...(Args), 1>::type Index; + return execute(Index()); + } + private: + template + result_type + execute(tuple_indices) + { + return detail::invoke(boost::move(csbl::get<0>(f_)), boost::move(csbl::get(f_))...); + } + }; + + template + class invoker_ret + { + //typedef typename decay::type Fpd; + //typedef tuple::type...> Argsd; + + //csbl::tuple f_; + csbl::tuple f_; + + public: + BOOST_THREAD_COPYABLE_AND_MOVABLE( invoker_ret) + typedef R result_type; + + template + BOOST_SYMBOL_VISIBLE + explicit invoker_ret(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(As)... args) + : f_(boost::forward(f), boost::forward(args)...) + {} + + BOOST_SYMBOL_VISIBLE + invoker_ret(BOOST_THREAD_RV_REF(invoker_ret) f) : f_(boost::move(BOOST_THREAD_RV(f).f_)) + {} + + result_type operator()() + { + typedef typename make_tuple_indices<1+sizeof...(Args), 1>::type Index; + return execute(Index()); + } + private: + template + result_type + execute(tuple_indices) + { + return detail::invoke(boost::move(csbl::get<0>(f_)), boost::move(csbl::get(f_))...); + } + }; + //BOOST_THREAD_DCL_MOVABLE_BEG(X) invoker BOOST_THREAD_DCL_MOVABLE_END +#else + +#if ! defined BOOST_MSVC && defined(BOOST_THREAD_PROVIDES_INVOKE) + +#define BOOST_THREAD_RV_REF_ARG_T(z, n, unused) BOOST_PP_COMMA_IF(n) BOOST_THREAD_RV_REF(Arg##n) +#define BOOST_THREAD_RV_REF_A_T(z, n, unused) BOOST_PP_COMMA_IF(n) BOOST_THREAD_RV_REF(A##n) +#define BOOST_THREAD_RV_REF_ARG(z, n, unused) , BOOST_THREAD_RV_REF(Arg##n) arg##n +#define BOOST_THREAD_FWD_REF_A(z, n, unused) , BOOST_THREAD_FWD_REF(A##n) arg##n +#define BOOST_THREAD_FWD_REF_ARG(z, n, unused) , BOOST_THREAD_FWD_REF(Arg##n) arg##n +#define BOOST_THREAD_FWD_PARAM(z, n, unused) , boost::forward(arg##n) +#define BOOST_THREAD_FWD_PARAM_A(z, n, unused) , boost::forward(arg##n) +#define BOOST_THREAD_DCL(z, n, unused) Arg##n v##n; +#define BOOST_THREAD_MOVE_PARAM(z, n, unused) , v##n(boost::move(arg##n)) +#define BOOST_THREAD_FORWARD_PARAM_A(z, n, unused) , v##n(boost::forward(arg##n)) +#define BOOST_THREAD_MOVE_RHS_PARAM(z, n, unused) , v##n(boost::move(x.v##n)) +#define BOOST_THREAD_MOVE_DCL(z, n, unused) , boost::move(v##n) +#define BOOST_THREAD_MOVE_DCL_T(z, n, unused) BOOST_PP_COMMA_IF(n) boost::move(v##n) +#define BOOST_THREAD_ARG_DEF(z, n, unused) , class Arg##n = tuples::null_type + + template + class invoker; + +#define BOOST_THREAD_ASYNC_FUNCT(z, n, unused) \ + template \ + class invoker \ + { \ + Fp fp_; \ + BOOST_PP_REPEAT(n, BOOST_THREAD_DCL, ~) \ + public: \ + BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker) \ + typedef typename result_of::type result_type; \ + \ + template \ + BOOST_SYMBOL_VISIBLE \ + explicit invoker(BOOST_THREAD_FWD_REF(F) f \ + BOOST_PP_REPEAT(n, BOOST_THREAD_FWD_REF_A, ~) \ + ) \ + : fp_(boost::forward(f)) \ + BOOST_PP_REPEAT(n, BOOST_THREAD_FORWARD_PARAM_A, ~) \ + {} \ + \ + BOOST_SYMBOL_VISIBLE \ + invoker(BOOST_THREAD_RV_REF(invoker) x) \ + : fp_(boost::move(x.fp_)) \ + BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_RHS_PARAM, ~) \ + {} \ + \ + result_type operator()() { \ + return detail::invoke(boost::move(fp_) \ + BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_DCL, ~) \ + ); \ + } \ + }; \ + \ + template \ + class invoker \ + { \ + typedef R(*Fp)(BOOST_PP_REPEAT(n, BOOST_THREAD_RV_REF_ARG_T, ~)); \ + Fp fp_; \ + BOOST_PP_REPEAT(n, BOOST_THREAD_DCL, ~) \ + public: \ + BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker) \ + typedef typename result_of::type result_type; \ + \ + template \ + BOOST_SYMBOL_VISIBLE \ + explicit invoker(R2(*f)(BOOST_PP_REPEAT(n, BOOST_THREAD_RV_REF_A_T, ~)) \ + BOOST_PP_REPEAT(n, BOOST_THREAD_FWD_REF_A, ~) \ + ) \ + : fp_(f) \ + BOOST_PP_REPEAT(n, BOOST_THREAD_FORWARD_PARAM_A, ~) \ + {} \ + \ + BOOST_SYMBOL_VISIBLE \ + invoker(BOOST_THREAD_RV_REF(invoker) x) \ + : fp_(x.fp_) \ + BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_RHS_PARAM, ~) \ + {} \ + \ + result_type operator()() { \ + return fp_( \ + BOOST_PP_REPEAT(n, BOOST_THREAD_MOVE_DCL_T, ~) \ + ); \ + } \ + }; + + BOOST_PP_REPEAT(BOOST_THREAD_MAX_ARGS, BOOST_THREAD_ASYNC_FUNCT, ~) + + #undef BOOST_THREAD_RV_REF_ARG_T + #undef BOOST_THREAD_RV_REF_ARG + #undef BOOST_THREAD_FWD_REF_ARG + #undef BOOST_THREAD_FWD_REF_A + #undef BOOST_THREAD_FWD_PARAM + #undef BOOST_THREAD_FWD_PARAM_A + #undef BOOST_THREAD_DCL + #undef BOOST_THREAD_MOVE_PARAM + #undef BOOST_THREAD_MOVE_RHS_PARAM + #undef BOOST_THREAD_MOVE_DCL + #undef BOOST_THREAD_ARG_DEF + #undef BOOST_THREAD_ASYNC_FUNCT + +#else + + template + class invoker; + + template + class invoker + { + Fp fp_; + T0 v0_; + T1 v1_; + T2 v2_; + T3 v3_; + T4 v4_; + T5 v5_; + T6 v6_; + T7 v7_; + T8 v8_; + //::boost::tuple f_; + + public: + BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker) + typedef typename result_of::type result_type; + + BOOST_SYMBOL_VISIBLE + explicit invoker(BOOST_THREAD_FWD_REF(Fp) f + , BOOST_THREAD_RV_REF(T0) a0 + , BOOST_THREAD_RV_REF(T1) a1 + , BOOST_THREAD_RV_REF(T2) a2 + , BOOST_THREAD_RV_REF(T3) a3 + , BOOST_THREAD_RV_REF(T4) a4 + , BOOST_THREAD_RV_REF(T5) a5 + , BOOST_THREAD_RV_REF(T6) a6 + , BOOST_THREAD_RV_REF(T7) a7 + , BOOST_THREAD_RV_REF(T8) a8 + ) + : fp_(boost::move(f)) + , v0_(boost::move(a0)) + , v1_(boost::move(a1)) + , v2_(boost::move(a2)) + , v3_(boost::move(a3)) + , v4_(boost::move(a4)) + , v5_(boost::move(a5)) + , v6_(boost::move(a6)) + , v7_(boost::move(a7)) + , v8_(boost::move(a8)) + {} + + BOOST_SYMBOL_VISIBLE + invoker(BOOST_THREAD_RV_REF(invoker) f) + : fp_(boost::move(BOOST_THREAD_RV(f).fp)) + , v0_(boost::move(BOOST_THREAD_RV(f).v0_)) + , v1_(boost::move(BOOST_THREAD_RV(f).v1_)) + , v2_(boost::move(BOOST_THREAD_RV(f).v2_)) + , v3_(boost::move(BOOST_THREAD_RV(f).v3_)) + , v4_(boost::move(BOOST_THREAD_RV(f).v4_)) + , v5_(boost::move(BOOST_THREAD_RV(f).v5_)) + , v6_(boost::move(BOOST_THREAD_RV(f).v6_)) + , v7_(boost::move(BOOST_THREAD_RV(f).v7_)) + , v8_(boost::move(BOOST_THREAD_RV(f).v8_)) + {} + + result_type operator()() + { + return detail::invoke(boost::move(fp_) + , boost::move(v0_) + , boost::move(v1_) + , boost::move(v2_) + , boost::move(v3_) + , boost::move(v4_) + , boost::move(v5_) + , boost::move(v6_) + , boost::move(v7_) + , boost::move(v8_) + ); + } + }; + template + class invoker + { + Fp fp_; + T0 v0_; + T1 v1_; + T2 v2_; + T3 v3_; + T4 v4_; + T5 v5_; + T6 v6_; + T7 v7_; + public: + BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker) + typedef typename result_of::type result_type; + + BOOST_SYMBOL_VISIBLE + explicit invoker(BOOST_THREAD_FWD_REF(Fp) f + , BOOST_THREAD_RV_REF(T0) a0 + , BOOST_THREAD_RV_REF(T1) a1 + , BOOST_THREAD_RV_REF(T2) a2 + , BOOST_THREAD_RV_REF(T3) a3 + , BOOST_THREAD_RV_REF(T4) a4 + , BOOST_THREAD_RV_REF(T5) a5 + , BOOST_THREAD_RV_REF(T6) a6 + , BOOST_THREAD_RV_REF(T7) a7 + ) + : fp_(boost::move(f)) + , v0_(boost::move(a0)) + , v1_(boost::move(a1)) + , v2_(boost::move(a2)) + , v3_(boost::move(a3)) + , v4_(boost::move(a4)) + , v5_(boost::move(a5)) + , v6_(boost::move(a6)) + , v7_(boost::move(a7)) + {} + + BOOST_SYMBOL_VISIBLE + invoker(BOOST_THREAD_RV_REF(invoker) f) + : fp_(boost::move(BOOST_THREAD_RV(f).fp)) + , v0_(boost::move(BOOST_THREAD_RV(f).v0_)) + , v1_(boost::move(BOOST_THREAD_RV(f).v1_)) + , v2_(boost::move(BOOST_THREAD_RV(f).v2_)) + , v3_(boost::move(BOOST_THREAD_RV(f).v3_)) + , v4_(boost::move(BOOST_THREAD_RV(f).v4_)) + , v5_(boost::move(BOOST_THREAD_RV(f).v5_)) + , v6_(boost::move(BOOST_THREAD_RV(f).v6_)) + , v7_(boost::move(BOOST_THREAD_RV(f).v7_)) + {} + + result_type operator()() + { + return detail::invoke(boost::move(fp_) + , boost::move(v0_) + , boost::move(v1_) + , boost::move(v2_) + , boost::move(v3_) + , boost::move(v4_) + , boost::move(v5_) + , boost::move(v6_) + , boost::move(v7_) + ); + } + }; + template + class invoker + { + Fp fp_; + T0 v0_; + T1 v1_; + T2 v2_; + T3 v3_; + T4 v4_; + T5 v5_; + T6 v6_; + public: + BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker) + typedef typename result_of::type result_type; + + BOOST_SYMBOL_VISIBLE + explicit invoker(BOOST_THREAD_FWD_REF(Fp) f + , BOOST_THREAD_RV_REF(T0) a0 + , BOOST_THREAD_RV_REF(T1) a1 + , BOOST_THREAD_RV_REF(T2) a2 + , BOOST_THREAD_RV_REF(T3) a3 + , BOOST_THREAD_RV_REF(T4) a4 + , BOOST_THREAD_RV_REF(T5) a5 + , BOOST_THREAD_RV_REF(T6) a6 + ) + : fp_(boost::move(f)) + , v0_(boost::move(a0)) + , v1_(boost::move(a1)) + , v2_(boost::move(a2)) + , v3_(boost::move(a3)) + , v4_(boost::move(a4)) + , v5_(boost::move(a5)) + , v6_(boost::move(a6)) + {} + + BOOST_SYMBOL_VISIBLE + invoker(BOOST_THREAD_RV_REF(invoker) f) + : fp_(boost::move(BOOST_THREAD_RV(f).fp)) + , v0_(boost::move(BOOST_THREAD_RV(f).v0_)) + , v1_(boost::move(BOOST_THREAD_RV(f).v1_)) + , v2_(boost::move(BOOST_THREAD_RV(f).v2_)) + , v3_(boost::move(BOOST_THREAD_RV(f).v3_)) + , v4_(boost::move(BOOST_THREAD_RV(f).v4_)) + , v5_(boost::move(BOOST_THREAD_RV(f).v5_)) + , v6_(boost::move(BOOST_THREAD_RV(f).v6_)) + {} + + result_type operator()() + { + return detail::invoke(boost::move(fp_) + , boost::move(v0_) + , boost::move(v1_) + , boost::move(v2_) + , boost::move(v3_) + , boost::move(v4_) + , boost::move(v5_) + , boost::move(v6_) + ); + } + }; + template + class invoker + { + Fp fp_; + T0 v0_; + T1 v1_; + T2 v2_; + T3 v3_; + T4 v4_; + T5 v5_; + public: + BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker) + typedef typename result_of::type result_type; + + BOOST_SYMBOL_VISIBLE + explicit invoker(BOOST_THREAD_FWD_REF(Fp) f + , BOOST_THREAD_RV_REF(T0) a0 + , BOOST_THREAD_RV_REF(T1) a1 + , BOOST_THREAD_RV_REF(T2) a2 + , BOOST_THREAD_RV_REF(T3) a3 + , BOOST_THREAD_RV_REF(T4) a4 + , BOOST_THREAD_RV_REF(T5) a5 + ) + : fp_(boost::move(f)) + , v0_(boost::move(a0)) + , v1_(boost::move(a1)) + , v2_(boost::move(a2)) + , v3_(boost::move(a3)) + , v4_(boost::move(a4)) + , v5_(boost::move(a5)) + {} + + BOOST_SYMBOL_VISIBLE + invoker(BOOST_THREAD_RV_REF(invoker) f) + : fp_(boost::move(BOOST_THREAD_RV(f).fp)) + , v0_(boost::move(BOOST_THREAD_RV(f).v0_)) + , v1_(boost::move(BOOST_THREAD_RV(f).v1_)) + , v2_(boost::move(BOOST_THREAD_RV(f).v2_)) + , v3_(boost::move(BOOST_THREAD_RV(f).v3_)) + , v4_(boost::move(BOOST_THREAD_RV(f).v4_)) + , v5_(boost::move(BOOST_THREAD_RV(f).v5_)) + {} + + result_type operator()() + { + return detail::invoke(boost::move(fp_) + , boost::move(v0_) + , boost::move(v1_) + , boost::move(v2_) + , boost::move(v3_) + , boost::move(v4_) + , boost::move(v5_) + ); + } + }; + template + class invoker + { + Fp fp_; + T0 v0_; + T1 v1_; + T2 v2_; + T3 v3_; + T4 v4_; + public: + BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker) + typedef typename result_of::type result_type; + + BOOST_SYMBOL_VISIBLE + explicit invoker(BOOST_THREAD_FWD_REF(Fp) f + , BOOST_THREAD_RV_REF(T0) a0 + , BOOST_THREAD_RV_REF(T1) a1 + , BOOST_THREAD_RV_REF(T2) a2 + , BOOST_THREAD_RV_REF(T3) a3 + , BOOST_THREAD_RV_REF(T4) a4 + ) + : fp_(boost::move(f)) + , v0_(boost::move(a0)) + , v1_(boost::move(a1)) + , v2_(boost::move(a2)) + , v3_(boost::move(a3)) + , v4_(boost::move(a4)) + {} + + BOOST_SYMBOL_VISIBLE + invoker(BOOST_THREAD_RV_REF(invoker) f) + : fp_(boost::move(BOOST_THREAD_RV(f).fp)) + , v0_(boost::move(BOOST_THREAD_RV(f).v0_)) + , v1_(boost::move(BOOST_THREAD_RV(f).v1_)) + , v2_(boost::move(BOOST_THREAD_RV(f).v2_)) + , v3_(boost::move(BOOST_THREAD_RV(f).v3_)) + , v4_(boost::move(BOOST_THREAD_RV(f).v4_)) + {} + + result_type operator()() + { + return detail::invoke(boost::move(fp_) + , boost::move(v0_) + , boost::move(v1_) + , boost::move(v2_) + , boost::move(v3_) + , boost::move(v4_) + ); + } + }; + template + class invoker + { + Fp fp_; + T0 v0_; + T1 v1_; + T2 v2_; + T3 v3_; + public: + BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker) + typedef typename result_of::type result_type; + + BOOST_SYMBOL_VISIBLE + explicit invoker(BOOST_THREAD_FWD_REF(Fp) f + , BOOST_THREAD_RV_REF(T0) a0 + , BOOST_THREAD_RV_REF(T1) a1 + , BOOST_THREAD_RV_REF(T2) a2 + , BOOST_THREAD_RV_REF(T3) a3 + ) + : fp_(boost::move(f)) + , v0_(boost::move(a0)) + , v1_(boost::move(a1)) + , v2_(boost::move(a2)) + , v3_(boost::move(a3)) + {} + + BOOST_SYMBOL_VISIBLE + invoker(BOOST_THREAD_RV_REF(invoker) f) + : fp_(boost::move(BOOST_THREAD_RV(f).fp)) + , v0_(boost::move(BOOST_THREAD_RV(f).v0_)) + , v1_(boost::move(BOOST_THREAD_RV(f).v1_)) + , v2_(boost::move(BOOST_THREAD_RV(f).v2_)) + , v3_(boost::move(BOOST_THREAD_RV(f).v3_)) + {} + + result_type operator()() + { + return detail::invoke(boost::move(fp_) + , boost::move(v0_) + , boost::move(v1_) + , boost::move(v2_) + , boost::move(v3_) + ); + } + }; + template + class invoker + { + Fp fp_; + T0 v0_; + T1 v1_; + T2 v2_; + public: + BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker) + typedef typename result_of::type result_type; + + BOOST_SYMBOL_VISIBLE + explicit invoker(BOOST_THREAD_FWD_REF(Fp) f + , BOOST_THREAD_RV_REF(T0) a0 + , BOOST_THREAD_RV_REF(T1) a1 + , BOOST_THREAD_RV_REF(T2) a2 + ) + : fp_(boost::move(f)) + , v0_(boost::move(a0)) + , v1_(boost::move(a1)) + , v2_(boost::move(a2)) + {} + + BOOST_SYMBOL_VISIBLE + invoker(BOOST_THREAD_RV_REF(invoker) f) + : fp_(boost::move(BOOST_THREAD_RV(f).fp)) + , v0_(boost::move(BOOST_THREAD_RV(f).v0_)) + , v1_(boost::move(BOOST_THREAD_RV(f).v1_)) + , v2_(boost::move(BOOST_THREAD_RV(f).v2_)) + {} + + result_type operator()() + { + return detail::invoke(boost::move(fp_) + , boost::move(v0_) + , boost::move(v1_) + , boost::move(v2_) + ); + } + }; + template + class invoker + { + Fp fp_; + T0 v0_; + T1 v1_; + public: + BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker) + typedef typename result_of::type result_type; + + BOOST_SYMBOL_VISIBLE + explicit invoker(BOOST_THREAD_FWD_REF(Fp) f + , BOOST_THREAD_RV_REF(T0) a0 + , BOOST_THREAD_RV_REF(T1) a1 + ) + : fp_(boost::move(f)) + , v0_(boost::move(a0)) + , v1_(boost::move(a1)) + {} + + BOOST_SYMBOL_VISIBLE + invoker(BOOST_THREAD_RV_REF(invoker) f) + : fp_(boost::move(BOOST_THREAD_RV(f).fp)) + , v0_(boost::move(BOOST_THREAD_RV(f).v0_)) + , v1_(boost::move(BOOST_THREAD_RV(f).v1_)) + {} + + result_type operator()() + { + return detail::invoke(boost::move(fp_) + , boost::move(v0_) + , boost::move(v1_) + ); + } + }; + template + class invoker + { + Fp fp_; + T0 v0_; + public: + BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker) + typedef typename result_of::type result_type; + + BOOST_SYMBOL_VISIBLE + explicit invoker(BOOST_THREAD_FWD_REF(Fp) f + , BOOST_THREAD_RV_REF(T0) a0 + ) + : fp_(boost::move(f)) + , v0_(boost::move(a0)) + {} + + BOOST_SYMBOL_VISIBLE + invoker(BOOST_THREAD_RV_REF(invoker) f) + : fp_(boost::move(BOOST_THREAD_RV(f).fp)) + , v0_(boost::move(BOOST_THREAD_RV(f).v0_)) + {} + + result_type operator()() + { + return detail::invoke(boost::move(fp_) + , boost::move(v0_) + ); + } + }; + template + class invoker + { + Fp fp_; + public: + BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker) + typedef typename result_of::type result_type; + BOOST_SYMBOL_VISIBLE + explicit invoker(BOOST_THREAD_FWD_REF(Fp) f) + : fp_(boost::move(f)) + {} + + BOOST_SYMBOL_VISIBLE + invoker(BOOST_THREAD_RV_REF(invoker) f) + : fp_(boost::move(f.fp_)) + {} + result_type operator()() + { + return fp_(); + } + }; + template + class invoker + { + typedef R(*Fp)(); + Fp fp_; + public: + BOOST_THREAD_COPYABLE_AND_MOVABLE(invoker) + typedef typename result_of::type result_type; + BOOST_SYMBOL_VISIBLE + explicit invoker(Fp f) + : fp_(f) + {} + + BOOST_SYMBOL_VISIBLE + invoker(BOOST_THREAD_RV_REF(invoker) f) + : fp_(f.fp_) + {} + result_type operator()() + { + return fp_(); + } + }; +#endif +#endif + + } +} + +#include + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/is_convertible.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/is_convertible.hpp new file mode 100644 index 00000000000..b77620cf179 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/is_convertible.hpp @@ -0,0 +1,49 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2011-2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_THREAD_DETAIL_IS_CONVERTIBLE_HPP +#define BOOST_THREAD_DETAIL_IS_CONVERTIBLE_HPP + +#include +#include + +namespace boost +{ + namespace thread_detail + { + template + struct is_convertible : boost::is_convertible {}; + +#if defined BOOST_NO_CXX11_RVALUE_REFERENCES + +#if defined(BOOST_INTEL_CXX_VERSION) && (BOOST_INTEL_CXX_VERSION <= 1300) + +#if defined BOOST_THREAD_USES_MOVE + template + struct is_convertible< + rv &, + rv > & + > : false_type {}; +#endif + +#elif defined __GNUC__ && (__GNUC__ < 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ <= 4 )) + + template + struct is_convertible : boost::is_convertible {}; +#endif + +#endif + } + +} // namespace boost + + +#endif // BOOST_THREAD_DETAIL_MEMORY_HPP diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/lockable_wrapper.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/lockable_wrapper.hpp new file mode 100644 index 00000000000..8dc5a6cc786 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/lockable_wrapper.hpp @@ -0,0 +1,45 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2012 Vicente J. Botet Escriba + +#ifndef BOOST_THREAD_DETAIL_LOCKABLE_WRAPPER_HPP +#define BOOST_THREAD_DETAIL_LOCKABLE_WRAPPER_HPP + +#include + +#if ! defined BOOST_THREAD_NO_CXX11_HDR_INITIALIZER_LIST +#include +#endif +#include + +namespace boost +{ + +#if ! defined BOOST_THREAD_NO_CXX11_HDR_INITIALIZER_LIST + namespace thread_detail + { + template + struct lockable_wrapper + { + Mutex* m; + explicit lockable_wrapper(Mutex& m_) : + m(&m_) + {} + }; + template + struct lockable_adopt_wrapper + { + Mutex* m; + explicit lockable_adopt_wrapper(Mutex& m_) : + m(&m_) + {} + }; + } +#endif + +} + +#include + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/log.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/log.hpp new file mode 100644 index 00000000000..84dcc8cb41f --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/log.hpp @@ -0,0 +1,83 @@ +// Copyright (C) 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_THREAD_DETAIL_LOG_HPP +#define BOOST_THREAD_DETAIL_LOG_HPP + +#include +#if defined BOOST_THREAD_USES_LOG +#include +#include +#if defined BOOST_THREAD_USES_LOG_THREAD_ID +#include +#endif +#include + +namespace boost +{ + namespace thread_detail + { + inline boost::recursive_mutex& terminal_mutex() + { + static boost::recursive_mutex mtx; + return mtx; + } + + } +} +#if defined BOOST_THREAD_USES_LOG_THREAD_ID + +#define BOOST_THREAD_LOG \ + { \ + boost::lock_guard _lk_(boost::thread_detail::terminal_mutex()); \ + std::cout << boost::this_thread::get_id() << " - "<<__FILE__<<"["<<__LINE__<<"] " < _lk_(boost::thread_detail::terminal_mutex()); \ + std::cout << __FILE__<<"["<<__LINE__<<"] " < + inline dummy_stream_t const& operator<<(dummy_stream_t const& os, T) + { + return os; + } + + inline dummy_stream_t const& operator<<(dummy_stream_t const& os, dummy_stream_t const&) + { + return os; + } + + + BOOST_CONSTEXPR_OR_CONST dummy_stream_t dummy_stream = {}; + + } +} + +#define BOOST_THREAD_LOG if (true) {} else boost::thread_detail::dummy_stream +#define BOOST_THREAD_END_LOG boost::thread_detail::dummy_stream + +#endif + +#define BOOST_THREAD_TRACE BOOST_THREAD_LOG << BOOST_THREAD_END_LOG + + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/make_tuple_indices.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/make_tuple_indices.hpp new file mode 100644 index 00000000000..73d54f11f81 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/make_tuple_indices.hpp @@ -0,0 +1,224 @@ +// Copyright (C) 2012-2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// 2013/04 Vicente J. Botet Escriba +// Provide implementation up to 10 parameters when BOOST_NO_CXX11_VARIADIC_TEMPLATES is defined. +// 2012/11 Vicente J. Botet Escriba +// Adapt to boost libc++ implementation + +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// The make_tuple_indices C++11 code is based on the one from libcxx. +//===----------------------------------------------------------------------===// + +#ifndef BOOST_THREAD_DETAIL_MAKE_TUPLE_INDICES_HPP +#define BOOST_THREAD_DETAIL_MAKE_TUPLE_INDICES_HPP + +#include +#include + +namespace boost +{ + namespace detail + { + +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + // make_tuple_indices + + template struct tuple_indices + {}; + + template + struct make_indices_imp; + + template + struct make_indices_imp, Ep> + { + typedef typename make_indices_imp, Ep>::type type; + }; + + template + struct make_indices_imp, Ep> + { + typedef tuple_indices type; + }; + + template + struct make_tuple_indices + { + BOOST_STATIC_ASSERT_MSG(Sp <= Ep, "make_tuple_indices input error"); + typedef typename make_indices_imp, Ep>::type type; + }; +#else + + // - tuple forward declaration ----------------------------------------------- + template < + std::size_t T0 = 0, std::size_t T1 = 0, std::size_t T2 = 0, + std::size_t T3 = 0, std::size_t T4 = 0, std::size_t T5 = 0, + std::size_t T6 = 0, std::size_t T7 = 0, std::size_t T8 = 0, + std::size_t T9 = 0> + class tuple_indices {}; + + template + struct make_indices_imp; + + template + struct make_indices_imp, Ep> + { + typedef typename make_indices_imp, Ep>::type type; + }; + template + struct make_indices_imp, Ep> + { + typedef typename make_indices_imp, Ep>::type type; + }; + template + struct make_indices_imp, Ep> + { + typedef typename make_indices_imp, Ep>::type type; + }; + template + struct make_indices_imp, Ep> + { + typedef typename make_indices_imp, Ep>::type type; + }; + template + struct make_indices_imp, Ep> + { + typedef typename make_indices_imp, Ep>::type type; + }; + template + struct make_indices_imp, Ep> + { + typedef typename make_indices_imp, Ep>::type type; + }; + template + struct make_indices_imp, Ep> + { + typedef typename make_indices_imp, Ep>::type type; + }; + template + struct make_indices_imp, Ep> + { + typedef typename make_indices_imp, Ep>::type type; + }; + template + struct make_indices_imp, Ep> + { + typedef typename make_indices_imp, Ep>::type type; + }; + template + struct make_indices_imp, Ep> + { + typedef typename make_indices_imp, Ep>::type type; + }; +// template +// struct make_indices_imp, Ep> +// { +// typedef typename make_indices_imp, Ep>::type type; +// }; + + template + struct make_indices_imp, Ep> + { + typedef tuple_indices<> type; + }; + template + struct make_indices_imp, Ep> + { + typedef tuple_indices type; + }; + template + struct make_indices_imp, Ep> + { + typedef tuple_indices type; + }; + template + struct make_indices_imp, Ep> + { + typedef tuple_indices type; + }; + template + struct make_indices_imp, Ep> + { + typedef tuple_indices type; + }; + template + struct make_indices_imp, Ep> + { + typedef tuple_indices type; + }; + template + struct make_indices_imp, Ep> + { + typedef tuple_indices type; + }; + template + struct make_indices_imp, Ep> + { + typedef tuple_indices type; + }; + template + struct make_indices_imp, Ep> + { + typedef tuple_indices type; + }; + template + struct make_indices_imp, Ep> + { + typedef tuple_indices type; + }; + + template + struct make_indices_imp, Ep> + { + typedef tuple_indices type; + }; + + template + struct make_tuple_indices + { + BOOST_STATIC_ASSERT_MSG(Sp <= Ep, "make_tuple_indices input error"); + typedef typename make_indices_imp, Ep>::type type; + }; + +#endif + } +} + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/memory.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/memory.hpp new file mode 100644 index 00000000000..51ce84f40bc --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/memory.hpp @@ -0,0 +1,48 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2011-2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_THREAD_DETAIL_MEMORY_HPP +#define BOOST_THREAD_DETAIL_MEMORY_HPP + +#include + +#include +#include +#include +#include + +namespace boost +{ + namespace thread_detail + { + template + class allocator_destructor + { + typedef csbl::allocator_traits<_Alloc> alloc_traits; + public: + typedef typename alloc_traits::pointer pointer; + typedef typename alloc_traits::size_type size_type; + private: + _Alloc alloc_; + size_type s_; + public: + allocator_destructor(_Alloc& a, size_type s)BOOST_NOEXCEPT + : alloc_(a), s_(s) + {} + void operator()(pointer p)BOOST_NOEXCEPT + { + alloc_traits::destroy(alloc_, p); + alloc_traits::deallocate(alloc_, p, s_); + } + }; + } //namespace thread_detail +} +#endif // BOOST_THREAD_DETAIL_MEMORY_HPP diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/move.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/move.hpp new file mode 100644 index 00000000000..26e4f9dc6dd --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/move.hpp @@ -0,0 +1,374 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2007-8 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba + +#ifndef BOOST_THREAD_MOVE_HPP +#define BOOST_THREAD_MOVE_HPP + +#include +#ifndef BOOST_NO_SFINAE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#include +#include +#include +#include +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#include +#endif +namespace boost +{ + + namespace detail + { + template + struct enable_move_utility_emulation_dummy_specialization; + template + struct thread_move_t + { + T& t; + explicit thread_move_t(T& t_): + t(t_) + {} + + T& operator*() const + { + return t; + } + + T* operator->() const + { + return &t; + } + private: + void operator=(thread_move_t&); + }; + } + +#if !defined BOOST_THREAD_USES_MOVE + +#ifndef BOOST_NO_SFINAE + template + typename enable_if >, boost::detail::thread_move_t >::type move(T& t) + { + return boost::detail::thread_move_t(t); + } +#endif + + template + boost::detail::thread_move_t move(boost::detail::thread_move_t t) + { + return t; + } + +#endif //#if !defined BOOST_THREAD_USES_MOVE +} + +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + +#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) BOOST_COPY_ASSIGN_REF(TYPE) +#define BOOST_THREAD_RV_REF(TYPE) BOOST_RV_REF(TYPE) +#define BOOST_THREAD_RV_REF_2_TEMPL_ARGS(TYPE) BOOST_RV_REF_2_TEMPL_ARGS(TYPE) +#define BOOST_THREAD_RV_REF_BEG BOOST_RV_REF_BEG +#define BOOST_THREAD_RV_REF_END BOOST_RV_REF_END +#define BOOST_THREAD_RV(V) V +#define BOOST_THREAD_MAKE_RV_REF(RVALUE) RVALUE +#define BOOST_THREAD_FWD_REF(TYPE) BOOST_FWD_REF(TYPE) +#define BOOST_THREAD_DCL_MOVABLE(TYPE) +#define BOOST_THREAD_DCL_MOVABLE_BEG(T) \ + namespace detail { \ + template \ + struct enable_move_utility_emulation_dummy_specialization< + +#define BOOST_THREAD_DCL_MOVABLE_BEG2(T1, T2) \ + namespace detail { \ + template \ + struct enable_move_utility_emulation_dummy_specialization< + +#define BOOST_THREAD_DCL_MOVABLE_END > \ + : integral_constant \ + {}; \ + } + +#elif ! defined BOOST_NO_CXX11_RVALUE_REFERENCES && defined BOOST_MSVC + +#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) BOOST_COPY_ASSIGN_REF(TYPE) +#define BOOST_THREAD_RV_REF(TYPE) BOOST_RV_REF(TYPE) +#define BOOST_THREAD_RV_REF_2_TEMPL_ARGS(TYPE) BOOST_RV_REF_2_TEMPL_ARGS(TYPE) +#define BOOST_THREAD_RV_REF_BEG BOOST_RV_REF_BEG +#define BOOST_THREAD_RV_REF_END BOOST_RV_REF_END +#define BOOST_THREAD_RV(V) V +#define BOOST_THREAD_MAKE_RV_REF(RVALUE) RVALUE +#define BOOST_THREAD_FWD_REF(TYPE) BOOST_FWD_REF(TYPE) +#define BOOST_THREAD_DCL_MOVABLE(TYPE) +#define BOOST_THREAD_DCL_MOVABLE_BEG(T) \ + namespace detail { \ + template \ + struct enable_move_utility_emulation_dummy_specialization< + +#define BOOST_THREAD_DCL_MOVABLE_BEG2(T1, T2) \ + namespace detail { \ + template \ + struct enable_move_utility_emulation_dummy_specialization< + +#define BOOST_THREAD_DCL_MOVABLE_END > \ + : integral_constant \ + {}; \ + } + +#else + +#if defined BOOST_THREAD_USES_MOVE +#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) BOOST_COPY_ASSIGN_REF(TYPE) +#define BOOST_THREAD_RV_REF(TYPE) BOOST_RV_REF(TYPE) +#define BOOST_THREAD_RV_REF_2_TEMPL_ARGS(TYPE) BOOST_RV_REF_2_TEMPL_ARGS(TYPE) +#define BOOST_THREAD_RV_REF_BEG BOOST_RV_REF_BEG +#define BOOST_THREAD_RV_REF_END BOOST_RV_REF_END +#define BOOST_THREAD_RV(V) V +#define BOOST_THREAD_FWD_REF(TYPE) BOOST_FWD_REF(TYPE) +#define BOOST_THREAD_DCL_MOVABLE(TYPE) +#define BOOST_THREAD_DCL_MOVABLE_BEG(T) \ + namespace detail { \ + template \ + struct enable_move_utility_emulation_dummy_specialization< + +#define BOOST_THREAD_DCL_MOVABLE_BEG2(T1, T2) \ + namespace detail { \ + template \ + struct enable_move_utility_emulation_dummy_specialization< + +#define BOOST_THREAD_DCL_MOVABLE_END > \ + : integral_constant \ + {}; \ + } + +#else + +#define BOOST_THREAD_COPY_ASSIGN_REF(TYPE) const TYPE& +#define BOOST_THREAD_RV_REF(TYPE) boost::detail::thread_move_t< TYPE > +#define BOOST_THREAD_RV_REF_BEG boost::detail::thread_move_t< +#define BOOST_THREAD_RV_REF_END > +#define BOOST_THREAD_RV(V) (*V) +#define BOOST_THREAD_FWD_REF(TYPE) BOOST_FWD_REF(TYPE) + +#define BOOST_THREAD_DCL_MOVABLE(TYPE) \ +template <> \ +struct enable_move_utility_emulation< TYPE > \ +{ \ + static const bool value = false; \ +}; + +#define BOOST_THREAD_DCL_MOVABLE_BEG(T) \ +template \ +struct enable_move_utility_emulation< + +#define BOOST_THREAD_DCL_MOVABLE_BEG2(T1, T2) \ +template \ +struct enable_move_utility_emulation< + +#define BOOST_THREAD_DCL_MOVABLE_END > \ +{ \ + static const bool value = false; \ +}; + +#endif + +namespace boost +{ +namespace detail +{ + template + BOOST_THREAD_RV_REF(typename ::boost::remove_cv::type>::type) + make_rv_ref(T v) BOOST_NOEXCEPT + { + return (BOOST_THREAD_RV_REF(typename ::boost::remove_cv::type>::type))(v); + } +// template +// BOOST_THREAD_RV_REF(typename ::boost::remove_cv::type>::type) +// make_rv_ref(T &v) BOOST_NOEXCEPT +// { +// return (BOOST_THREAD_RV_REF(typename ::boost::remove_cv::type>::type))(v); +// } +// template +// const BOOST_THREAD_RV_REF(typename ::boost::remove_cv::type>::type) +// make_rv_ref(T const&v) BOOST_NOEXCEPT +// { +// return (const BOOST_THREAD_RV_REF(typename ::boost::remove_cv::type>::type))(v); +// } +} +} + +#define BOOST_THREAD_MAKE_RV_REF(RVALUE) RVALUE.move() +//#define BOOST_THREAD_MAKE_RV_REF(RVALUE) boost::detail::make_rv_ref(RVALUE) +#endif + + +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + +#define BOOST_THREAD_MOVABLE(TYPE) + +#define BOOST_THREAD_COPYABLE(TYPE) + +#else + +#if defined BOOST_THREAD_USES_MOVE + +#define BOOST_THREAD_MOVABLE(TYPE) \ + ::boost::rv& move() BOOST_NOEXCEPT \ + { \ + return *static_cast< ::boost::rv* >(this); \ + } \ + const ::boost::rv& move() const BOOST_NOEXCEPT \ + { \ + return *static_cast* >(this); \ + } \ + operator ::boost::rv&() \ + { \ + return *static_cast< ::boost::rv* >(this); \ + } \ + operator const ::boost::rv&() const \ + { \ + return *static_cast* >(this); \ + }\ + +#define BOOST_THREAD_COPYABLE(TYPE) \ + TYPE& operator=(TYPE &t)\ + { this->operator=(static_cast &>(const_cast(t))); return *this;} + + +#else + +#define BOOST_THREAD_MOVABLE(TYPE) \ + operator ::boost::detail::thread_move_t() BOOST_NOEXCEPT \ + { \ + return move(); \ + } \ + ::boost::detail::thread_move_t move() BOOST_NOEXCEPT \ + { \ + ::boost::detail::thread_move_t x(*this); \ + return x; \ + } \ + +#define BOOST_THREAD_COPYABLE(TYPE) + +#endif +#endif + +#define BOOST_THREAD_MOVABLE_ONLY(TYPE) \ + BOOST_THREAD_NO_COPYABLE(TYPE) \ + BOOST_THREAD_MOVABLE(TYPE) \ + typedef int boost_move_no_copy_constructor_or_assign; \ + + +#define BOOST_THREAD_COPYABLE_AND_MOVABLE(TYPE) \ + BOOST_THREAD_COPYABLE(TYPE) \ + BOOST_THREAD_MOVABLE(TYPE) \ + + + +namespace boost +{ + namespace thread_detail + { + +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES +#elif defined BOOST_THREAD_USES_MOVE + template + struct is_rv + : ::boost::move_detail::is_rv + {}; + +#else + template + struct is_rv + : ::boost::integral_constant + {}; + + template + struct is_rv< ::boost::detail::thread_move_t > + : ::boost::integral_constant + {}; + + template + struct is_rv< const ::boost::detail::thread_move_t > + : ::boost::integral_constant + {}; +#endif + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template + struct remove_reference : boost::remove_reference {}; + template + struct decay : boost::decay {}; +#else + template + struct remove_reference + { + typedef Tp type; + }; + template + struct remove_reference + { + typedef Tp type; + }; + template + struct remove_reference< rv > { + typedef Tp type; + }; + + template + struct decay + { + private: + typedef typename boost::move_detail::remove_rvalue_reference::type Up0; + typedef typename boost::remove_reference::type Up; + public: + typedef typename conditional + < + is_array::value, + typename remove_extent::type*, + typename conditional + < + is_function::value, + typename add_pointer::type, + typename remove_cv::type + >::type + >::type type; + }; +#endif + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template + typename decay::type + decay_copy(T&& t) + { + return boost::forward(t); + } +#else + template + typename decay::type + decay_copy(BOOST_THREAD_FWD_REF(T) t) + { + return boost::forward(t); + } +#endif + } +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/nullary_function.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/nullary_function.hpp new file mode 100644 index 00000000000..b3989cf682e --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/nullary_function.hpp @@ -0,0 +1,234 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// 2013/09 Vicente J. Botet Escriba +// Adapt to boost from CCIA C++11 implementation +// Make use of Boost.Move + +#ifndef BOOST_THREAD_DETAIL_NULLARY_FUNCTION_HPP +#define BOOST_THREAD_DETAIL_NULLARY_FUNCTION_HPP + +#include +#include +#include +#include +#include + +namespace boost +{ + namespace detail + { + + template + class nullary_function; + template <> + class nullary_function + { + struct impl_base + { + virtual void call()=0; + virtual ~impl_base() + { + } + }; + csbl::shared_ptr impl; + template + struct impl_type: impl_base + { + F f; +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES + impl_type(F &f_) + : f(f_) + {} +#endif + impl_type(BOOST_THREAD_RV_REF(F) f_) + : f(boost::move(f_)) + {} + + void call() + { + f(); + } + }; + struct impl_type_ptr: impl_base + { + void (*f)(); + impl_type_ptr(void (*f_)()) + : f(f_) + {} + void call() + { + f(); + } + }; + public: + BOOST_THREAD_COPYABLE_AND_MOVABLE(nullary_function) + + explicit nullary_function(void (*f)()): + impl(new impl_type_ptr(f)) + {} + +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES + template + explicit nullary_function(F& f): + impl(new impl_type(f)) + {} +#endif + template + nullary_function(BOOST_THREAD_RV_REF(F) f): + impl(new impl_type::type>(thread_detail::decay_copy(boost::forward(f)))) + {} + + nullary_function() + : impl() + { + } + nullary_function(nullary_function const& other) BOOST_NOEXCEPT : + impl(other.impl) + { + } + nullary_function(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT : +#if defined BOOST_NO_CXX11_SMART_PTR + impl(BOOST_THREAD_RV(other).impl) + { + BOOST_THREAD_RV(other).impl.reset(); + } +#else + impl(boost::move(other.impl)) + { + } +#endif + ~nullary_function() + { + } + + nullary_function& operator=(BOOST_THREAD_COPY_ASSIGN_REF(nullary_function) other) BOOST_NOEXCEPT + { + impl=other.impl; + return *this; + } + nullary_function& operator=(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT + { +#if defined BOOST_NO_CXX11_SMART_PTR + impl=BOOST_THREAD_RV(other).impl; + BOOST_THREAD_RV(other).impl.reset(); +#else + impl = boost::move(other.impl); +#endif + return *this; + } + + + void operator()() + { if (impl) impl->call();} + + }; + + template + class nullary_function + { + struct impl_base + { + virtual R call()=0; + virtual ~impl_base() + { + } + }; + csbl::shared_ptr impl; + template + struct impl_type: impl_base + { + F f; +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES + impl_type(F &f_) + : f(f_) + {} +#endif + impl_type(BOOST_THREAD_RV_REF(F) f_) + : f(boost::move(f_)) + {} + + R call() + { + return f(); + } + }; + struct impl_type_ptr: impl_base + { + R (*f)(); + impl_type_ptr(R (*f_)()) + : f(f_) + {} + + R call() + { + return f(); + } + }; + public: + BOOST_THREAD_COPYABLE_AND_MOVABLE(nullary_function) + + nullary_function(R (*f)()): + impl(new impl_type_ptr(f)) + {} +#ifdef BOOST_NO_CXX11_RVALUE_REFERENCES + template + nullary_function(F& f): + impl(new impl_type(f)) + {} +#endif + template + nullary_function(BOOST_THREAD_RV_REF(F) f): + impl(new impl_type::type>(thread_detail::decay_copy(boost::forward(f)))) + {} + + nullary_function(nullary_function const& other) BOOST_NOEXCEPT : + impl(other.impl) + { + } + nullary_function(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT : +#if defined BOOST_NO_CXX11_SMART_PTR + impl(BOOST_THREAD_RV(other).impl) + { + BOOST_THREAD_RV(other).impl.reset(); + } +#else + impl(boost::move(other.impl)) + { + } +#endif + nullary_function() + : impl() + { + } + ~nullary_function() + { + } + + nullary_function& operator=(BOOST_THREAD_COPY_ASSIGN_REF(nullary_function) other) BOOST_NOEXCEPT + { + impl=other.impl; + return *this; + } + nullary_function& operator=(BOOST_THREAD_RV_REF(nullary_function) other) BOOST_NOEXCEPT + { +#if defined BOOST_NO_CXX11_SMART_PTR + impl=BOOST_THREAD_RV(other).impl; + BOOST_THREAD_RV(other).impl.reset(); +#else + impl = boost::move(other.impl); +#endif + return *this; + } + + R operator()() + { if (impl) return impl->call(); else return R();} + + }; + } + BOOST_THREAD_DCL_MOVABLE_BEG(F) detail::nullary_function BOOST_THREAD_DCL_MOVABLE_END +} + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/platform.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/platform.hpp new file mode 100644 index 00000000000..1f33b1a67ae --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/platform.hpp @@ -0,0 +1,73 @@ +// Copyright 2006 Roland Schwarz. +// (C) Copyright 2007 Anthony Williams +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// This work is a reimplementation along the design and ideas +// of William E. Kempf. + +#ifndef BOOST_THREAD_RS06040501_HPP +#define BOOST_THREAD_RS06040501_HPP + +// fetch compiler and platform configuration +#include + +// insist on threading support being available: +#include + +// choose platform +#if defined(linux) || defined(__linux) || defined(__linux__) +# define BOOST_THREAD_LINUX +//# define BOOST_THREAD_WAIT_BUG boost::posix_time::microseconds(100000) +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) +# define BOOST_THREAD_BSD +#elif defined(sun) || defined(__sun) +# define BOOST_THREAD_SOLARIS +#elif defined(__sgi) +# define BOOST_THREAD_IRIX +#elif defined(__hpux) +# define BOOST_THREAD_HPUX +#elif defined(__CYGWIN__) +# define BOOST_THREAD_CYGWIN +#elif (defined(_WIN32) || defined(__WIN32__) || defined(WIN32)) && !defined(BOOST_DISABLE_WIN32) +# define BOOST_THREAD_WIN32 +#elif defined(__BEOS__) +# define BOOST_THREAD_BEOS +#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) +# define BOOST_THREAD_MACOS +//# define BOOST_THREAD_WAIT_BUG boost::posix_time::microseconds(1000) +#elif defined(__IBMCPP__) || defined(_AIX) +# define BOOST_THREAD_AIX +#elif defined(__amigaos__) +# define BOOST_THREAD_AMIGAOS +#elif defined(__QNXNTO__) +# define BOOST_THREAD_QNXNTO +#elif defined(unix) || defined(__unix) || defined(_XOPEN_SOURCE) || defined(_POSIX_SOURCE) +# if defined(BOOST_HAS_PTHREADS) && !defined(BOOST_THREAD_POSIX) +# define BOOST_THREAD_POSIX +# endif +#endif + +// For every supported platform add a new entry into the dispatch table below. +// BOOST_THREAD_POSIX is tested first, so on platforms where posix and native +// threading is available, the user may choose, by defining BOOST_THREAD_POSIX +// in her source. If a platform is known to support pthreads and no native +// port of boost_thread is available just specify "pthread" in the +// dispatcher table. If there is no entry for a platform but pthreads is +// available on the platform, pthread is choosen as default. If nothing is +// available the preprocessor will fail with a diagnostic message. + +#if defined(BOOST_THREAD_POSIX) +# define BOOST_THREAD_PLATFORM_PTHREAD +#else +# if defined(BOOST_THREAD_WIN32) +# define BOOST_THREAD_PLATFORM_WIN32 +# elif defined(BOOST_HAS_PTHREADS) +# define BOOST_THREAD_PLATFORM_PTHREAD +# else +# error "Sorry, no boost threads are available for this platform." +# endif +#endif + +#endif // BOOST_THREAD_RS06040501_HPP diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/singleton.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/singleton.hpp new file mode 100644 index 00000000000..a20a42908d2 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/singleton.hpp @@ -0,0 +1,59 @@ +// Copyright (C) 2001-2003 +// Mac Murrett +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org for most recent version including documentation. + +#ifndef BOOST_SINGLETON_MJM012402_HPP +#define BOOST_SINGLETON_MJM012402_HPP + +#include + +namespace boost { +namespace detail { +namespace thread { + +// class singleton has the same goal as all singletons: create one instance of +// a class on demand, then dish it out as requested. + +template +class singleton : private T +{ +private: + singleton(); + ~singleton(); + +public: + static T &instance(); +}; + + +template +inline singleton::singleton() +{ + /* no-op */ +} + +template +inline singleton::~singleton() +{ + /* no-op */ +} + +template +/*static*/ T &singleton::instance() +{ + // function-local static to force this to work correctly at static + // initialization time. + static singleton s_oT; + return(s_oT); +} + +} // namespace thread +} // namespace detail +} // namespace boost + +#endif // BOOST_SINGLETON_MJM012402_HPP diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/thread.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/thread.hpp new file mode 100644 index 00000000000..9e7e8b8f5e9 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/thread.hpp @@ -0,0 +1,873 @@ +#ifndef BOOST_THREAD_THREAD_COMMON_HPP +#define BOOST_THREAD_THREAD_COMMON_HPP +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2007-2010 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba + +#include +#include + +#include +#ifndef BOOST_NO_IOSTREAM +#include +#endif +#include +#include +#if defined BOOST_THREAD_USES_DATETIME +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef BOOST_THREAD_USES_CHRONO +#include +#include +#endif + +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) +#include +#endif +#include + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4251) +#endif + +namespace boost +{ + + namespace detail + { + +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + + template + class thread_data: + public detail::thread_data_base + { + public: + BOOST_THREAD_NO_COPYABLE(thread_data) + thread_data(BOOST_THREAD_RV_REF(F) f_, BOOST_THREAD_RV_REF(ArgTypes)... args_): + fp(boost::forward(f_), boost::forward(args_)...) + {} + template + void run2(tuple_indices) + { + + detail::invoke(std::move(std::get<0>(fp)), std::move(std::get(fp))...); + } + void run() + { + typedef typename make_tuple_indices >::value, 1>::type index_type; + + run2(index_type()); + } + + private: + std::tuple::type, typename decay::type...> fp; + }; +#else // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + + template + class thread_data: + public detail::thread_data_base + { + public: + BOOST_THREAD_NO_COPYABLE(thread_data) +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + thread_data(BOOST_THREAD_RV_REF(F) f_): + f(boost::forward(f_)) + {} +// This overloading must be removed if we want the packaged_task's tests to pass. +// thread_data(F& f_): +// f(f_) +// {} +#else + + thread_data(BOOST_THREAD_RV_REF(F) f_): + f(f_) + {} + thread_data(F f_): + f(f_) + {} +#endif + //thread_data() {} + + void run() + { + f(); + } + + private: + F f; + }; + + template + class thread_data >: + public detail::thread_data_base + { + private: + F& f; + public: + BOOST_THREAD_NO_COPYABLE(thread_data) + thread_data(boost::reference_wrapper f_): + f(f_) + {} + void run() + { + f(); + } + }; + + template + class thread_data >: + public detail::thread_data_base + { + private: + F& f; + public: + BOOST_THREAD_NO_COPYABLE(thread_data) + thread_data(const boost::reference_wrapper f_): + f(f_) + {} + void run() + { + f(); + } + }; +#endif + } + + class BOOST_THREAD_DECL thread + { + public: + typedef thread_attributes attributes; + + BOOST_THREAD_MOVABLE_ONLY(thread) + private: + + struct dummy; + + void release_handle(); + + detail::thread_data_ptr thread_info; + + private: + bool start_thread_noexcept(); + bool start_thread_noexcept(const attributes& attr); + void start_thread() + { + if (!start_thread_noexcept()) + { + boost::throw_exception(thread_resource_error()); + } + } + void start_thread(const attributes& attr) + { + if (!start_thread_noexcept(attr)) + { + boost::throw_exception(thread_resource_error()); + } + } + + explicit thread(detail::thread_data_ptr data); + + detail::thread_data_ptr get_thread_info BOOST_PREVENT_MACRO_SUBSTITUTION () const; + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + template + static inline detail::thread_data_ptr make_thread_info(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_RV_REF(ArgTypes)... args) + { + return detail::thread_data_ptr(detail::heap_new< + detail::thread_data::type, ArgTypes...> + >( + boost::forward(f), boost::forward(args)... + ) + ); + } +#else + template + static inline detail::thread_data_ptr make_thread_info(BOOST_THREAD_RV_REF(F) f) + { + return detail::thread_data_ptr(detail::heap_new::type> >( + boost::forward(f))); + } +#endif + static inline detail::thread_data_ptr make_thread_info(void (*f)()) + { + return detail::thread_data_ptr(detail::heap_new >( + boost::forward(f))); + } +#else + template + static inline detail::thread_data_ptr make_thread_info(F f + , typename disable_if_c< + //boost::thread_detail::is_convertible::value || + is_same::type, thread>::value, + dummy* >::type=0 + ) + { + return detail::thread_data_ptr(detail::heap_new >(f)); + } + template + static inline detail::thread_data_ptr make_thread_info(BOOST_THREAD_RV_REF(F) f) + { + return detail::thread_data_ptr(detail::heap_new >(f)); + } + +#endif + public: +#if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF. +#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) + thread(const volatile thread&); +#endif +#endif + thread() BOOST_NOEXCEPT; + ~thread() + { + + #if defined BOOST_THREAD_PROVIDES_THREAD_DESTRUCTOR_CALLS_TERMINATE_IF_JOINABLE + if (joinable()) { + std::terminate(); + } + #else + detach(); + #endif + } +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template < + class F + > + explicit thread(BOOST_THREAD_RV_REF(F) f + //, typename disable_if::type, thread>, dummy* >::type=0 + ): + thread_info(make_thread_info(thread_detail::decay_copy(boost::forward(f)))) + { + start_thread(); + } + template < + class F + > + thread(attributes const& attrs, BOOST_THREAD_RV_REF(F) f): + thread_info(make_thread_info(thread_detail::decay_copy(boost::forward(f)))) + { + start_thread(attrs); + } + +#else +#ifdef BOOST_NO_SFINAE + template + explicit thread(F f): + thread_info(make_thread_info(f)) + { + start_thread(); + } + template + thread(attributes const& attrs, F f): + thread_info(make_thread_info(f)) + { + start_thread(attrs); + } +#else + template + explicit thread(F f + , typename disable_if_c< + boost::thread_detail::is_rv::value // todo ass a thread_detail::is_rv + //boost::thread_detail::is_convertible::value + //|| is_same::type, thread>::value + , dummy* >::type=0 + ): + thread_info(make_thread_info(f)) + { + start_thread(); + } + template + thread(attributes const& attrs, F f + , typename disable_if, dummy* >::type=0 + //, typename disable_if, dummy* >::type=0 + ): + thread_info(make_thread_info(f)) + { + start_thread(attrs); + } +#endif + template + explicit thread(BOOST_THREAD_RV_REF(F) f + , typename disable_if::type, thread>, dummy* >::type=0 + ): +#ifdef BOOST_THREAD_USES_MOVE + thread_info(make_thread_info(boost::move(f))) // todo : Add forward +#else + thread_info(make_thread_info(f)) // todo : Add forward +#endif + { + start_thread(); + } + + template + thread(attributes const& attrs, BOOST_THREAD_RV_REF(F) f): +#ifdef BOOST_THREAD_USES_MOVE + thread_info(make_thread_info(boost::move(f))) // todo : Add forward +#else + thread_info(make_thread_info(f)) // todo : Add forward +#endif + { + start_thread(attrs); + } +#endif + thread(BOOST_THREAD_RV_REF(thread) x) BOOST_NOEXCEPT + { + thread_info=BOOST_THREAD_RV(x).thread_info; + BOOST_THREAD_RV(x).thread_info.reset(); + } +#if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF. +#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) + thread& operator=(thread x) + { + swap(x); + return *this; + } +#endif +#endif + + thread& operator=(BOOST_THREAD_RV_REF(thread) other) BOOST_NOEXCEPT + { + +#if defined BOOST_THREAD_PROVIDES_THREAD_MOVE_ASSIGN_CALLS_TERMINATE_IF_JOINABLE + if (joinable()) std::terminate(); +#else + detach(); +#endif + thread_info=BOOST_THREAD_RV(other).thread_info; + BOOST_THREAD_RV(other).thread_info.reset(); + return *this; + } + +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + template + thread(F&& f, Arg&& arg, Args&&... args) : + thread_info(make_thread_info( + thread_detail::decay_copy(boost::forward(f)), + thread_detail::decay_copy(boost::forward(arg)), + thread_detail::decay_copy(boost::forward(args))...) + ) + + { + start_thread(); + } + template + thread(attributes const& attrs, F&& f, Arg&& arg, Args&&... args) : + thread_info(make_thread_info( + thread_detail::decay_copy(boost::forward(f)), + thread_detail::decay_copy(boost::forward(arg)), + thread_detail::decay_copy(boost::forward(args))...) + ) + + { + start_thread(attrs); + } +#else + template + thread(F f,A1 a1,typename disable_if, dummy* >::type=0): + thread_info(make_thread_info(boost::bind(boost::type(),f,a1))) + { + start_thread(); + } + template + thread(F f,A1 a1,A2 a2): + thread_info(make_thread_info(boost::bind(boost::type(),f,a1,a2))) + { + start_thread(); + } + + template + thread(F f,A1 a1,A2 a2,A3 a3): + thread_info(make_thread_info(boost::bind(boost::type(),f,a1,a2,a3))) + { + start_thread(); + } + + template + thread(F f,A1 a1,A2 a2,A3 a3,A4 a4): + thread_info(make_thread_info(boost::bind(boost::type(),f,a1,a2,a3,a4))) + { + start_thread(); + } + + template + thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5): + thread_info(make_thread_info(boost::bind(boost::type(),f,a1,a2,a3,a4,a5))) + { + start_thread(); + } + + template + thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6): + thread_info(make_thread_info(boost::bind(boost::type(),f,a1,a2,a3,a4,a5,a6))) + { + start_thread(); + } + + template + thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7): + thread_info(make_thread_info(boost::bind(boost::type(),f,a1,a2,a3,a4,a5,a6,a7))) + { + start_thread(); + } + + template + thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8): + thread_info(make_thread_info(boost::bind(boost::type(),f,a1,a2,a3,a4,a5,a6,a7,a8))) + { + start_thread(); + } + + template + thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8,A9 a9): + thread_info(make_thread_info(boost::bind(boost::type(),f,a1,a2,a3,a4,a5,a6,a7,a8,a9))) + { + start_thread(); + } +#endif + void swap(thread& x) BOOST_NOEXCEPT + { + thread_info.swap(x.thread_info); + } + + class id; +#ifdef BOOST_THREAD_PLATFORM_PTHREAD + inline id get_id() const BOOST_NOEXCEPT; +#else + id get_id() const BOOST_NOEXCEPT; +#endif + + + bool joinable() const BOOST_NOEXCEPT; + private: + bool join_noexcept(); + public: + inline void join(); + +#ifdef BOOST_THREAD_USES_CHRONO +#if defined(BOOST_THREAD_PLATFORM_WIN32) + template + bool try_join_for(const chrono::duration& rel_time) + { + chrono::milliseconds rel_time2= chrono::ceil(rel_time); + return do_try_join_until(rel_time2.count()); + } +#else + template + bool try_join_for(const chrono::duration& rel_time) + { + return try_join_until(chrono::steady_clock::now() + rel_time); + } +#endif + template + bool try_join_until(const chrono::time_point& t) + { + using namespace chrono; + bool joined= false; + do { + system_clock::time_point s_now = system_clock::now(); + typename Clock::duration d = ceil(t-Clock::now()); + if (d <= Clock::duration::zero()) return false; // in case the Clock::time_point t is already reached + joined = try_join_until(s_now + d); + } while (! joined); + return true; + } + template + bool try_join_until(const chrono::time_point& t) + { + using namespace chrono; + typedef time_point nano_sys_tmpt; + return try_join_until(nano_sys_tmpt(ceil(t.time_since_epoch()))); + } +#endif +#if defined(BOOST_THREAD_PLATFORM_WIN32) + private: + bool do_try_join_until_noexcept(uintmax_t milli, bool& res); + inline bool do_try_join_until(uintmax_t milli); + public: + bool timed_join(const system_time& abs_time); + //{ + // return do_try_join_until(get_milliseconds_until(wait_until)); + //} + +#ifdef BOOST_THREAD_USES_CHRONO + bool try_join_until(const chrono::time_point& tp) + { + chrono::milliseconds rel_time= chrono::ceil(tp-chrono::system_clock::now()); + return do_try_join_until(rel_time.count()); + } +#endif + + +#else + private: + bool do_try_join_until_noexcept(struct timespec const &timeout, bool& res); + inline bool do_try_join_until(struct timespec const &timeout); + public: +#if defined BOOST_THREAD_USES_DATETIME + bool timed_join(const system_time& abs_time) + { + struct timespec const ts=detail::to_timespec(abs_time); + return do_try_join_until(ts); + } +#endif +#ifdef BOOST_THREAD_USES_CHRONO + bool try_join_until(const chrono::time_point& tp) + { + using namespace chrono; + nanoseconds d = tp.time_since_epoch(); + timespec ts = boost::detail::to_timespec(d); + return do_try_join_until(ts); + } +#endif + +#endif + public: + +#if defined BOOST_THREAD_USES_DATETIME + template + inline bool timed_join(TimeDuration const& rel_time) + { + return timed_join(get_system_time()+rel_time); + } +#endif + void detach(); + + static unsigned hardware_concurrency() BOOST_NOEXCEPT; + static unsigned physical_concurrency() BOOST_NOEXCEPT; + +#define BOOST_THREAD_DEFINES_THREAD_NATIVE_HANDLE + typedef detail::thread_data_base::native_handle_type native_handle_type; + native_handle_type native_handle(); + +#if defined BOOST_THREAD_PROVIDES_THREAD_EQ + // Use thread::id when comparisions are needed + // backwards compatibility + bool operator==(const thread& other) const; + bool operator!=(const thread& other) const; +#endif +#if defined BOOST_THREAD_USES_DATETIME + static inline void yield() BOOST_NOEXCEPT + { + this_thread::yield(); + } + + static inline void sleep(const system_time& xt) + { + this_thread::sleep(xt); + } +#endif + +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + // extensions + void interrupt(); + bool interruption_requested() const BOOST_NOEXCEPT; +#endif + }; + + inline void swap(thread& lhs,thread& rhs) BOOST_NOEXCEPT + { + return lhs.swap(rhs); + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + inline thread&& move(thread& t) BOOST_NOEXCEPT + { + return static_cast(t); + } +#endif + + BOOST_THREAD_DCL_MOVABLE(thread) + + namespace this_thread + { +#ifdef BOOST_THREAD_PLATFORM_PTHREAD + inline thread::id get_id() BOOST_NOEXCEPT; +#else + thread::id BOOST_THREAD_DECL get_id() BOOST_NOEXCEPT; +#endif + +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + void BOOST_THREAD_DECL interruption_point(); + bool BOOST_THREAD_DECL interruption_enabled() BOOST_NOEXCEPT; + bool BOOST_THREAD_DECL interruption_requested() BOOST_NOEXCEPT; +#endif + +#if defined BOOST_THREAD_USES_DATETIME + inline BOOST_SYMBOL_VISIBLE void sleep(xtime const& abs_time) + { + sleep(system_time(abs_time)); + } +#endif + } + + class BOOST_SYMBOL_VISIBLE thread::id + { + private: + friend inline + std::size_t + hash_value(const thread::id &v) + { +#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID + return hash_value(v.thread_data); +#else + return hash_value(v.thread_data.get()); +#endif + } + +#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID +#if defined(BOOST_THREAD_PLATFORM_WIN32) + typedef unsigned int data; +#else + typedef thread::native_handle_type data; +#endif +#else + typedef detail::thread_data_ptr data; +#endif + data thread_data; + + id(data thread_data_): + thread_data(thread_data_) + {} + friend class thread; + friend id BOOST_THREAD_DECL this_thread::get_id() BOOST_NOEXCEPT; + public: + id() BOOST_NOEXCEPT: +#if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID + thread_data(0) +#else + thread_data() +#endif + {} + + id(const id& other) BOOST_NOEXCEPT : + thread_data(other.thread_data) + {} + + bool operator==(const id& y) const BOOST_NOEXCEPT + { + return thread_data==y.thread_data; + } + + bool operator!=(const id& y) const BOOST_NOEXCEPT + { + return thread_data!=y.thread_data; + } + + bool operator<(const id& y) const BOOST_NOEXCEPT + { + return thread_data(const id& y) const BOOST_NOEXCEPT + { + return y.thread_data=(const id& y) const BOOST_NOEXCEPT + { + return !(thread_data + friend BOOST_SYMBOL_VISIBLE + std::basic_ostream& + operator<<(std::basic_ostream& os, const id& x) + { + if(x.thread_data) + { + io::ios_flags_saver ifs( os ); + return os<< std::hex << x.thread_data; + } + else + { + return os<<"{Not-any-thread}"; + } + } +#else + template + BOOST_SYMBOL_VISIBLE + std::basic_ostream& + print(std::basic_ostream& os) const + { + if(thread_data) + { + io::ios_flags_saver ifs( os ); + return os<< std::hex << thread_data; + } + else + { + return os<<"{Not-any-thread}"; + } + } + +#endif +#endif + }; + +#ifdef BOOST_THREAD_PLATFORM_PTHREAD + thread::id thread::get_id() const BOOST_NOEXCEPT + { + #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID + return const_cast(this)->native_handle(); + #else + detail::thread_data_ptr const local_thread_info=(get_thread_info)(); + return (local_thread_info? id(local_thread_info) : id()); + #endif + } + + namespace this_thread + { + inline thread::id get_id() BOOST_NOEXCEPT + { + #if defined BOOST_THREAD_PROVIDES_BASIC_THREAD_ID + return pthread_self(); + #else + boost::detail::thread_data_base* const thread_info=get_or_make_current_thread_data(); + return (thread_info?thread::id(thread_info->shared_from_this()):thread::id()); + #endif + } + } +#endif + void thread::join() { + if (this_thread::get_id() == get_id()) + boost::throw_exception(thread_resource_error(static_cast(system::errc::resource_deadlock_would_occur), "boost thread: trying joining itself")); + + BOOST_THREAD_VERIFY_PRECONDITION( join_noexcept(), + thread_resource_error(static_cast(system::errc::invalid_argument), "boost thread: thread not joinable") + ); + } + +#ifdef BOOST_THREAD_PLATFORM_PTHREAD + bool thread::do_try_join_until(struct timespec const &timeout) +#else + bool thread::do_try_join_until(uintmax_t timeout) +#endif + { + if (this_thread::get_id() == get_id()) + boost::throw_exception(thread_resource_error(static_cast(system::errc::resource_deadlock_would_occur), "boost thread: trying joining itself")); + bool res; + if (do_try_join_until_noexcept(timeout, res)) + { + return res; + } + else + { + BOOST_THREAD_THROW_ELSE_RETURN( + (thread_resource_error(static_cast(system::errc::invalid_argument), "boost thread: thread not joinable")), + false + ); + } + } + +#if !defined(BOOST_NO_IOSTREAM) && defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) + template + BOOST_SYMBOL_VISIBLE + std::basic_ostream& + operator<<(std::basic_ostream& os, const thread::id& x) + { + return x.print(os); + } +#endif + +#if defined BOOST_THREAD_PROVIDES_THREAD_EQ + inline bool thread::operator==(const thread& other) const + { + return get_id()==other.get_id(); + } + + inline bool thread::operator!=(const thread& other) const + { + return get_id()!=other.get_id(); + } +#endif + + namespace detail + { + struct thread_exit_function_base + { + virtual ~thread_exit_function_base() + {} + virtual void operator()()=0; + }; + + template + struct thread_exit_function: + thread_exit_function_base + { + F f; + + thread_exit_function(F f_): + f(f_) + {} + + void operator()() + { + f(); + } + }; + + void BOOST_THREAD_DECL add_thread_exit_function(thread_exit_function_base*); + struct shared_state_base; +#if defined(BOOST_THREAD_PLATFORM_WIN32) + inline void make_ready_at_thread_exit(shared_ptr as) + { + detail::thread_data_base* const current_thread_data(detail::get_current_thread_data()); + if(current_thread_data) + { + current_thread_data->make_ready_at_thread_exit(as); + } + } +#else + void BOOST_THREAD_DECL make_ready_at_thread_exit(shared_ptr as); +#endif + } + + namespace this_thread + { + template + void at_thread_exit(F f) + { + detail::thread_exit_function_base* const thread_exit_func=detail::heap_new >(f); + detail::add_thread_exit_function(thread_exit_func); + } + } +} + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/thread_group.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/thread_group.hpp new file mode 100644 index 00000000000..4105c734688 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/thread_group.hpp @@ -0,0 +1,155 @@ +#ifndef BOOST_THREAD_DETAIL_THREAD_GROUP_HPP +#define BOOST_THREAD_DETAIL_THREAD_GROUP_HPP +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2007-9 Anthony Williams + +#include +#include +#include +#include +#include + +#include + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4251) +#endif + +namespace boost +{ + class thread_group + { + private: + thread_group(thread_group const&); + thread_group& operator=(thread_group const&); + public: + thread_group() {} + ~thread_group() + { + for(std::list::iterator it=threads.begin(),end=threads.end(); + it!=end; + ++it) + { + delete *it; + } + } + + bool is_this_thread_in() + { + thread::id id = this_thread::get_id(); + boost::shared_lock guard(m); + for(std::list::iterator it=threads.begin(),end=threads.end(); + it!=end; + ++it) + { + if ((*it)->get_id() == id) + return true; + } + return false; + } + + bool is_thread_in(thread* thrd) + { + if(thrd) + { + thread::id id = thrd->get_id(); + boost::shared_lock guard(m); + for(std::list::iterator it=threads.begin(),end=threads.end(); + it!=end; + ++it) + { + if ((*it)->get_id() == id) + return true; + } + return false; + } + else + { + return false; + } + } + + template + thread* create_thread(F threadfunc) + { + boost::lock_guard guard(m); + boost::csbl::unique_ptr new_thread(new thread(threadfunc)); + threads.push_back(new_thread.get()); + return new_thread.release(); + } + + void add_thread(thread* thrd) + { + if(thrd) + { + BOOST_THREAD_ASSERT_PRECONDITION( ! is_thread_in(thrd) , + thread_resource_error(static_cast(system::errc::resource_deadlock_would_occur), "boost::thread_group: trying to add a duplicated thread") + ); + + boost::lock_guard guard(m); + threads.push_back(thrd); + } + } + + void remove_thread(thread* thrd) + { + boost::lock_guard guard(m); + std::list::iterator const it=std::find(threads.begin(),threads.end(),thrd); + if(it!=threads.end()) + { + threads.erase(it); + } + } + + void join_all() + { + BOOST_THREAD_ASSERT_PRECONDITION( ! is_this_thread_in() , + thread_resource_error(static_cast(system::errc::resource_deadlock_would_occur), "boost::thread_group: trying joining itself") + ); + boost::shared_lock guard(m); + + for(std::list::iterator it=threads.begin(),end=threads.end(); + it!=end; + ++it) + { + if ((*it)->joinable()) + (*it)->join(); + } + } + +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + void interrupt_all() + { + boost::shared_lock guard(m); + + for(std::list::iterator it=threads.begin(),end=threads.end(); + it!=end; + ++it) + { + (*it)->interrupt(); + } + } +#endif + + size_t size() const + { + boost::shared_lock guard(m); + return threads.size(); + } + + private: + std::list threads; + mutable shared_mutex m; + }; +} + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/thread_heap_alloc.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/thread_heap_alloc.hpp new file mode 100644 index 00000000000..2f9bfd5c0b6 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/thread_heap_alloc.hpp @@ -0,0 +1,23 @@ +#ifndef BOOST_THREAD_THREAD_HEAP_ALLOC_HPP +#define BOOST_THREAD_THREAD_HEAP_ALLOC_HPP + +// thread_heap_alloc.hpp +// +// (C) Copyright 2008 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include + +#if defined(BOOST_THREAD_PLATFORM_WIN32) +#include +#elif defined(BOOST_THREAD_PLATFORM_PTHREAD) +#include +#else +#error "Boost threads unavailable on this platform" +#endif + + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/thread_interruption.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/thread_interruption.hpp new file mode 100644 index 00000000000..5d7d10fecdf --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/thread_interruption.hpp @@ -0,0 +1,39 @@ +#ifndef BOOST_THREAD_DETAIL_THREAD_INTERRUPTION_HPP +#define BOOST_THREAD_DETAIL_THREAD_INTERRUPTION_HPP +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2007-9 Anthony Williams +// (C) Copyright 2012 Vicente J. Botet Escriba + +#include +#include + +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + +namespace boost +{ + namespace this_thread + { + class BOOST_THREAD_DECL disable_interruption + { + bool interruption_was_enabled; + friend class restore_interruption; + public: + BOOST_THREAD_NO_COPYABLE(disable_interruption) + disable_interruption() BOOST_NOEXCEPT; + ~disable_interruption() BOOST_NOEXCEPT; + }; + + class BOOST_THREAD_DECL restore_interruption + { + public: + BOOST_THREAD_NO_COPYABLE(restore_interruption) + explicit restore_interruption(disable_interruption& d) BOOST_NOEXCEPT; + ~restore_interruption() BOOST_NOEXCEPT; + }; + } +} + +#endif // BOOST_THREAD_PROVIDES_INTERRUPTIONS +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/tss_hooks.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/tss_hooks.hpp new file mode 100644 index 00000000000..b2ceece3ddd --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/tss_hooks.hpp @@ -0,0 +1,65 @@ +// (C) Copyright Michael Glassford 2004. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#if !defined(BOOST_TLS_HOOKS_HPP) +#define BOOST_TLS_HOOKS_HPP + +#include + +#include + +#if defined(BOOST_HAS_WINTHREADS) + +namespace boost +{ + BOOST_THREAD_DECL void __cdecl on_process_enter(void); + //Function to be called when the exe or dll + //that uses Boost.Threads first starts + //or is first loaded. + //Should be called only before the first call to + //on_thread_enter(). + //Called automatically by Boost.Threads when + //a method for doing so has been discovered. + //May be omitted; may be called multiple times. + + BOOST_THREAD_DECL void __cdecl on_process_exit(void); + //Function to be called when the exe or dll + //that uses Boost.Threads first starts + //or is first loaded. + //Should be called only after the last call to + //on_exit_thread(). + //Called automatically by Boost.Threads when + //a method for doing so has been discovered. + //Must not be omitted; may be called multiple times. + + BOOST_THREAD_DECL void __cdecl on_thread_enter(void); + //Function to be called just after a thread starts + //in an exe or dll that uses Boost.Threads. + //Must be called in the context of the thread + //that is starting. + //Called automatically by Boost.Threads when + //a method for doing so has been discovered. + //May be omitted; may be called multiple times. + + BOOST_THREAD_DECL void __cdecl on_thread_exit(void); + //Function to be called just be fore a thread ends + //in an exe or dll that uses Boost.Threads. + //Must be called in the context of the thread + //that is ending. + //Called automatically by Boost.Threads when + //a method for doing so has been discovered. + //Must not be omitted; may be called multiple times. + + void tss_cleanup_implemented(); + //Dummy function used both to detect whether tss cleanup + //cleanup has been implemented and to force + //it to be linked into the Boost.Threads library. +} + +#endif //defined(BOOST_HAS_WINTHREADS) + +#include + +#endif //!defined(BOOST_TLS_HOOKS_HPP) diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/variadic_footer.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/variadic_footer.hpp new file mode 100644 index 00000000000..9ae25a847c3 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/variadic_footer.hpp @@ -0,0 +1,10 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + +#if defined BOOST_NO_CXX11_VARIADIC_TEMPLATES + + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/detail/variadic_header.hpp b/src/third_party/boost-1.60.0/boost/thread/detail/variadic_header.hpp new file mode 100644 index 00000000000..8015ae33cc2 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/detail/variadic_header.hpp @@ -0,0 +1,19 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include + +//#if defined BOOST_NO_CXX11_VARIADIC_TEMPLATES + +#include +#include +#include + +#ifndef BOOST_THREAD_MAX_ARGS +#define BOOST_THREAD_MAX_ARGS 9 +#endif + +//#endif + diff --git a/src/third_party/boost-1.60.0/boost/thread/exceptional_ptr.hpp b/src/third_party/boost-1.60.0/boost/thread/exceptional_ptr.hpp new file mode 100644 index 00000000000..49547923d92 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/exceptional_ptr.hpp @@ -0,0 +1,44 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2014 Vicente J. Botet Escriba + +#ifndef BOOST_THREAD_EXCEPTIONAL_PTR_HPP +#define BOOST_THREAD_EXCEPTIONAL_PTR_HPP + +#include +#include + +#include + +namespace boost +{ + struct exceptional_ptr { + exception_ptr ptr_; + + exceptional_ptr() : ptr_() {} + explicit exceptional_ptr(exception_ptr ex) : ptr_(ex) {} + template + explicit exceptional_ptr(BOOST_FWD_REF(E) ex) : ptr_(boost::copy_exception(boost::forward(ex))) {} + }; + + template + inline exceptional_ptr make_exceptional(BOOST_FWD_REF(E) ex) { + return exceptional_ptr(boost::forward(ex)); + } + + inline exceptional_ptr make_exceptional(exception_ptr ex) + { + return exceptional_ptr(ex); + } + + inline exceptional_ptr make_exceptional() + { + return exceptional_ptr(); + } + +} // namespace boost + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/exceptions.hpp b/src/third_party/boost-1.60.0/boost/thread/exceptions.hpp new file mode 100644 index 00000000000..d97465b754e --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/exceptions.hpp @@ -0,0 +1,225 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// Copyright (C) 2007-9 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_THREAD_EXCEPTIONS_PDM070801_H +#define BOOST_THREAD_EXCEPTIONS_PDM070801_H + +#include + +// pdm: Sorry, but this class is used all over the place & I end up +// with recursive headers if I don't separate it +// wek: Not sure why recursive headers would cause compilation problems +// given the include guards, but regardless it makes sense to +// seperate this out any way. + +#include +#include +#include +#include + + +#include + +namespace boost +{ + +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + class BOOST_SYMBOL_VISIBLE thread_interrupted + {}; +#endif + + class BOOST_SYMBOL_VISIBLE thread_exception: + public system::system_error + //public std::exception + { + typedef system::system_error base_type; + public: + thread_exception() + : base_type(0,system::system_category()) + {} + + thread_exception(int sys_error_code) + : base_type(sys_error_code, system::system_category()) + {} + + thread_exception( int ev, const char * what_arg ) + : base_type(system::error_code(ev, system::system_category()), what_arg) + { + } + thread_exception( int ev, const std::string & what_arg ) + : base_type(system::error_code(ev, system::system_category()), what_arg) + { + } + + ~thread_exception() throw() + {} + + + int native_error() const + { + return code().value(); + } + + }; + + class BOOST_SYMBOL_VISIBLE condition_error: + public system::system_error + //public std::exception + { + typedef system::system_error base_type; + public: + condition_error() + : base_type(system::error_code(0, system::system_category()), "Condition error") + {} + condition_error( int ev ) + : base_type(system::error_code(ev, system::system_category()), "Condition error") + { + } + condition_error( int ev, const char * what_arg ) + : base_type(system::error_code(ev, system::system_category()), what_arg) + { + } + condition_error( int ev, const std::string & what_arg ) + : base_type(system::error_code(ev, system::system_category()), what_arg) + { + } + }; + + + class BOOST_SYMBOL_VISIBLE lock_error: + public thread_exception + { + typedef thread_exception base_type; + public: + lock_error() + : base_type(0, "boost::lock_error") + {} + + lock_error( int ev ) + : base_type(ev, "boost::lock_error") + { + } + lock_error( int ev, const char * what_arg ) + : base_type(ev, what_arg) + { + } + lock_error( int ev, const std::string & what_arg ) + : base_type(ev, what_arg) + { + } + + ~lock_error() throw() + {} + + }; + + class BOOST_SYMBOL_VISIBLE thread_resource_error: + public thread_exception + { + typedef thread_exception base_type; + public: + thread_resource_error() + : base_type(static_cast(system::errc::resource_unavailable_try_again), "boost::thread_resource_error") + {} + + thread_resource_error( int ev ) + : base_type(ev, "boost::thread_resource_error") + { + } + thread_resource_error( int ev, const char * what_arg ) + : base_type(ev, what_arg) + { + } + thread_resource_error( int ev, const std::string & what_arg ) + : base_type(ev, what_arg) + { + } + + + ~thread_resource_error() throw() + {} + + }; + + class BOOST_SYMBOL_VISIBLE unsupported_thread_option: + public thread_exception + { + typedef thread_exception base_type; + public: + unsupported_thread_option() + : base_type(static_cast(system::errc::invalid_argument), "boost::unsupported_thread_option") + {} + + unsupported_thread_option( int ev ) + : base_type(ev, "boost::unsupported_thread_option") + { + } + unsupported_thread_option( int ev, const char * what_arg ) + : base_type(ev, what_arg) + { + } + unsupported_thread_option( int ev, const std::string & what_arg ) + : base_type(ev, what_arg) + { + } + + }; + + class BOOST_SYMBOL_VISIBLE invalid_thread_argument: + public thread_exception + { + typedef thread_exception base_type; + public: + invalid_thread_argument() + : base_type(static_cast(system::errc::invalid_argument), "boost::invalid_thread_argument") + {} + + invalid_thread_argument( int ev ) + : base_type(ev, "boost::invalid_thread_argument") + { + } + invalid_thread_argument( int ev, const char * what_arg ) + : base_type(ev, what_arg) + { + } + invalid_thread_argument( int ev, const std::string & what_arg ) + : base_type(ev, what_arg) + { + } + + }; + + class BOOST_SYMBOL_VISIBLE thread_permission_error: + public thread_exception + { + typedef thread_exception base_type; + public: + thread_permission_error() + : base_type(static_cast(system::errc::permission_denied), "boost::thread_permission_error") + {} + + thread_permission_error( int ev ) + : base_type(ev, "boost::thread_permission_error") + { + } + thread_permission_error( int ev, const char * what_arg ) + : base_type(ev, what_arg) + { + } + thread_permission_error( int ev, const std::string & what_arg ) + : base_type(ev, what_arg) + { + } + + }; + +} // namespace boost + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/executor.hpp b/src/third_party/boost-1.60.0/boost/thread/executor.hpp new file mode 100644 index 00000000000..c2b85a0eabe --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executor.hpp @@ -0,0 +1,15 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// 2013/09 Vicente J. Botet Escriba +// Adapt to boost from CCIA C++11 implementation + +#ifndef BOOST_THREAD_EXECUTOR_HPP +#define BOOST_THREAD_EXECUTOR_HPP + +#include +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/executors/basic_thread_pool.hpp b/src/third_party/boost-1.60.0/boost/thread/executors/basic_thread_pool.hpp new file mode 100644 index 00000000000..e0d4df2c76b --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executors/basic_thread_pool.hpp @@ -0,0 +1,318 @@ +// Copyright (C) 2013-2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// 2013/09 Vicente J. Botet Escriba +// Adapt to boost from CCIA C++11 implementation +// first implementation of a simple pool thread using a vector of threads and a sync_queue. + +#ifndef BOOST_THREAD_EXECUTORS_BASIC_THREAD_POOL_HPP +#define BOOST_THREAD_EXECUTORS_BASIC_THREAD_POOL_HPP + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost +{ +namespace executors +{ + class basic_thread_pool + { + public: + /// type-erasure to store the works to do + typedef executors::work work; + private: + typedef thread thread_t; + /// A move aware vector type + typedef csbl::vector thread_vector; + + /// A move aware vector + thread_vector threads; + /// the thread safe work queue + concurrent::sync_queue work_queue; + + public: + /** + * Effects: try to execute one task. + * Returns: whether a task has been executed. + * Throws: whatever the current task constructor throws or the task() throws. + */ + bool try_executing_one() + { + try + { + work task; + if (work_queue.try_pull(task) == queue_op_status::success) + { + task(); + return true; + } + return false; + } + catch (...) + { + std::terminate(); + //return false; + } + } + /** + * Effects: schedule one task or yields + * Throws: whatever the current task constructor throws or the task() throws. + */ + void schedule_one_or_yield() + { + if ( ! try_executing_one()) + { + this_thread::yield(); + } + } + private: + + /** + * The main loop of the worker threads + */ + void worker_thread() + { + try + { + for(;;) + { + work task; + queue_op_status st = work_queue.wait_pull(task); + if (st == queue_op_status::closed) { + return; + } + task(); + } + } + catch (...) + { + std::terminate(); + return; + } + } +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template + void worker_thread1(AtThreadEntry& at_thread_entry) + { + at_thread_entry(*this); + worker_thread(); + } +#endif + void worker_thread2(void(*at_thread_entry)(basic_thread_pool&)) + { + at_thread_entry(*this); + worker_thread(); + } + template + void worker_thread3(BOOST_THREAD_FWD_REF(AtThreadEntry) at_thread_entry) + { + at_thread_entry(*this); + worker_thread(); + } + static void do_nothing_at_thread_entry(basic_thread_pool&) {} + + public: + /// basic_thread_pool is not copyable. + BOOST_THREAD_NO_COPYABLE(basic_thread_pool) + + /** + * \b Effects: creates a thread pool that runs closures on \c thread_count threads. + * + * \b Throws: Whatever exception is thrown while initializing the needed resources. + */ + basic_thread_pool(unsigned const thread_count = thread::hardware_concurrency()+1) + { + try + { + threads.reserve(thread_count); + for (unsigned i = 0; i < thread_count; ++i) + { +#if 1 + thread th (&basic_thread_pool::worker_thread, this); + threads.push_back(thread_t(boost::move(th))); +#else + threads.push_back(thread_t(&basic_thread_pool::worker_thread, this)); // do not compile +#endif + } + } + catch (...) + { + close(); + throw; + } + } + /** + * \b Effects: creates a thread pool that runs closures on \c thread_count threads + * and executes the at_thread_entry function at the entry of each created thread. . + * + * \b Throws: Whatever exception is thrown while initializing the needed resources. + */ +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template + basic_thread_pool( unsigned const thread_count, AtThreadEntry& at_thread_entry) + { + try + { + threads.reserve(thread_count); + for (unsigned i = 0; i < thread_count; ++i) + { + thread th (&basic_thread_pool::worker_thread1, this, at_thread_entry); + threads.push_back(thread_t(boost::move(th))); + //threads.push_back(thread_t(&basic_thread_pool::worker_thread, this)); // do not compile + } + } + catch (...) + { + close(); + throw; + } + } +#endif + basic_thread_pool( unsigned const thread_count, void(*at_thread_entry)(basic_thread_pool&)) + { + try + { + threads.reserve(thread_count); + for (unsigned i = 0; i < thread_count; ++i) + { + thread th (&basic_thread_pool::worker_thread2, this, at_thread_entry); + threads.push_back(thread_t(boost::move(th))); + //threads.push_back(thread_t(&basic_thread_pool::worker_thread, this)); // do not compile + } + } + catch (...) + { + close(); + throw; + } + } + template + basic_thread_pool( unsigned const thread_count, BOOST_THREAD_FWD_REF(AtThreadEntry) at_thread_entry) + { + try + { + threads.reserve(thread_count); + for (unsigned i = 0; i < thread_count; ++i) + { + thread th (&basic_thread_pool::worker_thread3, this, boost::forward(at_thread_entry)); + threads.push_back(thread_t(boost::move(th))); + //threads.push_back(thread_t(&basic_thread_pool::worker_thread, this)); // do not compile + } + } + catch (...) + { + close(); + throw; + } + } + /** + * \b Effects: Destroys the thread pool. + * + * \b Synchronization: The completion of all the closures happen before the completion of the \c basic_thread_pool destructor. + */ + ~basic_thread_pool() + { + // signal to all the worker threads that there will be no more submissions. + close(); + // joins all the threads before destroying the thread pool resources (e.g. the queue). + join(); + } + + /** + * \b Effects: join all the threads. + */ + void join() + { + for (unsigned i = 0; i < threads.size(); ++i) + { + threads[i].join(); + } + } + + /** + * \b Effects: close the \c basic_thread_pool for submissions. + * The worker threads will work until there is no more closures to run. + */ + void close() + { + work_queue.close(); + } + + /** + * \b Returns: whether the pool is closed for submissions. + */ + bool closed() + { + return work_queue.closed(); + } + + /** + * \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible. + * + * \b Effects: The specified \c closure will be scheduled for execution at some point in the future. + * If invoked closure throws an exception the \c basic_thread_pool will call \c std::terminate, as is the case with threads. + * + * \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables. + * + * \b Throws: \c sync_queue_is_closed if the thread pool is closed. + * Whatever exception that can be throw while storing the closure. + */ + void submit(BOOST_THREAD_RV_REF(work) closure) { + work_queue.push(boost::move(closure)); + } + +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template + void submit(Closure & closure) + { + submit(work(closure)); + } +#endif + void submit(void (*closure)()) + { + submit(work(closure)); + } + + template + void submit(BOOST_THREAD_FWD_REF(Closure) closure) + { + //submit(work(boost::forward(closure))); + work w((boost::forward(closure))); + submit(boost::move(w)); + } + + /** + * \b Requires: This must be called from an scheduled task. + * + * \b Effects: reschedule functions until pred() + */ + template + bool reschedule_until(Pred const& pred) + { + do { + if ( ! try_executing_one()) + { + return false; + } + } while (! pred()); + return true; + } + + }; +} +using executors::basic_thread_pool; + +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/executors/detail/priority_executor_base.hpp b/src/third_party/boost-1.60.0/boost/thread/executors/detail/priority_executor_base.hpp new file mode 100644 index 00000000000..2191c0b37a3 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executors/detail/priority_executor_base.hpp @@ -0,0 +1,77 @@ +// Copyright (C) 2014 Ian Forbed +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_THREAD_EXECUTORS_DETAIL_PRIORITY_EXECUTOR_BASE_HPP +#define BOOST_THREAD_EXECUTORS_DETAIL_PRIORITY_EXECUTOR_BASE_HPP + +#include +#include +#include +#include +#include + +namespace boost +{ +namespace executors +{ +namespace detail +{ + template + class priority_executor_base + { + public: + //typedef boost::function work; + typedef executors::work_pq work; + protected: + typedef Queue queue_type; + queue_type _workq; + + priority_executor_base() {} + public: + + ~priority_executor_base() + { + if(!closed()) + { + this->close(); + } + } + + void close() + { + _workq.close(); + } + + bool closed() + { + return _workq.closed(); + } + + void loop() + { + try + { + for(;;) + { + work task; + queue_op_status st = _workq.wait_pull(task); + if (st == queue_op_status::closed) return; + task(); + } + } + catch (...) + { + std::terminate(); + return; + } + } + }; //end class + +} //end detail namespace +} //end executors namespace +} //end boost namespace +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/executors/detail/scheduled_executor_base.hpp b/src/third_party/boost-1.60.0/boost/thread/executors/detail/scheduled_executor_base.hpp new file mode 100644 index 00000000000..ec0038f7e3e --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executors/detail/scheduled_executor_base.hpp @@ -0,0 +1,66 @@ +// Copyright (C) 2014 Ian Forbed +// Copyright (C) 2014-2015 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_THREAD_EXECUTORS_DETAIL_SCHEDULED_EXECUTOR_BASE_HPP +#define BOOST_THREAD_EXECUTORS_DETAIL_SCHEDULED_EXECUTOR_BASE_HPP + +#include +#include +#include +#include + +#include +#include + +#include + +namespace boost +{ +namespace executors +{ +namespace detail +{ + template + class scheduled_executor_base : public priority_executor_base > + { + public: + typedef executors::work_pq work; + typedef Clock clock; + typedef typename clock::duration duration; + typedef typename clock::time_point time_point; + protected: + + scheduled_executor_base() {} + public: + + ~scheduled_executor_base() + { + if(! this->closed()) + { + this->close(); + } + } + + void submit_at(work w, const time_point& tp) + { + this->_workq.push(boost::move(w), tp); + } + + void submit_after(work w, const duration& dura) + { + this->_workq.push(boost::move(w), dura+clock::now()); + } + + }; //end class + +} //end detail namespace +} //end executors namespace +} //end boost namespace + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/executors/executor.hpp b/src/third_party/boost-1.60.0/boost/thread/executors/executor.hpp new file mode 100644 index 00000000000..96198201f08 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executors/executor.hpp @@ -0,0 +1,148 @@ +// Copyright (C) 2013,2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// 2013/09 Vicente J. Botet Escriba +// Adapt to boost from CCIA C++11 implementation + +#ifndef BOOST_THREAD_EXECUTORS_EXECUTOR_HPP +#define BOOST_THREAD_EXECUTORS_EXECUTOR_HPP + +#include + +#include +#include +#include + +#include + +namespace boost +{ + namespace executors + { + class executor + { + public: + /// type-erasure to store the works to do + typedef executors::work work; + + /// executor is not copyable. + BOOST_THREAD_NO_COPYABLE(executor) + executor() {} + + /** + * \par Effects + * Destroys the executor. + * + * \par Synchronization + * The completion of all the closures happen before the completion of the executor destructor. + */ + virtual ~executor() {}; + + /** + * \par Effects + * Close the \c executor for submissions. + * The worker threads will work until there is no more closures to run. + */ + virtual void close() = 0; + + /** + * \par Returns + * Whether the pool is closed for submissions. + */ + virtual bool closed() = 0; + + /** + * \par Effects + * The specified closure will be scheduled for execution at some point in the future. + * If invoked closure throws an exception the executor will call std::terminate, as is the case with threads. + * + * \par Synchronization + * Ccompletion of closure on a particular thread happens before destruction of thread's thread local variables. + * + * \par Throws + * \c sync_queue_is_closed if the thread pool is closed. + * Whatever exception that can be throw while storing the closure. + */ + virtual void submit(BOOST_THREAD_RV_REF(work) closure) = 0; +// virtual void submit(work& closure) = 0; + + /** + * \par Requires + * \c Closure is a model of Callable(void()) and a model of CopyConstructible/MoveConstructible. + * + * \par Effects + * The specified closure will be scheduled for execution at some point in the future. + * If invoked closure throws an exception the thread pool will call std::terminate, as is the case with threads. + * + * \par Synchronization + * Completion of closure on a particular thread happens before destruction of thread's thread local variables. + * + * \par Throws + * \c sync_queue_is_closed if the thread pool is closed. + * Whatever exception that can be throw while storing the closure. + */ + +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template + void submit(Closure & closure) + { + work w ((closure)); + submit(boost::move(w)); + } +#endif + void submit(void (*closure)()) + { + work w ((closure)); + submit(boost::move(w)); + } + + template + void submit(BOOST_THREAD_FWD_REF(Closure) closure) + { + //submit(work(boost::forward(closure))); + work w((boost::forward(closure))); + submit(boost::move(w)); + } + + /** + * \par Effects + * Try to execute one task. + * + * \par Returns + * Whether a task has been executed. + * + * \par Throws + * Whatever the current task constructor throws or the task() throws. + */ + virtual bool try_executing_one() = 0; + + /** + * \par Requires + * This must be called from an scheduled task. + * + * \par Effects + * Reschedule functions until pred() + */ + template + bool reschedule_until(Pred const& pred) + { + do { + //schedule_one_or_yield(); + if ( ! try_executing_one()) + { + return false; + } + } while (! pred()); + return true; + } + }; + + } + using executors::executor; +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/executors/executor_adaptor.hpp b/src/third_party/boost-1.60.0/boost/thread/executors/executor_adaptor.hpp new file mode 100644 index 00000000000..ca1a35f2d92 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executors/executor_adaptor.hpp @@ -0,0 +1,136 @@ +// Copyright (C) 2013,2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// 2013/09 Vicente J. Botet Escriba +// Adapt to boost from CCIA C++11 implementation + +#ifndef BOOST_THREAD_EXECUTORS_EXECUTOR_ADAPTOR_HPP +#define BOOST_THREAD_EXECUTORS_EXECUTOR_ADAPTOR_HPP + +#include + +#include + +#include + +namespace boost +{ +namespace executors +{ + /** + * Polymorphic adaptor of a model of Executor to an executor. + */ + template + class executor_adaptor : public executor + { + Executor ex; + public: + /// type-erasure to store the works to do + typedef executor::work work; + + /// executor is not copyable. + BOOST_THREAD_NO_COPYABLE(executor_adaptor) + + /** + * executor_adaptor constructor + */ +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template + executor_adaptor(BOOST_THREAD_RV_REF(Args) ... args) : ex(boost::forward(args)...) {} +#else + /** + * executor_adaptor constructor + */ + executor_adaptor() : ex() {} + + template + executor_adaptor( + BOOST_THREAD_FWD_REF(A1) a1 + ) : + ex( + boost::forward(a1) + ) {} + template + executor_adaptor( + BOOST_THREAD_FWD_REF(A1) a1, + BOOST_THREAD_FWD_REF(A2) a2 + ) : + ex( + boost::forward(a1), + boost::forward(a2) + ) {} + template + executor_adaptor( + BOOST_THREAD_FWD_REF(A1) a1, + BOOST_THREAD_FWD_REF(A2) a2, + BOOST_THREAD_FWD_REF(A3) a3 + ) : + ex( + boost::forward(a1), + boost::forward(a2), + boost::forward(a3) + ) {} +#endif + Executor& underlying_executor() { return ex; } + + /** + * \b Effects: close the \c executor for submissions. + * The worker threads will work until there is no more closures to run. + */ + void close() { ex.close(); } + + /** + * \b Returns: whether the pool is closed for submissions. + */ + bool closed() { return ex.closed(); } + + /** + * \b Effects: The specified closure will be scheduled for execution at some point in the future. + * If invoked closure throws an exception the executor will call std::terminate, as is the case with threads. + * + * \b Synchronization: completion of closure on a particular thread happens before destruction of thread's thread local variables. + * + * \b Throws: \c sync_queue_is_closed if the thread pool is closed. + * Whatever exception that can be throw while storing the closure. + */ + void submit(BOOST_THREAD_RV_REF(work) closure) { + return ex.submit(boost::move(closure)); + } + +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template + void submit(Closure & closure) + { + submit(work(closure)); + } +#endif + void submit(void (*closure)()) + { + submit(work(closure)); + } + + template + void submit(BOOST_THREAD_FWD_REF(Closure) closure) + { + //submit(work(boost::forward(closure))); + work w((boost::forward(closure))); + submit(boost::move(w)); + } + + /** + * Effects: try to execute one task. + * Returns: whether a task has been executed. + * Throws: whatever the current task constructor throws or the task() throws. + */ + bool try_executing_one() { return ex.try_executing_one(); } + + }; +} +using executors::executor_adaptor; +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/executors/generic_executor_ref.hpp b/src/third_party/boost-1.60.0/boost/thread/executors/generic_executor_ref.hpp new file mode 100644 index 00000000000..de270bcfed3 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executors/generic_executor_ref.hpp @@ -0,0 +1,213 @@ +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_THREAD_EXECUTORS_GENERIC_EXECUTOR_REF_HPP +#define BOOST_THREAD_EXECUTORS_GENERIC_EXECUTOR_REF_HPP + +#include + +#include +#include +#include + +#include + +#include + +namespace boost +{ + namespace executors + { + + template + class executor_ref : public executor + { + Executor& ex; + public: + /// type-erasure to store the works to do + typedef executors::work work; + + /// executor is not copyable. + BOOST_THREAD_NO_COPYABLE(executor_ref) + executor_ref(Executor& ex) : ex(ex) {} + + /** + * \par Effects + * Destroys the executor. + * + * \par Synchronization + * The completion of all the closures happen before the completion of the executor destructor. + */ + ~executor_ref() {}; + + /** + * \par Effects + * Close the \c executor for submissions. + * The worker threads will work until there is no more closures to run. + */ + void close() { ex.close(); } + + /** + * \par Returns + * Whether the pool is closed for submissions. + */ + bool closed() { return ex.closed(); } + + /** + * \par Effects + * The specified closure will be scheduled for execution at some point in the future. + * If invoked closure throws an exception the executor will call std::terminate, as is the case with threads. + * + * \par Synchronization + * Ccompletion of closure on a particular thread happens before destruction of thread's thread local variables. + * + * \par Throws + * \c sync_queue_is_closed if the thread pool is closed. + * Whatever exception that can be throw while storing the closure. + */ + void submit(BOOST_THREAD_RV_REF(work) closure) { + ex.submit(boost::move(closure)); + } +// void submit(work& closure) { +// ex.submit(closure); +// } + + + /** + * \par Effects + * Try to execute one task. + * + * \par Returns + * Whether a task has been executed. + * + * \par Throws + * Whatever the current task constructor throws or the task() throws. + */ + bool try_executing_one() { return ex.try_executing_one(); } + + }; + + class generic_executor_ref + { + shared_ptr ex; + public: + /// type-erasure to store the works to do + typedef executors::work work; + + template + generic_executor_ref(Executor& ex) + //: ex(make_shared >(ex)) // todo check why this doesn't works with C++03 + : ex( new executor_ref(ex) ) + { + } + + //generic_executor_ref(generic_executor_ref const& other) noexcept {} + //generic_executor_ref& operator=(generic_executor_ref const& other) noexcept {} + + + /** + * \par Effects + * Close the \c executor for submissions. + * The worker threads will work until there is no more closures to run. + */ + void close() { ex->close(); } + + /** + * \par Returns + * Whether the pool is closed for submissions. + */ + bool closed() { return ex->closed(); } + + /** + * \par Requires + * \c Closure is a model of Callable(void()) and a model of CopyConstructible/MoveConstructible. + * + * \par Effects + * The specified closure will be scheduled for execution at some point in the future. + * If invoked closure throws an exception the thread pool will call std::terminate, as is the case with threads. + * + * \par Synchronization + * Completion of closure on a particular thread happens before destruction of thread's thread local variables. + * + * \par Throws + * \c sync_queue_is_closed if the thread pool is closed. + * Whatever exception that can be throw while storing the closure. + */ + + void submit(BOOST_THREAD_RV_REF(work) closure) + { + ex->submit(boost::move(closure)); + } + +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template + void submit(Closure & closure) + { + //work w ((closure)); + //submit(boost::move(w)); + submit(work(closure)); + } +#endif + void submit(void (*closure)()) + { + work w ((closure)); + submit(boost::move(w)); + //submit(work(closure)); + } + + template + void submit(BOOST_THREAD_FWD_REF(Closure) closure) + { + work w((boost::forward(closure))); + submit(boost::move(w)); + } + +// size_t num_pending_closures() const +// { +// return ex->num_pending_closures(); +// } + + /** + * \par Effects + * Try to execute one task. + * + * \par Returns + * Whether a task has been executed. + * + * \par Throws + * Whatever the current task constructor throws or the task() throws. + */ + bool try_executing_one() { return ex->try_executing_one(); } + + /** + * \par Requires + * This must be called from an scheduled task. + * + * \par Effects + * reschedule functions until pred() + */ + template + bool reschedule_until(Pred const& pred) + { + do { + //schedule_one_or_yield(); + if ( ! try_executing_one()) + { + return false; + } + } while (! pred()); + return true; + } + + }; + } + using executors::executor_ref; + using executors::generic_executor_ref; +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/executors/inline_executor.hpp b/src/third_party/boost-1.60.0/boost/thread/executors/inline_executor.hpp new file mode 100644 index 00000000000..5dd523184ed --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executors/inline_executor.hpp @@ -0,0 +1,171 @@ +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// 2013/11 Vicente J. Botet Escriba +// first implementation of a simple serial scheduler. + +#ifndef BOOST_THREAD_INLINE_EXECUTOR_HPP +#define BOOST_THREAD_INLINE_EXECUTOR_HPP + +#include +#include +#include +#include + +#include + +namespace boost +{ +namespace executors +{ + class inline_executor + { + public: + /// type-erasure to store the works to do + typedef executors::work work; + bool closed_; + mutable mutex mtx_; + /** + * Effects: try to execute one task. + * Returns: whether a task has been executed. + * Throws: whatever the current task constructor throws or the task() throws. + */ + bool try_executing_one() + { + return false; + } + + public: + /// inline_executor is not copyable. + BOOST_THREAD_NO_COPYABLE(inline_executor) + + /** + * \b Effects: creates a inline executor that runs closures immediately. + * + * \b Throws: Nothing. + */ + inline_executor() + : closed_(false) + { + } + /** + * \b Effects: Destroys the inline executor. + * + * \b Synchronization: The completion of all the closures happen before the completion of the \c inline_executor destructor. + */ + ~inline_executor() + { + // signal to all the worker thread that there will be no more submissions. + close(); + } + + /** + * \b Effects: close the \c inline_executor for submissions. + * The loop will work until there is no more closures to run. + */ + void close() + { + lock_guard lk(mtx_); + closed_ = true; + } + + /** + * \b Returns: whether the pool is closed for submissions. + */ + bool closed(lock_guard& ) + { + return closed_; + } + bool closed() + { + lock_guard lk(mtx_); + return closed(lk); + } + + /** + * \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible. + * + * \b Effects: The specified \c closure will be scheduled for execution at some point in the future. + * If invoked closure throws an exception the \c inline_executor will call \c std::terminate, as is the case with threads. + * + * \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables. + * + * \b Throws: \c sync_queue_is_closed if the thread pool is closed. + * Whatever exception that can be throw while storing the closure. + */ + +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template + void submit(Closure & closure) + { + { + lock_guard lk(mtx_); + if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); + } + try + { + closure(); + } + catch (...) + { + std::terminate(); + return; + } + } +#endif + void submit(void (*closure)()) + { + { + lock_guard lk(mtx_); + if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); + } + try + { + closure(); + } + catch (...) + { + std::terminate(); + return; + } + } + + template + void submit(BOOST_THREAD_FWD_REF(Closure) closure) + { + { + lock_guard lk(mtx_); + if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); + } + try + { + closure(); + } + catch (...) + { + std::terminate(); + return; + } + } + + /** + * \b Requires: This must be called from an scheduled task. + * + * \b Effects: reschedule functions until pred() + */ + template + bool reschedule_until(Pred const& ) + { + return false; + } + + }; +} +using executors::inline_executor; +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/executors/loop_executor.hpp b/src/third_party/boost-1.60.0/boost/thread/executors/loop_executor.hpp new file mode 100644 index 00000000000..b08ff76f575 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executors/loop_executor.hpp @@ -0,0 +1,205 @@ +// Copyright (C) 2013,2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// 2013/11 Vicente J. Botet Escriba +// first implementation of a simple user scheduler. +// 2013/11 Vicente J. Botet Escriba +// rename loop_executor. + +#ifndef BOOST_THREAD_EXECUTORS_LOOP_EXECUTOR_HPP +#define BOOST_THREAD_EXECUTORS_LOOP_EXECUTOR_HPP + +#include +#include +#include +#include +#include + +#include + +namespace boost +{ +namespace executors +{ + + class loop_executor + { + public: + /// type-erasure to store the works to do + typedef executors::work work; + private: + /// the thread safe work queue + concurrent::sync_queue work_queue; + + public: + /** + * Effects: try to execute one task. + * Returns: whether a task has been executed. + * Throws: whatever the current task constructor throws or the task() throws. + */ + bool try_executing_one() + { + work task; + try + { + if (work_queue.try_pull(task) == queue_op_status::success) + { + task(); + return true; + } + return false; + } + catch (...) + { + std::terminate(); + //return false; + } + } + private: + /** + * Effects: schedule one task or yields + * Throws: whatever the current task constructor throws or the task() throws. + */ + void schedule_one_or_yield() + { + if ( ! try_executing_one()) + { + this_thread::yield(); + } + } + + + + + public: + /// loop_executor is not copyable. + BOOST_THREAD_NO_COPYABLE(loop_executor) + + /** + * \b Effects: creates a thread pool that runs closures using one of its closure-executing methods. + * + * \b Throws: Whatever exception is thrown while initializing the needed resources. + */ + loop_executor() + { + } + /** + * \b Effects: Destroys the thread pool. + * + * \b Synchronization: The completion of all the closures happen before the completion of the \c loop_executor destructor. + */ + ~loop_executor() + { + // signal to all the worker thread that there will be no more submissions. + close(); + } + + /** + * The main loop of the worker thread + */ + void loop() + { + while (!closed()) + { + schedule_one_or_yield(); + } + while (try_executing_one()) + { + } + } + + /** + * \b Effects: close the \c loop_executor for submissions. + * The loop will work until there is no more closures to run. + */ + void close() + { + work_queue.close(); + } + + /** + * \b Returns: whether the pool is closed for submissions. + */ + bool closed() + { + return work_queue.closed(); + } + + /** + * \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible. + * + * \b Effects: The specified \c closure will be scheduled for execution at some point in the future. + * If invoked closure throws an exception the \c loop_executor will call \c std::terminate, as is the case with threads. + * + * \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables. + * + * \b Throws: \c sync_queue_is_closed if the thread pool is closed. + * Whatever exception that can be throw while storing the closure. + */ + void submit(BOOST_THREAD_RV_REF(work) closure) { + work_queue.push(boost::move(closure)); + } + +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template + void submit(Closure & closure) + { + submit(work(closure)); + } +#endif + + void submit(void (*closure)()) + { + submit(work(closure)); + } + + template + void submit(BOOST_THREAD_FWD_REF(Closure) closure) + { + //work_queue.push(work(boost::forward(closure))); + work w((boost::forward(closure))); + submit(boost::move(w)); + } + + /** + * \b Requires: This must be called from an scheduled task. + * + * \b Effects: reschedule functions until pred() + */ + template + bool reschedule_until(Pred const& pred) + { + do { + if ( ! try_executing_one()) + { + return false; + } + } while (! pred()); + return true; + } + + /** + * run queued closures + */ + void run_queued_closures() + { + sync_queue::underlying_queue_type q = work_queue.underlying_queue(); + while (! q.empty()) + { + work& task = q.front(); + task(); + q.pop_front(); + } + } + + }; +} +using executors::loop_executor; + +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/executors/scheduled_thread_pool.hpp b/src/third_party/boost-1.60.0/boost/thread/executors/scheduled_thread_pool.hpp new file mode 100644 index 00000000000..408013b283e --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executors/scheduled_thread_pool.hpp @@ -0,0 +1,48 @@ +// Copyright (C) 2014 Ian Forbed +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_THREAD_EXECUTORS_SCHEDULED_THREAD_POOL_HPP +#define BOOST_THREAD_EXECUTORS_SCHEDULED_THREAD_POOL_HPP + +#include + +namespace boost +{ +namespace executors +{ + + class scheduled_thread_pool : public detail::scheduled_executor_base<> + { + private: + thread_group _workers; + public: + + scheduled_thread_pool(size_t num_threads) : super() + { + for(size_t i = 0; i < num_threads; i++) + { + _workers.create_thread(bind(&super::loop, this)); + } + } + + ~scheduled_thread_pool() + { + this->close(); + _workers.join_all(); + } + + private: + typedef detail::scheduled_executor_base<> super; + }; //end class + +} //end executors namespace + +using executors::scheduled_thread_pool; + +} //end boost +#endif + diff --git a/src/third_party/boost-1.60.0/boost/thread/executors/scheduler.hpp b/src/third_party/boost-1.60.0/boost/thread/executors/scheduler.hpp new file mode 100644 index 00000000000..5796a7d3947 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executors/scheduler.hpp @@ -0,0 +1,271 @@ +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_THREAD_EXECUTORS_SCHEDULER_HPP +#define BOOST_THREAD_EXECUTORS_SCHEDULER_HPP + +#include +#include + +#include +#include +#include + +#include + +namespace boost +{ + namespace executors + { + /// Wraps the reference to an executor and a function to make a work that submit the function using the executor. + template + class resubmitter + { + public: + resubmitter(Executor& ex, Function funct) : + ex(ex), + funct(boost::move(funct)) + {} + + void operator()() + { + ex.submit(funct); + } + + private: + Executor& ex; + Function funct; + }; + + /// resubmitter factory + template + resubmitter::type> + resubmit(Executor& ex, BOOST_THREAD_FWD_REF(Function) funct) { + return resubmitter::type >(ex, boost::move(funct)); + } + + /// Wraps references to a @c Scheduler and an @c Executor providing an @c Executor that + /// resubmit the function using the referenced Executor at a given @c time_point known at construction. + template + class resubmit_at_executor + { + public: + typedef typename Scheduler::clock clock; + typedef typename Scheduler::work work; + + template + resubmit_at_executor(Scheduler& sch, Executor& ex, chrono::time_point const& tp) : + sch(sch), + ex(ex), + tp(tp), + is_closed(false) + { + } + + ~resubmit_at_executor() + { + close(); + } + + template + void submit(BOOST_THREAD_FWD_REF(Work) w) + { + if (closed()) + { + BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); + } + sch.submit_at(resubmit(ex,boost::forward(w)), tp); + } + + Executor& underlying_executor() + { + return ex; + } + Scheduler& underlying_scheduler() + { + return sch; + } + + void close() + { + is_closed = true; + } + + bool closed() + { + return is_closed || sch.closed() || ex.closed(); + } + + private: + Scheduler& sch; + Executor& ex; + typename clock::time_point tp; + bool is_closed; + }; + + + /// Expression template helper storing a pair of references to an @c Scheduler and an @c Executor + /// It provides factory helper functions such as at/after that convert these a pair of @c Scheduler @c Executor + /// into an new @c Executor that submit the work using the referenced @c Executor at/after a specific time/duration + /// respectively, using the referenced @Scheduler. + template + class scheduler_executor_wrapper + { + public: + typedef typename Scheduler::clock clock; + typedef typename Scheduler::work work; + typedef resubmit_at_executor the_executor; + + scheduler_executor_wrapper(Scheduler& sch, Executor& ex) : + sch(sch), + ex(ex) + {} + + ~scheduler_executor_wrapper() + { + } + + Executor& underlying_executor() + { + return ex; + } + Scheduler& underlying_scheduler() + { + return sch; + } + + template + the_executor after(chrono::duration const& rel_time) + { + return at(clock::now() + rel_time ); + } + + template + the_executor at(chrono::time_point const& abs_time) + { + return the_executor(sch, ex, abs_time); + } + + private: + Scheduler& sch; + Executor& ex; + }; //end class + + /// Wraps a reference to a @c Scheduler providing an @c Executor that + /// run the function at a given @c time_point known at construction. + template + class at_executor + { + public: + typedef typename Scheduler::clock clock; + typedef typename Scheduler::work work; + typedef typename clock::time_point time_point; + + template + at_executor(Scheduler& sch, chrono::time_point const& tp) : + sch(sch), + tp(tp), + is_closed(false) + {} + + ~at_executor() + { + close(); + } + + Scheduler& underlying_scheduler() + { + return sch; + } + + void close() + { + is_closed = true; + } + + bool closed() + { + return is_closed || sch.closed(); + } + + template + void submit(BOOST_THREAD_FWD_REF(Work) w) + { + if (closed()) + { + BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); + } + sch.submit_at(boost::forward(w), tp); + } + + template + resubmit_at_executor on(Executor& ex) + { + return resubmit_at_executor(sch, ex, tp); + } + + private: + Scheduler& sch; + time_point tp; + bool is_closed; + }; //end class + + /// A @c Scheduler using a specific thread. Note that a Scheduler is not an Executor. + /// It provides factory helper functions such as at/after that convert a @c Scheduler into an @c Executor + /// that submit the work at/after a specific time/duration respectively. + template + class scheduler : public detail::scheduled_executor_base + { + public: + typedef typename detail::scheduled_executor_base::work work; + + typedef Clock clock; + + scheduler() + : super(), + thr(&super::loop, this) {} + + ~scheduler() + { + this->close(); + thr.join(); + } + template + scheduler_executor_wrapper on(Ex& ex) + { + return scheduler_executor_wrapper(*this, ex); + } + + template + at_executor after(chrono::duration const& rel_time) + { + return at(rel_time + clock::now()); + } + + template + at_executor at(chrono::time_point const& tp) + { + return at_executor(*this, tp); + } + + private: + typedef detail::scheduled_executor_base super; + thread thr; + }; + + + } + using executors::resubmitter; + using executors::resubmit; + using executors::resubmit_at_executor; + using executors::scheduler_executor_wrapper; + using executors::at_executor; + using executors::scheduler; +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/executors/scheduling_adaptor.hpp b/src/third_party/boost-1.60.0/boost/thread/executors/scheduling_adaptor.hpp new file mode 100644 index 00000000000..ac0a0acbce8 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executors/scheduling_adaptor.hpp @@ -0,0 +1,51 @@ +// Copyright (C) 2014 Ian Forbed +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_THREAD_EXECUTORS_SCHEDULING_ADAPTOR_HPP +#define BOOST_THREAD_EXECUTORS_SCHEDULING_ADAPTOR_HPP + +#include + +namespace boost +{ +namespace executors +{ + + template + class scheduling_adpator : public detail::scheduled_executor_base<> + { + private: + Executor& _exec; + thread _scheduler; + public: + + scheduling_adpator(Executor& ex) + : super(), + _exec(ex), + _scheduler(&super::loop, this) {} + + ~scheduling_adpator() + { + this->close(); + _scheduler.join(); + } + + Executor& underlying_executor() + { + return _exec; + } + + private: + typedef detail::scheduled_executor_base<> super; + }; //end class + +} //end executors + + using executors::scheduling_adpator; + +} //end boost +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/executors/serial_executor.hpp b/src/third_party/boost-1.60.0/boost/thread/executors/serial_executor.hpp new file mode 100644 index 00000000000..6d7ed9be97b --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executors/serial_executor.hpp @@ -0,0 +1,216 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// 2013/11 Vicente J. Botet Escriba +// first implementation of a simple serial scheduler. + +#ifndef BOOST_THREAD_SERIAL_EXECUTOR_HPP +#define BOOST_THREAD_SERIAL_EXECUTOR_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost +{ +namespace executors +{ + class serial_executor + { + public: + /// type-erasure to store the works to do + typedef executors::work work; + private: + typedef scoped_thread<> thread_t; + + /// the thread safe work queue + concurrent::sync_queue work_queue; + generic_executor_ref ex; + thread_t thr; + + struct try_executing_one_task { + work& task; + boost::promise &p; + try_executing_one_task(work& task, boost::promise &p) + : task(task), p(p) {} + void operator()() { + try { + task(); + p.set_value(); + } catch (...) + { + p.set_exception(current_exception()); + } + } + }; + public: + /** + * \par Returns + * The underlying executor wrapped on a generic executor reference. + */ + generic_executor_ref& underlying_executor() BOOST_NOEXCEPT { return ex; } + + /** + * Effects: try to execute one task. + * Returns: whether a task has been executed. + * Throws: whatever the current task constructor throws or the task() throws. + */ + bool try_executing_one() + { + work task; + try + { + if (work_queue.try_pull(task) == queue_op_status::success) + { + boost::promise p; + try_executing_one_task tmp(task,p); + ex.submit(tmp); + p.get_future().wait(); + return true; + } + return false; + } + catch (...) + { + std::terminate(); + //return false; + } + } + private: + /** + * Effects: schedule one task or yields + * Throws: whatever the current task constructor throws or the task() throws. + */ + void schedule_one_or_yield() + { + if ( ! try_executing_one()) + { + this_thread::yield(); + } + } + + /** + * The main loop of the worker thread + */ + void worker_thread() + { + while (!closed()) + { + schedule_one_or_yield(); + } + while (try_executing_one()) + { + } + } + + public: + /// serial_executor is not copyable. + BOOST_THREAD_NO_COPYABLE(serial_executor) + + /** + * \b Effects: creates a thread pool that runs closures using one of its closure-executing methods. + * + * \b Throws: Whatever exception is thrown while initializing the needed resources. + */ + template + serial_executor(Executor& ex) + : ex(ex), thr(&serial_executor::worker_thread, this) + { + } + /** + * \b Effects: Destroys the thread pool. + * + * \b Synchronization: The completion of all the closures happen before the completion of the \c serial_executor destructor. + */ + ~serial_executor() + { + // signal to the worker thread that there will be no more submissions. + close(); + } + + /** + * \b Effects: close the \c serial_executor for submissions. + * The loop will work until there is no more closures to run. + */ + void close() + { + work_queue.close(); + } + + /** + * \b Returns: whether the pool is closed for submissions. + */ + bool closed() + { + return work_queue.closed(); + } + + /** + * \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible. + * + * \b Effects: The specified \c closure will be scheduled for execution at some point in the future. + * If invoked closure throws an exception the \c serial_executor will call \c std::terminate, as is the case with threads. + * + * \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables. + * + * \b Throws: \c sync_queue_is_closed if the thread pool is closed. + * Whatever exception that can be throw while storing the closure. + */ + void submit(BOOST_THREAD_RV_REF(work) closure) + { + work_queue.push(boost::move(closure)); + } + +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template + void submit(Closure & closure) + { + submit(work(closure)); + } +#endif + void submit(void (*closure)()) + { + submit(work(closure)); + } + + template + void submit(BOOST_THREAD_FWD_REF(Closure) closure) + { + work w((boost::forward(closure))); + submit(boost::move(w)); + } + + /** + * \b Requires: This must be called from an scheduled task. + * + * \b Effects: reschedule functions until pred() + */ + template + bool reschedule_until(Pred const& pred) + { + do { + if ( ! try_executing_one()) + { + return false; + } + } while (! pred()); + return true; + } + + }; +} +using executors::serial_executor; +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/executors/serial_executor_cont.hpp b/src/third_party/boost-1.60.0/boost/thread/executors/serial_executor_cont.hpp new file mode 100644 index 00000000000..91087890be6 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executors/serial_executor_cont.hpp @@ -0,0 +1,170 @@ +// Copyright (C) 2015 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// 2013/11 Vicente J. Botet Escriba +// first implementation of a simple serial scheduler. + +#ifndef BOOST_THREAD_SERIAL_EXECUTOR_CONT_HPP +#define BOOST_THREAD_SERIAL_EXECUTOR_CONT_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost +{ +namespace executors +{ + class serial_executor_cont + { + public: + /// type-erasure to store the works to do + typedef executors::work work; + private: + + generic_executor_ref ex_; + future fut_; // protected by mtx_ + bool closed_; // protected by mtx_ + mutex mtx_; + + struct continuation { + work task; + template + struct result { + typedef void type; + }; + continuation(BOOST_THREAD_RV_REF(work) tsk) + : task(boost::move(tsk)) {} + void operator()(future f) + { + try { + task(); + } catch (...) { + std::terminate(); + } + } + }; + + bool closed(lock_guard&) const + { + return closed_; + } + public: + /** + * \par Returns + * The underlying executor wrapped on a generic executor reference. + */ + generic_executor_ref& underlying_executor() BOOST_NOEXCEPT { return ex_; } + + /// serial_executor_cont is not copyable. + BOOST_THREAD_NO_COPYABLE(serial_executor_cont) + + /** + * \b Effects: creates a serial executor that runs closures in fifo order using one the associated executor. + * + * \b Throws: Whatever exception is thrown while initializing the needed resources. + * + * \b Notes: + * * The lifetime of the associated executor must outlive the serial executor. + * * The current implementation doesn't support submission from synchronous continuation, that is, + * - the executor must execute the continuation asynchronously or + * - the continuation can not submit to this serial executor. + */ + template + serial_executor_cont(Executor& ex) + : ex_(ex), fut_(make_ready_future()), closed_(false) + { + } + /** + * \b Effects: Destroys the thread pool. + * + * \b Synchronization: The completion of all the closures happen before the completion of the \c serial_executor_cont destructor. + */ + ~serial_executor_cont() + { + // signal to the worker thread that there will be no more submissions. + close(); + } + + /** + * \b Effects: close the \c serial_executor_cont for submissions. + * The loop will work until there is no more closures to run. + */ + void close() + { + lock_guard lk(mtx_); + closed_ = true;; + } + + /** + * \b Returns: whether the pool is closed for submissions. + */ + bool closed() + { + lock_guard lk(mtx_); + return closed(lk); + } + + /** + * Effects: none. + * Returns: always false. + * Throws: No. + * Remark: A serial executor can not execute one of its pending tasks as the tasks depends on the other tasks. + */ + bool try_executing_one() + { + return false; + } + + /** + * \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible. + * + * \b Effects: The specified \c closure will be scheduled for execution after the last submitted closure finish. + * If the invoked closure throws an exception the \c serial_executor_cont will call \c std::terminate, as is the case with threads. + * + * \b Throws: \c sync_queue_is_closed if the executor is closed. + * Whatever exception that can be throw while storing the closure. + * + */ + +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template + void submit(Closure & closure) + { + lock_guard lk(mtx_); + if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); + fut_ = fut_.then(ex_, continuation(work(closure))); + } +#endif + void submit(void (*closure)()) + { + lock_guard lk(mtx_); + if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); + fut_ = fut_.then(ex_, continuation(work(closure))); + } + + template + void submit(BOOST_THREAD_FWD_REF(Closure) closure) + { + lock_guard lk(mtx_); + if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); + fut_ = fut_.then(ex_, continuation(work(boost::forward(closure)))); + } + + }; +} +using executors::serial_executor_cont; +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/executors/thread_executor.hpp b/src/third_party/boost-1.60.0/boost/thread/executors/thread_executor.hpp new file mode 100644 index 00000000000..c9f49a7b62f --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executors/thread_executor.hpp @@ -0,0 +1,157 @@ +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// 2014/01 Vicente J. Botet Escriba +// first implementation of a thread_executor. + +#ifndef BOOST_THREAD_THREAD_EXECUTOR_HPP +#define BOOST_THREAD_THREAD_EXECUTOR_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost +{ +namespace executors +{ + class thread_executor + { + public: + /// type-erasure to store the works to do + typedef executors::work work; + bool closed_; + typedef scoped_thread<> thread_t; + typedef csbl::vector threads_type; + threads_type threads_; + mutable mutex mtx_; + + /** + * Effects: try to execute one task. + * Returns: whether a task has been executed. + * Throws: whatever the current task constructor throws or the task() throws. + */ + bool try_executing_one() + { + return false; + } + + public: + /// thread_executor is not copyable. + BOOST_THREAD_NO_COPYABLE(thread_executor) + + /** + * \b Effects: creates a inline executor that runs closures immediately. + * + * \b Throws: Nothing. + */ + thread_executor() + : closed_(false) + { + } + /** + * \b Effects: Waits for closures (if any) to complete, then joins and destroys the threads. + * + * \b Synchronization: The completion of all the closures happen before the completion of the \c thread_executor destructor. + */ + ~thread_executor() + { + // signal to all the worker thread that there will be no more submissions. + close(); + // all the scoped threads will join before destroying + } + + /** + * \b Effects: close the \c thread_executor for submissions. + * The loop will work until there is no more closures to run. + */ + void close() + { + lock_guard lk(mtx_); + closed_ = true; + } + + /** + * \b Returns: whether the pool is closed for submissions. + */ + bool closed(lock_guard& ) + { + return closed_; + } + bool closed() + { + lock_guard lk(mtx_); + return closed(lk); + } + + /** + * \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible. + * + * \b Effects: The specified \c closure will be scheduled for execution at some point in the future. + * If invoked closure throws an exception the \c thread_executor will call \c std::terminate, as is the case with threads. + * + * \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables. + * + * \b Throws: \c sync_queue_is_closed if the thread pool is closed. + * Whatever exception that can be throw while storing the closure. + */ + +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template + void submit(Closure & closure) + { + lock_guard lk(mtx_); + if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); + threads_.reserve(threads_.size() + 1); + thread th(closure); + threads_.push_back(thread_t(boost::move(th))); + } +#endif + void submit(void (*closure)()) + { + lock_guard lk(mtx_); + if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); + threads_.reserve(threads_.size() + 1); + thread th(closure); + threads_.push_back(thread_t(boost::move(th))); + } + + template + void submit(BOOST_THREAD_FWD_REF(Closure) closure) + { + lock_guard lk(mtx_); + if (closed(lk)) BOOST_THROW_EXCEPTION( sync_queue_is_closed() ); + threads_.reserve(threads_.size() + 1); + thread th(boost::forward(closure)); + threads_.push_back(thread_t(boost::move(th))); + } + + /** + * \b Requires: This must be called from an scheduled task. + * + * \b Effects: reschedule functions until pred() + */ + template + bool reschedule_until(Pred const&) + { + return false; + } + + }; +} +using executors::thread_executor; +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/executors/work.hpp b/src/third_party/boost-1.60.0/boost/thread/executors/work.hpp new file mode 100644 index 00000000000..bdaf7651b92 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/executors/work.hpp @@ -0,0 +1,30 @@ +// (C) Copyright 2013,2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_THREAD_EXECUTORS_WORK_HPP +#define BOOST_THREAD_EXECUTORS_WORK_HPP + +#include +#include +#include + +namespace boost +{ + namespace executors + { + typedef detail::nullary_function work; + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + typedef detail::nullary_function work_pq; + //typedef csbl::function work_pq; +#else + typedef csbl::function work_pq; +#endif + } +} // namespace boost + + +#endif // BOOST_THREAD_EXECUTORS_WORK_HPP diff --git a/src/third_party/boost-1.60.0/boost/thread/experimental/config/inline_namespace.hpp b/src/third_party/boost-1.60.0/boost/thread/experimental/config/inline_namespace.hpp new file mode 100644 index 00000000000..9c3b081fbe4 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/experimental/config/inline_namespace.hpp @@ -0,0 +1,23 @@ +#ifndef BOOST_THREAD_EXPERIMENTAL_CONFIG_INLINE_NAMESPACE_HPP +#define BOOST_THREAD_EXPERIMENTAL_CONFIG_INLINE_NAMESPACE_HPP + +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Vicente J. Botet Escriba 2014. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include + +#if !defined(BOOST_NO_CXX11_INLINE_NAMESPACES) +# define BOOST_THREAD_INLINE_NAMESPACE(name) inline namespace name +#else +# define BOOST_THREAD_INLINE_NAMESPACE(name) namespace name +#endif + + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/experimental/exception_list.hpp b/src/third_party/boost-1.60.0/boost/thread/experimental/exception_list.hpp new file mode 100644 index 00000000000..748bfa85ee7 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/experimental/exception_list.hpp @@ -0,0 +1,16 @@ +#ifndef BOOST_THREAD_EXPERIMENTAL_EXCEPTION_LIST_HPP +#define BOOST_THREAD_EXPERIMENTAL_EXCEPTION_LIST_HPP + +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Vicente J. Botet Escriba 2014. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/experimental/parallel/v1/exception_list.hpp b/src/third_party/boost-1.60.0/boost/thread/experimental/parallel/v1/exception_list.hpp new file mode 100644 index 00000000000..e4d3354f1c1 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/experimental/parallel/v1/exception_list.hpp @@ -0,0 +1,70 @@ +#ifndef BOOST_THREAD_EXPERIMENTAL_PARALLEL_V1_EXCEPTION_LIST_HPP +#define BOOST_THREAD_EXPERIMENTAL_PARALLEL_V1_EXCEPTION_LIST_HPP + +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Vicente J. Botet Escriba 2014. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include +#include +#include + +#include + +namespace boost +{ +namespace experimental +{ +namespace parallel +{ +BOOST_THREAD_INLINE_NAMESPACE(v1) +{ + + class BOOST_SYMBOL_VISIBLE exception_list: public std::exception + { + typedef std::list exception_ptr_list; + exception_ptr_list list_; + public: + typedef exception_ptr_list::const_iterator const_iterator; + + ~exception_list() BOOST_NOEXCEPT_OR_NOTHROW {} + + void add(exception_ptr const& e) + { + list_.push_back(e); + } + size_t size() const BOOST_NOEXCEPT + { + return list_.size(); + } + const_iterator begin() const BOOST_NOEXCEPT + { + return list_.begin(); + } + const_iterator end() const BOOST_NOEXCEPT + { + return list_.end(); + } + const char* what() const BOOST_NOEXCEPT_OR_NOTHROW + { + return "exception_list"; + } + + }; +} + +} // parallel +} // experimental +} // boost +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/experimental/parallel/v1/inline_namespace.hpp b/src/third_party/boost-1.60.0/boost/thread/experimental/parallel/v1/inline_namespace.hpp new file mode 100644 index 00000000000..a607e53c468 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/experimental/parallel/v1/inline_namespace.hpp @@ -0,0 +1,28 @@ +#ifndef BOOST_THREAD_EXPERIMENTAL_PARALLEL_V1_INLINE_NAMESPACE_HPP +#define BOOST_THREAD_EXPERIMENTAL_PARALLEL_V1_INLINE_NAMESPACE_HPP + +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Vicente J. Botet Escriba 2014. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include +namespace boost { +namespace experimental { +namespace parallel { + + BOOST_THREAD_INLINE_NAMESPACE(v1) {} + +#if defined(BOOST_NO_CXX11_INLINE_NAMESPACES) + using namespace v1; +#endif + +} +} +} +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/experimental/parallel/v2/inline_namespace.hpp b/src/third_party/boost-1.60.0/boost/thread/experimental/parallel/v2/inline_namespace.hpp new file mode 100644 index 00000000000..52d8e2904e8 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/experimental/parallel/v2/inline_namespace.hpp @@ -0,0 +1,29 @@ +#ifndef BOOST_THREAD_EXPERIMENTAL_PARALLEL_V2_INLINE_NAMESPACE_HPP +#define BOOST_THREAD_EXPERIMENTAL_PARALLEL_V2_INLINE_NAMESPACE_HPP + +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Vicente J. Botet Escriba 2014. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include + +namespace boost { +namespace experimental { +namespace parallel { + + BOOST_THREAD_INLINE_NAMESPACE(v2) {} + +#if defined(BOOST_NO_CXX11_INLINE_NAMESPACES) + using namespace v2; +#endif + +} +} +} +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/experimental/parallel/v2/task_region.hpp b/src/third_party/boost-1.60.0/boost/thread/experimental/parallel/v2/task_region.hpp new file mode 100755 index 00000000000..e4a5833115f --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/experimental/parallel/v2/task_region.hpp @@ -0,0 +1,316 @@ +#ifndef BOOST_THREAD_EXPERIMENTAL_PARALLEL_V2_TASK_REGION_HPP +#define BOOST_THREAD_EXPERIMENTAL_PARALLEL_V2_TASK_REGION_HPP + +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Vicente J. Botet Escriba 2014-2015. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// +#include + +#include +#if defined BOOST_THREAD_PROVIDES_EXECUTORS +#include +#endif +#include +#include +#include + +#include + +#define BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED + +namespace boost +{ +namespace experimental +{ +namespace parallel +{ +BOOST_THREAD_INLINE_NAMESPACE(v2) +{ + class BOOST_SYMBOL_VISIBLE task_canceled_exception: public std::exception + { + public: + //task_canceled_exception() BOOST_NOEXCEPT {} + //task_canceled_exception(const task_canceled_exception&) BOOST_NOEXCEPT {} + //task_canceled_exception& operator=(const task_canceled_exception&) BOOST_NOEXCEPT {} + virtual const char* what() const BOOST_NOEXCEPT_OR_NOTHROW + { return "task_canceled_exception";} + }; + + template + class task_region_handle_gen; + + namespace detail + { + void handle_task_region_exceptions(exception_list& errors) + { + try { + throw; + } +#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED + catch (task_canceled_exception&) + { + } +#endif + catch (exception_list const& el) + { + for (exception_list::const_iterator it = el.begin(); it != el.end(); ++it) + { + boost::exception_ptr const& e = *it; + try { + rethrow_exception(e); + } + catch (...) + { + handle_task_region_exceptions(errors); + } + } + } + catch (...) + { + errors.add(boost::current_exception()); + } + } + +#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED + template + struct wrapped + { + TRH& tr; + F f; + wrapped(TRH& tr, BOOST_THREAD_RV_REF(F) f) : tr(tr), f(move(f)) + {} + void operator()() + { + try + { + f(); + } + catch (...) + { + lock_guard lk(tr.mtx); + tr.canceled = true; + throw; + } + } + }; +#endif + } + + template + class task_region_handle_gen + { + private: + // Private members and friends +#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED + template + friend struct detail::wrapped; +#endif + template + friend void task_region(BOOST_THREAD_FWD_REF(F) f); + template + friend void task_region_final(BOOST_THREAD_FWD_REF(F) f); + template + friend void task_region(Ex&, BOOST_THREAD_FWD_REF(F) f); + template + friend void task_region_final(Ex&, BOOST_THREAD_FWD_REF(F) f); + + void wait_all() + { + wait_for_all(group.begin(), group.end()); + + for (group_type::iterator it = group.begin(); it != group.end(); ++it) + { + future& f = *it; + if (f.has_exception()) + { + try + { + boost::rethrow_exception(f.get_exception_ptr()); + } + catch (...) + { + detail::handle_task_region_exceptions(exs); + } + } + } + if (exs.size() != 0) + { + boost::throw_exception(exs); + } + } +protected: +#if ! defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED && ! defined BOOST_THREAD_PROVIDES_EXECUTORS + task_region_handle_gen() + {} +#endif + +#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED && defined BOOST_THREAD_PROVIDES_EXECUTORS + task_region_handle_gen() + : canceled(false) + , ex(0) + {} + task_region_handle_gen(Executor& ex) + : canceled(false) + , ex(&ex) + {} + +#endif + +#if ! defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED && defined BOOST_THREAD_PROVIDES_EXECUTORS + task_region_handle_gen() + : ex(0) + {} + task_region_handle_gen(Executor& ex) + : ex(&ex) + {} +#endif + +#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED && ! defined BOOST_THREAD_PROVIDES_EXECUTORS + task_region_handle_gen() + : canceled(false) + { + } +#endif + + ~task_region_handle_gen() + { + //wait_all(); + } + +#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED + mutable mutex mtx; + bool canceled; +#endif +#if defined BOOST_THREAD_PROVIDES_EXECUTORS + Executor* ex; +#endif + exception_list exs; + typedef csbl::vector > group_type; + group_type group; + + public: + BOOST_DELETED_FUNCTION(task_region_handle_gen(const task_region_handle_gen&)) + BOOST_DELETED_FUNCTION(task_region_handle_gen& operator=(const task_region_handle_gen&)) + BOOST_DELETED_FUNCTION(task_region_handle_gen* operator&() const) + + public: + template + void run(BOOST_THREAD_FWD_REF(F) f) + { +#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED + { + lock_guard lk(mtx); + if (canceled) { + boost::throw_exception(task_canceled_exception()); + } + } +#if defined BOOST_THREAD_PROVIDES_EXECUTORS + group.push_back(async(*ex, detail::wrapped, F>(*this, forward(f)))); +#else + group.push_back(async(detail::wrapped, F>(*this, forward(f)))); +#endif +#else +#if defined BOOST_THREAD_PROVIDES_EXECUTORS + group.push_back(async(*ex, forward(f))); +#else + group.push_back(async(forward(f))); +#endif +#endif + } + + void wait() + { +#if defined BOOST_THREAD_TASK_REGION_HAS_SHARED_CANCELED + { + lock_guard lk(mtx); + if (canceled) { + boost::throw_exception(task_canceled_exception()); + } + } +#endif + wait_all(); + } + }; +#if defined BOOST_THREAD_PROVIDES_EXECUTORS + typedef basic_thread_pool default_executor; +#else + typedef int default_executor; +#endif + class task_region_handle : + public task_region_handle_gen + { + default_executor tp; + template + friend void task_region(BOOST_THREAD_FWD_REF(F) f); + template + friend void task_region_final(BOOST_THREAD_FWD_REF(F) f); + + protected: + task_region_handle() : task_region_handle_gen() + { +#if defined BOOST_THREAD_PROVIDES_EXECUTORS + ex = &tp; +#endif + } + BOOST_DELETED_FUNCTION(task_region_handle(const task_region_handle&)) + BOOST_DELETED_FUNCTION(task_region_handle& operator=(const task_region_handle&)) + BOOST_DELETED_FUNCTION(task_region_handle* operator&() const) + + }; + + template + void task_region_final(Executor& ex, BOOST_THREAD_FWD_REF(F) f) + { + task_region_handle_gen tr(ex); + try + { + f(tr); + } + catch (...) + { + detail::handle_task_region_exceptions(tr.exs); + } + tr.wait_all(); + } + + template + void task_region(Executor& ex, BOOST_THREAD_FWD_REF(F) f) + { + task_region_final(ex, forward(f)); + } + + template + void task_region_final(BOOST_THREAD_FWD_REF(F) f) + { + task_region_handle tr; + try + { + f(tr); + } + catch (...) + { + detail::handle_task_region_exceptions(tr.exs); + } + tr.wait_all(); + } + + template + void task_region(BOOST_THREAD_FWD_REF(F) f) + { + task_region_final(forward(f)); + } + +} // v2 +} // parallel +} // experimental +} // boost + +#include + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/experimental/task_region.hpp b/src/third_party/boost-1.60.0/boost/thread/experimental/task_region.hpp new file mode 100644 index 00000000000..9b60d8b19ee --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/experimental/task_region.hpp @@ -0,0 +1,16 @@ +#ifndef BOOST_THREAD_EXPERIMENTAL_TASK_REGION_HPP +#define BOOST_THREAD_EXPERIMENTAL_TASK_REGION_HPP + +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Vicente J. Botet Escriba 2014. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/externally_locked.hpp b/src/third_party/boost-1.60.0/boost/thread/externally_locked.hpp new file mode 100644 index 00000000000..0d4baaa512d --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/externally_locked.hpp @@ -0,0 +1,351 @@ +// (C) Copyright 2012 Vicente J. Botet Escriba +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#ifndef BOOST_THREAD_EXTERNALLY_LOCKED_HPP +#define BOOST_THREAD_EXTERNALLY_LOCKED_HPP + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +namespace boost +{ + + /** + * externally_locked cloaks an object of type T, and actually provides full + * access to that object through the get and set member functions, provided you + * pass a reference to a strict lock object + */ + + //[externally_locked + template + class externally_locked; + template + class externally_locked + { + //BOOST_CONCEPT_ASSERT(( CopyConstructible )); + BOOST_CONCEPT_ASSERT(( BasicLockable )); + + public: + typedef MutexType mutex_type; + + BOOST_THREAD_COPYABLE_AND_MOVABLE( externally_locked ) + /** + * Requires: T is a model of CopyConstructible. + * Effects: Constructs an externally locked object copying the cloaked type. + */ + externally_locked(mutex_type& mtx, const T& obj) : + obj_(obj), mtx_(&mtx) + { + } + + /** + * Requires: T is a model of Movable. + * Effects: Constructs an externally locked object by moving the cloaked type. + */ + externally_locked(mutex_type& mtx, BOOST_THREAD_RV_REF(T) obj) : + obj_(move(obj)), mtx_(&mtx) + { + } + + /** + * Requires: T is a model of DefaultConstructible. + * Effects: Constructs an externally locked object initializing the cloaked type with the default constructor. + */ + externally_locked(mutex_type& mtx) // BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR(T())) + : obj_(), mtx_(&mtx) + { + } + + /** + * Copy constructor + */ + externally_locked(externally_locked const& rhs) //BOOST_NOEXCEPT + : obj_(rhs.obj_), mtx_(rhs.mtx_) + { + } + /** + * Move constructor + */ + externally_locked(BOOST_THREAD_RV_REF(externally_locked) rhs) //BOOST_NOEXCEPT + : obj_(move(rhs.obj_)), mtx_(rhs.mtx_) + { + } + + /// assignment + externally_locked& operator=(externally_locked const& rhs) //BOOST_NOEXCEPT + { + obj_=rhs.obj_; + mtx_=rhs.mtx_; + return *this; + } + + /// move assignment + externally_locked& operator=(BOOST_THREAD_RV_REF(externally_locked) rhs) // BOOST_NOEXCEPT + { + obj_=move(BOOST_THREAD_RV(rhs).obj_); + mtx_=rhs.mtx_; + return *this; + } + + void swap(externally_locked& rhs) //BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT_EXPR) + { + swap(obj_, rhs.obj_); + swap(mtx_, rhs.mtx_); + } + + /** + * Requires: The lk parameter must be locking the associated mtx. + * + * Returns: The address of the cloaked object.. + * + * Throws: lock_error if BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined and the lk parameter doesn't satisfy the preconditions + */ + T& get(strict_lock& lk) + { + BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ + return obj_; + } + + const T& get(strict_lock& lk) const + { + BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ + return obj_; + } + + template + T& get(nested_strict_lock& lk) + { + BOOST_STATIC_ASSERT( (is_same::value)); /*< that locks the same type >*/ + BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ + return obj_; + } + + template + const T& get(nested_strict_lock& lk) const + { + BOOST_STATIC_ASSERT( (is_same::value)); /*< that locks the same type >*/ + BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ + return obj_; + } + + /** + * Requires: The lk parameter must be locking the associated mtx. + * Returns: The address of the cloaked object.. + * + * Throws: lock_error if BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined and the lk parameter doesn't satisfy the preconditions + */ + template + T& get(Lock& lk) + { + BOOST_CONCEPT_ASSERT(( StrictLock )); + BOOST_STATIC_ASSERT( (is_strict_lock::value)); /*< lk is a strict lock "sur parolle" >*/ + BOOST_STATIC_ASSERT( (is_same::value)); /*< that locks the same type >*/ + + BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ + + return obj_; + } + + mutex_type* mutex() const BOOST_NOEXCEPT + { + return mtx_; + } + + // modifiers + + void lock() + { + mtx_->lock(); + } + void unlock() + { + mtx_->unlock(); + } + bool try_lock() + { + return mtx_->try_lock(); + } + // todo add time related functions + + private: + T obj_; + mutex_type* mtx_; + }; + //] + + /** + * externally_locked specialization for T& that cloaks an reference to an object of type T, and actually + * provides full access to that object through the get and set member functions, provided you + * pass a reference to a strict lock object. + */ + + //[externally_locked_ref + template + class externally_locked + { + //BOOST_CONCEPT_ASSERT(( CopyConstructible )); + BOOST_CONCEPT_ASSERT(( BasicLockable )); + + public: + typedef MutexType mutex_type; + + BOOST_THREAD_COPYABLE_AND_MOVABLE( externally_locked ) + + /** + * Effects: Constructs an externally locked object storing the cloaked reference object. + */ + externally_locked(T& obj, mutex_type& mtx) BOOST_NOEXCEPT : + obj_(&obj), mtx_(&mtx) + { + } + + /// copy constructor + externally_locked(externally_locked const& rhs) BOOST_NOEXCEPT : + obj_(rhs.obj_), mtx_(rhs.mtx_) + { + } + + /// move constructor + externally_locked(BOOST_THREAD_RV_REF(externally_locked) rhs) BOOST_NOEXCEPT : + obj_(rhs.obj_), mtx_(rhs.mtx_) + { + } + + /// assignment + externally_locked& operator=(externally_locked const& rhs) BOOST_NOEXCEPT + { + obj_=rhs.obj_; + mtx_=rhs.mtx_; + return *this; + } + + /// move assignment + externally_locked& operator=(BOOST_THREAD_RV_REF(externally_locked) rhs) BOOST_NOEXCEPT + { + obj_=rhs.obj_; + mtx_=rhs.mtx_; + return *this; + } + + void swap(externally_locked& rhs) BOOST_NOEXCEPT + { + swap(obj_, rhs.obj_); + swap(mtx_, rhs.mtx_); + } + /** + * Requires: The lk parameter must be locking the associated mtx. + * + * Returns: The address of the cloaked object.. + * + * Throws: lock_error if BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined and the lk parameter doesn't satisfy the preconditions + */ + T& get(strict_lock const& lk) + { + BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ + return *obj_; + } + + const T& get(strict_lock const& lk) const + { + BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ + return *obj_; + } + + template + T& get(nested_strict_lock const& lk) + { + BOOST_STATIC_ASSERT( (is_same::value)); /*< that locks the same type >*/ + BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ + return *obj_; + } + + template + const T& get(nested_strict_lock const& lk) const + { + BOOST_STATIC_ASSERT( (is_same::value)); /*< that locks the same type >*/ + BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ + return *obj_; + } + + /** + * Requires: The lk parameter must be locking the associated mtx. + * Returns: The address of the cloaked object.. + * + * Throws: lock_error if BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined and the lk parameter doesn't satisfy the preconditions + */ + template + T& get(Lock const& lk) + { + BOOST_CONCEPT_ASSERT(( StrictLock )); + BOOST_STATIC_ASSERT( (is_strict_lock::value)); /*< lk is a strict lock "sur parolle" >*/ + BOOST_STATIC_ASSERT( (is_same::value)); /*< that locks the same type >*/ + BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ + return *obj_; + } + + /** + * Requires: The lk parameter must be locking the associated mtx. + * Returns: The address of the cloaked object.. + * + * Throws: lock_error if BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is not defined and the lk parameter doesn't satisfy the preconditions + */ + template + T const& get(Lock const& lk) const + { + BOOST_CONCEPT_ASSERT(( StrictLock )); + BOOST_STATIC_ASSERT( (is_strict_lock::value)); /*< lk is a strict lock "sur parolle" >*/ + BOOST_STATIC_ASSERT( (is_same::value)); /*< that locks the same type >*/ + BOOST_THREAD_ASSERT_PRECONDITION( lk.owns_lock(mtx_), lock_error() ); /*< run time check throw if not locks the same >*/ + return *obj_; + } + mutex_type* mutex() const BOOST_NOEXCEPT + { + return mtx_; + } + + void lock() + { + mtx_->lock(); + } + void unlock() + { + mtx_->unlock(); + } + bool try_lock() + { + return mtx_->try_lock(); + } + // todo add time related functions + + protected: + T* obj_; + mutex_type* mtx_; + }; + //] + + template + void swap(externally_locked & lhs, externally_locked & rhs) // BOOST_NOEXCEPT + { + lhs.swap(rhs); + } + +} + +#include + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/externally_locked_stream.hpp b/src/third_party/boost-1.60.0/boost/thread/externally_locked_stream.hpp new file mode 100644 index 00000000000..aa9aeff79d9 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/externally_locked_stream.hpp @@ -0,0 +1,170 @@ +// (C) Copyright 2012 Vicente J. Botet Escriba +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#ifndef BOOST_THREAD_EXTERNALLY_LOCKED_STREAM_HPP +#define BOOST_THREAD_EXTERNALLY_LOCKED_STREAM_HPP + +#include +#include +#include + +#include +#include +#include +#include + +#include + +namespace boost +{ + + template + class externally_locked_stream; + + template + class stream_guard + { + + friend class externally_locked_stream ; + public: + typedef typename externally_locked_stream::mutex_type mutex_type; + + BOOST_THREAD_MOVABLE_ONLY( stream_guard) + + stream_guard(externally_locked_stream& mtx) : + mtx_(&mtx) + { + mtx.lock(); + } + + stream_guard(externally_locked_stream& mtx, adopt_lock_t) : + mtx_(&mtx) + { + } + + stream_guard(BOOST_THREAD_RV_REF(stream_guard) rhs) BOOST_NOEXCEPT + : mtx_(rhs.mtx_) + { + rhs.mtx_= 0; + } + + ~stream_guard() + { + if (mtx_ != 0) mtx_->unlock(); + } + + bool owns_lock(const mutex_type * l) const BOOST_NOEXCEPT + { + return l == mtx_->mutex(); + } + + /** + * @Requires mtx_ + */ + Stream& get() const + { + BOOST_THREAD_ASSERT_PRECONDITION( mtx_, lock_error() ); + return mtx_->get(*this); + } + Stream& bypass() const + { + return get(); + } + + + private: + externally_locked_stream* mtx_; + }; + + template + struct is_strict_lock_sur_parole > : true_type + { + }; + + /** + * externally_locked_stream cloaks a reference to an stream of type Stream, and actually + * provides full access to that object through the get and set member functions, provided you + * pass a reference to a strict lock object. + */ + + //[externally_locked_stream + template + class externally_locked_stream: public externally_locked + { + typedef externally_locked base_type; + public: + BOOST_THREAD_NO_COPYABLE( externally_locked_stream) + + /** + * Effects: Constructs an externally locked object storing the cloaked reference object. + */ + externally_locked_stream(Stream& stream, RecursiveMutex& mtx) BOOST_NOEXCEPT : + base_type(stream, mtx) + { + } + + stream_guard hold() BOOST_NOEXCEPT + { + return stream_guard (*this); + } + Stream& bypass() const + { + stream_guard lk(*this); + return get(lk); + } + }; + //] + + template + inline const stream_guard& operator<<(const stream_guard& lck, T arg) + { + lck.get() << arg; + return lck; + } + + template + inline const stream_guard& operator<<(const stream_guard& lck, Stream& (*arg)(Stream&)) + { + lck.get() << arg; + return lck; + } + + template + inline const stream_guard& operator>>(const stream_guard& lck, T& arg) + { + lck.get() >> arg; + return lck; + } + + template + inline stream_guard operator<<(externally_locked_stream& mtx, T arg) + { + stream_guard lk(mtx); + mtx.get(lk) << arg; + return boost::move(lk); + } + + template + inline stream_guard operator<<(externally_locked_stream& mtx, Stream& (*arg)(Stream&)) + { + stream_guard lk(mtx); + mtx.get(lk) << arg; + return boost::move(lk); + } + + template + inline stream_guard operator>>(externally_locked_stream& mtx, T& arg) + { + stream_guard lk(mtx); + mtx.get(lk) >> arg; + return boost::move(lk); + } + +} + +#include + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/future.hpp b/src/third_party/boost-1.60.0/boost/thread/future.hpp new file mode 100644 index 00000000000..0ec484c2bf9 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/future.hpp @@ -0,0 +1,5552 @@ +// (C) Copyright 2008-10 Anthony Williams +// (C) Copyright 2011-2015 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_THREAD_FUTURE_HPP +#define BOOST_THREAD_FUTURE_HPP + +#include + +// boost::thread::future requires exception handling +// due to boost::exception::exception_ptr dependency + +//#define BOOST_THREAD_CONTINUATION_SYNC +#define BOOST_THREAD_FUTURE_BLOCKING + +#ifndef BOOST_NO_EXCEPTIONS + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL +#include +#else +#include +#endif + +#include +#include +#ifdef BOOST_THREAD_USES_CHRONO +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS +#include +#include +#if ! defined BOOST_NO_CXX11_ALLOCATOR +#include +#endif +#endif + +#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY +#include +#include +#endif + +#include +#include +#include +#include + +#if defined BOOST_THREAD_PROVIDES_FUTURE +#define BOOST_THREAD_FUTURE future +#else +#define BOOST_THREAD_FUTURE unique_future +#endif + +namespace boost +{ + template + shared_ptr static_shared_from_this(T* that) + { + return static_pointer_cast(that->shared_from_this()); + } + template + shared_ptr static_shared_from_this(T const* that) + { + return static_pointer_cast(that->shared_from_this()); + } + +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS +#else + namespace executors { + class executor; + } +#endif + typedef shared_ptr executor_ptr_type; + + namespace detail + { + + struct relocker + { + boost::unique_lock& lock_; + + relocker(boost::unique_lock& lk): + lock_(lk) + { + lock_.unlock(); + } + ~relocker() + { + if (! lock_.owns_lock()) { + lock_.lock(); + } + } + void lock() { + if (! lock_.owns_lock()) { + lock_.lock(); + } + } + private: + relocker& operator=(relocker const&); + }; + + struct shared_state_base : enable_shared_from_this + { + typedef std::list waiter_list; + typedef waiter_list::iterator notify_when_ready_handle; + // This type should be only included conditionally if interruptions are allowed, but is included to maintain the same layout. + typedef shared_ptr continuation_ptr_type; + typedef std::vector continuations_type; + + boost::exception_ptr exception; + bool done; + bool is_valid_; + bool is_deferred_; + bool is_constructed; + launch policy_; + mutable boost::mutex mutex; + boost::condition_variable waiters; + waiter_list external_waiters; + boost::function callback; + // This declaration should be only included conditionally, but is included to maintain the same layout. + continuations_type continuations; + executor_ptr_type ex; + + // This declaration should be only included conditionally, but is included to maintain the same layout. + virtual void launch_continuation() + { + } + + shared_state_base(): + done(false), + is_valid_(true), + is_deferred_(false), + is_constructed(false), + policy_(launch::none), + continuations(), + ex() + {} + + shared_state_base(exceptional_ptr const& ex): + exception(ex.ptr_), + done(true), + is_valid_(true), + is_deferred_(false), + is_constructed(false), + policy_(launch::none), + continuations(), + ex() + {} + + + virtual ~shared_state_base() + { + } + executor_ptr_type get_executor() + { + return ex; + } + + void set_executor_policy(executor_ptr_type aex) + { + set_executor(); + ex = aex; + } + void set_executor_policy(executor_ptr_type aex, boost::lock_guard&) + { + set_executor(); + ex = aex; + } + void set_executor_policy(executor_ptr_type aex, boost::unique_lock&) + { + set_executor(); + ex = aex; + } + + bool valid(boost::unique_lock&) { return is_valid_; } + bool valid() { + boost::unique_lock lk(this->mutex); + return valid(lk); + } + void invalidate(boost::unique_lock&) { is_valid_ = false; } + void invalidate() { + boost::unique_lock lk(this->mutex); + invalidate(lk); + } + void validate(boost::unique_lock&) { is_valid_ = true; } + void validate() { + boost::unique_lock lk(this->mutex); + validate(lk); + } + + void set_deferred() + { + is_deferred_ = true; + policy_ = launch::deferred; + } + void set_async() + { + is_deferred_ = false; + policy_ = launch::async; + } +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + void set_executor() + { + is_deferred_ = false; + policy_ = launch::executor; + } +#else + void set_executor() + { + } +#endif + notify_when_ready_handle notify_when_ready(boost::condition_variable_any& cv) + { + boost::unique_lock lock(this->mutex); + do_callback(lock); + return external_waiters.insert(external_waiters.end(),&cv); + } + + void unnotify_when_ready(notify_when_ready_handle it) + { + boost::lock_guard lock(this->mutex); + external_waiters.erase(it); + } + +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION + void do_continuation(boost::unique_lock& lock) + { + if (! continuations.empty()) { + continuations_type the_continuations = continuations; + continuations.clear(); + relocker rlk(lock); + for (continuations_type::iterator it = the_continuations.begin(); it != the_continuations.end(); ++it) { + (*it)->launch_continuation(); + } + } + } +#else + void do_continuation(boost::unique_lock&) + { + } +#endif +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION + virtual void set_continuation_ptr(continuation_ptr_type continuation, boost::unique_lock& lock) + { + continuations.push_back(continuation); + if (done) { + do_continuation(lock); + } + } +#endif + void mark_finished_internal(boost::unique_lock& lock) + { + done=true; + waiters.notify_all(); + for(waiter_list::const_iterator it=external_waiters.begin(), + end=external_waiters.end();it!=end;++it) + { + (*it)->notify_all(); + } + do_continuation(lock); + } + void make_ready() + { + boost::unique_lock lock(this->mutex); + mark_finished_internal(lock); + } + + void do_callback(boost::unique_lock& lock) + { + if(callback && !done) + { + boost::function local_callback=callback; + relocker relock(lock); + local_callback(); + } + } + + virtual bool run_if_is_deferred() + { + boost::unique_lock lk(this->mutex); + if (is_deferred_) + { + is_deferred_=false; + execute(lk); + return true; + } + else + return false; + } + virtual bool run_if_is_deferred_or_ready() + { + boost::unique_lock lk(this->mutex); + if (is_deferred_) + { + is_deferred_=false; + execute(lk); + + return true; + } + else + return done; + } + void wait_internal(boost::unique_lock &lk, bool rethrow=true) + { + do_callback(lk); + if (is_deferred_) + { + is_deferred_=false; + execute(lk); + } + while(!done) + { + waiters.wait(lk); + } + if(rethrow && exception) + { + boost::rethrow_exception(exception); + } + } + + virtual void wait(boost::unique_lock& lock, bool rethrow=true) + { + wait_internal(lock, rethrow); + } + + void wait(bool rethrow=true) + { + boost::unique_lock lock(this->mutex); + wait(lock, rethrow); + } + +#if defined BOOST_THREAD_USES_DATETIME + bool timed_wait_until(boost::system_time const& target_time) + { + boost::unique_lock lock(this->mutex); + if (is_deferred_) + return false; + + do_callback(lock); + while(!done) + { + bool const success=waiters.timed_wait(lock,target_time); + if(!success && !done) + { + return false; + } + } + return true; + } +#endif +#ifdef BOOST_THREAD_USES_CHRONO + + template + future_status + wait_until(const chrono::time_point& abs_time) + { + boost::unique_lock lock(this->mutex); + if (is_deferred_) + return future_status::deferred; + do_callback(lock); + while(!done) + { + cv_status const st=waiters.wait_until(lock,abs_time); + if(st==cv_status::timeout && !done) + { + return future_status::timeout; + } + } + return future_status::ready; + } +#endif + void mark_exceptional_finish_internal(boost::exception_ptr const& e, boost::unique_lock& lock) + { + exception=e; + mark_finished_internal(lock); + } + + void mark_exceptional_finish() + { + boost::unique_lock lock(this->mutex); + mark_exceptional_finish_internal(boost::current_exception(), lock); + } + + void set_exception_at_thread_exit(exception_ptr e) + { + unique_lock lk(this->mutex); + if (has_value(lk)) + { + throw_exception(promise_already_satisfied()); + } + exception=e; + this->is_constructed = true; + detail::make_ready_at_thread_exit(shared_from_this()); + } + + bool has_value() const + { + boost::lock_guard lock(this->mutex); + return done && ! exception; + } + + bool has_value(unique_lock& ) const + { + return done && ! exception; + } + + bool has_exception() const + { + boost::lock_guard lock(this->mutex); + return done && exception; + } + + launch launch_policy(boost::unique_lock&) const + { + return policy_; + } + + future_state::state get_state(boost::unique_lock&) const + { + if(!done) + { + return future_state::waiting; + } + else + { + return future_state::ready; + } + } + future_state::state get_state() const + { + boost::lock_guard guard(this->mutex); + if(!done) + { + return future_state::waiting; + } + else + { + return future_state::ready; + } + } + + exception_ptr get_exception_ptr() + { + boost::unique_lock lock(this->mutex); + wait_internal(lock, false); + return exception; + } + + template + void set_wait_callback(F f,U* u) + { + boost::lock_guard lock(this->mutex); + callback=boost::bind(f,boost::ref(*u)); + } + + virtual void execute(boost::unique_lock&) {} + + private: + shared_state_base(shared_state_base const&); + shared_state_base& operator=(shared_state_base const&); + }; + + // Used to create stand-alone futures + template + struct shared_state: + detail::shared_state_base + { +#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL + typedef boost::optional storage_type; +#else + typedef boost::csbl::unique_ptr storage_type; +#endif +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + typedef T const& source_reference_type; + typedef BOOST_THREAD_RV_REF(T) rvalue_source_type; + typedef T move_dest_type; +#elif defined BOOST_THREAD_USES_MOVE + typedef typename conditional::value,T,T const&>::type source_reference_type; + typedef BOOST_THREAD_RV_REF(T) rvalue_source_type; + typedef T move_dest_type; +#else + typedef T& source_reference_type; + typedef typename conditional::value, BOOST_THREAD_RV_REF(T),T const&>::type rvalue_source_type; + typedef typename conditional::value, BOOST_THREAD_RV_REF(T),T>::type move_dest_type; +#endif + + typedef const T& shared_future_get_result_type; + + storage_type result; + + shared_state(): + result() + {} + shared_state(exceptional_ptr const& ex): + detail::shared_state_base(ex), result() + {} + + + ~shared_state() + { + } + + void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock& lock) + { +#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL + result = result_; +#else + result.reset(new T(result_)); +#endif + this->mark_finished_internal(lock); + } + + void mark_finished_with_result_internal(rvalue_source_type result_, boost::unique_lock& lock) + { +#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL + result = boost::move(result_); +#elif ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + result.reset(new T(boost::move(result_))); +#else + result.reset(new T(static_cast(result_))); +#endif + this->mark_finished_internal(lock); + } + + +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template + void mark_finished_with_result_internal(boost::unique_lock& lock, BOOST_THREAD_FWD_REF(Args)... args) + { +#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL + result.emplace(boost::forward(args)...); +#else + result.reset(new T(boost::forward(args)...)); +#endif + this->mark_finished_internal(lock); + } +#endif + + void mark_finished_with_result(source_reference_type result_) + { + boost::unique_lock lock(this->mutex); + this->mark_finished_with_result_internal(result_, lock); + } + + void mark_finished_with_result(rvalue_source_type result_) + { + boost::unique_lock lock(this->mutex); + +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + mark_finished_with_result_internal(boost::move(result_), lock); +#else + mark_finished_with_result_internal(static_cast(result_), lock); +#endif + } + + storage_type& get_storage(boost::unique_lock& lk) + { + wait_internal(lk); + return result; + } + virtual move_dest_type get(boost::unique_lock& lk) + { + return boost::move(*get_storage(lk)); + } + move_dest_type get() + { + boost::unique_lock lk(this->mutex); + return this->get(lk); + } + + virtual shared_future_get_result_type get_sh(boost::unique_lock& lk) + { + return *get_storage(lk); + } + shared_future_get_result_type get_sh() + { + boost::unique_lock lk(this->mutex); + return this->get_sh(lk); + } + + void set_value_at_thread_exit(source_reference_type result_) + { + unique_lock lk(this->mutex); + if (this->has_value(lk)) + { + throw_exception(promise_already_satisfied()); + } +#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL + result = result_; +#else + result.reset(new T(result_)); +#endif + + this->is_constructed = true; + detail::make_ready_at_thread_exit(shared_from_this()); + } + void set_value_at_thread_exit(rvalue_source_type result_) + { + unique_lock lk(this->mutex); + if (this->has_value(lk)) + throw_exception(promise_already_satisfied()); + +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES +#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL + result = boost::move(result_); +#else + result.reset(new T(boost::move(result_))); +#endif +#else +#if defined BOOST_THREAD_FUTURE_USES_OPTIONAL + result = boost::move(result_); +#else + result.reset(new T(static_cast(result_))); +#endif +#endif + this->is_constructed = true; + detail::make_ready_at_thread_exit(shared_from_this()); + } + + private: + shared_state(shared_state const&); + shared_state& operator=(shared_state const&); + }; + + template + struct shared_state: + detail::shared_state_base + { + typedef T* storage_type; + typedef T& source_reference_type; + typedef T& move_dest_type; + typedef T& shared_future_get_result_type; + + T* result; + + shared_state(): + result(0) + {} + + shared_state(exceptional_ptr const& ex): + detail::shared_state_base(ex), result(0) + {} + + ~shared_state() + { + } + + void mark_finished_with_result_internal(source_reference_type result_, boost::unique_lock& lock) + { + result= &result_; + mark_finished_internal(lock); + } + + void mark_finished_with_result(source_reference_type result_) + { + boost::unique_lock lock(this->mutex); + mark_finished_with_result_internal(result_, lock); + } + + virtual T& get(boost::unique_lock& lock) + { + wait_internal(lock); + return *result; + } + T& get() + { + boost::unique_lock lk(this->mutex); + return get(lk); + } + + virtual T& get_sh(boost::unique_lock& lock) + { + wait_internal(lock); + return *result; + } + T& get_sh() + { + boost::unique_lock lock(this->mutex); + return get_sh(lock); + } + + void set_value_at_thread_exit(T& result_) + { + unique_lock lk(this->mutex); + if (this->has_value(lk)) + throw_exception(promise_already_satisfied()); + result= &result_; + this->is_constructed = true; + detail::make_ready_at_thread_exit(shared_from_this()); + } + + private: + shared_state(shared_state const&); + shared_state& operator=(shared_state const&); + }; + + template<> + struct shared_state: + detail::shared_state_base + { + typedef void shared_future_get_result_type; + typedef void move_dest_type; + + shared_state() + {} + + shared_state(exceptional_ptr const& ex): + detail::shared_state_base(ex) + {} + + void mark_finished_with_result_internal(boost::unique_lock& lock) + { + mark_finished_internal(lock); + } + + void mark_finished_with_result() + { + boost::unique_lock lock(this->mutex); + mark_finished_with_result_internal(lock); + } + + virtual void get(boost::unique_lock& lock) + { + this->wait_internal(lock); + } + void get() + { + boost::unique_lock lock(this->mutex); + this->get(lock); + } + + virtual void get_sh(boost::unique_lock& lock) + { + this->wait_internal(lock); + } + void get_sh() + { + boost::unique_lock lock(this->mutex); + this->get_sh(lock); + } + + void set_value_at_thread_exit() + { + unique_lock lk(this->mutex); + if (this->has_value(lk)) + { + throw_exception(promise_already_satisfied()); + } + this->is_constructed = true; + detail::make_ready_at_thread_exit(shared_from_this()); + } + private: + shared_state(shared_state const&); + shared_state& operator=(shared_state const&); + }; + + ///////////////////////// + /// future_async_shared_state_base + ///////////////////////// + template + struct future_async_shared_state_base: shared_state + { + typedef shared_state base_type; + protected: +#ifdef BOOST_THREAD_FUTURE_BLOCKING + boost::thread thr_; + void join() + { + if (this_thread::get_id() == thr_.get_id()) + { + thr_.detach(); + return; + } + if (thr_.joinable()) thr_.join(); + } +#endif + public: + future_async_shared_state_base() + { + this->set_async(); + } + + ~future_async_shared_state_base() + { +#ifdef BOOST_THREAD_FUTURE_BLOCKING + join(); +#endif + } + + virtual void wait(boost::unique_lock& lk, bool rethrow) + { +#ifdef BOOST_THREAD_FUTURE_BLOCKING + { + relocker rlk(lk); + join(); + } +#endif + this->base_type::wait(lk, rethrow); + } + }; + + ///////////////////////// + /// future_async_shared_state + ///////////////////////// + template + struct future_async_shared_state: future_async_shared_state_base + { + future_async_shared_state() + { + } + + void init(BOOST_THREAD_FWD_REF(Fp) f) + { +#ifdef BOOST_THREAD_FUTURE_BLOCKING + this->thr_ = thread(&future_async_shared_state::run, static_shared_from_this(this), boost::forward(f)); +#else + thread(&future_async_shared_state::run, static_shared_from_this(this), boost::forward(f)).detach(); +#endif + } + + static void run(shared_ptr that, BOOST_THREAD_FWD_REF(Fp) f) + { + try + { + that->mark_finished_with_result(f()); + } + catch(...) + { + that->mark_exceptional_finish(); + } + } + }; + + template + struct future_async_shared_state: public future_async_shared_state_base + { + void init(BOOST_THREAD_FWD_REF(Fp) f) + { +#ifdef BOOST_THREAD_FUTURE_BLOCKING + this->thr_ = thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f)); +#else + thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f)).detach(); +#endif + } + + static void run(shared_ptr that, BOOST_THREAD_FWD_REF(Fp) f) + { + try + { + f(); + that->mark_finished_with_result(); + } + catch(...) + { + that->mark_exceptional_finish(); + } + } + }; + + template + struct future_async_shared_state: future_async_shared_state_base + { + void init(BOOST_THREAD_FWD_REF(Fp) f) + { +#ifdef BOOST_THREAD_FUTURE_BLOCKING + this->thr_ = thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f)); +#else + thread(&future_async_shared_state::run, static_shared_from_this(this), boost::move(f)).detach(); +#endif + } + + static void run(shared_ptr that, BOOST_THREAD_FWD_REF(Fp) f) + { + try + { + that->mark_finished_with_result(f()); + } + catch(...) + { + that->mark_exceptional_finish(); + } + } + }; + + ////////////////////////// + /// future_deferred_shared_state + ////////////////////////// + template + struct future_deferred_shared_state: shared_state + { + typedef shared_state base_type; + Fp func_; + + public: + explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f) + : func_(boost::move(f)) + { + this->set_deferred(); + } + + virtual void execute(boost::unique_lock& lck) { + try + { + Fp local_fuct=boost::move(func_); + relocker relock(lck); + Rp res = local_fuct(); + relock.lock(); + this->mark_finished_with_result_internal(boost::move(res), lck); + } + catch (...) + { + this->mark_exceptional_finish_internal(current_exception(), lck); + } + } + }; + template + struct future_deferred_shared_state: shared_state + { + typedef shared_state base_type; + Fp func_; + + public: + explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f) + : func_(boost::move(f)) + { + this->set_deferred(); + } + + virtual void execute(boost::unique_lock& lck) { + try + { + this->mark_finished_with_result_internal(func_(), lck); + } + catch (...) + { + this->mark_exceptional_finish_internal(current_exception(), lck); + } + } + }; + + template + struct future_deferred_shared_state: shared_state + { + typedef shared_state base_type; + Fp func_; + + public: + explicit future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f) + : func_(boost::move(f)) + { + this->set_deferred(); + } + + virtual void execute(boost::unique_lock& lck) { + try + { + Fp local_fuct=boost::move(func_); + relocker relock(lck); + local_fuct(); + relock.lock(); + this->mark_finished_with_result_internal(lck); + } + catch (...) + { + this->mark_exceptional_finish_internal(current_exception(), lck); + } + } + }; + + class future_waiter + { + public: + typedef std::vector::size_type count_type; + private: + struct registered_waiter; + struct registered_waiter + { + boost::shared_ptr future_; + detail::shared_state_base::notify_when_ready_handle handle; + count_type index; + + registered_waiter(boost::shared_ptr const& a_future, + detail::shared_state_base::notify_when_ready_handle handle_, + count_type index_): + future_(a_future),handle(handle_),index(index_) + {} + }; + + struct all_futures_lock + { +#ifdef _MANAGED + typedef std::ptrdiff_t count_type_portable; +#else + typedef count_type count_type_portable; +#endif + count_type_portable count; + boost::scoped_array > locks; + + all_futures_lock(std::vector& futures): + count(futures.size()),locks(new boost::unique_lock[count]) + { + for(count_type_portable i=0;i(futures[i].future_->mutex)); + } + } + + void lock() + { + boost::lock(locks.get(),locks.get()+count); + } + + void unlock() + { + for(count_type_portable i=0;i futures_; + count_type future_count; + + public: + future_waiter(): + future_count(0) + {} + + template + void add(F& f) + { + if(f.future_) + { + registered_waiter waiter(f.future_,f.future_->notify_when_ready(cv),future_count); + try { + futures_.push_back(waiter); + } catch(...) { + f.future_->unnotify_when_ready(waiter.handle); + throw; + } + } + ++future_count; + } + +#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES + template + void add(F1& f1, Fs&... fs) + { + add(f1); add(fs...); + } +#endif + + count_type wait() + { + all_futures_lock lk(futures_); + for(;;) + { + for(count_type i=0;idone) + { + return futures_[i].index; + } + } + cv.wait(lk); + } + } + + ~future_waiter() + { + for(count_type i=0;iunnotify_when_ready(futures_[i].handle); + } + } + }; + + } + + template + class BOOST_THREAD_FUTURE; + + template + class shared_future; + + template + struct is_future_type > : true_type + { + }; + + template + struct is_future_type > : true_type + { + }; + +// template +// typename boost::disable_if,Iterator>::type wait_for_any(Iterator begin,Iterator end) +// { +// if(begin==end) +// return end; +// +// detail::future_waiter waiter; +// for(Iterator current=begin;current!=end;++current) +// { +// waiter.add(*current); +// } +// return boost::next(begin,waiter.wait()); +// } + +#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES + template + typename boost::enable_if,typename detail::future_waiter::count_type>::type wait_for_any(F1& f1,F2& f2) + { + detail::future_waiter waiter; + waiter.add(f1); + waiter.add(f2); + return waiter.wait(); + } + + template + typename detail::future_waiter::count_type wait_for_any(F1& f1,F2& f2,F3& f3) + { + detail::future_waiter waiter; + waiter.add(f1); + waiter.add(f2); + waiter.add(f3); + return waiter.wait(); + } + + template + typename detail::future_waiter::count_type wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4) + { + detail::future_waiter waiter; + waiter.add(f1); + waiter.add(f2); + waiter.add(f3); + waiter.add(f4); + return waiter.wait(); + } + + template + typename detail::future_waiter::count_type wait_for_any(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5) + { + detail::future_waiter waiter; + waiter.add(f1); + waiter.add(f2); + waiter.add(f3); + waiter.add(f4); + waiter.add(f5); + return waiter.wait(); + } +#else + template + typename boost::enable_if, typename detail::future_waiter::count_type>::type + wait_for_any(F1& f1, Fs&... fs) + { + detail::future_waiter waiter; + waiter.add(f1, fs...); + return waiter.wait(); + } +#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + + template + class promise; + + template + class packaged_task; + + namespace detail + { + /// Common implementation for all the futures independently of the return type + class base_future + { + public: + }; + /// Common implementation for future and shared_future. + template + class basic_future : public base_future + { + protected: + public: + + typedef boost::shared_ptr > future_ptr; + typedef typename detail::shared_state::move_dest_type move_dest_type; + + static //BOOST_CONSTEXPR + future_ptr make_exceptional_future_ptr(exceptional_ptr const& ex) { + return future_ptr(new detail::shared_state(ex)); + } + + future_ptr future_; + + basic_future(future_ptr a_future): + future_(a_future) + { + } + + public: + typedef future_state::state state; + + BOOST_THREAD_MOVABLE_ONLY(basic_future) + basic_future(): future_() {} + + + //BOOST_CONSTEXPR + basic_future(exceptional_ptr const& ex) + : future_(make_exceptional_future_ptr(ex)) + { + } + + ~basic_future() { + } + + basic_future(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT: + future_(BOOST_THREAD_RV(other).future_) + { + BOOST_THREAD_RV(other).future_.reset(); + } + basic_future& operator=(BOOST_THREAD_RV_REF(basic_future) other) BOOST_NOEXCEPT + { + future_=BOOST_THREAD_RV(other).future_; + BOOST_THREAD_RV(other).future_.reset(); + return *this; + } + void swap(basic_future& that) BOOST_NOEXCEPT + { + future_.swap(that.future_); + } + // functions to check state, and wait for ready + state get_state(boost::unique_lock& lk) const + { + if(!future_) + { + return future_state::uninitialized; + } + return future_->get_state(lk); + } + state get_state() const + { + if(!future_) + { + return future_state::uninitialized; + } + return future_->get_state(); + } + + bool is_ready() const + { + return get_state()==future_state::ready; + } + + bool is_ready(boost::unique_lock& lk) const + { + return get_state(lk)==future_state::ready; + } + bool has_exception() const + { + return future_ && future_->has_exception(); + } + + bool has_value() const + { + return future_ && future_->has_value(); + } + + launch launch_policy(boost::unique_lock& lk) const + { + if ( future_ ) return future_->launch_policy(lk); + else return launch(launch::none); + } + + launch launch_policy() const + { + if ( future_ ) { + boost::unique_lock lk(this->future_->mutex); + return future_->launch_policy(lk); + } + else return launch(launch::none); + } + + exception_ptr get_exception_ptr() + { + return future_ + ? future_->get_exception_ptr() + : exception_ptr(); + } + + bool valid() const BOOST_NOEXCEPT + { + return future_ != 0 && future_->valid(); + } + + void wait() const + { + if(!future_) + { + boost::throw_exception(future_uninitialized()); + } + future_->wait(false); + } + + typedef detail::shared_state_base::notify_when_ready_handle notify_when_ready_handle; + + boost::mutex& mutex() { + if(!future_) + { + boost::throw_exception(future_uninitialized()); + } + return future_->mutex; + }; + + notify_when_ready_handle notify_when_ready(boost::condition_variable_any& cv) + { + if(!future_) + { + boost::throw_exception(future_uninitialized()); + } + return future_->notify_when_ready(cv); + } + + void unnotify_when_ready(notify_when_ready_handle h) + { + if(!future_) + { + boost::throw_exception(future_uninitialized()); + } + return future_->unnotify_when_ready(h); + } + +#if defined BOOST_THREAD_USES_DATETIME + template + bool timed_wait(Duration const& rel_time) const + { + return timed_wait_until(boost::get_system_time()+rel_time); + } + + bool timed_wait_until(boost::system_time const& abs_time) const + { + if(!future_) + { + boost::throw_exception(future_uninitialized()); + } + return future_->timed_wait_until(abs_time); + } +#endif +#ifdef BOOST_THREAD_USES_CHRONO + template + future_status + wait_for(const chrono::duration& rel_time) const + { + return wait_until(chrono::steady_clock::now() + rel_time); + + } + template + future_status + wait_until(const chrono::time_point& abs_time) const + { + if(!future_) + { + boost::throw_exception(future_uninitialized()); + } + return future_->wait_until(abs_time); + } +#endif + + }; + + } // detail + BOOST_THREAD_DCL_MOVABLE_BEG(R) detail::basic_future BOOST_THREAD_DCL_MOVABLE_END + + namespace detail + { +#if (!defined _MSC_VER || _MSC_VER >= 1400) // _MSC_VER == 1400 on MSVC 2005 + template + BOOST_THREAD_FUTURE + make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f); + + template + BOOST_THREAD_FUTURE + make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f); +#endif // #if (!defined _MSC_VER || _MSC_VER >= 1400) +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION + template + struct future_deferred_continuation_shared_state; + template + struct future_async_continuation_shared_state; + + template + BOOST_THREAD_FUTURE + make_future_async_continuation_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); + + template + BOOST_THREAD_FUTURE + make_future_deferred_continuation_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); + + template + BOOST_THREAD_FUTURE + make_shared_future_deferred_continuation_shared_state(boost::unique_lock &lock, F f, BOOST_THREAD_FWD_REF(Fp) c); + + template + BOOST_THREAD_FUTURE + make_shared_future_async_continuation_shared_state(boost::unique_lock &lock, F f, BOOST_THREAD_FWD_REF(Fp) c); + + #ifdef BOOST_THREAD_PROVIDES_EXECUTORS + template + BOOST_THREAD_FUTURE + make_future_executor_continuation_shared_state(Ex& ex, boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); + + template + BOOST_THREAD_FUTURE + make_shared_future_executor_continuation_shared_state(Ex& ex, boost::unique_lock &lock, F f, BOOST_THREAD_FWD_REF(Fp) c); + + template + BOOST_THREAD_FUTURE + make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f); + #endif +#endif +#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP + template + struct future_unwrap_shared_state; + template + inline BOOST_THREAD_FUTURE + make_future_unwrap_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f); +#endif + } +#if defined(BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY) + template< typename InputIterator> + typename boost::disable_if, + BOOST_THREAD_FUTURE > + >::type + when_all(InputIterator first, InputIterator last); + + inline BOOST_THREAD_FUTURE > when_all(); + + #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template< typename T0, typename ...T> + BOOST_THREAD_FUTURE::type, typename decay::type...> > + when_all(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures); + #endif + + template< typename InputIterator> + typename boost::disable_if, + BOOST_THREAD_FUTURE > + >::type + when_any(InputIterator first, InputIterator last); + + inline BOOST_THREAD_FUTURE > when_any(); + + #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template< typename T0, typename ...T> + BOOST_THREAD_FUTURE::type, typename decay::type...> > + when_any(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures); + #endif +#endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY + + + template + class BOOST_THREAD_FUTURE : public detail::basic_future + { + private: + typedef detail::basic_future base_type; + typedef typename base_type::future_ptr future_ptr; + + friend class shared_future; + friend class promise; +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION + template + friend struct detail::future_async_continuation_shared_state; + template + friend struct detail::future_deferred_continuation_shared_state; + + template + friend BOOST_THREAD_FUTURE + detail::make_future_async_continuation_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); + + template + friend BOOST_THREAD_FUTURE + detail::make_future_deferred_continuation_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); + + template + friend BOOST_THREAD_FUTURE + detail::make_shared_future_deferred_continuation_shared_state(boost::unique_lock &lock, F f, BOOST_THREAD_FWD_REF(Fp) c); + + template + friend BOOST_THREAD_FUTURE + detail::make_shared_future_async_continuation_shared_state(boost::unique_lock &lock, F f, BOOST_THREAD_FWD_REF(Fp) c); + + #ifdef BOOST_THREAD_PROVIDES_EXECUTORS + template + friend BOOST_THREAD_FUTURE + detail::make_future_executor_continuation_shared_state(Ex& ex, boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); + + template + friend BOOST_THREAD_FUTURE + detail::make_shared_future_executor_continuation_shared_state(Ex& ex, boost::unique_lock &lock, F f, BOOST_THREAD_FWD_REF(Fp) c); + + template + friend BOOST_THREAD_FUTURE + detail::make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f); + #endif +#endif +#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP + template + friend struct detail::future_unwrap_shared_state; + template + friend BOOST_THREAD_FUTURE + detail::make_future_unwrap_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f); +#endif +#if defined(BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY) + template< typename InputIterator> + friend typename boost::disable_if, + BOOST_THREAD_FUTURE > + >::type + when_all(InputIterator first, InputIterator last); + + //friend inline BOOST_THREAD_FUTURE > when_all(); + + #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template< typename T0, typename ...T> + friend BOOST_THREAD_FUTURE::type, typename decay::type...> > + when_all(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures); + #endif + + template< typename InputIterator> + friend typename boost::disable_if, + BOOST_THREAD_FUTURE > + >::type + when_any(InputIterator first, InputIterator last); + + //friend inline BOOST_THREAD_FUTURE > when_any(); + + #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template< typename T0, typename ...T> + friend BOOST_THREAD_FUTURE::type, typename decay::type...> > + when_any(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures); + #endif +#endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + template friend class packaged_task; // todo check if this works in windows +#else + friend class packaged_task; +#endif + friend class detail::future_waiter; + + template + friend BOOST_THREAD_FUTURE + detail::make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f); + + template + friend BOOST_THREAD_FUTURE + detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f); + + typedef typename base_type::move_dest_type move_dest_type; + + BOOST_THREAD_FUTURE(future_ptr a_future): + base_type(a_future) + { + } + + public: + BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE) + typedef future_state::state state; + typedef R value_type; // EXTENSION + + BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {} + //BOOST_CONSTEXPR + BOOST_THREAD_FUTURE(exceptional_ptr const& ex): + base_type(ex) {} + + ~BOOST_THREAD_FUTURE() { + } + + BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT: + base_type(boost::move(static_cast(BOOST_THREAD_RV(other)))) + { + } + inline BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE >) other); // EXTENSION + + explicit BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(shared_future) other) : + base_type(boost::move(static_cast(BOOST_THREAD_RV(other)))) + {} + + BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT + { + this->base_type::operator=(boost::move(static_cast(BOOST_THREAD_RV(other)))); + return *this; + } + + shared_future share() + { + return shared_future(::boost::move(*this)); + } + + void swap(BOOST_THREAD_FUTURE& other) + { + static_cast(this)->swap(other); + } + + // todo this function must be private and friendship provided to the internal users. + void set_async() + { + this->future_->set_async(); + } + // todo this function must be private and friendship provided to the internal users. + void set_deferred() + { + this->future_->set_deferred(); + } + bool run_if_is_deferred() { + return this->future_->run_if_is_deferred(); + } + bool run_if_is_deferred_or_ready() { + return this->future_->run_if_is_deferred_or_ready(); + } + // retrieving the value + move_dest_type get() + { + if (this->future_ == 0) + { + boost::throw_exception(future_uninitialized()); + } + unique_lock lk(this->future_->mutex); + if (! this->future_->valid(lk)) + { + boost::throw_exception(future_uninitialized()); + } +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + this->future_->invalidate(lk); +#endif + return this->future_->get(lk); + } + + template + typename boost::disable_if< is_void, move_dest_type>::type + get_or(BOOST_THREAD_RV_REF(R2) v) + { + + if (this->future_ == 0) + { + boost::throw_exception(future_uninitialized()); + } + unique_lock lk(this->future_->mutex); + if (! this->future_->valid(lk)) + { + boost::throw_exception(future_uninitialized()); + } + this->future_->wait(lk, false); +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + this->future_->invalidate(lk); +#endif + + if (this->future_->has_value(lk)) { + return this->future_->get(lk); + } + else { + return boost::move(v); + } + } + + template + typename boost::disable_if< is_void, move_dest_type>::type + get_or(R2 const& v) // EXTENSION + { + if (this->future_ == 0) + { + boost::throw_exception(future_uninitialized()); + } + unique_lock lk(this->future_->mutex); + if (! this->future_->valid(lk)) + { + boost::throw_exception(future_uninitialized()); + } + this->future_->wait(lk, false); +#ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + this->future_->invalidate(lk); +#endif + if (this->future_->has_value(lk)) { + return this->future_->get(lk); + } + else { + return v; + } + } + +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION + template + inline BOOST_THREAD_FUTURE::type> + then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION + template + inline BOOST_THREAD_FUTURE::type> + then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION + #ifdef BOOST_THREAD_PROVIDES_EXECUTORS + template + inline BOOST_THREAD_FUTURE::type> + then(Ex& ex, BOOST_THREAD_FWD_REF(F) func); // EXTENSION + #endif + + template + inline typename boost::disable_if< is_void, BOOST_THREAD_FUTURE >::type + fallback_to(BOOST_THREAD_RV_REF(R2) v); // EXTENSION + template + inline typename boost::disable_if< is_void, BOOST_THREAD_FUTURE >::type + fallback_to(R2 const& v); // EXTENSION + +#endif + + }; + + BOOST_THREAD_DCL_MOVABLE_BEG(T) BOOST_THREAD_FUTURE BOOST_THREAD_DCL_MOVABLE_END + + template + class BOOST_THREAD_FUTURE > : public detail::basic_future > + { + typedef BOOST_THREAD_FUTURE R; + + private: + typedef detail::basic_future base_type; + typedef typename base_type::future_ptr future_ptr; + + friend class shared_future; + friend class promise; +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION + template + friend struct detail::future_async_continuation_shared_state; + template + friend struct detail::future_deferred_continuation_shared_state; + + template + friend BOOST_THREAD_FUTURE + detail::make_future_async_continuation_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); + + template + friend BOOST_THREAD_FUTURE + detail::make_future_deferred_continuation_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); + + template + friend BOOST_THREAD_FUTURE + detail::make_shared_future_deferred_continuation_shared_state(boost::unique_lock &lock, F f, BOOST_THREAD_FWD_REF(Fp) c); + + template + friend BOOST_THREAD_FUTURE + detail::make_shared_future_async_continuation_shared_state(boost::unique_lock &lock, F f, BOOST_THREAD_FWD_REF(Fp) c); + + #ifdef BOOST_THREAD_PROVIDES_EXECUTORS + template + friend BOOST_THREAD_FUTURE + detail::make_future_executor_continuation_shared_state(Ex& ex, boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); + + template + friend BOOST_THREAD_FUTURE + detail::make_shared_future_executor_continuation_shared_state(Ex& ex, boost::unique_lock &lock, F f, BOOST_THREAD_FWD_REF(Fp) c); + + template + friend BOOST_THREAD_FUTURE + detail::make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f); + #endif + +#endif +#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP + template + friend struct detail::future_unwrap_shared_state; + template + friend BOOST_THREAD_FUTURE + detail::make_future_unwrap_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f); +#endif +#if defined(BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY) + template< typename InputIterator> + friend typename boost::disable_if, + BOOST_THREAD_FUTURE > + >::type + when_all(InputIterator first, InputIterator last); + + friend inline BOOST_THREAD_FUTURE > when_all(); + + #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template< typename T0, typename ...T> + friend BOOST_THREAD_FUTURE::type, typename decay::type...> > + when_all(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures); + #endif + + template< typename InputIterator> + friend typename boost::disable_if, + BOOST_THREAD_FUTURE > + >::type + when_any(InputIterator first, InputIterator last); + + friend inline BOOST_THREAD_FUTURE > when_any(); + + #if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template< typename T0, typename ...T> + friend BOOST_THREAD_FUTURE::type, typename decay::type...> > + when_any(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures); + #endif +#endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY + + #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + template friend class packaged_task; // todo check if this works in windows + #else + friend class packaged_task; + #endif + friend class detail::future_waiter; + + template + friend BOOST_THREAD_FUTURE + detail::make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f); + + template + friend BOOST_THREAD_FUTURE + detail::make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f); + + typedef typename base_type::move_dest_type move_dest_type; + + BOOST_THREAD_FUTURE(future_ptr a_future): + base_type(a_future) + { + } + public: + + BOOST_THREAD_MOVABLE_ONLY(BOOST_THREAD_FUTURE) + typedef future_state::state state; + typedef R value_type; // EXTENSION + + BOOST_CONSTEXPR BOOST_THREAD_FUTURE() {} + //BOOST_CONSTEXPR + BOOST_THREAD_FUTURE(exceptional_ptr const& ex): + base_type(ex) {} + + ~BOOST_THREAD_FUTURE() { + } + + BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT: + base_type(boost::move(static_cast(BOOST_THREAD_RV(other)))) + { + } + + BOOST_THREAD_FUTURE& operator=(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE) other) BOOST_NOEXCEPT + { + this->base_type::operator=(boost::move(static_cast(BOOST_THREAD_RV(other)))); + return *this; + } + + shared_future share() + { + return shared_future(::boost::move(*this)); + } + + void swap(BOOST_THREAD_FUTURE& other) + { + static_cast(this)->swap(other); + } + + // todo this function must be private and friendship provided to the internal users. + void set_async() + { + this->future_->set_async(); + } + // todo this function must be private and friendship provided to the internal users. + void set_deferred() + { + this->future_->set_deferred(); + } + bool run_if_is_deferred() { + return this->future_->run_if_is_deferred(); + } + bool run_if_is_deferred_or_ready() { + return this->future_->run_if_is_deferred_or_ready(); + } + // retrieving the value + move_dest_type get() + { + if (this->future_ == 0) + { + boost::throw_exception(future_uninitialized()); + } + unique_lock lk(this->future_->mutex); + if (! this->future_->valid(lk)) + { + boost::throw_exception(future_uninitialized()); + } + #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + this->future_->invalidate(lk); + #endif + return this->future_->get(lk); + } + move_dest_type get_or(BOOST_THREAD_RV_REF(R) v) // EXTENSION + { + if (this->future_ == 0) + { + boost::throw_exception(future_uninitialized()); + } + unique_lock lk(this->future_->mutex); + if (! this->future_->valid(lk)) + { + boost::throw_exception(future_uninitialized()); + } + this->future_->wait(lk, false); + #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + this->future_->invalidate(lk); + #endif + if (this->future_->has_value(lk)) return this->future_->get(lk); + else return boost::move(v); + } + + move_dest_type get_or(R const& v) // EXTENSION + { + if (this->future_ == 0) + { + boost::throw_exception(future_uninitialized()); + } + unique_lock lk(this->future_->mutex); + if (! this->future_->valid(lk)) + { + boost::throw_exception(future_uninitialized()); + } + this->future_->wait(lk, false); + #ifdef BOOST_THREAD_PROVIDES_FUTURE_INVALID_AFTER_GET + this->future_->invalidate(lk); + #endif + if (this->future_->has_value(lk)) return this->future_->get(lk); + else return v; + } + + + #if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION + template + inline BOOST_THREAD_FUTURE::type> + then(BOOST_THREAD_FWD_REF(F) func); // EXTENSION + template + inline BOOST_THREAD_FUTURE::type> + then(launch policy, BOOST_THREAD_FWD_REF(F) func); // EXTENSION + #ifdef BOOST_THREAD_PROVIDES_EXECUTORS + template + inline BOOST_THREAD_FUTURE::type> + then(Ex &ex, BOOST_THREAD_FWD_REF(F) func); // EXTENSION + #endif + #endif + + #if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP + inline + BOOST_THREAD_FUTURE + unwrap(); // EXTENSION + #endif + + }; + + template + class shared_future : public detail::basic_future + { + typedef detail::basic_future base_type; + typedef typename base_type::future_ptr future_ptr; + + friend class detail::future_waiter; + friend class promise; + +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION + template + friend struct detail::future_async_continuation_shared_state; + template + friend struct detail::future_deferred_continuation_shared_state; + + template + friend BOOST_THREAD_FUTURE + detail::make_future_async_continuation_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); + + template + friend BOOST_THREAD_FUTURE + detail::make_future_deferred_continuation_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c); +#endif +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + template friend class packaged_task;// todo check if this works in windows +#else + friend class packaged_task; +#endif + shared_future(future_ptr a_future): + base_type(a_future) + {} + + public: + BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_future) + typedef R value_type; // EXTENSION + + shared_future(shared_future const& other): + base_type(other.future_) + {} + + typedef future_state::state state; + + BOOST_CONSTEXPR shared_future() + {} + //BOOST_CONSTEXPR + shared_future(exceptional_ptr const& ex): + base_type(ex) {} + ~shared_future() + {} + + shared_future& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_future) other) + { + this->future_ = other.future_; + return *this; + } + + shared_future(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT : + base_type(boost::move(static_cast(BOOST_THREAD_RV(other)))) + { + } + shared_future(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE ) other) BOOST_NOEXCEPT : + base_type(boost::move(static_cast(BOOST_THREAD_RV(other)))) + { + } + + shared_future& operator=(BOOST_THREAD_RV_REF(shared_future) other) BOOST_NOEXCEPT + { + base_type::operator=(boost::move(static_cast(BOOST_THREAD_RV(other)))); + return *this; + } + shared_future& operator=(BOOST_THREAD_RV_REF( BOOST_THREAD_FUTURE ) other) BOOST_NOEXCEPT + { + base_type::operator=(boost::move(static_cast(BOOST_THREAD_RV(other)))); + return *this; + } + + void swap(shared_future& other) BOOST_NOEXCEPT + { + static_cast(this)->swap(other); + } + bool run_if_is_deferred() { + return this->future_->run_if_is_deferred(); + } + bool run_if_is_deferred_or_ready() { + return this->future_->run_if_is_deferred_or_ready(); + } + // retrieving the value + typename detail::shared_state::shared_future_get_result_type get() const + { + if(!this->future_) + { + boost::throw_exception(future_uninitialized()); + } + return this->future_->get_sh(); + } + + template + typename boost::disable_if< is_void, typename detail::shared_state::shared_future_get_result_type>::type + get_or(BOOST_THREAD_RV_REF(R2) v) const // EXTENSION + { + if(!this->future_) + { + boost::throw_exception(future_uninitialized()); + } + this->future_->wait(); + if (this->future_->has_value()) return this->future_->get_sh(); + else return boost::move(v); + } + +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION + template + inline BOOST_THREAD_FUTURE::type> + then(BOOST_THREAD_FWD_REF(F) func) const; // EXTENSION + template + inline BOOST_THREAD_FUTURE::type> + then(launch policy, BOOST_THREAD_FWD_REF(F) func) const; // EXTENSION + #ifdef BOOST_THREAD_PROVIDES_EXECUTORS + template + inline BOOST_THREAD_FUTURE::type> + then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) const; // EXTENSION + #endif +#endif + + }; + + BOOST_THREAD_DCL_MOVABLE_BEG(T) shared_future BOOST_THREAD_DCL_MOVABLE_END + + template + class promise + { + typedef boost::shared_ptr > future_ptr; + + typedef typename detail::shared_state::source_reference_type source_reference_type; + typedef typename detail::shared_state::rvalue_source_type rvalue_source_type; + typedef typename detail::shared_state::move_dest_type move_dest_type; + typedef typename detail::shared_state::shared_future_get_result_type shared_future_get_result_type; + + future_ptr future_; + bool future_obtained; + + void lazy_init() + { +#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY +#include + if(!atomic_load(&future_)) + { + future_ptr blank; + atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state)); + } +#include +#endif + } + + public: + BOOST_THREAD_MOVABLE_ONLY(promise) +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS + template + promise(boost::allocator_arg_t, Allocator a) + { + typedef typename Allocator::template rebind >::other A2; + A2 a2(a); + typedef thread_detail::allocator_destructor D; + + future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state(), D(a2, 1) ); + future_obtained = false; + } +#endif + promise(): +#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY + future_(), +#else + future_(new detail::shared_state()), +#endif + future_obtained(false) + {} + + ~promise() + { + if(future_) + { + boost::unique_lock lock(future_->mutex); + + if(!future_->done && !future_->is_constructed) + { + future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock); + } + } + } + + // Assignment + promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT : + future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained) + { + BOOST_THREAD_RV(rhs).future_.reset(); + BOOST_THREAD_RV(rhs).future_obtained=false; + } + promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT + { + future_=BOOST_THREAD_RV(rhs).future_; + future_obtained=BOOST_THREAD_RV(rhs).future_obtained; + BOOST_THREAD_RV(rhs).future_.reset(); + BOOST_THREAD_RV(rhs).future_obtained=false; + return *this; + } + + void swap(promise& other) + { + future_.swap(other.future_); + std::swap(future_obtained,other.future_obtained); + } + +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + void set_executor(executor_ptr_type aex) + { + lazy_init(); + if (future_.get()==0) + { + boost::throw_exception(promise_moved()); + } + boost::lock_guard lk(future_->mutex); + future_->set_executor_policy(aex, lk); + } +#endif + // Result retrieval + BOOST_THREAD_FUTURE get_future() + { + lazy_init(); + if (future_.get()==0) + { + boost::throw_exception(promise_moved()); + } + if (future_obtained) + { + boost::throw_exception(future_already_retrieved()); + } + future_obtained=true; + return BOOST_THREAD_FUTURE(future_); + } + +#if defined BOOST_NO_CXX11_RVALUE_REFERENCES + template + typename boost::enable_if_c::value && is_same::value, void>::type set_value(TR const & r) + { + lazy_init(); + boost::unique_lock lock(future_->mutex); + if(future_->done) + { + boost::throw_exception(promise_already_satisfied()); + } + future_->mark_finished_with_result_internal(r, lock); + } +#else + void set_value(source_reference_type r) + { + lazy_init(); + boost::unique_lock lock(future_->mutex); + if(future_->done) + { + boost::throw_exception(promise_already_satisfied()); + } + future_->mark_finished_with_result_internal(r, lock); + } +#endif + + void set_value(rvalue_source_type r) + { + lazy_init(); + boost::unique_lock lock(future_->mutex); + if(future_->done) + { + boost::throw_exception(promise_already_satisfied()); + } +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + future_->mark_finished_with_result_internal(boost::move(r), lock); +#else + future_->mark_finished_with_result_internal(static_cast(r), lock); +#endif + } + +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template + void emplace(BOOST_THREAD_FWD_REF(Args) ...args) + { + lazy_init(); + boost::unique_lock lock(future_->mutex); + if(future_->done) + { + boost::throw_exception(promise_already_satisfied()); + } + future_->mark_finished_with_result_internal(lock, boost::forward(args)...); + } + +#endif + + void set_exception(boost::exception_ptr p) + { + lazy_init(); + boost::unique_lock lock(future_->mutex); + if(future_->done) + { + boost::throw_exception(promise_already_satisfied()); + } + future_->mark_exceptional_finish_internal(p, lock); + } + template + void set_exception(E ex) + { + set_exception(boost::copy_exception(ex)); + } + // setting the result with deferred notification +#if defined BOOST_NO_CXX11_RVALUE_REFERENCES + template + typename boost::enable_if_c::value && is_same::value, void>::type set_value_at_thread_exit(TR const& r) + { + if (future_.get()==0) + { + boost::throw_exception(promise_moved()); + } + future_->set_value_at_thread_exit(r); + } +#else + void set_value_at_thread_exit(source_reference_type r) + { + if (future_.get()==0) + { + boost::throw_exception(promise_moved()); + } + future_->set_value_at_thread_exit(r); + } +#endif + void set_value_at_thread_exit(BOOST_THREAD_RV_REF(R) r) + { + if (future_.get()==0) + { + boost::throw_exception(promise_moved()); + } + future_->set_value_at_thread_exit(boost::move(r)); + } + void set_exception_at_thread_exit(exception_ptr e) + { + if (future_.get()==0) + { + boost::throw_exception(promise_moved()); + } + future_->set_exception_at_thread_exit(e); + } + template + void set_exception_at_thread_exit(E ex) + { + set_exception_at_thread_exit(boost::copy_exception(ex)); + } + + template + void set_wait_callback(F f) + { + lazy_init(); + future_->set_wait_callback(f,this); + } + + }; + + template + class promise + { + typedef boost::shared_ptr > future_ptr; + + future_ptr future_; + bool future_obtained; + + void lazy_init() + { +#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY +#include + if(!atomic_load(&future_)) + { + future_ptr blank; + atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state)); + } +#include +#endif + } + + public: + BOOST_THREAD_MOVABLE_ONLY(promise) +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS + template + promise(boost::allocator_arg_t, Allocator a) + { + typedef typename Allocator::template rebind >::other A2; + A2 a2(a); + typedef thread_detail::allocator_destructor D; + + future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state(), D(a2, 1) ); + future_obtained = false; + } +#endif + promise(): +#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY + future_(), +#else + future_(new detail::shared_state()), +#endif + future_obtained(false) + {} + + ~promise() + { + if(future_) + { + boost::unique_lock lock(future_->mutex); + + if(!future_->done && !future_->is_constructed) + { + future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock); + } + } + } + + // Assignment + promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT : + future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained) + { + BOOST_THREAD_RV(rhs).future_.reset(); + BOOST_THREAD_RV(rhs).future_obtained=false; + } + promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT + { + future_=BOOST_THREAD_RV(rhs).future_; + future_obtained=BOOST_THREAD_RV(rhs).future_obtained; + BOOST_THREAD_RV(rhs).future_.reset(); + BOOST_THREAD_RV(rhs).future_obtained=false; + return *this; + } + + void swap(promise& other) + { + future_.swap(other.future_); + std::swap(future_obtained,other.future_obtained); + } + + // Result retrieval + BOOST_THREAD_FUTURE get_future() + { + lazy_init(); + if (future_.get()==0) + { + boost::throw_exception(promise_moved()); + } + if (future_obtained) + { + boost::throw_exception(future_already_retrieved()); + } + future_obtained=true; + return BOOST_THREAD_FUTURE(future_); + } + + void set_value(R& r) + { + lazy_init(); + boost::unique_lock lock(future_->mutex); + if(future_->done) + { + boost::throw_exception(promise_already_satisfied()); + } + future_->mark_finished_with_result_internal(r, lock); + } + + void set_exception(boost::exception_ptr p) + { + lazy_init(); + boost::unique_lock lock(future_->mutex); + if(future_->done) + { + boost::throw_exception(promise_already_satisfied()); + } + future_->mark_exceptional_finish_internal(p, lock); + } + template + void set_exception(E ex) + { + set_exception(boost::copy_exception(ex)); + } + + // setting the result with deferred notification + void set_value_at_thread_exit(R& r) + { + if (future_.get()==0) + { + boost::throw_exception(promise_moved()); + } + future_->set_value_at_thread_exit(r); + } + + void set_exception_at_thread_exit(exception_ptr e) + { + if (future_.get()==0) + { + boost::throw_exception(promise_moved()); + } + future_->set_exception_at_thread_exit(e); + } + template + void set_exception_at_thread_exit(E ex) + { + set_exception_at_thread_exit(boost::copy_exception(ex)); + } + + template + void set_wait_callback(F f) + { + lazy_init(); + future_->set_wait_callback(f,this); + } + }; + + template <> + class promise + { + typedef boost::shared_ptr > future_ptr; + + future_ptr future_; + bool future_obtained; + + void lazy_init() + { +#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY + if(!atomic_load(&future_)) + { + future_ptr blank; + atomic_compare_exchange(&future_,&blank,future_ptr(new detail::shared_state)); + } +#endif + } + public: + BOOST_THREAD_MOVABLE_ONLY(promise) + +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS + template + promise(boost::allocator_arg_t, Allocator a) + { + typedef typename Allocator::template rebind >::other A2; + A2 a2(a); + typedef thread_detail::allocator_destructor D; + + future_ = future_ptr(::new(a2.allocate(1)) detail::shared_state(), D(a2, 1) ); + future_obtained = false; + } +#endif + promise(): +#if defined BOOST_THREAD_PROVIDES_PROMISE_LAZY + future_(), +#else + future_(new detail::shared_state), +#endif + future_obtained(false) + {} + + ~promise() + { + if(future_) + { + boost::unique_lock lock(future_->mutex); + + if(!future_->done && !future_->is_constructed) + { + future_->mark_exceptional_finish_internal(boost::copy_exception(broken_promise()), lock); + } + } + } + + // Assignment + promise(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT : + future_(BOOST_THREAD_RV(rhs).future_),future_obtained(BOOST_THREAD_RV(rhs).future_obtained) + { + // we need to release the future as shared_ptr doesn't implements move semantics + BOOST_THREAD_RV(rhs).future_.reset(); + BOOST_THREAD_RV(rhs).future_obtained=false; + } + + promise & operator=(BOOST_THREAD_RV_REF(promise) rhs) BOOST_NOEXCEPT + { + future_=BOOST_THREAD_RV(rhs).future_; + future_obtained=BOOST_THREAD_RV(rhs).future_obtained; + BOOST_THREAD_RV(rhs).future_.reset(); + BOOST_THREAD_RV(rhs).future_obtained=false; + return *this; + } + + void swap(promise& other) + { + future_.swap(other.future_); + std::swap(future_obtained,other.future_obtained); + } + + // Result retrieval + BOOST_THREAD_FUTURE get_future() + { + lazy_init(); + + if (future_.get()==0) + { + boost::throw_exception(promise_moved()); + } + if(future_obtained) + { + boost::throw_exception(future_already_retrieved()); + } + future_obtained=true; + //return BOOST_THREAD_MAKE_RV_REF(BOOST_THREAD_FUTURE(future_)); + return BOOST_THREAD_FUTURE(future_); + } + + void set_value() + { + lazy_init(); + boost::unique_lock lock(future_->mutex); + if(future_->done) + { + boost::throw_exception(promise_already_satisfied()); + } + future_->mark_finished_with_result_internal(lock); + } + + void set_exception(boost::exception_ptr p) + { + lazy_init(); + boost::unique_lock lock(future_->mutex); + if(future_->done) + { + boost::throw_exception(promise_already_satisfied()); + } + future_->mark_exceptional_finish_internal(p,lock); + } + template + void set_exception(E ex) + { + set_exception(boost::copy_exception(ex)); + } + + // setting the result with deferred notification + void set_value_at_thread_exit() + { + if (future_.get()==0) + { + boost::throw_exception(promise_moved()); + } + future_->set_value_at_thread_exit(); + } + + void set_exception_at_thread_exit(exception_ptr e) + { + if (future_.get()==0) + { + boost::throw_exception(promise_moved()); + } + future_->set_exception_at_thread_exit(e); + } + template + void set_exception_at_thread_exit(E ex) + { + set_exception_at_thread_exit(boost::copy_exception(ex)); + } + + template + void set_wait_callback(F f) + { + lazy_init(); + future_->set_wait_callback(f,this); + } + + }; +} +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS +namespace boost { namespace container { + template + struct uses_allocator< ::boost::promise , Alloc> : true_type + { + }; +}} +#if ! defined BOOST_NO_CXX11_ALLOCATOR +namespace std { + template + struct uses_allocator< ::boost::promise , Alloc> : true_type + { + }; +} +#endif +#endif + +namespace boost +{ + + BOOST_THREAD_DCL_MOVABLE_BEG(T) promise BOOST_THREAD_DCL_MOVABLE_END + + namespace detail + { +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + template + struct task_base_shared_state; +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + template + struct task_base_shared_state: +#else + template + struct task_base_shared_state: +#endif +#else + template + struct task_base_shared_state: +#endif + detail::shared_state + { + bool started; + + task_base_shared_state(): + started(false) + {} + + void reset() + { + // todo The packaged_task::reset must be as if an assignemnt froma new packaged_task with the same function + // the reset function is an optimization that avoids reallocating a new task. + started=false; + this->validate(); + } +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + virtual void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0; + void run(BOOST_THREAD_RV_REF(ArgTypes) ... args) +#else + virtual void do_run()=0; + void run() +#endif + { + { + boost::lock_guard lk(this->mutex); + if(started) + { + boost::throw_exception(task_already_started()); + } + started=true; + } +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + do_run(boost::move(args)...); +#else + do_run(); +#endif + } + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + virtual void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args)=0; + void apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) +#else + virtual void do_apply()=0; + void apply() +#endif + { + { + boost::lock_guard lk(this->mutex); + if(started) + { + boost::throw_exception(task_already_started()); + } + started=true; + } +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + do_apply(boost::move(args)...); +#else + do_apply(); +#endif + } + + void owner_destroyed() + { + boost::unique_lock lk(this->mutex); + if(!started) + { + started=true; + this->mark_exceptional_finish_internal(boost::copy_exception(boost::broken_promise()), lk); + } + } + }; + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + template + struct task_shared_state; +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + template + struct task_shared_state: + task_base_shared_state +#else + template + struct task_shared_state: + task_base_shared_state +#endif +#else + template + struct task_shared_state: + task_base_shared_state +#endif + { + private: + task_shared_state(task_shared_state&); + public: + F f; + task_shared_state(F const& f_): + f(f_) + {} + task_shared_state(BOOST_THREAD_RV_REF(F) f_): + f(boost::move(f_)) + {} + + F callable() + { + return boost::move(f); + } + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) + { + try + { + this->set_value_at_thread_exit(f(boost::move(args)...)); + } +#else + void do_apply() + { + try + { + this->set_value_at_thread_exit(f()); + } +#endif + catch(...) + { + this->set_exception_at_thread_exit(current_exception()); + } + } + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) + { + try + { + this->mark_finished_with_result(f(boost::move(args)...)); + } +#else + void do_run() + { + try + { +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + R res((f())); + this->mark_finished_with_result(boost::move(res)); +#else + this->mark_finished_with_result(f()); +#endif + } +#endif + catch(...) + { + this->mark_exceptional_finish(); + } + } + }; + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + template + struct task_shared_state: + task_base_shared_state +#else + template + struct task_shared_state: + task_base_shared_state +#endif +#else + template + struct task_shared_state: + task_base_shared_state +#endif + { + private: + task_shared_state(task_shared_state&); + public: + F f; + task_shared_state(F const& f_): + f(f_) + {} + task_shared_state(BOOST_THREAD_RV_REF(F) f_): + f(boost::move(f_)) + {} + + F callable() + { + return f; + } + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) + { + try + { + this->set_value_at_thread_exit(f(boost::move(args)...)); + } +#else + void do_apply() + { + try + { + this->set_value_at_thread_exit(f()); + } +#endif + catch(...) + { + this->set_exception_at_thread_exit(current_exception()); + } + } + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) + { + try + { + this->mark_finished_with_result(f(boost::move(args)...)); + } +#else + void do_run() + { + try + { + R& res((f())); + this->mark_finished_with_result(res); + } +#endif + catch(...) + { + this->mark_exceptional_finish(); + } + } + }; + +#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + template + struct task_shared_state: + task_base_shared_state +#else + template + struct task_shared_state: + task_base_shared_state +#endif +#else + template + struct task_shared_state : + task_base_shared_state +#endif + { + private: + task_shared_state(task_shared_state&); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + typedef R (*CallableType)(ArgTypes ... ); +#else + typedef R (*CallableType)(); +#endif + public: + CallableType f; + task_shared_state(CallableType f_): + f(f_) + {} + + CallableType callable() + { + return f; + } + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) + { + try + { + this->set_value_at_thread_exit(f(boost::move(args)...)); + } +#else + void do_apply() + { + try + { + R r((f())); + this->set_value_at_thread_exit(boost::move(r)); + } +#endif + catch(...) + { + this->set_exception_at_thread_exit(current_exception()); + } + } + + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) + { + try + { + this->mark_finished_with_result(f(boost::move(args)...)); + } +#else + void do_run() + { + try + { + R res((f())); + this->mark_finished_with_result(boost::move(res)); + } +#endif + catch(...) + { + this->mark_exceptional_finish(); + } + } + }; +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + template + struct task_shared_state: + task_base_shared_state +#else + template + struct task_shared_state: + task_base_shared_state +#endif +#else + template + struct task_shared_state : + task_base_shared_state +#endif + { + private: + task_shared_state(task_shared_state&); + public: +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + typedef R& (*CallableType)(BOOST_THREAD_RV_REF(ArgTypes) ... ); +#else + typedef R& (*CallableType)(); +#endif + CallableType f; + task_shared_state(CallableType f_): + f(f_) + {} + + CallableType callable() + { + return boost::move(f); + } + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) + { + try + { + this->set_value_at_thread_exit(f(boost::move(args)...)); + } +#else + void do_apply() + { + try + { + this->set_value_at_thread_exit(f()); + } +#endif + catch(...) + { + this->set_exception_at_thread_exit(current_exception()); + } + } + + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) + { + try + { + this->mark_finished_with_result(f(boost::move(args)...)); + } +#else + void do_run() + { + try + { + this->mark_finished_with_result(f()); + } +#endif + catch(...) + { + this->mark_exceptional_finish(); + } + } + }; +#endif +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + template + struct task_shared_state: + task_base_shared_state +#else + template + struct task_shared_state: + task_base_shared_state +#endif +#else + template + struct task_shared_state: + task_base_shared_state +#endif + { + private: + task_shared_state(task_shared_state&); + public: + typedef F CallableType; + F f; + task_shared_state(F const& f_): + f(f_) + {} + task_shared_state(BOOST_THREAD_RV_REF(F) f_): + f(boost::move(f_)) + {} + F callable() + { + return boost::move(f); + } +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) + { + try + { + f(boost::move(args)...); +#else + void do_apply() + { + try + { + f(); +#endif + this->set_value_at_thread_exit(); + } + catch(...) + { + this->set_exception_at_thread_exit(current_exception()); + } + } + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) + { + try + { + f(boost::move(args)...); +#else + void do_run() + { + try + { + f(); +#endif + this->mark_finished_with_result(); + } + catch(...) + { + this->mark_exceptional_finish(); + } + } + }; + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + template + struct task_shared_state: + task_base_shared_state +#else + template<> + struct task_shared_state: + task_base_shared_state +#endif +#else + template<> + struct task_shared_state: + task_base_shared_state +#endif + { + private: + task_shared_state(task_shared_state&); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + typedef void (*CallableType)(ArgTypes...); +#else + typedef void (*CallableType)(); +#endif + public: + CallableType f; + task_shared_state(CallableType f_): + f(f_) + {} + CallableType callable() + { + return f; + } +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void do_apply(BOOST_THREAD_RV_REF(ArgTypes) ... args) + { + try + { + f(boost::move(args)...); +#else + void do_apply() + { + try + { + f(); +#endif + this->set_value_at_thread_exit(); + } + catch(...) + { + this->set_exception_at_thread_exit(current_exception()); + } + } + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void do_run(BOOST_THREAD_RV_REF(ArgTypes) ... args) + { + try + { + f(boost::move(args)...); +#else + void do_run() + { + try + { + f(); +#endif + this->mark_finished_with_result(); + } + catch(...) + { + this->mark_exceptional_finish(); + } + } + }; + } + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + template + class packaged_task + { + typedef boost::shared_ptr > task_ptr; + boost::shared_ptr > task; + #else + template + class packaged_task + { + typedef boost::shared_ptr > task_ptr; + boost::shared_ptr > task; + #endif +#else + template + class packaged_task + { + typedef boost::shared_ptr > task_ptr; + boost::shared_ptr > task; +#endif + bool future_obtained; + struct dummy; + + public: + typedef R result_type; + BOOST_THREAD_MOVABLE_ONLY(packaged_task) + + packaged_task(): + future_obtained(false) + {} + + // construction and destruction +#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + explicit packaged_task(R(*f)(), BOOST_THREAD_FWD_REF(ArgTypes)... args) + { + typedef R(*FR)(BOOST_THREAD_FWD_REF(ArgTypes)...); + typedef detail::task_shared_state task_shared_state_type; + task= task_ptr(new task_shared_state_type(f, boost::move(args)...)); + future_obtained=false; + } + #else + explicit packaged_task(R(*f)()) + { + typedef R(*FR)(); + typedef detail::task_shared_state task_shared_state_type; + task= task_ptr(new task_shared_state_type(f)); + future_obtained=false; + } + #endif +#else + explicit packaged_task(R(*f)()) + { + typedef R(*FR)(); + typedef detail::task_shared_state task_shared_state_type; + task= task_ptr(new task_shared_state_type(f)); + future_obtained=false; + } +#endif +#endif +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template + explicit packaged_task(BOOST_THREAD_FWD_REF(F) f + , typename boost::disable_if::type, packaged_task>, dummy* >::type=0 + ) + { + typedef typename decay::type FR; +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + typedef detail::task_shared_state task_shared_state_type; + #else + typedef detail::task_shared_state task_shared_state_type; + #endif +#else + typedef detail::task_shared_state task_shared_state_type; +#endif + task = task_ptr(new task_shared_state_type(boost::forward(f))); + future_obtained = false; + + } + +#else + template + explicit packaged_task(F const& f + , typename boost::disable_if::type, packaged_task>, dummy* >::type=0 + ) + { +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + typedef detail::task_shared_state task_shared_state_type; + #else + typedef detail::task_shared_state task_shared_state_type; + #endif +#else + typedef detail::task_shared_state task_shared_state_type; +#endif + task = task_ptr(new task_shared_state_type(f)); + future_obtained=false; + } + template + explicit packaged_task(BOOST_THREAD_RV_REF(F) f) + { +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + typedef detail::task_shared_state task_shared_state_type; + task = task_ptr(new task_shared_state_type(boost::move(f))); +#else + typedef detail::task_shared_state task_shared_state_type; + task = task_ptr(new task_shared_state_type(boost::move(f))); +#endif +#else + typedef detail::task_shared_state task_shared_state_type; + task = task_ptr(new task_shared_state_type(boost::move(f))); +#endif + future_obtained=false; + + } +#endif + +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS +#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) + template + packaged_task(boost::allocator_arg_t, Allocator a, R(*f)()) + { + typedef R(*FR)(); +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + typedef detail::task_shared_state task_shared_state_type; + #else + typedef detail::task_shared_state task_shared_state_type; + #endif +#else + typedef detail::task_shared_state task_shared_state_type; +#endif + typedef typename Allocator::template rebind::other A2; + A2 a2(a); + typedef thread_detail::allocator_destructor D; + + task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(f), D(a2, 1) ); + future_obtained = false; + } +#endif // BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR + +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + template + packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_FWD_REF(F) f) + { + typedef typename decay::type FR; + +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + typedef detail::task_shared_state task_shared_state_type; + #else + typedef detail::task_shared_state task_shared_state_type; + #endif +#else + typedef detail::task_shared_state task_shared_state_type; +#endif + typedef typename Allocator::template rebind::other A2; + A2 a2(a); + typedef thread_detail::allocator_destructor D; + + task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::forward(f)), D(a2, 1) ); + future_obtained = false; + } +#else // ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + template + packaged_task(boost::allocator_arg_t, Allocator a, const F& f) + { +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + typedef detail::task_shared_state task_shared_state_type; + #else + typedef detail::task_shared_state task_shared_state_type; + #endif +#else + typedef detail::task_shared_state task_shared_state_type; +#endif + typedef typename Allocator::template rebind::other A2; + A2 a2(a); + typedef thread_detail::allocator_destructor D; + + task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(f), D(a2, 1) ); + future_obtained = false; + } + template + packaged_task(boost::allocator_arg_t, Allocator a, BOOST_THREAD_RV_REF(F) f) + { +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + typedef detail::task_shared_state task_shared_state_type; + #else + typedef detail::task_shared_state task_shared_state_type; + #endif +#else + typedef detail::task_shared_state task_shared_state_type; +#endif + typedef typename Allocator::template rebind::other A2; + A2 a2(a); + typedef thread_detail::allocator_destructor D; + + task = task_ptr(::new(a2.allocate(1)) task_shared_state_type(boost::move(f)), D(a2, 1) ); + future_obtained = false; + } + +#endif //BOOST_NO_CXX11_RVALUE_REFERENCES +#endif // BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS + + ~packaged_task() { + if(task) { + task->owner_destroyed(); + } + } + + // assignment + packaged_task(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT + : future_obtained(BOOST_THREAD_RV(other).future_obtained) { + task.swap(BOOST_THREAD_RV(other).task); + BOOST_THREAD_RV(other).future_obtained=false; + } + packaged_task& operator=(BOOST_THREAD_RV_REF(packaged_task) other) BOOST_NOEXCEPT { + +#if ! defined BOOST_NO_CXX11_RVALUE_REFERENCES + packaged_task temp(boost::move(other)); +#else + packaged_task temp(static_cast(other)); +#endif + swap(temp); + return *this; + } + +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + void set_executor(executor_ptr_type aex) + { + if (!valid()) + boost::throw_exception(task_moved()); + boost::lock_guard lk(task->mutex); + task->set_executor_policy(aex, lk); + } +#endif + void reset() { + if (!valid()) + boost::throw_exception(future_error(system::make_error_code(future_errc::no_state))); + + // As if *this = packaged_task(task->callable()); + + task->reset(); + future_obtained=false; + } + + void swap(packaged_task& other) BOOST_NOEXCEPT { + task.swap(other.task); + std::swap(future_obtained,other.future_obtained); + } + bool valid() const BOOST_NOEXCEPT { + return task.get()!=0; + } + + // result retrieval + BOOST_THREAD_FUTURE get_future() { + if(!task) { + boost::throw_exception(task_moved()); + } else if(!future_obtained) { + future_obtained=true; + return BOOST_THREAD_FUTURE(task); + } else { + boost::throw_exception(future_already_retrieved()); + } + } + + // execution +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK && defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + void operator()(ArgTypes... args) { + if(!task) { + boost::throw_exception(task_moved()); + } + task->run(boost::move(args)...); + } + void make_ready_at_thread_exit(ArgTypes... args) { + if(!task) { + boost::throw_exception(task_moved()); + } + if (task->has_value()) { + boost::throw_exception(promise_already_satisfied()); + } + task->apply(boost::move(args)...); + } +#else + void operator()() { + if(!task) { + boost::throw_exception(task_moved()); + } + task->run(); + } + void make_ready_at_thread_exit() { + if(!task) { + boost::throw_exception(task_moved()); + } + if (task->has_value()) boost::throw_exception(promise_already_satisfied()); + task->apply(); + } +#endif + template + void set_wait_callback(F f) { + task->set_wait_callback(f,this); + } + }; +} +#if defined BOOST_THREAD_PROVIDES_FUTURE_CTOR_ALLOCATORS +namespace boost { namespace container { + template + struct uses_allocator< ::boost::packaged_task , Alloc> : true_type + {}; +}} +#if ! defined BOOST_NO_CXX11_ALLOCATOR +namespace std { + template + struct uses_allocator< ::boost::packaged_task , Alloc> : true_type + {}; +} +#endif +#endif + +namespace boost +{ + BOOST_THREAD_DCL_MOVABLE_BEG(T) packaged_task BOOST_THREAD_DCL_MOVABLE_END + +namespace detail +{ + //////////////////////////////// + // make_future_deferred_shared_state + //////////////////////////////// + template + BOOST_THREAD_FUTURE + make_future_deferred_shared_state(BOOST_THREAD_FWD_REF(Fp) f) { + shared_ptr > + h(new future_deferred_shared_state(boost::forward(f))); + return BOOST_THREAD_FUTURE(h); + } + + //////////////////////////////// + // make_future_async_shared_state + //////////////////////////////// + template + BOOST_THREAD_FUTURE + make_future_async_shared_state(BOOST_THREAD_FWD_REF(Fp) f) { + shared_ptr > + h(new future_async_shared_state()); + h->init(boost::forward(f)); + return BOOST_THREAD_FUTURE(h); + } +} + + //////////////////////////////// + // template + // future async(launch policy, F&&, ArgTypes&&...); + //////////////////////////////// + +#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR + +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + template + BOOST_THREAD_FUTURE + async(launch policy, R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) { + typedef R(*F)(BOOST_THREAD_FWD_REF(ArgTypes)...); + typedef detail::invoker::type, typename decay::type...> BF; + typedef typename BF::result_type Rp; + + if (underlying_cast(policy) & int(launch::async)) { + return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_shared_state( + BF( + f + , thread_detail::decay_copy(boost::forward(args))... + ) + )); + } else if (underlying_cast(policy) & int(launch::deferred)) { + return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_shared_state( + BF( + f + , thread_detail::decay_copy(boost::forward(args))... + ) + )); + } else { + std::terminate(); + //BOOST_THREAD_FUTURE ret; + //return ::boost::move(ret); + } + } + +#else // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + + template + BOOST_THREAD_FUTURE + async(launch policy, R(*f)()) { + #if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + typedef packaged_task packaged_task_type; + #else + typedef packaged_task packaged_task_type; + #endif + + if (underlying_cast(policy) & int(launch::async)) { + packaged_task_type pt( f ); + BOOST_THREAD_FUTURE ret = BOOST_THREAD_MAKE_RV_REF(pt.get_future()); + ret.set_async(); + boost::thread( boost::move(pt) ).detach(); + return ::boost::move(ret); + } else if (underlying_cast(policy) & int(launch::deferred)) { + std::terminate(); + //BOOST_THREAD_FUTURE ret; + //return ::boost::move(ret); + } else { + std::terminate(); + //BOOST_THREAD_FUTURE ret; + //return ::boost::move(ret); + } + } +#endif +#endif // defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) + +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + + template + BOOST_THREAD_FUTURE::type( + typename decay::type... + )>::type> + async(launch policy, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) { + typedef detail::invoker::type, typename decay::type...> BF; + typedef typename BF::result_type Rp; + + if (underlying_cast(policy) & int(launch::async)) { + return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_async_shared_state( + BF( + thread_detail::decay_copy(boost::forward(f)) + , thread_detail::decay_copy(boost::forward(args))... + ) + )); + } else if (underlying_cast(policy) & int(launch::deferred)) { + return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_deferred_shared_state( + BF( + thread_detail::decay_copy(boost::forward(f)) + , thread_detail::decay_copy(boost::forward(args))... + ) + )); + } else { + std::terminate(); + //BOOST_THREAD_FUTURE ret; + //return ::boost::move(ret); + } + } + +#else // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + + template + BOOST_THREAD_FUTURE::type()>::type> + async(launch policy, BOOST_THREAD_FWD_REF(F) f) { + typedef typename boost::result_of::type()>::type R; +#if defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + typedef packaged_task packaged_task_type; +#else // defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + typedef packaged_task packaged_task_type; +#endif // defined BOOST_THREAD_PROVIDES_SIGNATURE_PACKAGED_TASK + + if (underlying_cast(policy) & int(launch::async)) { + packaged_task_type pt( boost::forward(f) ); + BOOST_THREAD_FUTURE ret = pt.get_future(); + ret.set_async(); + boost::thread( boost::move(pt) ).detach(); + return ::boost::move(ret); + } else if (underlying_cast(policy) & int(launch::deferred)) { + std::terminate(); + //BOOST_THREAD_FUTURE ret; + //return ::boost::move(ret); + // return boost::detail::make_future_deferred_shared_state( + // BF( + // thread_detail::decay_copy(boost::forward(f)) + // ) + // ); + } else { + std::terminate(); + //BOOST_THREAD_FUTURE ret; + //return ::boost::move(ret); + } + } +#endif // defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS +namespace detail { + + ///////////////////////// + /// shared_state_nullary_task + ///////////////////////// + template + struct shared_state_nullary_task + { + + typedef shared_ptr storage_type; + storage_type that; + Fp f_; + public: + + shared_state_nullary_task(storage_type st, BOOST_THREAD_FWD_REF(Fp) f) + : that(st), f_(boost::move(f)) + {}; + +#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_state_nullary_task) + shared_state_nullary_task(shared_state_nullary_task const& x) //BOOST_NOEXCEPT + : that(x.that), f_(x.f_) + {} + shared_state_nullary_task& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT + { + if (this != &x) { + that=x.that; + f_=x.f_; + } + return *this; + } + // move + shared_state_nullary_task(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT + : that(x.that), f_(boost::move(x.f_)) + { + x.that.reset(); + } + shared_state_nullary_task& operator=(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT + { + if (this != &x) { + that=x.that; + f_=boost::move(x.f_); + x.that.reset(); + } + return *this; + } +#endif + void operator()() { + shared_ptr > that_ = static_pointer_cast >(that); + try { + that_->mark_finished_with_result(f_()); + } catch(...) { + that_->mark_exceptional_finish(); + } + } + ~shared_state_nullary_task() + { + } + }; + + template + struct shared_state_nullary_task + { + typedef shared_ptr storage_type; + storage_type that; + Fp f_; + public: + shared_state_nullary_task(storage_type st, BOOST_THREAD_FWD_REF(Fp) f) + : that(st), f_(boost::move(f)) + {}; + +#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + BOOST_THREAD_COPYABLE_AND_MOVABLE(shared_state_nullary_task) + shared_state_nullary_task(shared_state_nullary_task const& x) //BOOST_NOEXCEPT + : that(x.that), f_(x.f_) + {} + shared_state_nullary_task& operator=(BOOST_THREAD_COPY_ASSIGN_REF(shared_state_nullary_task) x) //BOOST_NOEXCEPT + { + if (this != &x) { + that=x.that; + f_=x.f_; + } + return *this; + } + // move + shared_state_nullary_task(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT + : that(x.that), f_(boost::move(x.f_)) + { + x.that.reset(); + } + shared_state_nullary_task& operator=(BOOST_THREAD_RV_REF(shared_state_nullary_task) x) BOOST_NOEXCEPT { + if (this != &x) { + that=x.that; + f_=boost::move(x.f_); + x.that.reset(); + } + return *this; + } +#endif + void operator()() { + shared_ptr > that_ = static_pointer_cast >(that); + try { + f_(); + that_->mark_finished_with_result(); + } catch(...) { + that_->mark_exceptional_finish(); + } + } + }; + +} + BOOST_THREAD_DCL_MOVABLE_BEG2(R,F) detail::shared_state_nullary_task BOOST_THREAD_DCL_MOVABLE_END +namespace detail { + + ///////////////////////// + /// future_executor_shared_state_base + ///////////////////////// + template + struct future_executor_shared_state: shared_state + { + typedef shared_state base_type; + protected: + public: + future_executor_shared_state() { + } + + template + void init(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f) + { + typedef typename decay::type Cont; + this->set_executor_policy(executor_ptr_type(new executor_ref(ex))); + shared_state_nullary_task t(this->shared_from_this(), boost::forward(f)); + ex.submit(boost::move(t)); + } + + ~future_executor_shared_state() {} + }; + + //////////////////////////////// + // make_future_executor_shared_state + //////////////////////////////// + template + BOOST_THREAD_FUTURE + make_future_executor_shared_state(Executor& ex, BOOST_THREAD_FWD_REF(Fp) f) { + shared_ptr > + h(new future_executor_shared_state()); + h->init(ex, boost::forward(f)); + return BOOST_THREAD_FUTURE(h); + } + +} // detail + + //////////////////////////////// + // template + // future async(Executor& ex, F&&, ArgTypes&&...); + //////////////////////////////// + +//#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#if defined(BOOST_THREAD_PROVIDES_INVOKE) && ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && ! defined(BOOST_NO_CXX11_HDR_TUPLE) + +#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR + + template + BOOST_THREAD_FUTURE + async(Executor& ex, R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) { + typedef R(*F)(BOOST_THREAD_FWD_REF(ArgTypes)...); + typedef detail::invoker::type, typename decay::type...> BF; + typedef typename BF::result_type Rp; + + return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state(ex, + BF( + f + , thread_detail::decay_copy(boost::forward(args))... + ) + )); + } +#endif // defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR + + template + BOOST_THREAD_FUTURE::type( + typename decay::type... + )>::type> + async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) { + typedef detail::invoker::type, typename decay::type...> BF; + typedef typename BF::result_type Rp; + + return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state(ex, + BF( + thread_detail::decay_copy(boost::forward(f)) + , thread_detail::decay_copy(boost::forward(args))... + ) + )); + } + +#else // ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR + + template + BOOST_THREAD_FUTURE + async(Executor& ex, R(*f)()) { + typedef R(*F)(); + typedef detail::invoker BF; + typedef typename BF::result_type Rp; + + return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state(ex, + BF( + f + ) + )); + } + + template + BOOST_THREAD_FUTURE + async(Executor& ex, R(*f)(BOOST_THREAD_FWD_REF(A1)), BOOST_THREAD_FWD_REF(A1) a1) { + typedef R(*F)(BOOST_THREAD_FWD_REF(A1)); + typedef detail::invoker::type> BF; + typedef typename BF::result_type Rp; + + return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state(ex, + BF( + f + , thread_detail::decay_copy(boost::forward(a1)) + ) + )); + } +#endif // defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR + + template + BOOST_THREAD_FUTURE::type()>::type> + async(Executor& ex, BOOST_THREAD_FWD_REF(F) f) { + typedef detail::invoker::type> BF; + typedef typename BF::result_type Rp; + + return boost::detail::make_future_executor_shared_state(ex, + BF( + thread_detail::decay_copy(boost::forward(f)) + ) + ); + } + + template + BOOST_THREAD_FUTURE::type( + typename decay::type + )>::type> + async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1) { + typedef detail::invoker::type, typename decay::type> BF; + typedef typename BF::result_type Rp; + + return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state(ex, + BF( + thread_detail::decay_copy(boost::forward(f)) + , thread_detail::decay_copy(boost::forward(a1)) + ) + )); + } + + template + BOOST_THREAD_FUTURE::type( + typename decay::type, typename decay::type + )>::type> + async(Executor& ex, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2) { + typedef detail::invoker::type, typename decay::type, typename decay::type> BF; + typedef typename BF::result_type Rp; + + return BOOST_THREAD_MAKE_RV_REF(boost::detail::make_future_executor_shared_state(ex, + BF( + thread_detail::decay_copy(boost::forward(f)) + , thread_detail::decay_copy(boost::forward(a1)) + , thread_detail::decay_copy(boost::forward(a2)) + ) + )); + } + +#endif //! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) +#endif + + //////////////////////////////// + // template + // future async(F&&, ArgTypes&&...); + //////////////////////////////// + +#if defined BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR + #if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + template + BOOST_THREAD_FUTURE + async(R(*f)(BOOST_THREAD_FWD_REF(ArgTypes)...), BOOST_THREAD_FWD_REF(ArgTypes)... args) { + return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f, boost::forward(args)...)); + } + #else + template + BOOST_THREAD_FUTURE + async(R(*f)()) { + return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), f)); + } + #endif +#endif + +#if defined(BOOST_THREAD_PROVIDES_VARIADIC_THREAD) + template + BOOST_THREAD_FUTURE::type( + typename decay::type... + )>::type> + async(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(ArgTypes)... args) { + return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward(f), boost::forward(args)...)); + } +#else + template + BOOST_THREAD_FUTURE::type> + async(BOOST_THREAD_FWD_REF(F) f) { + return BOOST_THREAD_MAKE_RV_REF(async(launch(launch::any), boost::forward(f))); + } +#endif + + //////////////////////////////// + // make_future deprecated + //////////////////////////////// + template + BOOST_THREAD_FUTURE::type> make_future(BOOST_THREAD_FWD_REF(T) value) { + typedef typename decay::type future_value_type; + promise p; + p.set_value(boost::forward(value)); + return BOOST_THREAD_MAKE_RV_REF(p.get_future()); + } + +#if defined BOOST_THREAD_USES_MOVE + inline BOOST_THREAD_FUTURE make_future() { + promise p; + p.set_value(); + return BOOST_THREAD_MAKE_RV_REF(p.get_future()); + } +#endif + + //////////////////////////////// + // make_ready_future + //////////////////////////////// + namespace detail { + template + struct deduced_type_impl + { + typedef T type; + }; + + template + struct deduced_type_impl const> + { + typedef T& type; + }; + template + struct deduced_type_impl > + { + typedef T& type; + }; +#if __cplusplus > 201103L + template + struct deduced_type_impl > + { + typedef T& type; + }; +#endif + template + struct deduced_type + { + typedef typename detail::deduced_type_impl::type>::type type; + }; + + } + + +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template +#else + template +#endif + BOOST_THREAD_FUTURE::type> make_ready_future(BOOST_THREAD_FWD_REF(T) value) { + typedef typename detail::deduced_type::type future_value_type; + promise p; + p.set_value(boost::forward(value)); + return BOOST_THREAD_MAKE_RV_REF(p.get_future()); + } + + // explicit overloads + template + BOOST_THREAD_FUTURE make_ready_future(typename remove_reference::type & x) + { + promise p; + p.set_value(x); + return p.get_future(); + } + + template + BOOST_THREAD_FUTURE make_ready_future(BOOST_THREAD_FWD_REF(typename remove_reference::type) x) + { + promise p; + p.set_value(forward::type>(x)); + return p.get_future(); + } + + // variadic overload +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template + BOOST_THREAD_FUTURE make_ready_future(Args&&... args) + { + promise p; + p.emplace(forward(args)...); + return p.get_future(); + + } +#endif + + template + BOOST_THREAD_FUTURE make_ready_no_decay_future(T1 value) { + typedef T future_value_type; + promise p; + p.set_value(value); + return BOOST_THREAD_MAKE_RV_REF(p.get_future()); + } + +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined BOOST_THREAD_USES_MOVE + inline BOOST_THREAD_FUTURE make_ready_future() { + promise p; + p.set_value(); + return p.get_future(); + } +#endif + + + template + BOOST_THREAD_FUTURE make_exceptional_future(exception_ptr ex) { + promise p; + p.set_exception(ex); + return BOOST_THREAD_MAKE_RV_REF(p.get_future()); + } + + template + BOOST_THREAD_FUTURE make_exceptional_future(E ex) { + promise p; + p.set_exception(boost::copy_exception(ex)); + return BOOST_THREAD_MAKE_RV_REF(p.get_future()); + } + + template + BOOST_THREAD_FUTURE make_exceptional_future() { + promise p; + p.set_exception(boost::current_exception()); + return BOOST_THREAD_MAKE_RV_REF(p.get_future()); + } + template + BOOST_THREAD_FUTURE make_ready_future(exception_ptr ex) { + return make_exceptional_future(ex); + } + +#if 0 + template + make_future(CLOSURE closure) -> BOOST_THREAD_FUTURE { + typedef decltype(closure()) T; + promise p; + try { + p.set_value(closure()); + } catch(...) { + p.set_exception(std::current_exception()); + } + return BOOST_THREAD_MAKE_RV_REF(p.get_future()); + } +#endif + + //////////////////////////////// + // make_shared_future deprecated + //////////////////////////////// + template + shared_future::type> make_shared_future(BOOST_THREAD_FWD_REF(T) value) { + typedef typename decay::type future_type; + promise p; + p.set_value(boost::forward(value)); + return BOOST_THREAD_MAKE_RV_REF(p.get_future().share()); + } + + inline shared_future make_shared_future() { + promise p; + return BOOST_THREAD_MAKE_RV_REF(p.get_future().share()); + } + + //////////////////////////////// + // detail::future_async_continuation_shared_state + //////////////////////////////// +#if defined BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION + +#if defined BOOST_THREAD_CONTINUATION_SYNC +#define continuation_shared_state_base shared_state +#else +#define continuation_shared_state_base future_async_shared_state_base +#endif + +namespace detail +{ + ////////////////////// + // detail::continuation_shared_state + ////////////////////// + template > + struct continuation_shared_state: ShSt + { + F parent; + Fp continuation; + + public: + continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) + : parent(boost::move(f)), + continuation(boost::move(c)) + { + } + + void init(boost::unique_lock &lock) + { + parent.future_->set_continuation_ptr(this->shared_from_this(), lock); + } + + void call() { + try { + this->mark_finished_with_result(this->continuation(boost::move(this->parent))); + } catch(...) { + this->mark_exceptional_finish(); + } + // make sure parent is really cleared to prevent memory "leaks" + this->parent = F(); + } + + void call(boost::unique_lock& lck) { + try { + relocker relock(lck); + + // neither continuation nor parent are protected by the lock - call() must only + // be called once, and no one else must modify it. + Rp res = this->continuation(boost::move(this->parent)); + + // make sure parent is really cleared to prevent memory "leaks" + this->parent = F(); + + relock.lock(); + + this->mark_finished_with_result_internal(boost::move(res), lck); + } catch (...) { + this->mark_exceptional_finish_internal(current_exception(), lck); + + // make sure parent is really cleared to prevent memory "leaks" + relocker relock(lck); + this->parent = F(); + } + } + + static void run(shared_ptr that_) + { + continuation_shared_state* that = static_cast(that_.get()); + that->call(); + } + + ~continuation_shared_state() {} + }; + + template + struct continuation_shared_state: ShSt + { + F parent; + Fp continuation; + + public: + continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) + : parent(boost::move(f)), + continuation(boost::move(c)) + { + } + + void init(boost::unique_lock &lock) + { + parent.future_->set_continuation_ptr(this->shared_from_this(), lock); + } + + void call() + { + try { + this->continuation(boost::move(this->parent)); + this->mark_finished_with_result(); + } catch(...) { + this->mark_exceptional_finish(); + } + // make sure parent is really cleared to prevent memory "leaks" + this->parent = F(); + } + + void call(boost::unique_lock& lck) { + try { + { + relocker relock(lck); + // neither continuation nor parent are protected by the lock - call() must only + // be called once, and no one else must modify it. + this->continuation(boost::move(this->parent)); + + // make sure parent is really cleared to prevent memory "leaks" + this->parent = F(); + } + this->mark_finished_with_result_internal(lck); + } catch (...) { + this->mark_exceptional_finish_internal(current_exception(), lck); + + // make sure parent is really cleared to prevent memory "leaks" + relocker relock(lck); + this->parent = F(); + } + } + + static void run(shared_ptr that_) + { + continuation_shared_state* that = static_cast(that_.get()); + that->call(); + } + + ~continuation_shared_state() {} + }; + ///////////////////////// + /// future_async_continuation_shared_state + ///////////////////////// + + template + struct future_async_continuation_shared_state: continuation_shared_state > + { + typedef continuation_shared_state > base_type; + public: + future_async_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) + : base_type(boost::move(f), boost::forward(c)) + { } + + void launch_continuation() { +#if defined BOOST_THREAD_CONTINUATION_SYNC + this->call(); +#elif defined BOOST_THREAD_FUTURE_BLOCKING + boost::lock_guard lk(this->mutex); + this->thr_ = thread(&future_async_continuation_shared_state::run, static_shared_from_this(this)); +#else + thread(&future_async_continuation_shared_state::run, static_shared_from_this(this)).detach(); +#endif + } + }; + + ///////////////////////// + /// future_executor_continuation_shared_state + ///////////////////////// +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + + template + struct run_it { + shared_ptr that_; + +#if ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + BOOST_THREAD_COPYABLE_AND_MOVABLE(run_it) + run_it(run_it const& x) //BOOST_NOEXCEPT + : that_(x.that_) + {} + run_it& operator=(BOOST_THREAD_COPY_ASSIGN_REF(run_it) x) //BOOST_NOEXCEPT + { + if (this != &x) { + that_=x.that_; + } + return *this; + } + // move + run_it(BOOST_THREAD_RV_REF(run_it) x) BOOST_NOEXCEPT + : that_(x.that_) + { + x.that_.reset(); + } + run_it& operator=(BOOST_THREAD_RV_REF(run_it) x) BOOST_NOEXCEPT { + if (this != &x) { + that_=x.that; + x.that_.reset(); + } + return *this; + } +#endif + run_it(shared_ptr that) : that_ (that) {} + + void operator()() + { + that_->run(that_); + } + }; + +} + BOOST_THREAD_DCL_MOVABLE_BEG(F) detail::run_it BOOST_THREAD_DCL_MOVABLE_END + +namespace detail { + + template + struct future_executor_continuation_shared_state: continuation_shared_state + { + typedef continuation_shared_state base_type; + + public: + future_executor_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) + : base_type(boost::move(f), boost::forward(c)) + { + } + + template + void init(boost::unique_lock &lk, Ex& ex) + { + this->set_executor_policy(executor_ptr_type(new executor_ref(ex)), lk); + this->base_type::init(lk); + } + + void launch_continuation() { + run_it fct(static_shared_from_this(this)); + this->get_executor()->submit(boost::move(fct)); + } + + ~future_executor_continuation_shared_state() {} + }; +#endif + + ///////////////////////// + /// shared_future_async_continuation_shared_state + ///////////////////////// + + template + struct shared_future_async_continuation_shared_state: continuation_shared_state > + { + typedef continuation_shared_state > base_type; + + public: + shared_future_async_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c) + : base_type(boost::move(f), boost::forward(c)) + { + } + + void launch_continuation() { +#if defined BOOST_THREAD_CONTINUATION_SYNC + this->call(); +#elif defined BOOST_THREAD_FUTURE_BLOCKING + boost::lock_guard lk(this->mutex); + this->thr_ = thread(&shared_future_async_continuation_shared_state::run, static_shared_from_this(this)); +#else + thread(&shared_future_async_continuation_shared_state::run, static_shared_from_this(this)).detach(); +#endif + } + + ~shared_future_async_continuation_shared_state() {} + }; + + ///////////////////////// + /// shared_future_executor_continuation_shared_state + ///////////////////////// +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + + template + struct shared_future_executor_continuation_shared_state: continuation_shared_state + { + typedef continuation_shared_state base_type; + + public: + + shared_future_executor_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c) + : base_type(boost::move(f), boost::forward(c)) + { + } + + template + void init(boost::unique_lock &lk, Ex& ex) + { + this->set_executor_policy(executor_ptr_type(new executor_ref(ex)), lk); + this->base_type::init(lk); + } + + void launch_continuation() { + run_it fct(static_shared_from_this(this)); + this->get_executor()->submit(boost::move(fct)); + } + + ~shared_future_executor_continuation_shared_state() {} + }; + +#endif + ////////////////////////// + /// future_deferred_continuation_shared_state + ////////////////////////// + template + struct future_deferred_continuation_shared_state: continuation_shared_state + { + typedef continuation_shared_state base_type; + public: + future_deferred_continuation_shared_state(BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) + : base_type(boost::move(f), boost::forward(c)) + { + this->set_deferred(); + } + + virtual void execute(boost::unique_lock& lk) { + this->parent.wait(); + this->call(lk); + } + + virtual void launch_continuation() { } + }; + + ////////////////////////// + /// shared_future_deferred_continuation_shared_state + ////////////////////////// + template + struct shared_future_deferred_continuation_shared_state: continuation_shared_state + { + typedef continuation_shared_state base_type; + + public: + shared_future_deferred_continuation_shared_state(F f, BOOST_THREAD_FWD_REF(Fp) c) + : base_type(boost::move(f), boost::forward(c)) + { + this->set_deferred(); + } + + virtual void execute(boost::unique_lock& lk) { + this->parent.wait(); + this->call(lk); + } + + virtual void launch_continuation() { } + }; + + //////////////////////////////// + // make_future_deferred_continuation_shared_state + //////////////////////////////// + template + BOOST_THREAD_FUTURE + make_future_deferred_continuation_shared_state( + boost::unique_lock &lock, + BOOST_THREAD_RV_REF(F) f, BOOST_THREAD_FWD_REF(Fp) c) { + typedef typename decay::type Cont; + shared_ptr > + h(new future_deferred_continuation_shared_state(boost::move(f), boost::forward(c))); + h->init(lock); + return BOOST_THREAD_FUTURE(h); + } + + //////////////////////////////// + // make_future_async_continuation_shared_state + //////////////////////////////// + template + BOOST_THREAD_FUTURE + make_future_async_continuation_shared_state( + boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f, + BOOST_THREAD_FWD_REF(Fp) c) { + typedef typename decay::type Cont; + shared_ptr > + h(new future_async_continuation_shared_state(boost::move(f), boost::forward(c))); + h->init(lock); + + return BOOST_THREAD_FUTURE(h); + } + + //////////////////////////////// + // make_future_executor_continuation_shared_state + //////////////////////////////// +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + + template + BOOST_THREAD_FUTURE + make_future_executor_continuation_shared_state(Ex& ex, + boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f, + BOOST_THREAD_FWD_REF(Fp) c) { + typedef typename decay::type Cont; + shared_ptr > + h(new future_executor_continuation_shared_state(boost::move(f), boost::forward(c))); + h->init(lock, ex); + + return BOOST_THREAD_FUTURE(h); + } +#endif + + //////////////////////////////// + // make_shared_future_deferred_continuation_shared_state + //////////////////////////////// + template + BOOST_THREAD_FUTURE + make_shared_future_deferred_continuation_shared_state( + boost::unique_lock &lock, + F f, BOOST_THREAD_FWD_REF(Fp) c) { + typedef typename decay::type Cont; + shared_ptr > + h(new shared_future_deferred_continuation_shared_state(f, boost::forward(c))); + h->init(lock); + + return BOOST_THREAD_FUTURE(h); + } + //////////////////////////////// + // make_shared_future_async_continuation_shared_state + //////////////////////////////// + template + BOOST_THREAD_FUTURE + make_shared_future_async_continuation_shared_state( + boost::unique_lock &lock, F f, + BOOST_THREAD_FWD_REF(Fp) c) { + typedef typename decay::type Cont; + shared_ptr > + h(new shared_future_async_continuation_shared_state(f, boost::forward(c))); + h->init(lock); + + return BOOST_THREAD_FUTURE(h); + } + //////////////////////////////// + // make_shared_future_executor_continuation_shared_state + //////////////////////////////// +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + template + BOOST_THREAD_FUTURE + make_shared_future_executor_continuation_shared_state(Ex& ex, + boost::unique_lock &lock, F f, + BOOST_THREAD_FWD_REF(Fp) c) { + typedef typename decay::type Cont; + shared_ptr > + h(new shared_future_executor_continuation_shared_state(f, boost::forward(c))); + h->init(lock, ex); + + return BOOST_THREAD_FUTURE(h); + } +#endif +} + + //////////////////////////////// + // template + // auto future::then(launch policy, F&& func) -> BOOST_THREAD_FUTURE; + //////////////////////////////// + template + template + inline BOOST_THREAD_FUTURE)>::type> + BOOST_THREAD_FUTURE::then(launch policy, BOOST_THREAD_FWD_REF(F) func) { + typedef typename boost::result_of)>::type future_type; + BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); + + // keep state alive as we move ourself but hold the lock + shared_ptr sentinel(this->future_); + boost::unique_lock lock(sentinel->mutex); + + if (underlying_cast(policy) & int(launch::async)) { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state, future_type>( + lock, boost::move(*this), boost::forward(func) + ))); + } else if (underlying_cast(policy) & int(launch::deferred)) { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state, future_type>( + lock, boost::move(*this), boost::forward(func) + ))); +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + } else if (underlying_cast(policy) & int(launch::executor)) { + assert(this->future_->get_executor()); + typedef executor Ex; + Ex& ex = *(this->future_->get_executor()); + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state, future_type>(ex, + lock, boost::move(*this), boost::forward(func) + ))); +#endif + } else if (underlying_cast(policy) & int(launch::inherit)) { + + launch policy = this->launch_policy(lock); + if (underlying_cast(policy) & int(launch::async)) { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state, future_type>( + lock, boost::move(*this), boost::forward(func) + ))); + } else if (underlying_cast(policy) & int(launch::deferred)) { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state, future_type>( + lock, boost::move(*this), boost::forward(func) + ))); +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + } else if (underlying_cast(policy) & int(launch::executor)) { + assert(this->future_->get_executor()); + typedef executor Ex; + Ex& ex = *(this->future_->get_executor()); + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state, future_type>(ex, + lock, boost::move(*this), boost::forward(func) + ))); +#endif + } else { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state, future_type>( + lock, boost::move(*this), boost::forward(func) + ))); + } + } else { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state, future_type>( + lock, boost::move(*this), boost::forward(func) + ))); + } + } +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + //////////////////////////////// + // template + // auto future >::then(Ex&, F&& func) -> BOOST_THREAD_FUTURE; + //////////////////////////////// + template + template + inline BOOST_THREAD_FUTURE)>::type> + BOOST_THREAD_FUTURE::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) { + typedef typename boost::result_of)>::type future_type; + BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); + + // keep state alive as we move ourself but hold the lock + shared_ptr sentinel(this->future_); + boost::unique_lock lock(sentinel->mutex); + + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state, future_type>(ex, + lock, boost::move(*this), boost::forward(func) + ))); + } +#endif + //////////////////////////////// + // template + // auto future >::then(F&& func) -> BOOST_THREAD_FUTURE; + //////////////////////////////// + template + template + inline BOOST_THREAD_FUTURE)>::type> + BOOST_THREAD_FUTURE::then(BOOST_THREAD_FWD_REF(F) func) { + +#ifndef BOOST_THREAD_CONTINUATION_SYNC + return this->then(this->launch_policy(), boost::forward(func)); +#else + typedef typename boost::result_of)>::type future_type; + BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); + + // keep state alive as we move ourself but hold the lock + shared_ptr sentinel(this->future_); + boost::unique_lock lock(sentinel->mutex); + + launch policy = this->launch_policy(lock); + if (underlying_cast(policy) & int(launch::deferred)) { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state, future_type>( + lock, boost::move(*this), boost::forward(func) + ))); + } else { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state, future_type>( + lock, boost::move(*this), boost::forward(func) + ))); + } +#endif + + } + + //////////////////////////////// + // template + // auto future >::then(launch, F&& func) -> BOOST_THREAD_FUTURE; + //////////////////////////////// + template + template + inline BOOST_THREAD_FUTURE >)>::type> + BOOST_THREAD_FUTURE >::then(launch policy, BOOST_THREAD_FWD_REF(F) func) { + typedef BOOST_THREAD_FUTURE R; + typedef typename boost::result_of)>::type future_type; + BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); + + // keep state alive as we move ourself but hold the lock + shared_ptr sentinel(this->future_); + boost::unique_lock lock(sentinel->mutex); + + if (underlying_cast(policy) & int(launch::async)) { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state, future_type>( + lock, boost::move(*this), boost::forward(func) + ))); + } else if (underlying_cast(policy) & int(launch::deferred)) { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state, future_type>( + lock, boost::move(*this), boost::forward(func) + ))); +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + } else if (underlying_cast(policy) & int(launch::executor)) { + assert(this->future_->get_executor()); + typedef executor Ex; + Ex& ex = *(this->future_->get_executor()); + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state, future_type>(ex, + lock, boost::move(*this), boost::forward(func) + ))); +#endif + } else if (underlying_cast(policy) & int(launch::inherit)) { + launch policy = this->launch_policy(lock); + + if (underlying_cast(policy) & int(launch::async)) { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state, future_type>( + lock, boost::move(*this), boost::forward(func) + ))); + } else if (underlying_cast(policy) & int(launch::deferred)) { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state, future_type>( + lock, boost::move(*this), boost::forward(func) + ))); +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + } else if (underlying_cast(policy) & int(launch::executor)) { + assert(this->future_->get_executor()); + typedef executor Ex; + Ex& ex = *(this->future_->get_executor()); + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state, future_type>(ex, + lock, boost::move(*this), boost::forward(func) + ))); +#endif + } else { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state, future_type>( + lock, boost::move(*this), boost::forward(func) + ))); + } + } else { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state, future_type>( + lock, boost::move(*this), boost::forward(func) + ))); + } + } + +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + //////////////////////////////// + // template + // auto future >::then(Ex&, F&& func) -> BOOST_THREAD_FUTURE; + //////////////////////////////// + template + template + inline BOOST_THREAD_FUTURE >)>::type> + BOOST_THREAD_FUTURE >::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) { + typedef BOOST_THREAD_FUTURE R; + typedef typename boost::result_of)>::type future_type; + BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); + + // keep state alive as we move ourself but hold the lock + shared_ptr sentinel(this->future_); + boost::unique_lock lock(sentinel->mutex); + + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_executor_continuation_shared_state, future_type>(ex, + lock, boost::move(*this), boost::forward(func) + ))); + } +#endif + + //////////////////////////////// + // template + // auto future >::then(F&& func) -> BOOST_THREAD_FUTURE; + //////////////////////////////// + template + template + inline BOOST_THREAD_FUTURE >)>::type> + BOOST_THREAD_FUTURE >::then(BOOST_THREAD_FWD_REF(F) func) { + +#ifndef BOOST_THREAD_CONTINUATION_SYNC + return this->then(this->launch_policy(), boost::forward(func)); +#else + typedef BOOST_THREAD_FUTURE R; + typedef typename boost::result_of)>::type future_type; + BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); + + // keep state alive as we move ourself but hold the lock + shared_ptr sentinel(this->future_); + boost::unique_lock lock(sentinel->mutex); + + launch policy = this->launch_policy(lock); + + if (underlying_cast(policy) & int(launch::deferred)) { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_deferred_continuation_shared_state, future_type>( + lock, boost::move(*this), boost::forward(func) + ))); + } else { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_future_async_continuation_shared_state, future_type>( + lock, boost::move(*this), boost::forward(func) + ))); + } +#endif + } + + //////////////////////////////// + // template + // auto shared_future::then(launch policy, F&& func) -> BOOST_THREAD_FUTURE; + //////////////////////////////// + template + template + inline BOOST_THREAD_FUTURE)>::type> + shared_future::then(launch policy, BOOST_THREAD_FWD_REF(F) func) const + { + typedef typename boost::result_of)>::type future_type; + BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); + + boost::unique_lock lock(this->future_->mutex); + if (underlying_cast(policy) & int(launch::async)) { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state, future_type>( + lock, *this, boost::forward(func) + ))); + } else if (underlying_cast(policy) & int(launch::deferred)) { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_deferred_continuation_shared_state, future_type>( + lock, *this, boost::forward(func) + ))); +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + } else if (underlying_cast(policy) & int(launch::executor)) { + typedef executor Ex; + Ex& ex = *(this->future_->get_executor()); + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state, future_type>(ex, + lock, *this, boost::forward(func) + ))); +#endif + } else if (underlying_cast(policy) & int(launch::inherit)) { + + launch policy = this->launch_policy(lock); + if (underlying_cast(policy) & int(launch::async)) { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state, future_type>( + lock, *this, boost::forward(func) + ))); + } else if (underlying_cast(policy) & int(launch::deferred)) { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_deferred_continuation_shared_state, future_type>( + lock, *this, boost::forward(func) + ))); +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + } else if (underlying_cast(policy) & int(launch::executor)) { + typedef executor Ex; + Ex& ex = *(this->future_->get_executor()); + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state, future_type>(ex, + lock, *this, boost::forward(func) + ))); +#endif + } else { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state, future_type>( + lock, *this, boost::forward(func) + ))); + } + + } else { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state, future_type>( + lock, *this, boost::forward(func) + ))); + } + } +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + //////////////////////////////// + // template + // auto shared_future::then(Ex&, F&& func) -> BOOST_THREAD_FUTURE; + //////////////////////////////// + template + template + inline BOOST_THREAD_FUTURE)>::type> + shared_future::then(Ex& ex, BOOST_THREAD_FWD_REF(F) func) const + { + typedef typename boost::result_of)>::type future_type; + BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); + + boost::unique_lock lock(this->future_->mutex); + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_executor_continuation_shared_state, future_type>(ex, + lock, *this, boost::forward(func) + ))); + } +#endif + + //////////////////////////////// + // template + // auto shared_future::then(F&& func) -> BOOST_THREAD_FUTURE; + //////////////////////////////// + template + template + inline BOOST_THREAD_FUTURE)>::type> + shared_future::then(BOOST_THREAD_FWD_REF(F) func) const { +#ifndef BOOST_THREAD_CONTINUATION_SYNC + return this->then(this->launch_policy(), boost::forward(func)); +#else + typedef typename boost::result_of)>::type future_type; + BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); + + boost::unique_lock lock(this->future_->mutex); + launch policy = this->launch_policy(lock); + if (underlying_cast(policy) & int(launch::deferred)) { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_deferred_continuation_shared_state, future_type>( + lock, *this, boost::forward(func) + ))); + } else { + return BOOST_THREAD_MAKE_RV_REF((boost::detail::make_shared_future_async_continuation_shared_state, future_type>( + lock, *this, boost::forward(func) + ))); + } +#endif + } + +namespace detail +{ + template + struct mfallbacker_to + { + T value_; + typedef T result_type; + mfallbacker_to(BOOST_THREAD_RV_REF(T) v) + : value_(boost::move(v)) + {} + + T operator()(BOOST_THREAD_FUTURE fut) { + return fut.get_or(boost::move(value_)); + } + }; + template + struct cfallbacker_to + { + T value_; + typedef T result_type; + cfallbacker_to(T const& v) + : value_(v) + {} + + T operator()(BOOST_THREAD_FUTURE fut) const { + return fut.get_or(value_); + + } + }; +} + //////////////////////////////// + // future future::fallback_to(R&& v); + //////////////////////////////// + + template + template + inline typename boost::disable_if< is_void, BOOST_THREAD_FUTURE >::type + BOOST_THREAD_FUTURE::fallback_to(BOOST_THREAD_RV_REF(R2) v) { + return then(detail::mfallbacker_to(boost::move(v))); + } + + template + template + inline typename boost::disable_if< is_void, BOOST_THREAD_FUTURE >::type + BOOST_THREAD_FUTURE::fallback_to(R2 const& v) { + return then(detail::cfallbacker_to(v)); + } + +#endif + +#if defined BOOST_THREAD_PROVIDES_FUTURE_UNWRAP +namespace detail +{ + ///////////////////////// + /// future_unwrap_shared_state + ///////////////////////// + + template + struct future_unwrap_shared_state: shared_state + { + F wrapped; + typename F::value_type unwrapped; + public: + explicit future_unwrap_shared_state(BOOST_THREAD_RV_REF(F) f) + : wrapped(boost::move(f)) { + } + + void launch_continuation() + { + boost::unique_lock lk(this->mutex); + // assert(wrapped.is_ready()); + if (! unwrapped.valid() ) + { + if (wrapped.has_exception()) { + this->mark_exceptional_finish_internal(wrapped.get_exception_ptr(), lk); + } else { + unwrapped = wrapped.get(); + if (unwrapped.valid()) + { + lk.unlock(); + boost::unique_lock lk2(unwrapped.future_->mutex); + unwrapped.future_->set_continuation_ptr(this->shared_from_this(), lk2); + } else { + this->mark_exceptional_finish_internal(boost::copy_exception(future_uninitialized()), lk); + } + } + } else { + // assert(unwrapped.is_ready()); + if (unwrapped.has_exception()) { + this->mark_exceptional_finish_internal(unwrapped.get_exception_ptr(), lk); + } else { + this->mark_finished_with_result_internal(unwrapped.get(), lk); + } + } + } + }; + + template + struct future_unwrap_shared_state: shared_state + { + F wrapped; + typename F::value_type unwrapped; + public: + explicit future_unwrap_shared_state(BOOST_THREAD_RV_REF(F) f) + : wrapped(boost::move(f)) { + } + + void launch_continuation() + { + boost::unique_lock lk(this->mutex); + // assert(wrapped.is_ready()); + if (! unwrapped.valid() ) + { + if (wrapped.has_exception()) { + this->mark_exceptional_finish_internal(wrapped.get_exception_ptr(), lk); + } else { + unwrapped = wrapped.get(); + if (unwrapped.valid()) + { + lk.unlock(); + boost::unique_lock lk2(unwrapped.future_->mutex); + unwrapped.future_->set_continuation_ptr(this->shared_from_this(), lk2); + } else { + this->mark_exceptional_finish_internal(boost::copy_exception(future_uninitialized()), lk); + } + } + } else { + // assert(unwrapped.is_ready()); + if (unwrapped.has_exception()) { + this->mark_exceptional_finish_internal(unwrapped.get_exception_ptr(), lk); + } else { + this->mark_finished_with_result_internal(lk); + } + } + } + }; + + template + BOOST_THREAD_FUTURE + make_future_unwrap_shared_state(boost::unique_lock &lock, BOOST_THREAD_RV_REF(F) f) { + shared_ptr > + h(new future_unwrap_shared_state(boost::move(f))); + h->wrapped.future_->set_continuation_ptr(h, lock); + + return BOOST_THREAD_FUTURE(h); + } +} + + template + inline BOOST_THREAD_FUTURE::BOOST_THREAD_FUTURE(BOOST_THREAD_RV_REF(BOOST_THREAD_FUTURE >) other) + : base_type(other.unwrap()) {} + + template + BOOST_THREAD_FUTURE + BOOST_THREAD_FUTURE >::unwrap() + { + BOOST_THREAD_ASSERT_PRECONDITION(this->future_!=0, future_uninitialized()); + + // keep state alive as we move ourself but hold the lock + shared_ptr sentinel(this->future_); + boost::unique_lock lock(sentinel->mutex); + + return boost::detail::make_future_unwrap_shared_state >, R2>(lock, boost::move(*this)); + } +#endif + +#if defined BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY +namespace detail +{ + struct input_iterator_tag {}; + struct vector_tag {}; + struct values_tag {}; + template + struct alias_t { typedef T type; }; + + BOOST_CONSTEXPR_OR_CONST input_iterator_tag input_iterator_tag_value = {}; + BOOST_CONSTEXPR_OR_CONST vector_tag vector_tag_value = {}; + BOOST_CONSTEXPR_OR_CONST values_tag values_tag_value = {}; + //////////////////////////////// + // detail::future_async_when_all_shared_state + //////////////////////////////// + template + struct future_when_all_vector_shared_state: future_async_shared_state_base > + { + typedef csbl::vector vector_type; + typedef typename F::value_type value_type; + vector_type vec_; + + static void run(shared_ptr that_) { + future_when_all_vector_shared_state* that = static_cast(that_.get()); + try { + boost::wait_for_all(that->vec_.begin(), that->vec_.end()); + that->mark_finished_with_result(boost::move(that->vec_)); + } catch(...) { + that->mark_exceptional_finish(); + } + } + bool run_deferred() { + + bool res = false; + for (typename csbl::vector::iterator it = vec_.begin(); it != vec_.end(); ++it) { + if (! it->run_if_is_deferred()) + { + res = true; + } + } + return res; + } + void init() { + if (! run_deferred()) + { + future_when_all_vector_shared_state::run(this->shared_from_this()); + return; + } +#ifdef BOOST_THREAD_FUTURE_BLOCKING + this->thr_ = thread(&future_when_all_vector_shared_state::run, this->shared_from_this()); +#else + thread(&future_when_all_vector_shared_state::run, this->shared_from_this()).detach(); +#endif + } + + public: + template< typename InputIterator> + future_when_all_vector_shared_state(input_iterator_tag, InputIterator first, InputIterator last) + : vec_(std::make_move_iterator(first), std::make_move_iterator(last)) + { + } + + future_when_all_vector_shared_state(vector_tag, BOOST_THREAD_RV_REF(csbl::vector) v) + : vec_(boost::move(v)) + { + } + +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template< typename T0, typename ...T> + future_when_all_vector_shared_state(values_tag, BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures) { + vec_.push_back(boost::forward(f)); + typename alias_t::type{ + ( //first part of magic unpacker + vec_.push_back(boost::forward(futures)),'0' + )..., '0' + }; //second part of magic unpacker + } +#endif + + ~future_when_all_vector_shared_state() {} + }; + + //////////////////////////////// + // detail::future_async_when_any_shared_state + //////////////////////////////// + template + struct future_when_any_vector_shared_state: future_async_shared_state_base > + { + typedef csbl::vector vector_type; + typedef typename F::value_type value_type; + vector_type vec_; + + static void run(shared_ptr that_) + { + future_when_any_vector_shared_state* that = static_cast(that_.get()); + try { + boost::wait_for_any(that->vec_.begin(), that->vec_.end()); + that->mark_finished_with_result(boost::move(that->vec_)); + } catch(...) { + that->mark_exceptional_finish(); + } + } + bool run_deferred() { + + for (typename csbl::vector::iterator it = vec_.begin(); it != vec_.end(); ++it) { + if (it->run_if_is_deferred_or_ready()) + { + return true; + } + } + return false; + } + void init() { + if (run_deferred()) + { + future_when_any_vector_shared_state::run(this->shared_from_this()); + return; + } + +#ifdef BOOST_THREAD_FUTURE_BLOCKING + this->thr_ = thread(&future_when_any_vector_shared_state::run, this->shared_from_this()); +#else + thread(&future_when_any_vector_shared_state::run, this->shared_from_this()).detach(); +#endif + } + + public: + template< typename InputIterator> + future_when_any_vector_shared_state(input_iterator_tag, InputIterator first, InputIterator last) + : vec_(std::make_move_iterator(first), std::make_move_iterator(last)) + { + } + + future_when_any_vector_shared_state(vector_tag, BOOST_THREAD_RV_REF(csbl::vector) v) + : vec_(boost::move(v)) + { + } + +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template< typename T0, typename ...T> + future_when_any_vector_shared_state(values_tag, + BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures + ) { + vec_.push_back(boost::forward(f)); + typename alias_t::type{ + ( //first part of magic unpacker + vec_.push_back(boost::forward(futures)) + ,'0' + )..., + '0' + }; //second part of magic unpacker + } +#endif + + ~future_when_any_vector_shared_state() {} + }; + +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + struct wait_for_all_fctr { + template + void operator()(T&&... v) { + boost::wait_for_all(boost::forward(v)...); + } + }; + + struct wait_for_any_fctr { + template + void operator()(T&&... v) { + boost::wait_for_any(boost::forward(v)...); + } + }; + + + template ::value> + struct accumulate_run_if_is_deferred { + bool operator ()(Tuple& t) + { + return (! csbl::get(t).run_if_is_deferred()) || accumulate_run_if_is_deferred()(t); + } + }; + template + struct accumulate_run_if_is_deferred { + bool operator ()(Tuple& ) + { + return false; + } + }; + + + template< typename Tuple, typename T0, typename ...T> + struct future_when_all_tuple_shared_state: future_async_shared_state_base + { + Tuple tup_; + typedef typename make_tuple_indices<1+sizeof...(T)>::type Index; + + static void run(shared_ptr that_) { + future_when_all_tuple_shared_state* that = static_cast(that_.get()); + try { + // TODO make use of apply(that->tup_, boost::detail::wait_for_all_fctor()); + that->wait_for_all(Index()); + + that->mark_finished_with_result(boost::move(that->tup_)); + } catch(...) { + that->mark_exceptional_finish(); + } + } + + template + void wait_for_all(tuple_indices) { +#if defined BOOST_THREAD_PROVIDES_INVOKE + return invoke(wait_for_all_fctr(), csbl::get(tup_)...); +#else + return wait_for_all_fctr()(csbl::get(tup_)...); +#endif + } + + bool run_deferred() { + + return accumulate_run_if_is_deferred()(tup_); + } + void init() { + if (! run_deferred()) + { + future_when_all_tuple_shared_state::run(this->shared_from_this()); + return; + } +#ifdef BOOST_THREAD_FUTURE_BLOCKING + this->thr_ = thread(&future_when_all_tuple_shared_state::run, this->shared_from_this()); +#else + thread(&future_when_all_tuple_shared_state::run, this->shared_from_this()).detach(); +#endif + + } + public: + template< typename F, typename ...Fs> + future_when_all_tuple_shared_state(values_tag, BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Fs) ... futures) : + tup_(boost::csbl::make_tuple(boost::forward(f), boost::forward(futures)...)) + { + } + + ~future_when_all_tuple_shared_state() {} + + }; + + + template ::value> + struct apply_any_run_if_is_deferred_or_ready { + bool operator ()(Tuple& t) + { + if (csbl::get(t).run_if_is_deferred_or_ready()) return true; + return apply_any_run_if_is_deferred_or_ready()(t); + } + }; + template + struct apply_any_run_if_is_deferred_or_ready { + bool operator ()(Tuple& ) + { + return false; + } + }; + + template< typename Tuple, typename T0, typename ...T > + struct future_when_any_tuple_shared_state: future_async_shared_state_base + { + Tuple tup_; + typedef typename make_tuple_indices<1+sizeof...(T)>::type Index; + + static void run(shared_ptr that_) + { + future_when_any_tuple_shared_state* that = static_cast(that_.get()); + try { + // TODO make use of apply(that->tup_, wait_for_any_fctr); + that->wait_for_any(Index()); + + that->mark_finished_with_result(boost::move(that->tup_)); + } catch(...) { + that->mark_exceptional_finish(); + } + } + template + void wait_for_any(tuple_indices) { +#if defined BOOST_THREAD_PROVIDES_INVOKE + return invoke(wait_for_any_fctr(), csbl::get(tup_)...); +#else + return wait_for_any_fctr()(csbl::get(tup_)...); +#endif + } + bool run_deferred() { + return apply_any_run_if_is_deferred_or_ready()(tup_); + } + void init() { + if (run_deferred()) + { + future_when_any_tuple_shared_state::run(this->shared_from_this()); + return; + } + +#ifdef BOOST_THREAD_FUTURE_BLOCKING + this->thr_ = thread(&future_when_any_tuple_shared_state::run, this->shared_from_this()); +#else + thread(&future_when_any_tuple_shared_state::run, this->shared_from_this()).detach(); +#endif + } + + public: + template< typename F, typename ...Fs> + future_when_any_tuple_shared_state(values_tag, + BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Fs) ... futures + ) : + tup_(boost::csbl::make_tuple(boost::forward(f), boost::forward(futures)...)) + { + } + + ~future_when_any_tuple_shared_state() {} + }; +#endif + +} + + template< typename InputIterator> + typename boost::disable_if, + BOOST_THREAD_FUTURE > + >::type + when_all(InputIterator first, InputIterator last) { + typedef typename InputIterator::value_type value_type; + typedef csbl::vector container_type; + typedef detail::future_when_all_vector_shared_state factory_type; + + if (first==last) return make_ready_future(container_type()); + shared_ptr + h(new factory_type(detail::input_iterator_tag_value, first,last)); + h->init(); + return BOOST_THREAD_FUTURE(h); + } + + inline BOOST_THREAD_FUTURE > when_all() { + return make_ready_future(csbl::tuple<>()); + } + +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template< typename T0, typename ...T> + BOOST_THREAD_FUTURE::type, typename decay::type...> > + when_all(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures) { + typedef csbl::tuple::type, typename decay::type...> container_type; + typedef detail::future_when_all_tuple_shared_state::type, typename decay::type...> factory_type; + + shared_ptr + h(new factory_type(detail::values_tag_value, boost::forward(f), boost::forward(futures)...)); + h->init(); + return BOOST_THREAD_FUTURE(h); + } +#endif + + template< typename InputIterator> + typename boost::disable_if, + BOOST_THREAD_FUTURE > + >::type + when_any(InputIterator first, InputIterator last) { + typedef typename InputIterator::value_type value_type; + typedef csbl::vector container_type; + typedef detail::future_when_any_vector_shared_state factory_type; + + if (first==last) return make_ready_future(container_type()); + shared_ptr + h(new factory_type(detail::input_iterator_tag_value, first,last)); + h->init(); + return BOOST_THREAD_FUTURE(h); + } + + inline BOOST_THREAD_FUTURE > when_any() { + return make_ready_future(csbl::tuple<>()); + } + +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template< typename T0, typename ...T> + BOOST_THREAD_FUTURE::type, typename decay::type...> > + when_any(BOOST_THREAD_FWD_REF(T0) f, BOOST_THREAD_FWD_REF(T) ... futures) { + typedef csbl::tuple::type, typename decay::type...> container_type; + typedef detail::future_when_any_tuple_shared_state::type, typename decay::type...> factory_type; + + shared_ptr + h(new factory_type(detail::values_tag_value, boost::forward(f), boost::forward(futures)...)); + h->init(); + return BOOST_THREAD_FUTURE(h); + } +#endif +#endif // BOOST_THREAD_PROVIDES_FUTURE_WHEN_ALL_WHEN_ANY +} + +#endif // BOOST_NO_EXCEPTION +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/futures/future_error.hpp b/src/third_party/boost-1.60.0/boost/thread/futures/future_error.hpp new file mode 100644 index 00000000000..6212deece36 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/futures/future_error.hpp @@ -0,0 +1,98 @@ +// (C) Copyright 2008-10 Anthony Williams +// (C) Copyright 2011-2015 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_THREAD_FUTURES_FUTURE_ERROR_HPP +#define BOOST_THREAD_FUTURES_FUTURE_ERROR_HPP + +#include + +#include +#include + +#include + +namespace boost +{ + class BOOST_SYMBOL_VISIBLE future_error + : public std::logic_error + { + system::error_code ec_; + public: + future_error(system::error_code ec) + : logic_error(ec.message()), + ec_(ec) + { + } + + const system::error_code& code() const BOOST_NOEXCEPT + { + return ec_; + } + }; + + class BOOST_SYMBOL_VISIBLE future_uninitialized: + public future_error + { + public: + future_uninitialized() : + future_error(system::make_error_code(future_errc::no_state)) + {} + }; + class BOOST_SYMBOL_VISIBLE broken_promise: + public future_error + { + public: + broken_promise(): + future_error(system::make_error_code(future_errc::broken_promise)) + {} + }; + class BOOST_SYMBOL_VISIBLE future_already_retrieved: + public future_error + { + public: + future_already_retrieved(): + future_error(system::make_error_code(future_errc::future_already_retrieved)) + {} + }; + class BOOST_SYMBOL_VISIBLE promise_already_satisfied: + public future_error + { + public: + promise_already_satisfied(): + future_error(system::make_error_code(future_errc::promise_already_satisfied)) + {} + }; + + class BOOST_SYMBOL_VISIBLE task_already_started: + public future_error + { + public: + task_already_started(): + future_error(system::make_error_code(future_errc::promise_already_satisfied)) + {} + }; + + class BOOST_SYMBOL_VISIBLE task_moved: + public future_error + { + public: + task_moved(): + future_error(system::make_error_code(future_errc::no_state)) + {} + }; + + class promise_moved: + public future_error + { + public: + promise_moved(): + future_error(system::make_error_code(future_errc::no_state)) + {} + }; +} + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/futures/future_error_code.hpp b/src/third_party/boost-1.60.0/boost/thread/futures/future_error_code.hpp new file mode 100644 index 00000000000..7c8b6f2696a --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/futures/future_error_code.hpp @@ -0,0 +1,61 @@ +// (C) Copyright 2008-10 Anthony Williams +// (C) Copyright 2011-2012,2015 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_THREAD_FUTURES_FUTURE_ERROR_CODE_HPP +#define BOOST_THREAD_FUTURES_FUTURE_ERROR_CODE_HPP + +#include +#include +#include +#include + +namespace boost +{ + + //enum class future_errc + BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_errc) + { + broken_promise = 1, + future_already_retrieved, + promise_already_satisfied, + no_state + } + BOOST_SCOPED_ENUM_DECLARE_END(future_errc) + + namespace system + { + template <> + struct BOOST_SYMBOL_VISIBLE is_error_code_enum< ::boost::future_errc> : public true_type {}; + + #ifdef BOOST_NO_CXX11_SCOPED_ENUMS + template <> + struct BOOST_SYMBOL_VISIBLE is_error_code_enum< ::boost::future_errc::enum_type> : public true_type { }; + #endif + } // system + + BOOST_THREAD_DECL + const system::error_category& future_category() BOOST_NOEXCEPT; + + namespace system + { + inline + error_code + make_error_code(future_errc e) BOOST_NOEXCEPT + { + return error_code(underlying_cast(e), boost::future_category()); + } + + inline + error_condition + make_error_condition(future_errc e) BOOST_NOEXCEPT + { + return error_condition(underlying_cast(e), boost::future_category()); + } + } // system +} // boost + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/futures/future_status.hpp b/src/third_party/boost-1.60.0/boost/thread/futures/future_status.hpp new file mode 100644 index 00000000000..383ac4673cf --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/futures/future_status.hpp @@ -0,0 +1,30 @@ +// (C) Copyright 2008-10 Anthony Williams +// (C) Copyright 2011-2015 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_THREAD_FUTURES_FUTURE_STATUS_HPP +#define BOOST_THREAD_FUTURES_FUTURE_STATUS_HPP + +#include +#include + +namespace boost +{ + //enum class future_status + BOOST_SCOPED_ENUM_DECLARE_BEGIN(future_status) + { + ready, + timeout, + deferred + } + BOOST_SCOPED_ENUM_DECLARE_END(future_status) + namespace future_state + { + enum state { uninitialized, waiting, ready, moved, deferred }; + } +} + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/futures/is_future_type.hpp b/src/third_party/boost-1.60.0/boost/thread/futures/is_future_type.hpp new file mode 100644 index 00000000000..df7a680faae --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/futures/is_future_type.hpp @@ -0,0 +1,21 @@ +// (C) Copyright 2008-10 Anthony Williams +// (C) Copyright 2011-2015 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_THREAD_FUTURES_IS_FUTURE_TYPE_HPP +#define BOOST_THREAD_FUTURES_IS_FUTURE_TYPE_HPP + +#include + +namespace boost +{ + template + struct is_future_type : false_type + { + }; +} + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/futures/launch.hpp b/src/third_party/boost-1.60.0/boost/thread/futures/launch.hpp new file mode 100644 index 00000000000..8eed42cf4d0 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/futures/launch.hpp @@ -0,0 +1,31 @@ +// (C) Copyright 2008-10 Anthony Williams +// (C) Copyright 2011-2015 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_THREAD_FUTURES_LAUNCH_HPP +#define BOOST_THREAD_FUTURES_LAUNCH_HPP + +#include +#include + +namespace boost +{ + //enum class launch + BOOST_SCOPED_ENUM_DECLARE_BEGIN(launch) + { + none = 0, + async = 1, + deferred = 2, +#ifdef BOOST_THREAD_PROVIDES_EXECUTORS + executor = 4, +#endif + inherit = 8, + any = async | deferred + } + BOOST_SCOPED_ENUM_DECLARE_END(launch) +} + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/futures/wait_for_all.hpp b/src/third_party/boost-1.60.0/boost/thread/futures/wait_for_all.hpp new file mode 100644 index 00000000000..90cc2b77cb3 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/futures/wait_for_all.hpp @@ -0,0 +1,74 @@ +// (C) Copyright 2008-10 Anthony Williams +// (C) Copyright 2011-2015 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_THREAD_FUTURES_WAIT_FOR_ALL_HPP +#define BOOST_THREAD_FUTURES_WAIT_FOR_ALL_HPP + +#include +#include + +#include + +namespace boost +{ + template + typename boost::disable_if,void>::type wait_for_all(Iterator begin,Iterator end) + { + for(Iterator current=begin;current!=end;++current) + { + current->wait(); + } + } + +#ifdef BOOST_NO_CXX11_VARIADIC_TEMPLATES + template + typename boost::enable_if,void>::type wait_for_all(F1& f1,F2& f2) + { + f1.wait(); + f2.wait(); + } + + template + void wait_for_all(F1& f1,F2& f2,F3& f3) + { + f1.wait(); + f2.wait(); + f3.wait(); + } + + template + void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4) + { + f1.wait(); + f2.wait(); + f3.wait(); + f4.wait(); + } + + template + void wait_for_all(F1& f1,F2& f2,F3& f3,F4& f4,F5& f5) + { + f1.wait(); + f2.wait(); + f3.wait(); + f4.wait(); + f5.wait(); + } +#else + template + void wait_for_all(F1& f1, Fs&... fs) + { + bool dummy[] = { (f1.wait(), true), (fs.wait(), true)... }; + + // prevent unused parameter warning + (void) dummy; + } +#endif // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)} + +} + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/futures/wait_for_any.hpp b/src/third_party/boost-1.60.0/boost/thread/futures/wait_for_any.hpp new file mode 100644 index 00000000000..b869a4318a8 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/futures/wait_for_any.hpp @@ -0,0 +1,161 @@ +// (C) Copyright 2008-10 Anthony Williams +// (C) Copyright 2011-2015 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_THREAD_FUTURES_WAIT_FOR_ANY_HPP +#define BOOST_THREAD_FUTURES_WAIT_FOR_ANY_HPP + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +namespace boost +{ + namespace detail + { + template + class waiter_for_any_in_seq + { + struct registered_waiter; + typedef std::vector::size_type count_type; + + struct registered_waiter + { + typedef Future future_type; + future_type* future_; + typedef typename Future::notify_when_ready_handle notify_when_ready_handle; + notify_when_ready_handle handle; + count_type index; + + registered_waiter(future_type & a_future, + notify_when_ready_handle handle_, count_type index_) : + future_(&a_future), handle(handle_), index(index_) + { + } + }; + + struct all_futures_lock + { +#ifdef _MANAGED + typedef std::ptrdiff_t count_type_portable; +#else + typedef count_type count_type_portable; +#endif + count_type_portable count; + boost::scoped_array > locks; + + all_futures_lock(std::vector& waiters) : + count(waiters.size()), locks(new boost::unique_lock[count]) + { + for (count_type_portable i = 0; i < count; ++i) + { + locks[i] = BOOST_THREAD_MAKE_RV_REF(boost::unique_lock(waiters[i].future_->mutex())); + } + } + + void lock() + { + boost::lock(locks.get(), locks.get() + count); + } + + void unlock() + { + for (count_type_portable i = 0; i < count; ++i) + { + locks[i].unlock(); + } + } + }; + + boost::condition_variable_any cv; + std::vector waiters_; + count_type future_count; + + public: + waiter_for_any_in_seq() : + future_count(0) + { + } + + template + void add(F& f) + { + if (f.valid()) + { + registered_waiter waiter(f, f.notify_when_ready(cv), future_count); + try + { + waiters_.push_back(waiter); + } + catch (...) + { + f.future_->unnotify_when_ready(waiter.handle); + throw; + } + ++future_count; + } + } + +#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES + template + void add(F1& f1, Fs&... fs) + { + add(f1); + add(fs...); + } +#endif + + count_type wait() + { + all_futures_lock lk(waiters_); + for (;;) + { + for (count_type i = 0; i < waiters_.size(); ++i) + { + if (waiters_[i].future_->is_ready(lk.locks[i])) + { + return waiters_[i].index; + } + } + cv.wait(lk); + } + } + + ~waiter_for_any_in_seq() + { + for (count_type i = 0; i < waiters_.size(); ++i) + { + waiters_[i].future_->unnotify_when_ready(waiters_[i].handle); + } + } + }; + } + + template + typename boost::disable_if , Iterator>::type wait_for_any(Iterator begin, Iterator end) + { + if (begin == end) return end; + + detail::waiter_for_any_in_seq::value_type> waiter; + for (Iterator current = begin; current != end; ++current) + { + waiter.add(*current); + } + return boost::next(begin, waiter.wait()); + } +} + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/is_locked_by_this_thread.hpp b/src/third_party/boost-1.60.0/boost/thread/is_locked_by_this_thread.hpp new file mode 100644 index 00000000000..6344c0ff6dd --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/is_locked_by_this_thread.hpp @@ -0,0 +1,39 @@ +// (C) Copyright 2012 Vicente J. Botet Escriba +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#ifndef BOOST_THREAD_IS_LOCKED_BY_THIS_THREAD_HPP +#define BOOST_THREAD_IS_LOCKED_BY_THIS_THREAD_HPP + +#include + +#include + +namespace boost +{ + template + class testable_mutex; + + /** + * Overloaded function used to check if the mutex is locked when it is testable and do nothing otherwise. + * + * This function is used usually to assert the pre-condition when the function can only be called when the mutex + * must be locked by the current thread. + */ + template + bool is_locked_by_this_thread(testable_mutex const& mtx) + { + return mtx.is_locked_by_this_thread(); + } + template + bool is_locked_by_this_thread(Lockable const&) + { + return true; + } +} + +#include + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/latch.hpp b/src/third_party/boost-1.60.0/boost/thread/latch.hpp new file mode 100644 index 00000000000..dc921e68fe6 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/latch.hpp @@ -0,0 +1,170 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2013 Vicente J. Botet Escriba + +#ifndef BOOST_THREAD_LATCH_HPP +#define BOOST_THREAD_LATCH_HPP + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +namespace boost +{ + class latch + { + /// @Requires: count_ must be greater than 0 + /// Effect: Decrement the count. Unlocks the lock and notify anyone waiting if we reached zero. + /// Returns: true if count_ reached the value 0. + /// @ThreadSafe ensured by the @c lk parameter + bool count_down(unique_lock &) + /// pre_condition (count_ > 0) + { + BOOST_ASSERT(count_ > 0); + if (--count_ == 0) + { + ++generation_; + //lk.unlock(); + cond_.notify_all(); + return true; + } + return false; + } + /// Effect: Decrement the count is > 0. Unlocks the lock notify anyone waiting if we reached zero. + /// Returns: true if count_ is 0. + /// @ThreadSafe ensured by the @c lk parameter + bool try_count_down(unique_lock &lk) + { + if (count_ > 0) + { + return count_down(lk); + } + return true; + } + public: + BOOST_THREAD_NO_COPYABLE( latch) + + /// Constructs a latch with a given count. + latch(std::size_t count) : + count_(count), generation_(0) + { + } + + /// Destructor + /// Precondition: No threads are waiting or invoking count_down on @c *this. + + ~latch() + { + + } + + /// Blocks until the latch has counted down to zero. + void wait() + { + boost::unique_lock lk(mutex_); + if (count_ == 0) return; + std::size_t generation(generation_); + cond_.wait(lk, detail::not_equal(generation, generation_)); + } + + /// @return true if the internal counter is already 0, false otherwise + bool try_wait() + { + boost::unique_lock lk(mutex_); + return (count_ == 0); + } + + /// try to wait for a specified amount of time is elapsed. + /// @return whether there is a timeout or not. + template + cv_status wait_for(const chrono::duration& rel_time) + { + boost::unique_lock lk(mutex_); + if (count_ == 0) return cv_status::no_timeout; + std::size_t generation(generation_); + return cond_.wait_for(lk, rel_time, detail::not_equal(generation, generation_)) + ? cv_status::no_timeout + : cv_status::timeout; + } + + /// try to wait until the specified time_point is reached + /// @return whether there were a timeout or not. + template + cv_status wait_until(const chrono::time_point& abs_time) + { + boost::unique_lock lk(mutex_); + if (count_ == 0) return cv_status::no_timeout; + std::size_t generation(generation_); + return cond_.wait_until(lk, abs_time, detail::not_equal(generation, generation_)) + ? cv_status::no_timeout + : cv_status::timeout; + } + + /// Decrement the count and notify anyone waiting if we reach zero. + /// @Requires count must be greater than 0 + void count_down() + { + boost::unique_lock lk(mutex_); + count_down(lk); + } + /// Effect: Decrement the count if it is > 0 and notify anyone waiting if we reached zero. + /// Returns: true if count_ was 0 or reached 0. + bool try_count_down() + { + boost::unique_lock lk(mutex_); + return try_count_down(lk); + } + void signal() + { + count_down(); + } + + /// Decrement the count and notify anyone waiting if we reach zero. + /// Blocks until the latch has counted down to zero. + /// @Requires count must be greater than 0 + void count_down_and_wait() + { + boost::unique_lock lk(mutex_); + std::size_t generation(generation_); + if (count_down(lk)) + { + return; + } + cond_.wait(lk, detail::not_equal(generation, generation_)); + } + void sync() + { + count_down_and_wait(); + } + + /// Reset the counter + /// #Requires This method may only be invoked when there are no other threads currently inside the count_down_and_wait() method. + void reset(std::size_t count) + { + boost::lock_guard lk(mutex_); + //BOOST_ASSERT(count_ == 0); + count_ = count; + } + + private: + mutex mutex_; + condition_variable cond_; + std::size_t count_; + std::size_t generation_; + }; + +} // namespace boost + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/lock_algorithms.hpp b/src/third_party/boost-1.60.0/boost/thread/lock_algorithms.hpp new file mode 100644 index 00000000000..7a55f92a289 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/lock_algorithms.hpp @@ -0,0 +1,468 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba + +#ifndef BOOST_THREAD_LOCK_ALGORITHMS_HPP +#define BOOST_THREAD_LOCK_ALGORITHMS_HPP + +#include +#include +#include + +#include +#include + +#include + +namespace boost +{ + namespace detail + { + template + unsigned try_lock_internal(MutexType1& m1, MutexType2& m2) + { + boost::unique_lock l1(m1, boost::try_to_lock); + if (!l1) + { + return 1; + } + if (!m2.try_lock()) + { + return 2; + } + l1.release(); + return 0; + } + + template + unsigned try_lock_internal(MutexType1& m1, MutexType2& m2, MutexType3& m3) + { + boost::unique_lock l1(m1, boost::try_to_lock); + if (!l1) + { + return 1; + } + if (unsigned const failed_lock=try_lock_internal(m2,m3)) + { + return failed_lock + 1; + } + l1.release(); + return 0; + } + + template + unsigned try_lock_internal(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4) + { + boost::unique_lock l1(m1, boost::try_to_lock); + if (!l1) + { + return 1; + } + if (unsigned const failed_lock=try_lock_internal(m2,m3,m4)) + { + return failed_lock + 1; + } + l1.release(); + return 0; + } + + template + unsigned try_lock_internal(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4, MutexType5& m5) + { + boost::unique_lock l1(m1, boost::try_to_lock); + if (!l1) + { + return 1; + } + if (unsigned const failed_lock=try_lock_internal(m2,m3,m4,m5)) + { + return failed_lock + 1; + } + l1.release(); + return 0; + } + + template + unsigned lock_helper(MutexType1& m1, MutexType2& m2) + { + boost::unique_lock l1(m1); + if (!m2.try_lock()) + { + return 1; + } + l1.release(); + return 0; + } + + template + unsigned lock_helper(MutexType1& m1, MutexType2& m2, MutexType3& m3) + { + boost::unique_lock l1(m1); + if (unsigned const failed_lock=try_lock_internal(m2,m3)) + { + return failed_lock; + } + l1.release(); + return 0; + } + + template + unsigned lock_helper(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4) + { + boost::unique_lock l1(m1); + if (unsigned const failed_lock=try_lock_internal(m2,m3,m4)) + { + return failed_lock; + } + l1.release(); + return 0; + } + + template + unsigned lock_helper(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4, MutexType5& m5) + { + boost::unique_lock l1(m1); + if (unsigned const failed_lock=try_lock_internal(m2,m3,m4,m5)) + { + return failed_lock; + } + l1.release(); + return 0; + } + } + + namespace detail + { + template + struct is_mutex_type_wrapper + { + }; + + template + void lock_impl(MutexType1& m1, MutexType2& m2, is_mutex_type_wrapper ) + { + unsigned const lock_count = 2; + unsigned lock_first = 0; + for (;;) + { + switch (lock_first) + { + case 0: + lock_first = detail::lock_helper(m1, m2); + if (!lock_first) return; + break; + case 1: + lock_first = detail::lock_helper(m2, m1); + if (!lock_first) return; + lock_first = (lock_first + 1) % lock_count; + break; + } + } + } + + template + void lock_impl(Iterator begin, Iterator end, is_mutex_type_wrapper ); + } + + template + void lock(MutexType1& m1, MutexType2& m2) + { + detail::lock_impl(m1, m2, detail::is_mutex_type_wrapper::value>()); + } + + template + void lock(const MutexType1& m1, MutexType2& m2) + { + detail::lock_impl(m1, m2, detail::is_mutex_type_wrapper::value>()); + } + + template + void lock(MutexType1& m1, const MutexType2& m2) + { + detail::lock_impl(m1, m2, detail::is_mutex_type_wrapper::value>()); + } + + template + void lock(const MutexType1& m1, const MutexType2& m2) + { + detail::lock_impl(m1, m2, detail::is_mutex_type_wrapper::value>()); + } + + template + void lock(MutexType1& m1, MutexType2& m2, MutexType3& m3) + { + unsigned const lock_count = 3; + unsigned lock_first = 0; + for (;;) + { + switch (lock_first) + { + case 0: + lock_first = detail::lock_helper(m1, m2, m3); + if (!lock_first) return; + break; + case 1: + lock_first = detail::lock_helper(m2, m3, m1); + if (!lock_first) return; + lock_first = (lock_first + 1) % lock_count; + break; + case 2: + lock_first = detail::lock_helper(m3, m1, m2); + if (!lock_first) return; + lock_first = (lock_first + 2) % lock_count; + break; + } + } + } + + template + void lock(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4) + { + unsigned const lock_count = 4; + unsigned lock_first = 0; + for (;;) + { + switch (lock_first) + { + case 0: + lock_first = detail::lock_helper(m1, m2, m3, m4); + if (!lock_first) return; + break; + case 1: + lock_first = detail::lock_helper(m2, m3, m4, m1); + if (!lock_first) return; + lock_first = (lock_first + 1) % lock_count; + break; + case 2: + lock_first = detail::lock_helper(m3, m4, m1, m2); + if (!lock_first) return; + lock_first = (lock_first + 2) % lock_count; + break; + case 3: + lock_first = detail::lock_helper(m4, m1, m2, m3); + if (!lock_first) return; + lock_first = (lock_first + 3) % lock_count; + break; + } + } + } + + template + void lock(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4, MutexType5& m5) + { + unsigned const lock_count = 5; + unsigned lock_first = 0; + for (;;) + { + switch (lock_first) + { + case 0: + lock_first = detail::lock_helper(m1, m2, m3, m4, m5); + if (!lock_first) return; + break; + case 1: + lock_first = detail::lock_helper(m2, m3, m4, m5, m1); + if (!lock_first) return; + lock_first = (lock_first + 1) % lock_count; + break; + case 2: + lock_first = detail::lock_helper(m3, m4, m5, m1, m2); + if (!lock_first) return; + lock_first = (lock_first + 2) % lock_count; + break; + case 3: + lock_first = detail::lock_helper(m4, m5, m1, m2, m3); + if (!lock_first) return; + lock_first = (lock_first + 3) % lock_count; + break; + case 4: + lock_first = detail::lock_helper(m5, m1, m2, m3, m4); + if (!lock_first) return; + lock_first = (lock_first + 4) % lock_count; + break; + } + } + } + + namespace detail + { + template ::value> + struct try_lock_impl_return + { + typedef int type; + }; + + template + struct try_lock_impl_return + { + typedef Iterator type; + }; + + template + int try_lock_impl(MutexType1& m1, MutexType2& m2, is_mutex_type_wrapper ) + { + return ((int) detail::try_lock_internal(m1, m2)) - 1; + } + + template + Iterator try_lock_impl(Iterator begin, Iterator end, is_mutex_type_wrapper ); + } + + template + typename detail::try_lock_impl_return::type try_lock(MutexType1& m1, MutexType2& m2) + { + return detail::try_lock_impl(m1, m2, detail::is_mutex_type_wrapper::value>()); + } + + template + typename detail::try_lock_impl_return::type try_lock(const MutexType1& m1, MutexType2& m2) + { + return detail::try_lock_impl(m1, m2, detail::is_mutex_type_wrapper::value>()); + } + + template + typename detail::try_lock_impl_return::type try_lock(MutexType1& m1, const MutexType2& m2) + { + return detail::try_lock_impl(m1, m2, detail::is_mutex_type_wrapper::value>()); + } + + template + typename detail::try_lock_impl_return::type try_lock(const MutexType1& m1, const MutexType2& m2) + { + return detail::try_lock_impl(m1, m2, detail::is_mutex_type_wrapper::value>()); + } + + template + int try_lock(MutexType1& m1, MutexType2& m2, MutexType3& m3) + { + return ((int) detail::try_lock_internal(m1, m2, m3)) - 1; + } + + template + int try_lock(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4) + { + return ((int) detail::try_lock_internal(m1, m2, m3, m4)) - 1; + } + + template + int try_lock(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4, MutexType5& m5) + { + return ((int) detail::try_lock_internal(m1, m2, m3, m4, m5)) - 1; + } + + namespace detail + { + template + struct range_lock_guard + { + Iterator begin; + Iterator end; + + range_lock_guard(Iterator begin_, Iterator end_) : + begin(begin_), end(end_) + { + boost::lock(begin, end); + } + + void release() + { + begin = end; + } + + ~range_lock_guard() + { + for (; begin != end; ++begin) + { + begin->unlock(); + } + } + }; + + template + Iterator try_lock_impl(Iterator begin, Iterator end, is_mutex_type_wrapper ) + + { + if (begin == end) + { + return end; + } + typedef typename std::iterator_traits::value_type lock_type; + unique_lock guard(*begin, try_to_lock); + + if (!guard.owns_lock()) + { + return begin; + } + Iterator const failed = boost::try_lock(++begin, end); + if (failed == end) + { + guard.release(); + } + + return failed; + } + } + + namespace detail + { + template + void lock_impl(Iterator begin, Iterator end, is_mutex_type_wrapper ) + { + typedef typename std::iterator_traits::value_type lock_type; + + if (begin == end) + { + return; + } + bool start_with_begin = true; + Iterator second = begin; + ++second; + Iterator next = second; + + for (;;) + { + unique_lock begin_lock(*begin, defer_lock); + if (start_with_begin) + { + begin_lock.lock(); + Iterator const failed_lock = boost::try_lock(next, end); + if (failed_lock == end) + { + begin_lock.release(); + return; + } + start_with_begin = false; + next = failed_lock; + } + else + { + detail::range_lock_guard guard(next, end); + if (begin_lock.try_lock()) + { + Iterator const failed_lock = boost::try_lock(second, next); + if (failed_lock == next) + { + begin_lock.release(); + guard.release(); + return; + } + start_with_begin = false; + next = failed_lock; + } + else + { + start_with_begin = true; + next = second; + } + } + } + } + + } + +} +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/lock_concepts.hpp b/src/third_party/boost-1.60.0/boost/thread/lock_concepts.hpp new file mode 100644 index 00000000000..d96c3dc1b96 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/lock_concepts.hpp @@ -0,0 +1,197 @@ +// (C) Copyright 2012 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_THREAD_LOCK_CONCEPTS_HPP +#define BOOST_THREAD_LOCK_CONCEPTS_HPP + +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace boost +{ + + /** + * BasicLock object supports the basic features + * required to delimit a critical region + * Supports the basic lock, unlock and try_lock functions and + * defines the lock traits + */ + + template + struct BasicLock + { + typedef typename Lk::mutex_type mutex_type; + void cvt_mutex_ptr(mutex_type*) {} + BOOST_CONCEPT_ASSERT(( BasicLockable )); + + BOOST_CONCEPT_USAGE(BasicLock) + { + const Lk l1(mtx); + Lk l2(mtx, defer_lock); + Lk l3(mtx, adopt_lock); + Lk l4(( Lk())); + Lk l5(( boost::move(l2))); + cvt_mutex_ptr(l1.mutex()); + if (l1.owns_lock()) return; + if (l1) return; + if (!l1) return; + + l2.lock(); + l2.unlock(); + l2.release(); + + } + BasicLock() : + mtx(*static_cast(0)) + {} + private: + BasicLock operator=(BasicLock const&); + mutex_type& mtx; + } + ; + + template + struct Lock + { + BOOST_CONCEPT_ASSERT(( BasicLock )); + typedef typename Lk::mutex_type mutex_type; + BOOST_CONCEPT_ASSERT(( Lockable )); + + BOOST_CONCEPT_USAGE(Lock) + { + Lk l1(mtx, try_to_lock); + if (l1.try_lock()) return; + } + Lock() : + mtx(*static_cast(0)) + {} + private: + Lock operator=(Lock const&); + mutex_type& mtx; + }; + + template + struct TimedLock + { + BOOST_CONCEPT_ASSERT(( Lock )); + typedef typename Lk::mutex_type mutex_type; + BOOST_CONCEPT_ASSERT(( TimedLockable )); + + BOOST_CONCEPT_USAGE(TimedLock) + { + const Lk l1(mtx, t); + Lk l2(mtx, d); + if (l1.try_lock_until(t)) return; + if (l1.try_lock_for(d)) return; + } + TimedLock() : + mtx(*static_cast(0)) + {} + private: + TimedLock operator=(TimedLock const&); + mutex_type& mtx; + boost::chrono::system_clock::time_point t; + boost::chrono::system_clock::duration d; + }; + + template + struct UniqueLock + { + BOOST_CONCEPT_ASSERT(( TimedLock )); + typedef typename Lk::mutex_type mutex_type; + + BOOST_CONCEPT_USAGE(UniqueLock) + { + + } + UniqueLock() : + mtx(*static_cast(0)) + {} + private: + UniqueLock operator=(UniqueLock const&); + mutex_type& mtx; + }; + + template + struct SharedLock + { + BOOST_CONCEPT_ASSERT(( TimedLock )); + typedef typename Lk::mutex_type mutex_type; + + BOOST_CONCEPT_USAGE(SharedLock) + { + } + SharedLock() : + mtx(*static_cast(0)) + {} + private: + SharedLock operator=(SharedLock const&); + mutex_type& mtx; + + }; + + template + struct UpgradeLock + { + BOOST_CONCEPT_ASSERT(( SharedLock )); + typedef typename Lk::mutex_type mutex_type; + + BOOST_CONCEPT_USAGE(UpgradeLock) + { + } + UpgradeLock() : + mtx(*static_cast(0)) + {} + private: + UpgradeLock operator=(UpgradeLock const&); + mutex_type& mtx; + }; + + /** + * An StrictLock is a scoped lock guard ensuring the mutex is locked on the + * scope of the lock, by locking the mutex on construction and unlocking it on + * destruction. + * + * Essentially, a StrictLock's role is only to live on the stack as an + * automatic variable. strict_lock must adhere to a non-copy and non-alias + * policy. StrictLock disables copying by making the copy constructor and the + * assignment operator private. While we're at it, let's disable operator new + * and operator delete; strict locks are not intended to be allocated on the + * heap. StrictLock avoids aliasing by using a slightly less orthodox and + * less well-known technique: disable address taking. + */ + + template + struct StrictLock + { + typedef typename Lk::mutex_type mutex_type; + BOOST_CONCEPT_ASSERT(( BasicLockable )); + BOOST_STATIC_ASSERT(( is_strict_lock::value )); + + BOOST_CONCEPT_USAGE( StrictLock) + { + if (l1.owns_lock(&mtx)) return; + } + StrictLock() : + l1(*static_cast(0)), + mtx(*static_cast(0)) + {} + private: + StrictLock operator=(StrictLock const&); + + Lk const& l1; + mutex_type const& mtx; + + }; + +} +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/lock_factories.hpp b/src/third_party/boost-1.60.0/boost/thread/lock_factories.hpp new file mode 100644 index 00000000000..523b90a5eac --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/lock_factories.hpp @@ -0,0 +1,78 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2012 Vicente J. Botet Escriba + +#ifndef BOOST_THREAD_LOCK_FACTORIES_HPP +#define BOOST_THREAD_LOCK_FACTORIES_HPP + +#include +#include +#if ! defined(BOOST_THREAD_NO_MAKE_UNIQUE_LOCKS) +#include // todo change to once Boost.Tuple or Boost.Fusion provides Move semantics. +#endif +#include + +namespace boost +{ + + template + unique_lock make_unique_lock(Lockable& mtx) + { + return unique_lock (mtx); + } + + template + unique_lock make_unique_lock(Lockable& mtx, adopt_lock_t) + { + return unique_lock (mtx, adopt_lock); + } + + template + unique_lock make_unique_lock(Lockable& mtx, defer_lock_t) + { + return unique_lock (mtx, defer_lock); + } + + template + unique_lock make_unique_lock(Lockable& mtx, try_to_lock_t) + { + return unique_lock (mtx, try_to_lock); + } +#if ! defined(BOOST_THREAD_NO_MAKE_UNIQUE_LOCKS) + +#if ! defined BOOST_NO_CXX11_VARIADIC_TEMPLATES + template + std::tuple ...> make_unique_locks(Lockable& ...mtx) + { + boost::lock(mtx...); + return std::tuple ...>(unique_lock(mtx, adopt_lock)...); + } +#else + template + std::tuple, unique_lock > make_unique_locks(L1& m1, L2& m2) + { + boost::lock(m1, m2); + return std::tuple,unique_lock >( + unique_lock(m1, adopt_lock), + unique_lock(m2, adopt_lock) + ); + } + template + std::tuple, unique_lock, unique_lock > make_unique_locks(L1& m1, L2& m2, L3& m3) + { + boost::lock(m1, m2, m3); + return std::tuple,unique_lock,unique_lock >( + unique_lock(m1, adopt_lock), + unique_lock(m2, adopt_lock), + unique_lock(m3, adopt_lock) + ); + } + +#endif +#endif + +} + +#include +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/lock_guard.hpp b/src/third_party/boost-1.60.0/boost/thread/lock_guard.hpp new file mode 100644 index 00000000000..4c2908af43f --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/lock_guard.hpp @@ -0,0 +1,88 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba + +#ifndef BOOST_THREAD_LOCK_GUARD_HPP +#define BOOST_THREAD_LOCK_GUARD_HPP + +#include +#include +#include +#include +#include +#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS +#include +#include +#endif + +#include + +namespace boost +{ + + template + class lock_guard + { + private: + Mutex& m; + + public: + typedef Mutex mutex_type; + BOOST_THREAD_NO_COPYABLE( lock_guard ) + + explicit lock_guard(Mutex& m_) : + m(m_) + { + m.lock(); + } + + lock_guard(Mutex& m_, adopt_lock_t) : + m(m_) + { +#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS + BOOST_ASSERT(is_locked_by_this_thread(m)); +#endif + } + +#if ! defined BOOST_THREAD_NO_CXX11_HDR_INITIALIZER_LIST + lock_guard(std::initializer_list > l_) : + m(*(const_cast*>(l_.begin())->m)) + { + m.lock(); + } + + lock_guard(std::initializer_list > l_) : + m(*(const_cast*>(l_.begin())->m)) + { +#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS + BOOST_ASSERT(is_locked_by_this_thread(m)); +#endif + } + +#endif + ~lock_guard() + { + m.unlock(); + } + }; + + +#if ! defined BOOST_THREAD_NO_MAKE_LOCK_GUARD + template + lock_guard make_lock_guard(Lockable& mtx) + { + return { thread_detail::lockable_wrapper(mtx) }; + } + template + lock_guard make_lock_guard(Lockable& mtx, adopt_lock_t) + { + return { thread_detail::lockable_adopt_wrapper(mtx) }; + } +#endif +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/lock_options.hpp b/src/third_party/boost-1.60.0/boost/thread/lock_options.hpp new file mode 100644 index 00000000000..68899ca89fe --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/lock_options.hpp @@ -0,0 +1,31 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba + +#ifndef BOOST_THREAD_LOCK_OPTIONS_HPP +#define BOOST_THREAD_LOCK_OPTIONS_HPP + +#include + +namespace boost +{ + struct defer_lock_t + { + }; + struct try_to_lock_t + { + }; + struct adopt_lock_t + { + }; + + BOOST_CONSTEXPR_OR_CONST defer_lock_t defer_lock = {}; + BOOST_CONSTEXPR_OR_CONST try_to_lock_t try_to_lock = {}; + BOOST_CONSTEXPR_OR_CONST adopt_lock_t adopt_lock = {}; + +} +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/lock_traits.hpp b/src/third_party/boost-1.60.0/boost/thread/lock_traits.hpp new file mode 100644 index 00000000000..e45d8229831 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/lock_traits.hpp @@ -0,0 +1,45 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2009-2012 Vicente J. Botet Escriba + +#ifndef BOOST_THREAD_LOCK_TRAITS_HPP +#define BOOST_THREAD_LOCK_TRAITS_HPP + +#include +//#include +//#include +// +//#ifdef BOOST_THREAD_USES_CHRONO +//#include +//#include +//#endif + +#include + +#include + +namespace boost +{ + +/** + * An strict lock is a lock ensuring the mutex is locked on the scope of the lock + * There is no single way to define a strict lock as the strict_lock and + * nesteed_strict_lock shows. So we need a metafunction that states if a + * lock is a strict lock "sur parole". + */ + +template +struct is_strict_lock_sur_parolle : false_type {}; + + +template +struct is_strict_lock_sur_parole : is_strict_lock_sur_parolle {}; + +template +struct is_strict_lock : is_strict_lock_sur_parole {}; + +} +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/lock_types.hpp b/src/third_party/boost-1.60.0/boost/thread/lock_types.hpp new file mode 100644 index 00000000000..2b73edfb02a --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/lock_types.hpp @@ -0,0 +1,1230 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba + +#ifndef BOOST_THREAD_LOCK_TYPES_HPP +#define BOOST_THREAD_LOCK_TYPES_HPP + +#include +#include +#include +#include +#include +#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS +#include +#endif +#include + +#include +#ifdef BOOST_THREAD_USES_CHRONO +#include +#include +#endif +#include + +#include + +namespace boost +{ + struct xtime; + + template + class shared_lock; + + template + class upgrade_lock; + + template + class unique_lock; + + namespace detail + { + template + class try_lock_wrapper; + } + +#ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES + namespace sync + { + template + struct is_basic_lockable > + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + template + struct is_lockable > + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + + template + struct is_basic_lockable > + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + template + struct is_lockable > + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + + template + struct is_basic_lockable > + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + template + struct is_lockable > + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + + template + struct is_basic_lockable > + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + template + struct is_lockable > + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + } +#endif + + + template + class unique_lock + { + private: + Mutex* m; + bool is_locked; + + private: + explicit unique_lock(upgrade_lock&); + unique_lock& operator=(upgrade_lock& other); + public: + typedef Mutex mutex_type; + BOOST_THREAD_MOVABLE_ONLY( unique_lock) + +#if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF. +#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) + unique_lock(const volatile unique_lock&); +#endif +#endif + unique_lock()BOOST_NOEXCEPT : + m(0),is_locked(false) + {} + + explicit unique_lock(Mutex& m_) : + m(&m_), is_locked(false) + { + lock(); + } + unique_lock(Mutex& m_, adopt_lock_t) : + m(&m_), is_locked(true) + { +#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS + BOOST_ASSERT(is_locked_by_this_thread(m)); +#endif + } + unique_lock(Mutex& m_, defer_lock_t)BOOST_NOEXCEPT: + m(&m_),is_locked(false) + {} + unique_lock(Mutex& m_, try_to_lock_t) : + m(&m_), is_locked(false) + { + try_lock(); + } +#if defined BOOST_THREAD_USES_DATETIME + template + unique_lock(Mutex& m_,TimeDuration const& target_time): + m(&m_),is_locked(false) + { + timed_lock(target_time); + } + unique_lock(Mutex& m_,system_time const& target_time): + m(&m_),is_locked(false) + { + timed_lock(target_time); + } +#endif +#ifdef BOOST_THREAD_USES_CHRONO + template + unique_lock(Mutex& mtx, const chrono::time_point& t) + : m(&mtx), is_locked(mtx.try_lock_until(t)) + { + } + template + unique_lock(Mutex& mtx, const chrono::duration& d) + : m(&mtx), is_locked(mtx.try_lock_for(d)) + { + } +#endif + + unique_lock(BOOST_THREAD_RV_REF(unique_lock) other) BOOST_NOEXCEPT: + m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked) + { + BOOST_THREAD_RV(other).is_locked=false; + BOOST_THREAD_RV(other).m=0; + } + + BOOST_THREAD_EXPLICIT_LOCK_CONVERSION unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock BOOST_THREAD_RV_REF_END other); + +#ifndef BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION + //std-2104 unique_lock move-assignment should not be noexcept + unique_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_lock BOOST_THREAD_RV_REF_END other) //BOOST_NOEXCEPT + { + unique_lock temp(::boost::move(other)); + swap(temp); + return *this; + } +#endif + + //std-2104 unique_lock move-assignment should not be noexcept + unique_lock& operator=(BOOST_THREAD_RV_REF(unique_lock) other) //BOOST_NOEXCEPT + { + unique_lock temp(::boost::move(other)); + swap(temp); + return *this; + } +#if 0 // This should not be needed anymore. Use instead BOOST_THREAD_MAKE_RV_REF. +#if BOOST_WORKAROUND(__SUNPRO_CC, < 0x5100) + unique_lock& operator=(unique_lock other) + { + swap(other); + return *this; + } +#endif // BOOST_WORKAROUND +#endif + + // Conversion from upgrade locking + unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock BOOST_THREAD_RV_REF_END ul, try_to_lock_t) + : m(0),is_locked(false) + { + if (BOOST_THREAD_RV(ul).owns_lock()) + { + if (BOOST_THREAD_RV(ul).mutex()->try_unlock_upgrade_and_lock()) + { + m = BOOST_THREAD_RV(ul).release(); + is_locked = true; + } + } + else + { + m = BOOST_THREAD_RV(ul).release(); + } + } + +#ifdef BOOST_THREAD_USES_CHRONO + template + unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock BOOST_THREAD_RV_REF_END ul, + const chrono::time_point& abs_time) + : m(0),is_locked(false) + { + if (BOOST_THREAD_RV(ul).owns_lock()) + { + if (BOOST_THREAD_RV(ul).mutex()->try_unlock_upgrade_and_lock_until(abs_time)) + { + m = BOOST_THREAD_RV(ul).release(); + is_locked = true; + } + } + else + { + m = BOOST_THREAD_RV(ul).release(); + } + } + + template + unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock BOOST_THREAD_RV_REF_END ul, + const chrono::duration& rel_time) + : m(0),is_locked(false) + { + if (BOOST_THREAD_RV(ul).owns_lock()) + { + if (BOOST_THREAD_RV(ul).mutex()->try_unlock_upgrade_and_lock_for(rel_time)) + { + m = BOOST_THREAD_RV(ul).release(); + is_locked = true; + } + } + else + { + m = BOOST_THREAD_RV(ul).release(); + } + } +#endif + +#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS + // Conversion from shared locking + unique_lock(BOOST_THREAD_RV_REF_BEG shared_lock BOOST_THREAD_RV_REF_END sl, try_to_lock_t) + : m(0),is_locked(false) + { + if (BOOST_THREAD_RV(sl).owns_lock()) + { + if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock()) + { + m = BOOST_THREAD_RV(sl).release(); + is_locked = true; + } + } + else + { + m = BOOST_THREAD_RV(sl).release(); + } + } + +#ifdef BOOST_THREAD_USES_CHRONO + template + unique_lock(BOOST_THREAD_RV_REF_BEG shared_lock BOOST_THREAD_RV_REF_END sl, + const chrono::time_point& abs_time) + : m(0),is_locked(false) + { + if (BOOST_THREAD_RV(sl).owns_lock()) + { + if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_until(abs_time)) + { + m = BOOST_THREAD_RV(sl).release(); + is_locked = true; + } + } + else + { + m = BOOST_THREAD_RV(sl).release(); + } + } + + template + unique_lock(BOOST_THREAD_RV_REF_BEG shared_lock BOOST_THREAD_RV_REF_END sl, + const chrono::duration& rel_time) + : m(0),is_locked(false) + { + if (BOOST_THREAD_RV(sl).owns_lock()) + { + if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_for(rel_time)) + { + m = BOOST_THREAD_RV(sl).release(); + is_locked = true; + } + } + else + { + m = BOOST_THREAD_RV(sl).release(); + } + } +#endif // BOOST_THREAD_USES_CHRONO +#endif // BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS + + void swap(unique_lock& other)BOOST_NOEXCEPT + { + std::swap(m,other.m); + std::swap(is_locked,other.is_locked); + } + + ~unique_lock() + { + if (owns_lock()) + { + m->unlock(); + } + } + void lock() + { + if (m == 0) + { + boost::throw_exception( + boost::lock_error(static_cast(system::errc::operation_not_permitted), "boost unique_lock has no mutex")); + } + if (owns_lock()) + { + boost::throw_exception( + boost::lock_error(static_cast(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex")); + } + m->lock(); + is_locked = true; + } + bool try_lock() + { + if (m == 0) + { + boost::throw_exception( + boost::lock_error(static_cast(system::errc::operation_not_permitted), "boost unique_lock has no mutex")); + } + if (owns_lock()) + { + boost::throw_exception( + boost::lock_error(static_cast(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex")); + } + is_locked = m->try_lock(); + return is_locked; + } +#if defined BOOST_THREAD_USES_DATETIME + template + bool timed_lock(TimeDuration const& relative_time) + { + if(m==0) + { + boost::throw_exception(boost::lock_error(static_cast(system::errc::operation_not_permitted), "boost unique_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(static_cast(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex")); + } + is_locked=m->timed_lock(relative_time); + return is_locked; + } + + bool timed_lock(::boost::system_time const& absolute_time) + { + if(m==0) + { + boost::throw_exception(boost::lock_error(static_cast(system::errc::operation_not_permitted), "boost unique_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(static_cast(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex")); + } + is_locked=m->timed_lock(absolute_time); + return is_locked; + } + bool timed_lock(::boost::xtime const& absolute_time) + { + if(m==0) + { + boost::throw_exception(boost::lock_error(static_cast(system::errc::operation_not_permitted), "boost unique_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(static_cast(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex")); + } + is_locked=m->timed_lock(absolute_time); + return is_locked; + } +#endif +#ifdef BOOST_THREAD_USES_CHRONO + + template + bool try_lock_for(const chrono::duration& rel_time) + { + if(m==0) + { + boost::throw_exception(boost::lock_error(static_cast(system::errc::operation_not_permitted), "boost unique_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(static_cast(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex")); + } + is_locked=m->try_lock_for(rel_time); + return is_locked; + } + template + bool try_lock_until(const chrono::time_point& abs_time) + { + if(m==0) + { + boost::throw_exception(boost::lock_error(static_cast(system::errc::operation_not_permitted), "boost unique_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(static_cast(system::errc::resource_deadlock_would_occur), "boost unique_lock owns already the mutex")); + } + is_locked=m->try_lock_until(abs_time); + return is_locked; + } +#endif + + void unlock() + { + if (m == 0) + { + boost::throw_exception( + boost::lock_error(static_cast(system::errc::operation_not_permitted), "boost unique_lock has no mutex")); + } + if (!owns_lock()) + { + boost::throw_exception( + boost::lock_error(static_cast(system::errc::operation_not_permitted), "boost unique_lock doesn't own the mutex")); + } + m->unlock(); + is_locked = false; + } + +#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) + typedef void (unique_lock::*bool_type)(); + operator bool_type() const BOOST_NOEXCEPT + { + return is_locked?&unique_lock::lock:0; + } + bool operator!() const BOOST_NOEXCEPT + { + return !owns_lock(); + } +#else + explicit operator bool() const BOOST_NOEXCEPT + { + return owns_lock(); + } +#endif + bool owns_lock() const BOOST_NOEXCEPT + { + return is_locked; + } + + Mutex* mutex() const BOOST_NOEXCEPT + { + return m; + } + + Mutex* release()BOOST_NOEXCEPT + { + Mutex* const res=m; + m=0; + is_locked=false; + return res; + } + + friend class shared_lock ; + friend class upgrade_lock ; + }; + + template + void swap(unique_lock& lhs, unique_lock& rhs) + BOOST_NOEXCEPT + { + lhs.swap(rhs); + } + + BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) unique_lock BOOST_THREAD_DCL_MOVABLE_END + + template + class shared_lock + { + protected: + Mutex* m; + bool is_locked; + + public: + typedef Mutex mutex_type; + BOOST_THREAD_MOVABLE_ONLY(shared_lock) + + shared_lock() BOOST_NOEXCEPT: + m(0),is_locked(false) + {} + + explicit shared_lock(Mutex& m_): + m(&m_),is_locked(false) + { + lock(); + } + shared_lock(Mutex& m_,adopt_lock_t): + m(&m_),is_locked(true) + { +#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS + BOOST_ASSERT(is_locked_by_this_thread(m)); +#endif + } + shared_lock(Mutex& m_,defer_lock_t) BOOST_NOEXCEPT: + m(&m_),is_locked(false) + {} + shared_lock(Mutex& m_,try_to_lock_t): + m(&m_),is_locked(false) + { + try_lock(); + } +#if defined BOOST_THREAD_USES_DATETIME + shared_lock(Mutex& m_,system_time const& target_time): + m(&m_),is_locked(false) + { + timed_lock(target_time); + } +#endif +#ifdef BOOST_THREAD_USES_CHRONO + template + shared_lock(Mutex& mtx, const chrono::time_point& t) + : m(&mtx), is_locked(mtx.try_lock_shared_until(t)) + { + } + template + shared_lock(Mutex& mtx, const chrono::duration& d) + : m(&mtx), is_locked(mtx.try_lock_shared_for(d)) + { + } +#endif + + shared_lock(BOOST_THREAD_RV_REF_BEG shared_lock BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT: + m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked) + { + BOOST_THREAD_RV(other).is_locked=false; + BOOST_THREAD_RV(other).m=0; + } + + BOOST_THREAD_EXPLICIT_LOCK_CONVERSION shared_lock(BOOST_THREAD_RV_REF_BEG unique_lock BOOST_THREAD_RV_REF_END other): + m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked) + { + if(is_locked) + { + m->unlock_and_lock_shared(); + } + BOOST_THREAD_RV(other).is_locked=false; + BOOST_THREAD_RV(other).m=0; + } + + BOOST_THREAD_EXPLICIT_LOCK_CONVERSION shared_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock BOOST_THREAD_RV_REF_END other): + m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked) + { + if(is_locked) + { + m->unlock_upgrade_and_lock_shared(); + } + BOOST_THREAD_RV(other).is_locked=false; + BOOST_THREAD_RV(other).m=0; + } + + //std-2104 unique_lock move-assignment should not be noexcept + shared_lock& operator=(BOOST_THREAD_RV_REF_BEG shared_lock BOOST_THREAD_RV_REF_END other) //BOOST_NOEXCEPT + { + shared_lock temp(::boost::move(other)); + swap(temp); + return *this; + } +#ifndef BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION + shared_lock& operator=(BOOST_THREAD_RV_REF_BEG unique_lock BOOST_THREAD_RV_REF_END other) + { + shared_lock temp(::boost::move(other)); + swap(temp); + return *this; + } + + shared_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_lock BOOST_THREAD_RV_REF_END other) + { + shared_lock temp(::boost::move(other)); + swap(temp); + return *this; + } +#endif + + void swap(shared_lock& other) BOOST_NOEXCEPT + { + std::swap(m,other.m); + std::swap(is_locked,other.is_locked); + } + + Mutex* mutex() const BOOST_NOEXCEPT + { + return m; + } + + Mutex* release() BOOST_NOEXCEPT + { + Mutex* const res=m; + m=0; + is_locked=false; + return res; + } + + ~shared_lock() + { + if(owns_lock()) + { + m->unlock_shared(); + } + } + void lock() + { + if(m==0) + { + boost::throw_exception(boost::lock_error(static_cast(system::errc::operation_not_permitted), "boost shared_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(static_cast(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex")); + } + m->lock_shared(); + is_locked=true; + } + bool try_lock() + { + if(m==0) + { + boost::throw_exception(boost::lock_error(static_cast(system::errc::operation_not_permitted), "boost shared_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(static_cast(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex")); + } + is_locked=m->try_lock_shared(); + return is_locked; + } +#if defined BOOST_THREAD_USES_DATETIME + bool timed_lock(boost::system_time const& target_time) + { + if(m==0) + { + boost::throw_exception(boost::lock_error(static_cast(system::errc::operation_not_permitted), "boost shared_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(static_cast(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex")); + } + is_locked=m->timed_lock_shared(target_time); + return is_locked; + } + template + bool timed_lock(Duration const& target_time) + { + if(m==0) + { + boost::throw_exception(boost::lock_error(static_cast(system::errc::operation_not_permitted), "boost shared_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(static_cast(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex")); + } + is_locked=m->timed_lock_shared(target_time); + return is_locked; + } +#endif +#ifdef BOOST_THREAD_USES_CHRONO + template + bool try_lock_for(const chrono::duration& rel_time) + { + if(m==0) + { + boost::throw_exception(boost::lock_error(static_cast(system::errc::operation_not_permitted), "boost shared_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(static_cast(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex")); + } + is_locked=m->try_lock_shared_for(rel_time); + return is_locked; + } + template + bool try_lock_until(const chrono::time_point& abs_time) + { + if(m==0) + { + boost::throw_exception(boost::lock_error(static_cast(system::errc::operation_not_permitted), "boost shared_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(static_cast(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex")); + } + is_locked=m->try_lock_shared_until(abs_time); + return is_locked; + } +#endif + void unlock() + { + if(m==0) + { + boost::throw_exception(boost::lock_error(static_cast(system::errc::operation_not_permitted), "boost shared_lock has no mutex")); + } + if(!owns_lock()) + { + boost::throw_exception(boost::lock_error(static_cast(system::errc::operation_not_permitted), "boost shared_lock doesn't own the mutex")); + } + m->unlock_shared(); + is_locked=false; + } + +#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) + typedef void (shared_lock::*bool_type)(); + operator bool_type() const BOOST_NOEXCEPT + { + return is_locked?&shared_lock::lock:0; + } + bool operator!() const BOOST_NOEXCEPT + { + return !owns_lock(); + } +#else + explicit operator bool() const BOOST_NOEXCEPT + { + return owns_lock(); + } +#endif + bool owns_lock() const BOOST_NOEXCEPT + { + return is_locked; + } + + }; + + BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) shared_lock BOOST_THREAD_DCL_MOVABLE_END + + template + void swap(shared_lock& lhs,shared_lock& rhs) BOOST_NOEXCEPT + { + lhs.swap(rhs); + } + + template + class upgrade_lock + { + protected: + Mutex* m; + bool is_locked; + + public: + typedef Mutex mutex_type; + BOOST_THREAD_MOVABLE_ONLY( upgrade_lock) + + upgrade_lock()BOOST_NOEXCEPT: + m(0),is_locked(false) + {} + + explicit upgrade_lock(Mutex& m_) : + m(&m_), is_locked(false) + { + lock(); + } + upgrade_lock(Mutex& m_, adopt_lock_t) : + m(&m_), is_locked(true) + { +#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS + BOOST_ASSERT(is_locked_by_this_thread(m)); +#endif + } + upgrade_lock(Mutex& m_, defer_lock_t)BOOST_NOEXCEPT: + m(&m_),is_locked(false) + {} + upgrade_lock(Mutex& m_, try_to_lock_t) : + m(&m_), is_locked(false) + { + try_lock(); + } + +#ifdef BOOST_THREAD_USES_CHRONO + template + upgrade_lock(Mutex& mtx, const chrono::time_point& t) + : m(&mtx), is_locked(mtx.try_lock_upgrade_until(t)) + { + } + template + upgrade_lock(Mutex& mtx, const chrono::duration& d) + : m(&mtx), is_locked(mtx.try_lock_upgrade_for(d)) + { + } +#endif + + upgrade_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT: + m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked) + { + BOOST_THREAD_RV(other).is_locked=false; + BOOST_THREAD_RV(other).m=0; + } + + BOOST_THREAD_EXPLICIT_LOCK_CONVERSION upgrade_lock(BOOST_THREAD_RV_REF_BEG unique_lock BOOST_THREAD_RV_REF_END other): + m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked) + { + if(is_locked) + { + m->unlock_and_lock_upgrade(); + } + BOOST_THREAD_RV(other).is_locked=false; + BOOST_THREAD_RV(other).m=0; + } + + //std-2104 unique_lock move-assignment should not be noexcept + upgrade_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_lock BOOST_THREAD_RV_REF_END other) //BOOST_NOEXCEPT + { + upgrade_lock temp(::boost::move(other)); + swap(temp); + return *this; + } + +#ifndef BOOST_THREAD_PROVIDES_EXPLICIT_LOCK_CONVERSION + upgrade_lock& operator=(BOOST_THREAD_RV_REF_BEG unique_lock BOOST_THREAD_RV_REF_END other) + { + upgrade_lock temp(::boost::move(other)); + swap(temp); + return *this; + } +#endif + +#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS + // Conversion from shared locking + upgrade_lock(BOOST_THREAD_RV_REF_BEG shared_lock BOOST_THREAD_RV_REF_END sl, try_to_lock_t) + : m(0),is_locked(false) + { + if (BOOST_THREAD_RV(sl).owns_lock()) + { + if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_upgrade()) + { + m = BOOST_THREAD_RV(sl).release(); + is_locked = true; + } + } + else + { + m = BOOST_THREAD_RV(sl).release(); + } + } + +#ifdef BOOST_THREAD_USES_CHRONO + template + upgrade_lock(BOOST_THREAD_RV_REF_BEG shared_lock BOOST_THREAD_RV_REF_END sl, + const chrono::time_point& abs_time) + : m(0),is_locked(false) + { + if (BOOST_THREAD_RV(sl).owns_lock()) + { + if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_upgrade_until(abs_time)) + { + m = BOOST_THREAD_RV(sl).release(); + is_locked = true; + } + } + else + { + m = BOOST_THREAD_RV(sl).release(); + } + } + + template + upgrade_lock(BOOST_THREAD_RV_REF_BEG shared_lock BOOST_THREAD_RV_REF_END sl, + const chrono::duration& rel_time) + : m(0),is_locked(false) + { + if (BOOST_THREAD_RV(sl).owns_lock()) + { + if (BOOST_THREAD_RV(sl).mutex()->try_unlock_shared_and_lock_upgrade_for(rel_time)) + { + m = BOOST_THREAD_RV(sl).release(); + is_locked = true; + } + } + else + { + m = BOOST_THREAD_RV(sl).release(); + } + } +#endif // BOOST_THREAD_USES_CHRONO +#endif // BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS + void swap(upgrade_lock& other)BOOST_NOEXCEPT + { + std::swap(m,other.m); + std::swap(is_locked,other.is_locked); + } + Mutex* mutex() const BOOST_NOEXCEPT + { + return m; + } + + Mutex* release()BOOST_NOEXCEPT + { + Mutex* const res=m; + m=0; + is_locked=false; + return res; + } + ~upgrade_lock() + { + if (owns_lock()) + { + m->unlock_upgrade(); + } + } + void lock() + { + if (m == 0) + { + boost::throw_exception( + boost::lock_error(static_cast(system::errc::operation_not_permitted), "boost shared_lock has no mutex")); + } + if (owns_lock()) + { + boost::throw_exception( + boost::lock_error(static_cast(system::errc::resource_deadlock_would_occur), "boost upgrade_lock owns already the mutex")); + } + m->lock_upgrade(); + is_locked = true; + } + bool try_lock() + { + if (m == 0) + { + boost::throw_exception( + boost::lock_error(static_cast(system::errc::operation_not_permitted), "boost shared_lock has no mutex")); + } + if (owns_lock()) + { + boost::throw_exception( + boost::lock_error(static_cast(system::errc::resource_deadlock_would_occur), "boost upgrade_lock owns already the mutex")); + } + is_locked = m->try_lock_upgrade(); + return is_locked; + } + void unlock() + { + if (m == 0) + { + boost::throw_exception( + boost::lock_error(static_cast(system::errc::operation_not_permitted), "boost shared_lock has no mutex")); + } + if (!owns_lock()) + { + boost::throw_exception( + boost::lock_error(static_cast(system::errc::operation_not_permitted), "boost upgrade_lock doesn't own the mutex")); + } + m->unlock_upgrade(); + is_locked = false; + } +#ifdef BOOST_THREAD_USES_CHRONO + template + bool try_lock_for(const chrono::duration& rel_time) + { + if(m==0) + { + boost::throw_exception(boost::lock_error(static_cast(system::errc::operation_not_permitted), "boost shared_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(static_cast(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex")); + } + is_locked=m->try_lock_upgrade_for(rel_time); + return is_locked; + } + template + bool try_lock_until(const chrono::time_point& abs_time) + { + if(m==0) + { + boost::throw_exception(boost::lock_error(static_cast(system::errc::operation_not_permitted), "boost shared_lock has no mutex")); + } + if(owns_lock()) + { + boost::throw_exception(boost::lock_error(static_cast(system::errc::resource_deadlock_would_occur), "boost shared_lock owns already the mutex")); + } + is_locked=m->try_lock_upgrade_until(abs_time); + return is_locked; + } +#endif +#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) + typedef void (upgrade_lock::*bool_type)(); + operator bool_type() const BOOST_NOEXCEPT + { + return is_locked?&upgrade_lock::lock:0; + } + bool operator!() const BOOST_NOEXCEPT + { + return !owns_lock(); + } +#else + explicit operator bool() const BOOST_NOEXCEPT + { + return owns_lock(); + } +#endif + bool owns_lock() const BOOST_NOEXCEPT + { + return is_locked; + } + friend class shared_lock ; + friend class unique_lock ; + }; + + template + void swap(upgrade_lock& lhs, upgrade_lock& rhs) + BOOST_NOEXCEPT + { + lhs.swap(rhs); + } + + BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) upgrade_lock BOOST_THREAD_DCL_MOVABLE_END + + template + unique_lock::unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_lock BOOST_THREAD_RV_REF_END other): + m(BOOST_THREAD_RV(other).m),is_locked(BOOST_THREAD_RV(other).is_locked) + { + if(is_locked) + { + m->unlock_upgrade_and_lock(); + } + BOOST_THREAD_RV(other).release(); + } + + template + class upgrade_to_unique_lock + { + private: + upgrade_lock* source; + unique_lock exclusive; + + public: + typedef Mutex mutex_type; + BOOST_THREAD_MOVABLE_ONLY( upgrade_to_unique_lock) + + explicit upgrade_to_unique_lock(upgrade_lock& m_) : + source(&m_), exclusive(::boost::move(*source)) + { + } + ~upgrade_to_unique_lock() + { + if (source) + { + *source = BOOST_THREAD_MAKE_RV_REF(upgrade_lock (::boost::move(exclusive))); + } + } + + upgrade_to_unique_lock(BOOST_THREAD_RV_REF_BEG upgrade_to_unique_lock BOOST_THREAD_RV_REF_END other) BOOST_NOEXCEPT: + source(BOOST_THREAD_RV(other).source),exclusive(::boost::move(BOOST_THREAD_RV(other).exclusive)) + { + BOOST_THREAD_RV(other).source=0; + } + + //std-2104 unique_lock move-assignment should not be noexcept + upgrade_to_unique_lock& operator=(BOOST_THREAD_RV_REF_BEG upgrade_to_unique_lock BOOST_THREAD_RV_REF_END other) //BOOST_NOEXCEPT + { + upgrade_to_unique_lock temp(other); + swap(temp); + return *this; + } + + void swap(upgrade_to_unique_lock& other)BOOST_NOEXCEPT + { + std::swap(source,other.source); + exclusive.swap(other.exclusive); + } + +#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) + typedef void (upgrade_to_unique_lock::*bool_type)(upgrade_to_unique_lock&); + operator bool_type() const BOOST_NOEXCEPT + { + return exclusive.owns_lock()?&upgrade_to_unique_lock::swap:0; + } + bool operator!() const BOOST_NOEXCEPT + { + return !owns_lock(); + } +#else + explicit operator bool() const BOOST_NOEXCEPT + { + return owns_lock(); + } +#endif + + bool owns_lock() const BOOST_NOEXCEPT + { + return exclusive.owns_lock(); + } + Mutex* mutex() const BOOST_NOEXCEPT + { + return exclusive.mutex(); + } + }; + +BOOST_THREAD_DCL_MOVABLE_BEG(Mutex) upgrade_to_unique_lock BOOST_THREAD_DCL_MOVABLE_END + +namespace detail +{ + template + class try_lock_wrapper: +private unique_lock + { + typedef unique_lock base; + public: + BOOST_THREAD_MOVABLE_ONLY(try_lock_wrapper) + + try_lock_wrapper() + {} + + explicit try_lock_wrapper(Mutex& m): + base(m,try_to_lock) + {} + + try_lock_wrapper(Mutex& m_,adopt_lock_t): + base(m_,adopt_lock) + { +#if ! defined BOOST_THREAD_PROVIDES_NESTED_LOCKS + BOOST_ASSERT(is_locked_by_this_thread(m_)); +#endif + } + try_lock_wrapper(Mutex& m_,defer_lock_t): + base(m_,defer_lock) + {} + try_lock_wrapper(Mutex& m_,try_to_lock_t): + base(m_,try_to_lock) + {} +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + try_lock_wrapper(BOOST_THREAD_RV_REF(try_lock_wrapper) other): + base(::boost::move(other)) + {} + +#elif defined BOOST_THREAD_USES_MOVE + try_lock_wrapper(BOOST_THREAD_RV_REF(try_lock_wrapper) other): + base(::boost::move(static_cast(other))) + {} + +#else + try_lock_wrapper(BOOST_THREAD_RV_REF(try_lock_wrapper) other): + base(BOOST_THREAD_RV_REF(base)(*other)) + {} +#endif + try_lock_wrapper& operator=(BOOST_THREAD_RV_REF_BEG try_lock_wrapper BOOST_THREAD_RV_REF_END other) + { + try_lock_wrapper temp(other); + swap(temp); + return *this; + } + void swap(try_lock_wrapper& other) + { + base::swap(other); + } + void lock() + { + base::lock(); + } + bool try_lock() + { + return base::try_lock(); + } + void unlock() + { + base::unlock(); + } + bool owns_lock() const + { + return base::owns_lock(); + } + Mutex* mutex() const BOOST_NOEXCEPT + { + return base::mutex(); + } + Mutex* release() + { + return base::release(); + } + +#if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) + typedef typename base::bool_type bool_type; + operator bool_type() const + { + return base::operator bool_type(); + } + bool operator!() const + { + return !this->owns_lock(); + } +#else + explicit operator bool() const + { + return owns_lock(); + } +#endif + }; + + template + void swap(try_lock_wrapper& lhs,try_lock_wrapper& rhs) + { + lhs.swap(rhs); + } +} +} +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/lockable_adapter.hpp b/src/third_party/boost-1.60.0/boost/thread/lockable_adapter.hpp new file mode 100644 index 00000000000..93d9ba5023c --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/lockable_adapter.hpp @@ -0,0 +1,226 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Vicente J. Botet Escriba 2008-2009,2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_THREAD_LOCKABLE_ADAPTER_HPP +#define BOOST_THREAD_LOCKABLE_ADAPTER_HPP + +#include +#include + +namespace boost +{ + + //[basic_lockable_adapter + template + class basic_lockable_adapter + { + public: + typedef BasicLockable mutex_type; + + protected: + mutex_type& lockable() const + { + return lockable_; + } + mutable mutex_type lockable_; /*< mutable so that it can be modified by const functions >*/ + public: + + BOOST_THREAD_NO_COPYABLE( basic_lockable_adapter) /*< no copyable >*/ + + basic_lockable_adapter() + {} + + void lock() const + { + lockable().lock(); + } + void unlock() const + { + lockable().unlock(); + } + + }; + //] + + //[lockable_adapter + template + class lockable_adapter : public basic_lockable_adapter + { + public: + typedef Lockable mutex_type; + + bool try_lock() const + { + return this->lockable().try_lock(); + } + }; + //] + + //[timed_lockable_adapter + template + class timed_lockable_adapter: public lockable_adapter + { + public: + typedef TimedLock mutex_type; + + template + bool try_lock_until(chrono::time_point const & abs_time) const + { + return this->lockable().try_lock_until(abs_time); + } + template + bool try_lock_for(chrono::duration const & rel_time) const + { + return this->lockable().try_lock_for(rel_time); + } + + }; + //] + + //[shared_lockable_adapter + template + class shared_lockable_adapter: public timed_lockable_adapter + { + public: + typedef SharableLock mutex_type; + + void lock_shared() const + { + this->lockable().lock_shared(); + } + bool try_lock_shared() const + { + return this->lockable().try_lock_shared(); + } + void unlock_shared() const + { + this->lockable().unlock_shared(); + } + + template + bool try_lock_shared_until(chrono::time_point const & abs_time) const + { + return this->lockable().try_lock_shared_until(abs_time); + } + template + bool try_lock_shared_for(chrono::duration const & rel_time) const + { + return this->lockable().try_lock_shared_for(rel_time); + } + + }; + + //] + + //[upgrade_lockable_adapter + template + class upgrade_lockable_adapter: public shared_lockable_adapter + { + public: + typedef UpgradableLock mutex_type; + + void lock_upgrade() const + { + this->lockable().lock_upgrade(); + } + + bool try_lock_upgrade() const + { + return this->lockable().try_lock_upgrade(); + } + + void unlock_upgrade() const + { + this->lockable().unlock_upgrade(); + } + + template + bool try_lock_upgrade_until(chrono::time_point const & abs_time) const + { + return this->lockable().try_lock_upgrade_until(abs_time); + } + template + bool try_lock_upgrade_for(chrono::duration const & rel_time) const + { + return this->lockable().try_lock_upgrade_for(rel_time); + } + + bool try_unlock_shared_and_lock() const + { + return this->lockable().try_unlock_shared_and_lock(); + } + + template + bool try_unlock_shared_and_lock_until(chrono::time_point const & abs_time) const + { + return this->lockable().try_unlock_shared_and_lock_until(abs_time); + } + template + bool try_unlock_shared_and_lock_for(chrono::duration const & rel_time) const + { + return this->lockable().try_unlock_shared_and_lock_for(rel_time); + } + + void unlock_and_lock_shared() const + { + this->lockable().unlock_and_lock_shared(); + } + + bool try_unlock_shared_and_lock_upgrade() const + { + return this->lockable().try_unlock_shared_and_lock_upgrade(); + } + + template + bool try_unlock_shared_and_lock_upgrade_until(chrono::time_point const & abs_time) const + { + return this->lockable().try_unlock_shared_and_lock_upgrade_until(abs_time); + } + template + bool try_unlock_shared_and_lock_upgrade_for(chrono::duration const & rel_time) const + { + return this->lockable().try_unlock_shared_and_lock_upgrade_for(rel_time); + } + + void unlock_and_lock_upgrade() const + { + this->lockable().unlock_and_lock_upgrade(); + } + + void unlock_upgrade_and_lock() const + { + this->lockable().unlock_upgrade_and_lock(); + } + + bool try_unlock_upgrade_and_lock() const + { + return this->lockable().try_unlock_upgrade_and_lock(); + } + template + bool try_unlock_upgrade_and_lock_until(chrono::time_point const & abs_time) const + { + return this->lockable().try_unlock_upgrade_and_lock_until(abs_time); + } + template + bool try_unlock_upgrade_and_lock_for(chrono::duration const & rel_time) const + { + return this->lockable().try_unlock_upgrade_and_lock_for(rel_time); + } + + void unlock_upgrade_and_lock_shared() const + { + this->lockable().unlock_upgrade_and_lock_shared(); + } + + }; +//] + +} +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/lockable_concepts.hpp b/src/third_party/boost-1.60.0/boost/thread/lockable_concepts.hpp new file mode 100644 index 00000000000..bedd962e3be --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/lockable_concepts.hpp @@ -0,0 +1,157 @@ +// (C) Copyright 2012 Vicente Botet +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_THREAD_LOCKABLE_CONCEPTS_HPP +#define BOOST_THREAD_LOCKABLE_CONCEPTS_HPP + +#include +#include + +namespace boost +{ + + /** + * BasicLockable object supports the basic features + * required to delimit a critical region + * Supports the basic lock and unlock functions. + */ + + //[BasicLockable + template + struct BasicLockable + { + + BOOST_CONCEPT_USAGE(BasicLockable) + { + l.lock(); + l.unlock(); + } + BasicLockable() : l(*static_cast(0)) {} + private: + BasicLockable operator=(BasicLockable const&); + + Mutex& l; + } + ; + //] + /** + * Lockable extends BasicLockable + * with try_lock functions. + */ + + //[Lockable + template + struct Lockable + { + BOOST_CONCEPT_ASSERT(( BasicLockable )); + + BOOST_CONCEPT_USAGE(Lockable) + { + if (l.try_lock()) return; + } + Lockable() : l(*static_cast(0)) {} + private: + Lockable operator=(Lockable const&); + Mutex& l; + }; + //] + + /** + * TimedLockable object extends Lockable + * with timed lock functions: try_lock_until and try_lock_for and the exception based lock_until and lock_for + */ + + //[TimedLockable + template + struct TimedLockable + { + BOOST_CONCEPT_ASSERT(( Lockable )); + + BOOST_CONCEPT_USAGE(TimedLockable) + { + if (l.try_lock_until(t)) return; + if (l.try_lock_for(d)) return; + } + TimedLockable() : l(*static_cast(0)) {} + private: + TimedLockable operator=(TimedLockable const&); + Mutex& l; + chrono::system_clock::time_point t; + chrono::system_clock::duration d; + }; + //] + + /** + * SharedLockable object extends TimedLockable + * with the lock_shared, lock_shared_until, lock_shared_for, try_lock_shared_until, try_lock_shared + * and unlock_shared functions + */ + //[SharedLockable + template + struct SharedLockable + { + BOOST_CONCEPT_ASSERT(( TimedLockable )); + + BOOST_CONCEPT_USAGE(SharedLockable) + { + l.lock_shared(); + l.unlock_shared(); + if (l.try_lock_shared()) return; + if (l.try_lock_shared_until(t)) return; + if (l.try_lock_shared_for(d)) return; + } + SharedLockable() : l(*static_cast(0)) {} + private: + SharedLockable operator=(SharedLockable const&); + Mutex& l; + chrono::system_clock::time_point t; + chrono::system_clock::duration d; + }; + //] + + /** + * UpgradeLockable object extends SharedLockable + * with the lock_upgrade, lock_upgrade_until, unlock_upgrade_and_lock, + * unlock_and_lock_shared and unlock_upgrade_and_lock_shared functions + */ + + //[UpgradeLockable + template + struct UpgradeLockable + { + BOOST_CONCEPT_ASSERT(( SharedLockable )); + + BOOST_CONCEPT_USAGE(UpgradeLockable) + { + l.lock_upgrade(); + l.unlock_upgrade(); + if (l.try_lock_upgrade()) return; + if (l.try_lock_upgrade_until(t)) return; + if (l.try_lock_upgrade_for(d)) return; + if (l.try_unlock_shared_and_lock()) return; + if (l.try_unlock_shared_and_lock_until(t)) return; + if (l.try_unlock_shared_and_lock_for(d)) return; + l.unlock_and_lock_shared(); + if (l.try_unlock_shared_and_lock_upgrade()) return; + if (l.try_unlock_shared_and_lock_upgrade_until(t)) return; + if (l.try_unlock_shared_and_lock_upgrade_for(d)) return; + l.unlock_and_lock_upgrade(); + l.unlock_upgrade_and_lock(); + if (l.try_unlock_upgrade_and_lock()) return; + if (l.try_unlock_upgrade_and_lock_until(t)) return; + if (l.try_unlock_upgrade_and_lock_for(d)) return; + l.unlock_upgrade_and_lock_shared(); + } + UpgradeLockable() : l(*static_cast(0)) {} + private: + UpgradeLockable operator=(UpgradeLockable const&); + Mutex& l; + chrono::system_clock::time_point t; + chrono::system_clock::duration d; + }; + //] + +} +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/lockable_traits.hpp b/src/third_party/boost-1.60.0/boost/thread/lockable_traits.hpp new file mode 100644 index 00000000000..8a17ae72d3f --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/lockable_traits.hpp @@ -0,0 +1,207 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba + +#ifndef BOOST_THREAD_LOCKABLE_TRAITS_HPP +#define BOOST_THREAD_LOCKABLE_TRAITS_HPP + +#include + +#include +#include +#include + +#include + +// todo make use of integral_constant, true_type and false_type + +namespace boost +{ + namespace sync + { + +#if defined(BOOST_NO_SFINAE) || \ + BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) || \ + BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) +#if ! defined BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES +#define BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES +#endif +#endif + +#ifndef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES + namespace detail + { +#define BOOST_THREAD_DEFINE_HAS_MEMBER_CALLED(member_name) \ + template::value> \ + struct has_member_called_##member_name \ + { \ + BOOST_STATIC_CONSTANT(bool, value=false); \ + }; \ + \ + template \ + struct has_member_called_##member_name \ + { \ + typedef char true_type; \ + struct false_type \ + { \ + true_type dummy[2]; \ + }; \ + \ + struct fallback { int member_name; }; \ + struct derived: \ + T, fallback \ + { \ + derived(); \ + }; \ + \ + template struct tester; \ + \ + template \ + static false_type has_member(tester<&U::member_name>*); \ + template \ + static true_type has_member(...); \ + \ + BOOST_STATIC_CONSTANT( \ + bool, value=sizeof(has_member(0))==sizeof(true_type)); \ + } + + BOOST_THREAD_DEFINE_HAS_MEMBER_CALLED(lock) +; BOOST_THREAD_DEFINE_HAS_MEMBER_CALLED(unlock); + BOOST_THREAD_DEFINE_HAS_MEMBER_CALLED(try_lock); + + template::value > + struct has_member_lock + { + BOOST_STATIC_CONSTANT(bool, value=false); + }; + + template + struct has_member_lock + { + typedef char true_type; + struct false_type + { + true_type dummy[2]; + }; + + template + static true_type has_member(V (U::*)()); + template + static false_type has_member(U); + + BOOST_STATIC_CONSTANT( + bool,value=sizeof(has_member_lock::has_member(&T::lock))==sizeof(true_type)); + }; + + template::value > + struct has_member_unlock + { + BOOST_STATIC_CONSTANT(bool, value=false); + }; + + template + struct has_member_unlock + { + typedef char true_type; + struct false_type + { + true_type dummy[2]; + }; + + template + static true_type has_member(V (U::*)()); + template + static false_type has_member(U); + + BOOST_STATIC_CONSTANT( + bool,value=sizeof(has_member_unlock::has_member(&T::unlock))==sizeof(true_type)); + }; + + template::value > + struct has_member_try_lock + { + BOOST_STATIC_CONSTANT(bool, value=false); + }; + + template + struct has_member_try_lock + { + typedef char true_type; + struct false_type + { + true_type dummy[2]; + }; + + template + static true_type has_member(bool (U::*)()); + template + static false_type has_member(U); + + BOOST_STATIC_CONSTANT( + bool,value=sizeof(has_member_try_lock::has_member(&T::try_lock))==sizeof(true_type)); + }; + + } + + template + struct is_basic_lockable + { + BOOST_STATIC_CONSTANT(bool, value = detail::has_member_lock::value && + detail::has_member_unlock::value); + }; + template + struct is_lockable + { + BOOST_STATIC_CONSTANT(bool, value = + is_basic_lockable::value && + detail::has_member_try_lock::value); + }; + +#else + template + struct is_basic_lockable + { + BOOST_STATIC_CONSTANT(bool, value = false); + }; + template + struct is_lockable + { + BOOST_STATIC_CONSTANT(bool, value = false); + }; +#endif + + template + struct is_recursive_mutex_sur_parole + { + BOOST_STATIC_CONSTANT(bool, value = false); + }; + template + struct is_recursive_mutex_sur_parolle : is_recursive_mutex_sur_parole + { + }; + + template + struct is_recursive_basic_lockable + { + BOOST_STATIC_CONSTANT(bool, value = is_basic_lockable::value && + is_recursive_mutex_sur_parolle::value); + }; + template + struct is_recursive_lockable + { + BOOST_STATIC_CONSTANT(bool, value = is_lockable::value && + is_recursive_mutex_sur_parolle::value); + }; + } + template + struct is_mutex_type + { + BOOST_STATIC_CONSTANT(bool, value = sync::is_lockable::value); + }; + +} +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/locks.hpp b/src/third_party/boost-1.60.0/boost/thread/locks.hpp new file mode 100644 index 00000000000..6749964cf52 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/locks.hpp @@ -0,0 +1,16 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba + +#ifndef BOOST_THREAD_LOCKS_HPP +#define BOOST_THREAD_LOCKS_HPP + +#include +#include +#include +#include +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/mutex.hpp b/src/third_party/boost-1.60.0/boost/thread/mutex.hpp new file mode 100644 index 00000000000..05c60941c46 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/mutex.hpp @@ -0,0 +1,53 @@ +#ifndef BOOST_THREAD_MUTEX_HPP +#define BOOST_THREAD_MUTEX_HPP + +// mutex.hpp +// +// (C) Copyright 2007 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#if defined(BOOST_THREAD_PLATFORM_WIN32) +#include +#elif defined(BOOST_THREAD_PLATFORM_PTHREAD) +#include +#else +#error "Boost threads unavailable on this platform" +#endif + +#include + + +namespace boost +{ + namespace sync + { +#ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES + template<> + struct is_basic_lockable + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + template<> + struct is_lockable + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + template<> + struct is_basic_lockable + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + template<> + struct is_lockable + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; +#endif + } +} + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/null_mutex.hpp b/src/third_party/boost-1.60.0/boost/thread/null_mutex.hpp new file mode 100644 index 00000000000..f439f9ffb27 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/null_mutex.hpp @@ -0,0 +1,243 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Vicente J. Botet Escriba 2008-2009,2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_THREAD_NULL_MUTEX_HPP +#define BOOST_THREAD_NULL_MUTEX_HPP + +#include +#include +#include + +/// \file +/// Describes null_mutex class + +namespace boost +{ + + /// Implements a mutex that simulates a mutex without doing any operation and + /// simulates a successful operation. + class null_mutex + { + public: + + BOOST_THREAD_NO_COPYABLE( null_mutex) /*< no copyable >*/ + + null_mutex() {} + + /// Simulates a mutex lock() operation. Empty function. + void lock() + { + } + + /// Simulates a mutex try_lock() operation. + /// Equivalent to "return true;" + bool try_lock() + { + return true; + } + + /// Simulates a mutex unlock() operation. + /// Empty function. + void unlock() + { + } + +#ifdef BOOST_THREAD_USES_CHRONO + /// Simulates a mutex try_lock_until() operation. + /// Equivalent to "return true;" + template + bool try_lock_until(chrono::time_point const &) + { + return true; + } + + /// Simulates a mutex try_lock_for() operation. + /// Equivalent to "return true;" + template + bool try_lock_for(chrono::duration const &) + { + return true; + } +#endif + + /// Simulates a mutex lock_shared() operation. + /// Empty function. + void lock_shared() + { + } + + /// Simulates a mutex try_lock_shared() operation. + /// Equivalent to "return true;" + bool try_lock_shared() + { + return true; + } + + /// Simulates a mutex unlock_shared() operation. + /// Empty function. + void unlock_shared() + { + } + + /// Simulates a mutex try_lock_shared_until() operation. + /// Equivalent to "return true;" + template + bool try_lock_shared_until(chrono::time_point const &) + { + return true; + } + /// Simulates a mutex try_lock_shared_for() operation. + /// Equivalent to "return true;" + template + bool try_lock_shared_for(chrono::duration const &) + { + return true; + } + + /// Simulates a mutex lock_upgrade() operation. + /// Empty function. + void lock_upgrade() + { + } + + /// Simulates a mutex try_lock_upgrade() operation. + /// Equivalent to "return true;" + bool try_lock_upgrade() + { + return true; + } + + /// Simulates a mutex unlock_upgrade() operation. + /// Empty function. + void unlock_upgrade() + { + } + + /// Simulates a mutex try_lock_upgrade_until() operation. + /// Equivalent to "return true;" + template + bool try_lock_upgrade_until(chrono::time_point const &) + { + return true; + } + + /// Simulates a mutex try_lock_upgrade_for() operation. + /// Equivalent to "return true;" + template + bool try_lock_upgrade_for(chrono::duration const &) + { + return true; + } + + /// Simulates a mutex try_unlock_shared_and_lock() operation. + /// Equivalent to "return true;" + bool try_unlock_shared_and_lock() + { + return true; + } + +#ifdef BOOST_THREAD_USES_CHRONO + /// Simulates a mutex try_unlock_shared_and_lock_until() operation. + /// Equivalent to "return true;" + template + bool try_unlock_shared_and_lock_until(chrono::time_point const &) + { + return true; + } + + /// Simulates a mutex try_unlock_shared_and_lock_for() operation. + /// Equivalent to "return true;" + template + bool try_unlock_shared_and_lock_for(chrono::duration const &) + { + return true; + } +#endif + + /// Simulates unlock_and_lock_shared(). + /// Empty function. + void unlock_and_lock_shared() + { + } + + /// Simulates a mutex try_unlock_shared_and_lock_upgrade() operation. + /// Equivalent to "return true;" + bool try_unlock_shared_and_lock_upgrade() + { + return true; + } + +#ifdef BOOST_THREAD_USES_CHRONO + /// Simulates a mutex try_unlock_shared_and_lock_upgrade_until() operation. + /// Equivalent to "return true;" + template + bool try_unlock_shared_and_lock_upgrade_until(chrono::time_point const &) + { + return true; + } + + /// Simulates a mutex try_unlock_shared_and_lock_upgrade_for() operation. + /// Equivalent to "return true;" + template + bool try_unlock_shared_and_lock_upgrade_for(chrono::duration const &) + { + return true; + } +#endif + + /// Simulates unlock_and_lock_upgrade(). + /// Empty function. + void unlock_and_lock_upgrade() + { + } + + /// Simulates unlock_upgrade_and_lock(). + /// Empty function. + void unlock_upgrade_and_lock() + { + } + + /// Simulates a mutex try_unlock_upgrade_and_lock() operation. + /// Equivalent to "return true;" + bool try_unlock_upgrade_and_lock() + { + return true; + } + +#ifdef BOOST_THREAD_USES_CHRONO + /// Simulates a mutex try_unlock_upgrade_and_lock_until() operation. + /// Equivalent to "return true;" + template + bool try_unlock_upgrade_and_lock_until(chrono::time_point const &) + { + return true; + } + + /// Simulates a mutex try_unlock_upgrade_and_lock_for() operation. + /// Equivalent to "return true;" + template + bool try_unlock_upgrade_and_lock_for(chrono::duration const &) + { + return true; + } +#endif + + /// Simulates unlock_upgrade_and_lock_shared(). + /// Empty function. + void unlock_upgrade_and_lock_shared() + { + } + + }; + +} //namespace boost { + + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/once.hpp b/src/third_party/boost-1.60.0/boost/thread/once.hpp new file mode 100644 index 00000000000..9fcfb533397 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/once.hpp @@ -0,0 +1,44 @@ +#ifndef BOOST_THREAD_ONCE_HPP +#define BOOST_THREAD_ONCE_HPP + +// once.hpp +// +// (C) Copyright 2006-7 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#if defined(BOOST_THREAD_PLATFORM_WIN32) +#include +#elif defined(BOOST_THREAD_PLATFORM_PTHREAD) +#if defined BOOST_THREAD_ONCE_FAST_EPOCH +#include +#elif defined BOOST_THREAD_ONCE_ATOMIC +#include +#else +#error "Once Not Implemented" +#endif +#else +#error "Boost threads unavailable on this platform" +#endif + +#include + +namespace boost +{ + // template void + // call_once(once_flag& flag, Callable&& func, Args&&... args); +template +inline void call_once(Function func,once_flag& flag) +//inline void call_once(void (*func)(),once_flag& flag) + { + call_once(flag,func); + } +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/ostream_buffer.hpp b/src/third_party/boost-1.60.0/boost/thread/ostream_buffer.hpp new file mode 100644 index 00000000000..cc02a9c0cee --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/ostream_buffer.hpp @@ -0,0 +1,45 @@ +// (C) Copyright 2013 Vicente J. Botet Escriba +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#ifndef BOOST_THREAD_OSTREAM_BUFFER_HPP +#define BOOST_THREAD_OSTREAM_BUFFER_HPP + +#include +#include +#include + +#include + +namespace boost +{ + + template + class ostream_buffer + { + public: + typedef std::basic_ostringstream stream_type; + ostream_buffer(OStream& os) : + os_(os) + { + } + ~ostream_buffer() + { + os_ << o_str_.str(); + } + stream_type& stream() + { + return o_str_; + } + private: + OStream& os_; + stream_type o_str_; + }; + +} + +#include + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/poly_lockable.hpp b/src/third_party/boost-1.60.0/boost/thread/poly_lockable.hpp new file mode 100644 index 00000000000..fffcbce1330 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/poly_lockable.hpp @@ -0,0 +1,68 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Vicente J. Botet Escriba 2008-2009,2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_THREAD_POLY_LOCKABLE_HPP +#define BOOST_THREAD_POLY_LOCKABLE_HPP + +#include +#include + +namespace boost +{ + + //[basic_poly_lockable + class basic_poly_lockable + { + public: + + virtual ~basic_poly_lockable() = 0; + + virtual void lock() = 0; + virtual void unlock() = 0; + + }; + //] + + //[poly_lockable + class poly_lockable : public basic_poly_lockable + { + public: + + virtual ~poly_lockable() = 0; + virtual bool try_lock() = 0; + }; + //] + + //[timed_poly_lockable + class timed_poly_lockable: public poly_lockable + { + public: + virtual ~timed_poly_lockable()=0; + + virtual bool try_lock_until(chrono::system_clock::time_point const & abs_time)=0; + virtual bool try_lock_until(chrono::steady_clock::time_point const & abs_time)=0; + template + bool try_lock_until(chrono::time_point const & abs_time) + { + return try_lock_until(time_point_cast(abs_time)); + } + + virtual bool try_lock_for(chrono::nanoseconds const & relative_time)=0; + template + bool try_lock_for(chrono::duration const & rel_time) + { + return try_lock_for(duration_cast(rel_time)); + } + + }; + //] + +} +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/poly_lockable_adapter.hpp b/src/third_party/boost-1.60.0/boost/thread/poly_lockable_adapter.hpp new file mode 100644 index 00000000000..448789ecbc8 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/poly_lockable_adapter.hpp @@ -0,0 +1,89 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Vicente J. Botet Escriba 2008-2009,2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_THREAD_POLY_LOCKABLE_ADAPTER_HPP +#define BOOST_THREAD_POLY_LOCKABLE_ADAPTER_HPP + +#include + +namespace boost +{ + + //[poly_basic_lockable_adapter + template + class poly_basic_lockable_adapter : public Base + { + public: + typedef Mutex mutex_type; + + protected: + mutex_type& mtx() const + { + return mtx_; + } + mutable mutex_type mtx_; /*< mutable so that it can be modified by const functions >*/ + public: + + BOOST_THREAD_NO_COPYABLE( poly_basic_lockable_adapter) /*< no copyable >*/ + + poly_basic_lockable_adapter() + {} + + void lock() + { + mtx().lock(); + } + void unlock() + { + mtx().unlock(); + } + + }; + //] + + //[poly_lockable_adapter + template + class poly_lockable_adapter : public poly_basic_lockable_adapter + { + public: + typedef Mutex mutex_type; + + bool try_lock() + { + return this->mtx().try_lock(); + } + }; + //] + + //[poly_timed_lockable_adapter + template + class poly_timed_lockable_adapter: public poly_lockable_adapter + { + public: + typedef Mutex mutex_type; + + bool try_lock_until(chrono::system_clock::time_point const & abs_time) + { + return this->mtx().try_lock_until(abs_time); + } + bool try_lock_until(chrono::steady_clock::time_point const & abs_time) + { + return this->mtx().try_lock_until(abs_time); + } + bool try_lock_for(chrono::nanoseconds const & rel_time) + { + return this->mtx().try_lock_for(rel_time); + } + + }; + //] + +} +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/poly_shared_lockable.hpp b/src/third_party/boost-1.60.0/boost/thread/poly_shared_lockable.hpp new file mode 100644 index 00000000000..4348ed76c25 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/poly_shared_lockable.hpp @@ -0,0 +1,135 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Vicente J. Botet Escriba 2008-2009,2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_THREAD_POLY_SHARED_LOCKABLE_HPP +#define BOOST_THREAD_POLY_SHARED_LOCKABLE_HPP + +#include +#include + +namespace boost +{ + + + //[shared_poly_lockable + class shared_poly_lockable: public timed_poly_lockable + { + public: + virtual ~shared_poly_lockable() = 0; + + virtual void lock_shared() = 0; + virtual bool try_lock_shared() = 0; + virtual void unlock_shared() = 0; + + virtual bool try_lock_shared_until(chrono::system_clock::time_point const & abs_time)=0; + virtual bool try_lock_shared_until(chrono::steady_clock::time_point const & abs_time)=0; + template + bool try_lock_shared_until(chrono::time_point const & abs_time) + { + return try_lock_shared_until(time_point_cast(abs_time)); + } + + virtual bool try_lock_shared_for(chrono::nanoseconds const & relative_time)=0; + template + bool try_lock_shared_for(chrono::duration const & rel_time) + { + return try_lock_shared_for(duration_cast(rel_time)); + } + + }; + + //] + + //[upgrade_poly_lockable + class upgrade_poly_lockable: public shared_poly_lockable + { + public: + virtual ~upgrade_poly_lockable() = 0; + + virtual void lock_upgrade() = 0; + virtual bool try_lock_upgrade() = 0; + virtual void unlock_upgrade() = 0; + + virtual bool try_lock_upgrade_until(chrono::system_clock::time_point const & abs_time)=0; + virtual bool try_lock_upgrade_until(chrono::steady_clock::time_point const & abs_time)=0; + template + bool try_lock_upgrade_until(chrono::time_point const & abs_time) + { + return try_lock_upgrade_until(time_point_cast(abs_time)); + } + + virtual bool try_lock_upgrade_for(chrono::nanoseconds const & relative_time)=0; + template + bool try_lock_upgrade_for(chrono::duration const & rel_time) + { + return try_lock_upgrade_for(duration_cast(rel_time)); + } + + virtual bool try_unlock_shared_and_lock() = 0; + + virtual bool try_unlock_shared_and_lock_until(chrono::system_clock::time_point const & abs_time)=0; + virtual bool try_unlock_shared_and_lock_until(chrono::steady_clock::time_point const & abs_time)=0; + template + bool try_unlock_shared_and_lock_until(chrono::time_point const & abs_time) + { + return try_unlock_shared_and_lock_until(time_point_cast(abs_time)); + } + + virtual bool try_unlock_shared_and_lock_for(chrono::nanoseconds const & relative_time)=0; + template + bool try_unlock_shared_and_lock_for(chrono::duration const & rel_time) + { + return try_unlock_shared_and_lock_for(duration_cast(rel_time)); + } + + virtual void unlock_and_lock_shared() = 0; + virtual bool try_unlock_shared_and_lock_upgrade() = 0; + + virtual bool try_unlock_shared_and_lock_upgrade_until(chrono::system_clock::time_point const & abs_time)=0; + virtual bool try_unlock_shared_and_lock_upgrade_until(chrono::steady_clock::time_point const & abs_time)=0; + template + bool try_unlock_shared_and_lock_upgrade_until(chrono::time_point const & abs_time) + { + return try_unlock_shared_and_lock_upgrade_until(time_point_cast(abs_time)); + } + + virtual bool try_unlock_shared_and_lock_upgrade_for(chrono::nanoseconds const & relative_time)=0; + template + bool try_unlock_shared_and_lock_upgrade_for(chrono::duration const & rel_time) + { + return try_unlock_shared_and_lock_upgrade_for(duration_cast(rel_time)); + } + + virtual void unlock_and_lock_upgrade() = 0; + virtual void unlock_upgrade_and_lock() = 0; + virtual bool try_unlock_upgrade_and_lock() = 0; + + virtual bool try_unlock_upgrade_and_lock_until(chrono::system_clock::time_point const & abs_time)=0; + virtual bool try_unlock_upgrade_and_lock_until(chrono::steady_clock::time_point const & abs_time)=0; + template + bool try_unlock_upgrade_and_lock_until(chrono::time_point const & abs_time) + { + return try_unlock_upgrade_and_lock_until(time_point_cast(abs_time)); + } + + virtual bool try_unlock_upgrade_and_lock_for(chrono::nanoseconds const & relative_time)=0; + template + bool try_unlock_upgrade_and_lock_for(chrono::duration const & rel_time) + { + return try_unlock_upgrade_and_lock_for(duration_cast(rel_time)); + } + + virtual void unlock_upgrade_and_lock_shared() = 0; + + }; +//] + +} +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/poly_shared_lockable_adapter.hpp b/src/third_party/boost-1.60.0/boost/thread/poly_shared_lockable_adapter.hpp new file mode 100644 index 00000000000..f1361289078 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/poly_shared_lockable_adapter.hpp @@ -0,0 +1,170 @@ +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Vicente J. Botet Escriba 2008-2009,2012. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#ifndef BOOST_THREAD_POLY_SHARED_LOCKABLE_ADAPTER_HPP +#define BOOST_THREAD_POLY_SHARED_LOCKABLE_ADAPTER_HPP + +#include +#include + +namespace boost +{ + + //[shared_lockable_adapter + template + class poly_shared_lockable_adapter: public poly_timed_lockable_adapter + { + public: + typedef Mutex mutex_type; + + void lock_shared() + { + this->mtx().lock_shared(); + } + bool try_lock_shared() + { + return this->mtx().try_lock_shared(); + } + void unlock_shared() + { + this->mtx().unlock_shared(); + } + + bool try_lock_shared_until(chrono::system_clock::time_point const & abs_time) + { + return this->mtx().try_lock_shared_until(abs_time); + } + bool try_lock_shared_until(chrono::steady_clock::time_point const & abs_time) + { + return this->mtx().try_lock_shared_until(abs_time); + } + bool try_lock_shared_for(chrono::nanoseconds const & rel_time) + { + return this->mtx().try_lock_shared_for(rel_time); + } + + }; + + //] + + //[upgrade_lockable_adapter + template + class upgrade_lockable_adapter: public shared_lockable_adapter + { + public: + typedef Mutex mutex_type; + + void lock_upgrade() + { + this->mtx().lock_upgrade(); + } + + bool try_lock_upgrade() + { + return this->mtx().try_lock_upgrade(); + } + + void unlock_upgrade() + { + this->mtx().unlock_upgrade(); + } + + bool try_lock_upgrade_until(chrono::system_clock::time_point const & abs_time) + { + return this->mtx().try_lock_upgrade_until(abs_time); + } + bool try_lock_upgrade_until(chrono::steady_clock::time_point const & abs_time) + { + return this->mtx().try_lock_upgrade_until(abs_time); + } + bool try_lock_upgrade_for(chrono::nanoseconds const & rel_time) + { + return this->mtx().try_lock_upgrade_for(rel_time); + } + + bool try_unlock_shared_and_lock() + { + return this->mtx().try_unlock_shared_and_lock(); + } + + bool try_unlock_shared_and_lock_until(chrono::system_clock::time_point const & abs_time) + { + return this->mtx().try_unlock_shared_and_lock_until(abs_time); + } + bool try_unlock_shared_and_lock_until(chrono::steady_clock::time_point const & abs_time) + { + return this->mtx().try_unlock_shared_and_lock_until(abs_time); + } + template + bool try_unlock_shared_and_lock_for(chrono::nanoseconds const & rel_time) + { + return this->mtx().try_unlock_shared_and_lock_for(rel_time); + } + + void unlock_and_lock_shared() + { + this->mtx().unlock_and_lock_shared(); + } + + bool try_unlock_shared_and_lock_upgrade() + { + return this->mtx().try_unlock_shared_and_lock_upgrade(); + } + + bool try_unlock_shared_and_lock_upgrade_until(chrono::system_clock::time_point const & abs_time) + { + return this->mtx().try_unlock_shared_and_lock_upgrade_until(abs_time); + } + bool try_unlock_shared_and_lock_upgrade_until(chrono::steady_clock::time_point const & abs_time) + { + return this->mtx().try_unlock_shared_and_lock_upgrade_until(abs_time); + } + bool try_unlock_shared_and_lock_upgrade_for(chrono::nanoseconds const & rel_time) + { + return this->mtx().try_unlock_shared_and_lock_upgrade_for(rel_time); + } + + void unlock_and_lock_upgrade() + { + this->mtx().unlock_and_lock_upgrade(); + } + + void unlock_upgrade_and_lock() + { + this->mtx().unlock_upgrade_and_lock(); + } + + bool try_unlock_upgrade_and_lock() + { + return this->mtx().try_unlock_upgrade_and_lock(); + } + bool try_unlock_upgrade_and_lock_until(chrono::system_clock::time_point const & abs_time) + { + return this->mtx().try_unlock_upgrade_and_lock_until(abs_time); + } + bool try_unlock_upgrade_and_lock_until(chrono::steady_clock::time_point const & abs_time) + { + return this->mtx().try_unlock_upgrade_and_lock_until(abs_time); + } + bool try_unlock_upgrade_and_lock_for(chrono::nanoseconds const & rel_time) + { + return this->mtx().try_unlock_upgrade_and_lock_for(rel_time); + } + + void unlock_upgrade_and_lock_shared() + { + this->mtx().unlock_upgrade_and_lock_shared(); + } + + }; +//] + +} +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/pthread/condition_variable.hpp b/src/third_party/boost-1.60.0/boost/thread/pthread/condition_variable.hpp new file mode 100644 index 00000000000..a6033515915 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/pthread/condition_variable.hpp @@ -0,0 +1,428 @@ +#ifndef BOOST_THREAD_CONDITION_VARIABLE_PTHREAD_HPP +#define BOOST_THREAD_CONDITION_VARIABLE_PTHREAD_HPP +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2007-10 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba + +#include +#include +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS +#include +#endif +#include +#ifdef BOOST_THREAD_USES_CHRONO +#include +#include +#endif +#include + +#include + +namespace boost +{ +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + namespace this_thread + { + void BOOST_THREAD_DECL interruption_point(); + } +#endif + + namespace thread_cv_detail + { + template + struct lock_on_exit + { + MutexType* m; + + lock_on_exit(): + m(0) + {} + + void activate(MutexType& m_) + { + m_.unlock(); + m=&m_; + } + ~lock_on_exit() + { + if(m) + { + m->lock(); + } + } + }; + } + + inline void condition_variable::wait(unique_lock& m) + { +#if defined BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED + if(! m.owns_lock()) + { + boost::throw_exception(condition_error(-1, "boost::condition_variable::wait() failed precondition mutex not owned")); + } +#endif + int res=0; + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + thread_cv_detail::lock_on_exit > guard; + detail::interruption_checker check_for_interruption(&internal_mutex,&cond); + pthread_mutex_t* the_mutex = &internal_mutex; + guard.activate(m); +#else + pthread_mutex_t* the_mutex = m.mutex()->native_handle(); +#endif + do { + res = pthread_cond_wait(&cond,the_mutex); + } while (res == EINTR); + } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + this_thread::interruption_point(); +#endif + if(res) + { + boost::throw_exception(condition_error(res, "boost::condition_variable::wait failed in pthread_cond_wait")); + } + } + + inline bool condition_variable::do_wait_until( + unique_lock& m, + struct timespec const &timeout) + { +#if defined BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED + if (!m.owns_lock()) + { + boost::throw_exception(condition_error(EPERM, "boost::condition_variable::do_wait_until() failed precondition mutex not owned")); + } +#endif + int cond_res; + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + thread_cv_detail::lock_on_exit > guard; + detail::interruption_checker check_for_interruption(&internal_mutex,&cond); + pthread_mutex_t* the_mutex = &internal_mutex; + guard.activate(m); +#else + pthread_mutex_t* the_mutex = m.mutex()->native_handle(); +#endif + cond_res=pthread_cond_timedwait(&cond,the_mutex,&timeout); + } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + this_thread::interruption_point(); +#endif + if(cond_res==ETIMEDOUT) + { + return false; + } + if(cond_res) + { + boost::throw_exception(condition_error(cond_res, "boost::condition_variable::do_wait_until failed in pthread_cond_timedwait")); + } + return true; + } + + inline void condition_variable::notify_one() BOOST_NOEXCEPT + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex); +#endif + BOOST_VERIFY(!pthread_cond_signal(&cond)); + } + + inline void condition_variable::notify_all() BOOST_NOEXCEPT + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex); +#endif + BOOST_VERIFY(!pthread_cond_broadcast(&cond)); + } + + class condition_variable_any + { + pthread_mutex_t internal_mutex; + pthread_cond_t cond; + + public: + BOOST_THREAD_NO_COPYABLE(condition_variable_any) + condition_variable_any() + { + int const res=pthread_mutex_init(&internal_mutex,NULL); + if(res) + { + boost::throw_exception(thread_resource_error(res, "boost::condition_variable_any::condition_variable_any() failed in pthread_mutex_init")); + } + int const res2 = detail::monotonic_pthread_cond_init(cond); + if(res2) + { + BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex)); + boost::throw_exception(thread_resource_error(res2, "boost::condition_variable_any::condition_variable_any() failed in detail::monotonic_pthread_cond_init")); + } + } + ~condition_variable_any() + { + BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex)); + BOOST_VERIFY(!pthread_cond_destroy(&cond)); + } + + template + void wait(lock_type& m) + { + int res=0; + { + thread_cv_detail::lock_on_exit guard; +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + detail::interruption_checker check_for_interruption(&internal_mutex,&cond); +#else + boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex); +#endif + guard.activate(m); + res=pthread_cond_wait(&cond,&internal_mutex); + } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + this_thread::interruption_point(); +#endif + if(res) + { + boost::throw_exception(condition_error(res, "boost::condition_variable_any::wait() failed in pthread_cond_wait")); + } + } + + template + void wait(lock_type& m,predicate_type pred) + { + while(!pred()) wait(m); + } + +#if defined BOOST_THREAD_USES_DATETIME + template + bool timed_wait(lock_type& m,boost::system_time const& abs_time) + { + struct timespec const timeout=detail::to_timespec(abs_time); + return do_wait_until(m, timeout); + } + template + bool timed_wait(lock_type& m,xtime const& abs_time) + { + return timed_wait(m,system_time(abs_time)); + } + + template + bool timed_wait(lock_type& m,duration_type const& wait_duration) + { + return timed_wait(m,get_system_time()+wait_duration); + } + + template + bool timed_wait(lock_type& m,boost::system_time const& abs_time, predicate_type pred) + { + while (!pred()) + { + if(!timed_wait(m, abs_time)) + return pred(); + } + return true; + } + + template + bool timed_wait(lock_type& m,xtime const& abs_time, predicate_type pred) + { + return timed_wait(m,system_time(abs_time),pred); + } + + template + bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred) + { + return timed_wait(m,get_system_time()+wait_duration,pred); + } +#endif +#ifndef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC + +#ifdef BOOST_THREAD_USES_CHRONO + template + cv_status + wait_until( + lock_type& lock, + const chrono::time_point& t) + { + using namespace chrono; + typedef time_point nano_sys_tmpt; + wait_until(lock, + nano_sys_tmpt(ceil(t.time_since_epoch()))); + return system_clock::now() < t ? cv_status::no_timeout : + cv_status::timeout; + } + + template + cv_status + wait_until( + lock_type& lock, + const chrono::time_point& t) + { + using namespace chrono; + system_clock::time_point s_now = system_clock::now(); + typename Clock::time_point c_now = Clock::now(); + wait_until(lock, s_now + ceil(t - c_now)); + return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout; + } + + template + cv_status + wait_for( + lock_type& lock, + const chrono::duration& d) + { + using namespace chrono; + system_clock::time_point s_now = system_clock::now(); + steady_clock::time_point c_now = steady_clock::now(); + wait_until(lock, s_now + ceil(d)); + return steady_clock::now() - c_now < d ? cv_status::no_timeout : + cv_status::timeout; + + } + + template + cv_status wait_until( + lock_type& lk, + chrono::time_point tp) + { + using namespace chrono; + nanoseconds d = tp.time_since_epoch(); + timespec ts = boost::detail::to_timespec(d); + if (do_wait_until(lk, ts)) return cv_status::no_timeout; + else return cv_status::timeout; + } +#endif +#else // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +#ifdef BOOST_THREAD_USES_CHRONO + + template + cv_status + wait_until( + lock_type& lock, + const chrono::time_point& t) + { + using namespace chrono; + typedef time_point nano_sys_tmpt; + wait_until(lock, + nano_sys_tmpt(ceil(t.time_since_epoch()))); + return steady_clock::now() < t ? cv_status::no_timeout : + cv_status::timeout; + } + + template + cv_status + wait_until( + lock_type& lock, + const chrono::time_point& t) + { + using namespace chrono; + steady_clock::time_point s_now = steady_clock::now(); + typename Clock::time_point c_now = Clock::now(); + wait_until(lock, s_now + ceil(t - c_now)); + return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout; + } + + template + cv_status + wait_for( + lock_type& lock, + const chrono::duration& d) + { + using namespace chrono; + steady_clock::time_point c_now = steady_clock::now(); + wait_until(lock, c_now + ceil(d)); + return steady_clock::now() - c_now < d ? cv_status::no_timeout : + cv_status::timeout; + } + + inline cv_status wait_until( + unique_lock& lk, + chrono::time_point tp) + { + using namespace chrono; + nanoseconds d = tp.time_since_epoch(); + timespec ts = boost::detail::to_timespec(d); + if (do_wait_until(lk, ts)) return cv_status::no_timeout; + else return cv_status::timeout; + } + +#endif +#endif // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC + +#ifdef BOOST_THREAD_USES_CHRONO + template + bool + wait_until( + lock_type& lock, + const chrono::time_point& t, + Predicate pred) + { + while (!pred()) + { + if (wait_until(lock, t) == cv_status::timeout) + return pred(); + } + return true; + } + + template + bool + wait_for( + lock_type& lock, + const chrono::duration& d, + Predicate pred) + { + return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred)); + } +#endif + + void notify_one() BOOST_NOEXCEPT + { + boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex); + BOOST_VERIFY(!pthread_cond_signal(&cond)); + } + + void notify_all() BOOST_NOEXCEPT + { + boost::pthread::pthread_mutex_scoped_lock internal_lock(&internal_mutex); + BOOST_VERIFY(!pthread_cond_broadcast(&cond)); + } + private: // used by boost::thread::try_join_until + + template + inline bool do_wait_until( + lock_type& m, + struct timespec const &timeout) + { + int res=0; + { + thread_cv_detail::lock_on_exit guard; +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + detail::interruption_checker check_for_interruption(&internal_mutex,&cond); +#else + boost::pthread::pthread_mutex_scoped_lock check_for_interruption(&internal_mutex); +#endif + guard.activate(m); + res=pthread_cond_timedwait(&cond,&internal_mutex,&timeout); + } +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + this_thread::interruption_point(); +#endif + if(res==ETIMEDOUT) + { + return false; + } + if(res) + { + boost::throw_exception(condition_error(res, "boost::condition_variable_any::do_wait_until() failed in pthread_cond_timedwait")); + } + return true; + } + }; + +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/pthread/condition_variable_fwd.hpp b/src/third_party/boost-1.60.0/boost/thread/pthread/condition_variable_fwd.hpp new file mode 100644 index 00000000000..1255eac59b7 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/pthread/condition_variable_fwd.hpp @@ -0,0 +1,360 @@ +#ifndef BOOST_THREAD_PTHREAD_CONDITION_VARIABLE_FWD_HPP +#define BOOST_THREAD_PTHREAD_CONDITION_VARIABLE_FWD_HPP +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2007-8 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba + +#include +#include +#include +#include +#include +#include +#include +#include +#if defined BOOST_THREAD_USES_DATETIME +#include +#endif +#ifdef BOOST_THREAD_USES_CHRONO +#include +#include +#endif +#include +#include + +#include + +namespace boost +{ + namespace detail { + inline int monotonic_pthread_cond_init(pthread_cond_t& cond) { + +#ifdef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC + pthread_condattr_t attr; + int res = pthread_condattr_init(&attr); + if (res) + { + return res; + } + pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); + res=pthread_cond_init(&cond,&attr); + pthread_condattr_destroy(&attr); + return res; +#else + return pthread_cond_init(&cond,NULL); +#endif + + } + } + + class condition_variable + { + private: +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + pthread_mutex_t internal_mutex; +#endif + pthread_cond_t cond; + + public: + //private: // used by boost::thread::try_join_until + + inline bool do_wait_until( + unique_lock& lock, + struct timespec const &timeout); + + bool do_wait_for( + unique_lock& lock, + struct timespec const &timeout) + { + return do_wait_until(lock, boost::detail::timespec_plus(timeout, boost::detail::timespec_now())); + } + + public: + BOOST_THREAD_NO_COPYABLE(condition_variable) + condition_variable() + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + int res=pthread_mutex_init(&internal_mutex,NULL); + if(res) + { + boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in pthread_mutex_init")); + } +#endif + res = detail::monotonic_pthread_cond_init(cond); + if (res) + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + BOOST_VERIFY(!pthread_mutex_destroy(&internal_mutex)); +#endif + boost::throw_exception(thread_resource_error(res, "boost::condition_variable::condition_variable() constructor failed in detail::monotonic_pthread_cond_init")); + } + } + ~condition_variable() + { + int ret; +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + do { + ret = pthread_mutex_destroy(&internal_mutex); + } while (ret == EINTR); + BOOST_ASSERT(!ret); +#endif + do { + ret = pthread_cond_destroy(&cond); + } while (ret == EINTR); + BOOST_ASSERT(!ret); + } + + void wait(unique_lock& m); + + template + void wait(unique_lock& m,predicate_type pred) + { + while(!pred()) wait(m); + } + +#if defined BOOST_THREAD_USES_DATETIME + inline bool timed_wait( + unique_lock& m, + boost::system_time const& abs_time) + { +#if defined BOOST_THREAD_WAIT_BUG + struct timespec const timeout=detail::to_timespec(abs_time + BOOST_THREAD_WAIT_BUG); + return do_wait_until(m, timeout); +#else + struct timespec const timeout=detail::to_timespec(abs_time); + return do_wait_until(m, timeout); +#endif + } + bool timed_wait( + unique_lock& m, + xtime const& abs_time) + { + return timed_wait(m,system_time(abs_time)); + } + + template + bool timed_wait( + unique_lock& m, + duration_type const& wait_duration) + { + if (wait_duration.is_pos_infinity()) + { + wait(m); // or do_wait(m,detail::timeout::sentinel()); + return true; + } + if (wait_duration.is_special()) + { + return true; + } + return timed_wait(m,get_system_time()+wait_duration); + } + + template + bool timed_wait( + unique_lock& m, + boost::system_time const& abs_time,predicate_type pred) + { + while (!pred()) + { + if(!timed_wait(m, abs_time)) + return pred(); + } + return true; + } + + template + bool timed_wait( + unique_lock& m, + xtime const& abs_time,predicate_type pred) + { + return timed_wait(m,system_time(abs_time),pred); + } + + template + bool timed_wait( + unique_lock& m, + duration_type const& wait_duration,predicate_type pred) + { + if (wait_duration.is_pos_infinity()) + { + while (!pred()) + { + wait(m); // or do_wait(m,detail::timeout::sentinel()); + } + return true; + } + if (wait_duration.is_special()) + { + return pred(); + } + return timed_wait(m,get_system_time()+wait_duration,pred); + } +#endif + +#ifndef BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC + +#ifdef BOOST_THREAD_USES_CHRONO + + template + cv_status + wait_until( + unique_lock& lock, + const chrono::time_point& t) + { + using namespace chrono; + typedef time_point nano_sys_tmpt; + wait_until(lock, + nano_sys_tmpt(ceil(t.time_since_epoch()))); + return system_clock::now() < t ? cv_status::no_timeout : + cv_status::timeout; + } + + template + cv_status + wait_until( + unique_lock& lock, + const chrono::time_point& t) + { + using namespace chrono; + system_clock::time_point s_now = system_clock::now(); + typename Clock::time_point c_now = Clock::now(); + wait_until(lock, s_now + ceil(t - c_now)); + return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout; + } + + + + template + cv_status + wait_for( + unique_lock& lock, + const chrono::duration& d) + { + using namespace chrono; + system_clock::time_point s_now = system_clock::now(); + steady_clock::time_point c_now = steady_clock::now(); + wait_until(lock, s_now + ceil(d)); + return steady_clock::now() - c_now < d ? cv_status::no_timeout : + cv_status::timeout; + + } + + inline cv_status wait_until( + unique_lock& lk, + chrono::time_point tp) + { + using namespace chrono; + nanoseconds d = tp.time_since_epoch(); + timespec ts = boost::detail::to_timespec(d); + if (do_wait_until(lk, ts)) return cv_status::no_timeout; + else return cv_status::timeout; + } +#endif + +#else // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC +#ifdef BOOST_THREAD_USES_CHRONO + + template + cv_status + wait_until( + unique_lock& lock, + const chrono::time_point& t) + { + using namespace chrono; + typedef time_point nano_sys_tmpt; + wait_until(lock, + nano_sys_tmpt(ceil(t.time_since_epoch()))); + return steady_clock::now() < t ? cv_status::no_timeout : + cv_status::timeout; + } + + template + cv_status + wait_until( + unique_lock& lock, + const chrono::time_point& t) + { + using namespace chrono; + steady_clock::time_point s_now = steady_clock::now(); + typename Clock::time_point c_now = Clock::now(); + wait_until(lock, s_now + ceil(t - c_now)); + return Clock::now() < t ? cv_status::no_timeout : cv_status::timeout; + } + + template + cv_status + wait_for( + unique_lock& lock, + const chrono::duration& d) + { + using namespace chrono; + steady_clock::time_point c_now = steady_clock::now(); + wait_until(lock, c_now + ceil(d)); + return steady_clock::now() - c_now < d ? cv_status::no_timeout : + cv_status::timeout; + } + + inline cv_status wait_until( + unique_lock& lk, + chrono::time_point tp) + { + using namespace chrono; + nanoseconds d = tp.time_since_epoch(); + timespec ts = boost::detail::to_timespec(d); + if (do_wait_until(lk, ts)) return cv_status::no_timeout; + else return cv_status::timeout; + } +#endif + +#endif // defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC + +#ifdef BOOST_THREAD_USES_CHRONO + template + bool + wait_until( + unique_lock& lock, + const chrono::time_point& t, + Predicate pred) + { + while (!pred()) + { + if (wait_until(lock, t) == cv_status::timeout) + return pred(); + } + return true; + } + + template + bool + wait_for( + unique_lock& lock, + const chrono::duration& d, + Predicate pred) + { + return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred)); + } +#endif + +#define BOOST_THREAD_DEFINES_CONDITION_VARIABLE_NATIVE_HANDLE + typedef pthread_cond_t* native_handle_type; + native_handle_type native_handle() + { + return &cond; + } + + void notify_one() BOOST_NOEXCEPT; + void notify_all() BOOST_NOEXCEPT; + + + }; + + BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock lk); + +} + + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/pthread/mutex.hpp b/src/third_party/boost-1.60.0/boost/thread/pthread/mutex.hpp new file mode 100644 index 00000000000..9ac808b6f4a --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/pthread/mutex.hpp @@ -0,0 +1,361 @@ +#ifndef BOOST_THREAD_PTHREAD_MUTEX_HPP +#define BOOST_THREAD_PTHREAD_MUTEX_HPP +// (C) Copyright 2007-8 Anthony Williams +// (C) Copyright 2011,2012,2015 Vicente J. Botet Escriba +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include +#include +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS +#include +#endif +#include +#include +#include +#include +#include +#include +#ifdef BOOST_THREAD_USES_CHRONO +#include +#include +#endif +#include + +#if (defined(_POSIX_TIMEOUTS) && (_POSIX_TIMEOUTS-0)>=200112L) \ + || (defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ >= 21) +#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK +#define BOOST_PTHREAD_HAS_TIMEDLOCK +#endif +#endif + + +#include + +#ifndef BOOST_THREAD_HAS_NO_EINTR_BUG +#define BOOST_THREAD_HAS_EINTR_BUG +#endif + +namespace boost +{ + namespace posix { +#ifdef BOOST_THREAD_HAS_EINTR_BUG + BOOST_FORCEINLINE int pthread_mutex_destroy(pthread_mutex_t* m) + { + int ret; + do + { + ret = ::pthread_mutex_destroy(m); + } while (ret == EINTR); + return ret; + } + BOOST_FORCEINLINE int pthread_mutex_lock(pthread_mutex_t* m) + { + int ret; + do + { + ret = ::pthread_mutex_lock(m); + } while (ret == EINTR); + return ret; + } + BOOST_FORCEINLINE int pthread_mutex_unlock(pthread_mutex_t* m) + { + int ret; + do + { + ret = ::pthread_mutex_unlock(m); + } while (ret == EINTR); + return ret; + } +#else + BOOST_FORCEINLINE int pthread_mutex_destroy(pthread_mutex_t* m) + { + return ::pthread_mutex_destroy(m); + } + BOOST_FORCEINLINE int pthread_mutex_lock(pthread_mutex_t* m) + { + return ::pthread_mutex_lock(m); + } + BOOST_FORCEINLINE int pthread_mutex_unlock(pthread_mutex_t* m) + { + return ::pthread_mutex_unlock(m); + } + +#endif + + } + class mutex + { + private: + pthread_mutex_t m; + public: + BOOST_THREAD_NO_COPYABLE(mutex) + + mutex() + { + int const res=pthread_mutex_init(&m,NULL); + if(res) + { + boost::throw_exception(thread_resource_error(res, "boost:: mutex constructor failed in pthread_mutex_init")); + } + } + ~mutex() + { + int const res = posix::pthread_mutex_destroy(&m); + boost::ignore_unused(res); + BOOST_ASSERT(!res); + } + + void lock() + { + int res = posix::pthread_mutex_lock(&m); + if (res) + { + boost::throw_exception(lock_error(res,"boost: mutex lock failed in pthread_mutex_lock")); + } + } + + void unlock() + { + int res = posix::pthread_mutex_unlock(&m); + (void)res; + BOOST_ASSERT(res == 0); +// if (res) +// { +// boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock")); +// } + } + + bool try_lock() + { + int res; + do + { + res = pthread_mutex_trylock(&m); + } while (res == EINTR); + if (res==EBUSY) + { + return false; + } + + return !res; + } + +#define BOOST_THREAD_DEFINES_MUTEX_NATIVE_HANDLE + typedef pthread_mutex_t* native_handle_type; + native_handle_type native_handle() + { + return &m; + } + +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS + typedef unique_lock scoped_lock; + typedef detail::try_lock_wrapper scoped_try_lock; +#endif + }; + + typedef mutex try_mutex; + + class timed_mutex + { + private: + pthread_mutex_t m; +#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK + pthread_cond_t cond; + bool is_locked; +#endif + public: + BOOST_THREAD_NO_COPYABLE(timed_mutex) + timed_mutex() + { + int const res=pthread_mutex_init(&m,NULL); + if(res) + { + boost::throw_exception(thread_resource_error(res, "boost:: timed_mutex constructor failed in pthread_mutex_init")); + } +#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK + int const res2=pthread_cond_init(&cond,NULL); + if(res2) + { + BOOST_VERIFY(!posix::pthread_mutex_destroy(&m)); + //BOOST_VERIFY(!pthread_mutex_destroy(&m)); + boost::throw_exception(thread_resource_error(res2, "boost:: timed_mutex constructor failed in pthread_cond_init")); + } + is_locked=false; +#endif + } + ~timed_mutex() + { + BOOST_VERIFY(!posix::pthread_mutex_destroy(&m)); +#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK + BOOST_VERIFY(!pthread_cond_destroy(&cond)); +#endif + } + +#if defined BOOST_THREAD_USES_DATETIME + template + bool timed_lock(TimeDuration const & relative_time) + { + return timed_lock(get_system_time()+relative_time); + } + bool timed_lock(boost::xtime const & absolute_time) + { + return timed_lock(system_time(absolute_time)); + } +#endif +#ifdef BOOST_PTHREAD_HAS_TIMEDLOCK + void lock() + { + int res = posix::pthread_mutex_lock(&m); + if (res) + { + boost::throw_exception(lock_error(res,"boost: mutex lock failed in pthread_mutex_lock")); + } + } + + void unlock() + { + int res = posix::pthread_mutex_unlock(&m); + (void)res; + BOOST_ASSERT(res == 0); +// if (res) +// { +// boost::throw_exception(lock_error(res,"boost: mutex unlock failed in pthread_mutex_unlock")); +// } + } + + bool try_lock() + { + int res; + do + { + res = pthread_mutex_trylock(&m); + } while (res == EINTR); + if (res==EBUSY) + { + return false; + } + + return !res; + } + + + private: + bool do_try_lock_until(struct timespec const &timeout) + { + int const res=pthread_mutex_timedlock(&m,&timeout); + BOOST_ASSERT(!res || res==ETIMEDOUT); + return !res; + } + public: + +#else + void lock() + { + boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); + while(is_locked) + { + BOOST_VERIFY(!pthread_cond_wait(&cond,&m)); + } + is_locked=true; + } + + void unlock() + { + boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); + is_locked=false; + BOOST_VERIFY(!pthread_cond_signal(&cond)); + } + + bool try_lock() + { + boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); + if(is_locked) + { + return false; + } + is_locked=true; + return true; + } + + private: + bool do_try_lock_until(struct timespec const &timeout) + { + boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); + while(is_locked) + { + int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout); + if(cond_res==ETIMEDOUT) + { + return false; + } + BOOST_ASSERT(!cond_res); + } + is_locked=true; + return true; + } + public: +#endif + +#if defined BOOST_THREAD_USES_DATETIME + bool timed_lock(system_time const & abs_time) + { + struct timespec const ts=boost::detail::to_timespec(abs_time); + return do_try_lock_until(ts); + } +#endif +#ifdef BOOST_THREAD_USES_CHRONO + template + bool try_lock_for(const chrono::duration& rel_time) + { + return try_lock_until(chrono::steady_clock::now() + rel_time); + } + template + bool try_lock_until(const chrono::time_point& t) + { + using namespace chrono; + system_clock::time_point s_now = system_clock::now(); + typename Clock::time_point c_now = Clock::now(); + return try_lock_until(s_now + ceil(t - c_now)); + } + template + bool try_lock_until(const chrono::time_point& t) + { + using namespace chrono; + typedef time_point nano_sys_tmpt; + return try_lock_until(nano_sys_tmpt(ceil(t.time_since_epoch()))); + } + bool try_lock_until(const chrono::time_point& tp) + { + //using namespace chrono; + chrono::nanoseconds d = tp.time_since_epoch(); + timespec ts = boost::detail::to_timespec(d); + return do_try_lock_until(ts); + } +#endif + +#define BOOST_THREAD_DEFINES_TIMED_MUTEX_NATIVE_HANDLE + typedef pthread_mutex_t* native_handle_type; + native_handle_type native_handle() + { + return &m; + } + +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS + typedef unique_lock scoped_timed_lock; + typedef detail::try_lock_wrapper scoped_try_lock; + typedef scoped_timed_lock scoped_lock; +#endif + }; + +} + +#include + + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/pthread/once.hpp b/src/third_party/boost-1.60.0/boost/thread/pthread/once.hpp new file mode 100644 index 00000000000..0bef0387de7 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/pthread/once.hpp @@ -0,0 +1,540 @@ +#ifndef BOOST_THREAD_PTHREAD_ONCE_HPP +#define BOOST_THREAD_PTHREAD_ONCE_HPP + +// once.hpp +// +// (C) Copyright 2007-8 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +namespace boost +{ + + struct once_flag; + + #define BOOST_ONCE_INITIAL_FLAG_VALUE 0 + + namespace thread_detail + { + typedef boost::uint32_t uintmax_atomic_t; + #define BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_C2(value) value##u + #define BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_MAX_C BOOST_THREAD_DETAIL_UINTMAX_ATOMIC_C2(~0) + + } + +#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11 +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(ArgTypes)... args); +#else + template + inline void call_once(once_flag& flag, Function f); + template + inline void call_once(once_flag& flag, Function f, T1 p1); + template + inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2); + template + inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2, T3 p3); +#endif + + struct once_flag + { + BOOST_THREAD_NO_COPYABLE(once_flag) + BOOST_CONSTEXPR once_flag() BOOST_NOEXCEPT + : epoch(BOOST_ONCE_INITIAL_FLAG_VALUE) + {} + private: + volatile thread_detail::uintmax_atomic_t epoch; + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template + friend void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(ArgTypes)... args); +#else + template + friend void call_once(once_flag& flag, Function f); + template + friend void call_once(once_flag& flag, Function f, T1 p1); + template + friend void call_once(once_flag& flag, Function f, T1 p1, T2 p2); + template + friend void call_once(once_flag& flag, Function f, T1 p1, T2 p2, T3 p3); + +#endif + + }; + +#define BOOST_ONCE_INIT once_flag() + +#else // BOOST_THREAD_PROVIDES_ONCE_CXX11 + + struct once_flag + { + volatile thread_detail::uintmax_atomic_t epoch; + }; + +#define BOOST_ONCE_INIT {BOOST_ONCE_INITIAL_FLAG_VALUE} +#endif // BOOST_THREAD_PROVIDES_ONCE_CXX11 + + +#if defined BOOST_THREAD_PROVIDES_INVOKE +#define BOOST_THREAD_INVOKE_RET_VOID detail::invoke +#define BOOST_THREAD_INVOKE_RET_VOID_CALL +#elif defined BOOST_THREAD_PROVIDES_INVOKE_RET +#define BOOST_THREAD_INVOKE_RET_VOID detail::invoke +#define BOOST_THREAD_INVOKE_RET_VOID_CALL +#else +#define BOOST_THREAD_INVOKE_RET_VOID boost::bind +#define BOOST_THREAD_INVOKE_RET_VOID_CALL () +#endif + + namespace thread_detail + { + BOOST_THREAD_DECL uintmax_atomic_t& get_once_per_thread_epoch(); + BOOST_THREAD_DECL extern uintmax_atomic_t once_global_epoch; + BOOST_THREAD_DECL extern pthread_mutex_t once_epoch_mutex; + BOOST_THREAD_DECL extern pthread_cond_t once_epoch_cv; + } + + // Based on Mike Burrows fast_pthread_once algorithm as described in + // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2444.html + + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + + + template + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(ArgTypes)... args) + { + static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE; + static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1; + thread_detail::uintmax_atomic_t const epoch=flag.epoch; + thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch(); + + if(epoch(f)), + thread_detail::decay_copy(boost::forward(args))... + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + flag.epoch=uninitialized_flag; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + BOOST_RETHROW + } + BOOST_CATCH_END + flag.epoch=--thread_detail::once_global_epoch; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + } + else + { + while(flag.epoch==being_initialized) + { + BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); + } + } + } + this_thread_epoch=thread_detail::once_global_epoch; + + } + } +#else + template + inline void call_once(once_flag& flag, Function f) + { + static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE; + static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1; + thread_detail::uintmax_atomic_t const epoch=flag.epoch; + thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch(); + + if(epoch + inline void call_once(once_flag& flag, Function f, T1 p1) + { + static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE; + static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1; + thread_detail::uintmax_atomic_t const epoch=flag.epoch; + thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch(); + + if(epoch + inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2) + { + static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE; + static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1; + thread_detail::uintmax_atomic_t const epoch=flag.epoch; + thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch(); + + if(epoch + inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2, T3 p3) + { + static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE; + static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1; + thread_detail::uintmax_atomic_t const epoch=flag.epoch; + thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch(); + + if(epoch + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f) + { + static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE; + static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1; + thread_detail::uintmax_atomic_t const epoch=flag.epoch; + thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch(); + + if(epoch + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1) + { + static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE; + static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1; + thread_detail::uintmax_atomic_t const epoch=flag.epoch; + thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch(); + + if(epoch(f)), + thread_detail::decay_copy(boost::forward(p1)) + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + flag.epoch=uninitialized_flag; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + BOOST_RETHROW + } + BOOST_CATCH_END + flag.epoch=--thread_detail::once_global_epoch; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + } + else + { + while(flag.epoch==being_initialized) + { + BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); + } + } + } + this_thread_epoch=thread_detail::once_global_epoch; + } + } + template + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2) + { + static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE; + static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1; + thread_detail::uintmax_atomic_t const epoch=flag.epoch; + thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch(); + + if(epoch(f)), + thread_detail::decay_copy(boost::forward(p1)), + thread_detail::decay_copy(boost::forward(p2)) + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + flag.epoch=uninitialized_flag; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + BOOST_RETHROW + } + BOOST_CATCH_END + flag.epoch=--thread_detail::once_global_epoch; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + } + else + { + while(flag.epoch==being_initialized) + { + BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); + } + } + } + this_thread_epoch=thread_detail::once_global_epoch; + } + } + + template + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2, BOOST_THREAD_RV_REF(T3) p3) + { + static thread_detail::uintmax_atomic_t const uninitialized_flag=BOOST_ONCE_INITIAL_FLAG_VALUE; + static thread_detail::uintmax_atomic_t const being_initialized=uninitialized_flag+1; + thread_detail::uintmax_atomic_t const epoch=flag.epoch; + thread_detail::uintmax_atomic_t& this_thread_epoch=thread_detail::get_once_per_thread_epoch(); + + if(epoch(f)), + thread_detail::decay_copy(boost::forward(p1)), + thread_detail::decay_copy(boost::forward(p2)), + thread_detail::decay_copy(boost::forward(p3)) + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + flag.epoch=uninitialized_flag; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + BOOST_RETHROW + } + BOOST_CATCH_END + flag.epoch=--thread_detail::once_global_epoch; + BOOST_VERIFY(!pthread_cond_broadcast(&thread_detail::once_epoch_cv)); + } + else + { + while(flag.epoch==being_initialized) + { + BOOST_VERIFY(!pthread_cond_wait(&thread_detail::once_epoch_cv,&thread_detail::once_epoch_mutex)); + } + } + } + this_thread_epoch=thread_detail::once_global_epoch; + } + } + +#endif + +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/pthread/once_atomic.hpp b/src/third_party/boost-1.60.0/boost/thread/pthread/once_atomic.hpp new file mode 100644 index 00000000000..c54a35c5413 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/pthread/once_atomic.hpp @@ -0,0 +1,313 @@ +#ifndef BOOST_THREAD_PTHREAD_ONCE_ATOMIC_HPP +#define BOOST_THREAD_PTHREAD_ONCE_ATOMIC_HPP + +// once.hpp +// +// (C) Copyright 2013 Andrey Semashev +// (C) Copyright 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include + +#include +#include +#include +#include +#include +#include + +#include + +namespace boost +{ + + struct once_flag; + + namespace thread_detail + { + +#if BOOST_ATOMIC_INT_LOCK_FREE == 2 + typedef unsigned int atomic_int_type; +#elif BOOST_ATOMIC_SHORT_LOCK_FREE == 2 + typedef unsigned short atomic_int_type; +#elif BOOST_ATOMIC_CHAR_LOCK_FREE == 2 + typedef unsigned char atomic_int_type; +#elif BOOST_ATOMIC_LONG_LOCK_FREE == 2 + typedef unsigned long atomic_int_type; +#elif defined(BOOST_HAS_LONG_LONG) && BOOST_ATOMIC_LLONG_LOCK_FREE == 2 + typedef ulong_long_type atomic_int_type; +#else + // All tested integer types are not atomic, the spinlock pool will be used + typedef unsigned int atomic_int_type; +#endif + + typedef boost::atomic atomic_type; + + BOOST_THREAD_DECL bool enter_once_region(once_flag& flag) BOOST_NOEXCEPT; + BOOST_THREAD_DECL void commit_once_region(once_flag& flag) BOOST_NOEXCEPT; + BOOST_THREAD_DECL void rollback_once_region(once_flag& flag) BOOST_NOEXCEPT; + inline atomic_type& get_atomic_storage(once_flag& flag) BOOST_NOEXCEPT; + } + +#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11 + + struct once_flag + { + BOOST_THREAD_NO_COPYABLE(once_flag) + BOOST_CONSTEXPR once_flag() BOOST_NOEXCEPT : storage(0) + { + } + + private: + thread_detail::atomic_type storage; + + friend BOOST_THREAD_DECL bool thread_detail::enter_once_region(once_flag& flag) BOOST_NOEXCEPT; + friend BOOST_THREAD_DECL void thread_detail::commit_once_region(once_flag& flag) BOOST_NOEXCEPT; + friend BOOST_THREAD_DECL void thread_detail::rollback_once_region(once_flag& flag) BOOST_NOEXCEPT; + friend thread_detail::atomic_type& thread_detail::get_atomic_storage(once_flag& flag) BOOST_NOEXCEPT; + }; + +#define BOOST_ONCE_INIT boost::once_flag() + + namespace thread_detail + { + inline atomic_type& get_atomic_storage(once_flag& flag) BOOST_NOEXCEPT + { + //return reinterpret_cast< atomic_type& >(flag.storage); + return flag.storage; + } + } + +#else // BOOST_THREAD_PROVIDES_ONCE_CXX11 + struct once_flag + { + // The thread_detail::atomic_int_type storage is marked + // with this attribute in order to let the compiler know that it will alias this member + // and silence compilation warnings. + BOOST_THREAD_ATTRIBUTE_MAY_ALIAS thread_detail::atomic_int_type storage; + }; + + #define BOOST_ONCE_INIT {0} + + namespace thread_detail + { + inline atomic_type& get_atomic_storage(once_flag& flag) BOOST_NOEXCEPT + { + return reinterpret_cast< atomic_type& >(flag.storage); + } + + } + +#endif // BOOST_THREAD_PROVIDES_ONCE_CXX11 + +#if defined BOOST_THREAD_PROVIDES_INVOKE +#define BOOST_THREAD_INVOKE_RET_VOID detail::invoke +#define BOOST_THREAD_INVOKE_RET_VOID_CALL +#elif defined BOOST_THREAD_PROVIDES_INVOKE_RET +#define BOOST_THREAD_INVOKE_RET_VOID detail::invoke +#define BOOST_THREAD_INVOKE_RET_VOID_CALL +#else +#define BOOST_THREAD_INVOKE_RET_VOID boost::bind +#define BOOST_THREAD_INVOKE_RET_VOID_CALL () +#endif + + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + + template + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(ArgTypes)... args) + { + if (thread_detail::enter_once_region(flag)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward(f)), + thread_detail::decay_copy(boost::forward(args))... + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + thread_detail::rollback_once_region(flag); + BOOST_RETHROW + } + BOOST_CATCH_END + thread_detail::commit_once_region(flag); + } + } +#else + template + inline void call_once(once_flag& flag, Function f) + { + if (thread_detail::enter_once_region(flag)) + { + BOOST_TRY + { + f(); + } + BOOST_CATCH (...) + { + thread_detail::rollback_once_region(flag); + BOOST_RETHROW + } + BOOST_CATCH_END + thread_detail::commit_once_region(flag); + } + } + + template + inline void call_once(once_flag& flag, Function f, T1 p1) + { + if (thread_detail::enter_once_region(flag)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID(f, p1) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + thread_detail::rollback_once_region(flag); + BOOST_RETHROW + } + BOOST_CATCH_END + thread_detail::commit_once_region(flag); + } + } + + template + inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2) + { + if (thread_detail::enter_once_region(flag)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID(f, p1, p2) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + thread_detail::rollback_once_region(flag); + BOOST_RETHROW + } + BOOST_CATCH_END + thread_detail::commit_once_region(flag); + } + } + + template + inline void call_once(once_flag& flag, Function f, T1 p1, T2 p2, T3 p3) + { + if (thread_detail::enter_once_region(flag)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID(f, p1, p2, p3) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + thread_detail::rollback_once_region(flag); + BOOST_RETHROW + } + BOOST_CATCH_END + thread_detail::commit_once_region(flag); + } + } +#if !(defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5130)) + template + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f) + { + if (thread_detail::enter_once_region(flag)) + { + BOOST_TRY + { + f(); + } + BOOST_CATCH (...) + { + thread_detail::rollback_once_region(flag); + BOOST_RETHROW + } + BOOST_CATCH_END + thread_detail::commit_once_region(flag); + } + } + + template + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1) + { + if (thread_detail::enter_once_region(flag)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward(f)), + thread_detail::decay_copy(boost::forward(p1)) + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + thread_detail::rollback_once_region(flag); + BOOST_RETHROW + } + BOOST_CATCH_END + thread_detail::commit_once_region(flag); + } + } + template + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2) + { + if (thread_detail::enter_once_region(flag)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward(f)), + thread_detail::decay_copy(boost::forward(p1)), + thread_detail::decay_copy(boost::forward(p2)) + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH (...) + { + thread_detail::rollback_once_region(flag); + BOOST_RETHROW + } + BOOST_CATCH_END + thread_detail::commit_once_region(flag); + } + } + template + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2, BOOST_THREAD_RV_REF(T3) p3) + { + if (thread_detail::enter_once_region(flag)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward(f)), + thread_detail::decay_copy(boost::forward(p1)), + thread_detail::decay_copy(boost::forward(p2)), + thread_detail::decay_copy(boost::forward(p3)) + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + + } + BOOST_CATCH (...) + { + thread_detail::rollback_once_region(flag); + BOOST_RETHROW + } + BOOST_CATCH_END + thread_detail::commit_once_region(flag); + } + } + +#endif // __SUNPRO_CC + +#endif +} + +#include + +#endif + diff --git a/src/third_party/boost-1.60.0/boost/thread/pthread/pthread_mutex_scoped_lock.hpp b/src/third_party/boost-1.60.0/boost/thread/pthread/pthread_mutex_scoped_lock.hpp new file mode 100644 index 00000000000..cdbf8c67408 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/pthread/pthread_mutex_scoped_lock.hpp @@ -0,0 +1,64 @@ +#ifndef BOOST_PTHREAD_MUTEX_SCOPED_LOCK_HPP +#define BOOST_PTHREAD_MUTEX_SCOPED_LOCK_HPP +// (C) Copyright 2007-8 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +#include + +namespace boost +{ + namespace pthread + { + class pthread_mutex_scoped_lock + { + pthread_mutex_t* m; + bool locked; + public: + explicit pthread_mutex_scoped_lock(pthread_mutex_t* m_): + m(m_),locked(true) + { + BOOST_VERIFY(!pthread_mutex_lock(m)); + } + void unlock() + { + BOOST_VERIFY(!pthread_mutex_unlock(m)); + locked=false; + } + + ~pthread_mutex_scoped_lock() + { + if(locked) + { + unlock(); + } + } + + }; + + class pthread_mutex_scoped_unlock + { + pthread_mutex_t* m; + public: + explicit pthread_mutex_scoped_unlock(pthread_mutex_t* m_): + m(m_) + { + BOOST_VERIFY(!pthread_mutex_unlock(m)); + } + ~pthread_mutex_scoped_unlock() + { + BOOST_VERIFY(!pthread_mutex_lock(m)); + } + + }; + } +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/pthread/recursive_mutex.hpp b/src/third_party/boost-1.60.0/boost/thread/pthread/recursive_mutex.hpp new file mode 100644 index 00000000000..4caae0b5df9 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/pthread/recursive_mutex.hpp @@ -0,0 +1,404 @@ +#ifndef BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP +#define BOOST_THREAD_PTHREAD_RECURSIVE_MUTEX_HPP +// (C) Copyright 2007-8 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS +#include +#endif +#include +#include +#ifndef _WIN32 +#include +#endif +#include +#include +#include +#include +#ifdef BOOST_THREAD_USES_CHRONO +#include +#include +#endif +#include + +#if (defined _POSIX_TIMEOUTS && (_POSIX_TIMEOUTS-0)>=200112L) \ + || (defined __ANDROID__ && defined __ANDROID_API__ && __ANDROID_API__ >= 21) +#ifndef BOOST_PTHREAD_HAS_TIMEDLOCK +#define BOOST_PTHREAD_HAS_TIMEDLOCK +#endif +#endif + +#if defined BOOST_HAS_PTHREAD_MUTEXATTR_SETTYPE \ + || defined __ANDROID__ +#define BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE +#endif + +#if defined BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE && defined BOOST_PTHREAD_HAS_TIMEDLOCK +#define BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK +#endif + +#include + +namespace boost +{ + class recursive_mutex + { + private: + pthread_mutex_t m; +#ifndef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE + pthread_cond_t cond; + bool is_locked; + pthread_t owner; + unsigned count; +#endif + public: + BOOST_THREAD_NO_COPYABLE(recursive_mutex) + recursive_mutex() + { +#ifdef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE + pthread_mutexattr_t attr; + + int const init_attr_res=pthread_mutexattr_init(&attr); + if(init_attr_res) + { + boost::throw_exception(thread_resource_error(init_attr_res, "boost:: recursive_mutex constructor failed in pthread_mutexattr_init")); + } + int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE); + if(set_attr_res) + { + BOOST_VERIFY(!pthread_mutexattr_destroy(&attr)); + boost::throw_exception(thread_resource_error(set_attr_res, "boost:: recursive_mutex constructor failed in pthread_mutexattr_settype")); + } + + int const res=pthread_mutex_init(&m,&attr); + if(res) + { + BOOST_VERIFY(!pthread_mutexattr_destroy(&attr)); + boost::throw_exception(thread_resource_error(res, "boost:: recursive_mutex constructor failed in pthread_mutex_init")); + } + BOOST_VERIFY(!pthread_mutexattr_destroy(&attr)); +#else + int const res=pthread_mutex_init(&m,NULL); + if(res) + { + boost::throw_exception(thread_resource_error(res, "boost:: recursive_mutex constructor failed in pthread_mutex_init")); + } + int const res2=pthread_cond_init(&cond,NULL); + if(res2) + { + BOOST_VERIFY(!pthread_mutex_destroy(&m)); + boost::throw_exception(thread_resource_error(res2, "boost:: recursive_mutex constructor failed in pthread_cond_init")); + } + is_locked=false; + count=0; +#endif + } + ~recursive_mutex() + { + BOOST_VERIFY(!pthread_mutex_destroy(&m)); +#ifndef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE + BOOST_VERIFY(!pthread_cond_destroy(&cond)); +#endif + } + +#ifdef BOOST_THREAD_HAS_PTHREAD_MUTEXATTR_SETTYPE + void lock() + { + BOOST_VERIFY(!pthread_mutex_lock(&m)); + } + + void unlock() + { + BOOST_VERIFY(!pthread_mutex_unlock(&m)); + } + + bool try_lock() BOOST_NOEXCEPT + { + int const res=pthread_mutex_trylock(&m); + BOOST_ASSERT(!res || res==EBUSY); + return !res; + } +#define BOOST_THREAD_DEFINES_RECURSIVE_MUTEX_NATIVE_HANDLE + typedef pthread_mutex_t* native_handle_type; + native_handle_type native_handle() + { + return &m; + } + +#else + void lock() + { + boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); + if(is_locked && pthread_equal(owner,pthread_self())) + { + ++count; + return; + } + + while(is_locked) + { + BOOST_VERIFY(!pthread_cond_wait(&cond,&m)); + } + is_locked=true; + ++count; + owner=pthread_self(); + } + + void unlock() + { + boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); + if(!--count) + { + is_locked=false; + } + BOOST_VERIFY(!pthread_cond_signal(&cond)); + } + + bool try_lock() + { + boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); + if(is_locked && !pthread_equal(owner,pthread_self())) + { + return false; + } + is_locked=true; + ++count; + owner=pthread_self(); + return true; + } + +#endif + +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS + typedef unique_lock scoped_lock; + typedef detail::try_lock_wrapper scoped_try_lock; +#endif + }; + + typedef recursive_mutex recursive_try_mutex; + + class recursive_timed_mutex + { + private: + pthread_mutex_t m; +#ifndef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK + pthread_cond_t cond; + bool is_locked; + pthread_t owner; + unsigned count; +#endif + public: + BOOST_THREAD_NO_COPYABLE(recursive_timed_mutex) + recursive_timed_mutex() + { +#ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK + pthread_mutexattr_t attr; + + int const init_attr_res=pthread_mutexattr_init(&attr); + if(init_attr_res) + { + boost::throw_exception(thread_resource_error(init_attr_res, "boost:: recursive_timed_mutex constructor failed in pthread_mutexattr_init")); + } + int const set_attr_res=pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE); + if(set_attr_res) + { + boost::throw_exception(thread_resource_error(set_attr_res, "boost:: recursive_timed_mutex constructor failed in pthread_mutexattr_settype")); + } + + int const res=pthread_mutex_init(&m,&attr); + if(res) + { + BOOST_VERIFY(!pthread_mutexattr_destroy(&attr)); + boost::throw_exception(thread_resource_error(res, "boost:: recursive_timed_mutex constructor failed in pthread_mutex_init")); + } + BOOST_VERIFY(!pthread_mutexattr_destroy(&attr)); +#else + int const res=pthread_mutex_init(&m,NULL); + if(res) + { + boost::throw_exception(thread_resource_error(res, "boost:: recursive_timed_mutex constructor failed in pthread_mutex_init")); + } + int const res2=pthread_cond_init(&cond,NULL); + if(res2) + { + BOOST_VERIFY(!pthread_mutex_destroy(&m)); + boost::throw_exception(thread_resource_error(res2, "boost:: recursive_timed_mutex constructor failed in pthread_cond_init")); + } + is_locked=false; + count=0; +#endif + } + ~recursive_timed_mutex() + { + BOOST_VERIFY(!pthread_mutex_destroy(&m)); +#ifndef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK + BOOST_VERIFY(!pthread_cond_destroy(&cond)); +#endif + } + +#if defined BOOST_THREAD_USES_DATETIME + template + bool timed_lock(TimeDuration const & relative_time) + { + return timed_lock(get_system_time()+relative_time); + } +#endif + +#ifdef BOOST_USE_PTHREAD_RECURSIVE_TIMEDLOCK + void lock() + { + BOOST_VERIFY(!pthread_mutex_lock(&m)); + } + + void unlock() + { + BOOST_VERIFY(!pthread_mutex_unlock(&m)); + } + + bool try_lock() + { + int const res=pthread_mutex_trylock(&m); + BOOST_ASSERT(!res || res==EBUSY); + return !res; + } + private: + bool do_try_lock_until(struct timespec const &timeout) + { + int const res=pthread_mutex_timedlock(&m,&timeout); + BOOST_ASSERT(!res || res==ETIMEDOUT); + return !res; + } + + public: + +#else + void lock() + { + boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); + if(is_locked && pthread_equal(owner,pthread_self())) + { + ++count; + return; + } + + while(is_locked) + { + BOOST_VERIFY(!pthread_cond_wait(&cond,&m)); + } + is_locked=true; + ++count; + owner=pthread_self(); + } + + void unlock() + { + boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); + if(!--count) + { + is_locked=false; + } + BOOST_VERIFY(!pthread_cond_signal(&cond)); + } + + bool try_lock() BOOST_NOEXCEPT + { + boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); + if(is_locked && !pthread_equal(owner,pthread_self())) + { + return false; + } + is_locked=true; + ++count; + owner=pthread_self(); + return true; + } + + private: + bool do_try_lock_until(struct timespec const &timeout) + { + boost::pthread::pthread_mutex_scoped_lock const local_lock(&m); + if(is_locked && pthread_equal(owner,pthread_self())) + { + ++count; + return true; + } + while(is_locked) + { + int const cond_res=pthread_cond_timedwait(&cond,&m,&timeout); + if(cond_res==ETIMEDOUT) + { + return false; + } + BOOST_ASSERT(!cond_res); + } + is_locked=true; + ++count; + owner=pthread_self(); + return true; + } + public: + +#endif + +#if defined BOOST_THREAD_USES_DATETIME + bool timed_lock(system_time const & abs_time) + { + struct timespec const ts=detail::to_timespec(abs_time); + return do_try_lock_until(ts); + } +#endif +#ifdef BOOST_THREAD_USES_CHRONO + template + bool try_lock_for(const chrono::duration& rel_time) + { + return try_lock_until(chrono::steady_clock::now() + rel_time); + } + template + bool try_lock_until(const chrono::time_point& t) + { + using namespace chrono; + system_clock::time_point s_now = system_clock::now(); + typename Clock::time_point c_now = Clock::now(); + return try_lock_until(s_now + ceil(t - c_now)); + } + template + bool try_lock_until(const chrono::time_point& t) + { + using namespace chrono; + typedef time_point nano_sys_tmpt; + return try_lock_until(nano_sys_tmpt(ceil(t.time_since_epoch()))); + } + bool try_lock_until(const chrono::time_point& tp) + { + //using namespace chrono; + chrono::nanoseconds d = tp.time_since_epoch(); + timespec ts = boost::detail::to_timespec(d); + return do_try_lock_until(ts); + } +#endif + +#define BOOST_THREAD_DEFINES_RECURSIVE_TIMED_MUTEX_NATIVE_HANDLE + typedef pthread_mutex_t* native_handle_type; + native_handle_type native_handle() + { + return &m; + } + +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS + typedef unique_lock scoped_timed_lock; + typedef detail::try_lock_wrapper scoped_try_lock; + typedef scoped_timed_lock scoped_lock; +#endif + }; + +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/pthread/shared_mutex.hpp b/src/third_party/boost-1.60.0/boost/thread/pthread/shared_mutex.hpp new file mode 100644 index 00000000000..458d6c83613 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/pthread/shared_mutex.hpp @@ -0,0 +1,716 @@ +#ifndef BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP +#define BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP + +// (C) Copyright 2006-8 Anthony Williams +// (C) Copyright 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS +#include +#endif +#ifdef BOOST_THREAD_USES_CHRONO +#include +#include +#endif +#include +#include + +#include + +namespace boost +{ + class shared_mutex + { + private: + class state_data + { + public: + state_data () : + shared_count(0), + exclusive(false), + upgrade(false), + exclusive_waiting_blocked(false) + {} + + void assert_free() const + { + BOOST_ASSERT( ! exclusive ); + BOOST_ASSERT( ! upgrade ); + BOOST_ASSERT( shared_count==0 ); + } + + void assert_locked() const + { + BOOST_ASSERT( exclusive ); + BOOST_ASSERT( shared_count==0 ); + BOOST_ASSERT( ! upgrade ); + } + + void assert_lock_shared () const + { + BOOST_ASSERT( ! exclusive ); + BOOST_ASSERT( shared_count>0 ); + //BOOST_ASSERT( (! upgrade) || (shared_count>1)); + // if upgraded there are at least 2 threads sharing the mutex, + // except when unlock_upgrade_and_lock has decreased the number of readers but has not taken yet exclusive ownership. + } + + void assert_lock_upgraded () const + { + BOOST_ASSERT( ! exclusive ); + BOOST_ASSERT( upgrade ); + BOOST_ASSERT( shared_count>0 ); + } + + void assert_lock_not_upgraded () const + { + BOOST_ASSERT( ! upgrade ); + } + + bool can_lock () const + { + return ! (shared_count || exclusive); + } + + void exclusive_blocked (bool blocked) + { + exclusive_waiting_blocked = blocked; + } + + void lock () + { + exclusive = true; + } + + void unlock () + { + exclusive = false; + exclusive_waiting_blocked = false; + } + + bool can_lock_shared () const + { + return ! (exclusive || exclusive_waiting_blocked); + } + + bool more_shared () const + { + return shared_count > 0 ; + } + unsigned get_shared_count () const + { + return shared_count ; + } + unsigned lock_shared () + { + return ++shared_count; + } + + + void unlock_shared () + { + --shared_count; + } + + bool unlock_shared_downgrades() + { + if (upgrade) { + upgrade=false; + exclusive=true; + return true; + } else { + exclusive_waiting_blocked=false; + return false; + } + } + + void lock_upgrade () + { + ++shared_count; + upgrade=true; + } + bool can_lock_upgrade () const + { + return ! (exclusive || exclusive_waiting_blocked || upgrade); + } + + void unlock_upgrade () + { + upgrade=false; + --shared_count; + } + + //private: + unsigned shared_count; + bool exclusive; + bool upgrade; + bool exclusive_waiting_blocked; + }; + + + + state_data state; + boost::mutex state_change; + boost::condition_variable shared_cond; + boost::condition_variable exclusive_cond; + boost::condition_variable upgrade_cond; + + void release_waiters() + { + exclusive_cond.notify_one(); + shared_cond.notify_all(); + } + + public: + + BOOST_THREAD_NO_COPYABLE(shared_mutex) + + shared_mutex() + { + } + + ~shared_mutex() + { + } + + void lock_shared() + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + boost::this_thread::disable_interruption do_not_disturb; +#endif + boost::unique_lock lk(state_change); + while(!state.can_lock_shared()) + { + shared_cond.wait(lk); + } + state.lock_shared(); + } + + bool try_lock_shared() + { + boost::unique_lock lk(state_change); + + if(!state.can_lock_shared()) + { + return false; + } + state.lock_shared(); + return true; + } + +#if defined BOOST_THREAD_USES_DATETIME + bool timed_lock_shared(system_time const& timeout) + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + boost::this_thread::disable_interruption do_not_disturb; +#endif + boost::unique_lock lk(state_change); + + while(!state.can_lock_shared()) + { + if(!shared_cond.timed_wait(lk,timeout)) + { + return false; + } + } + state.lock_shared(); + return true; + } + + template + bool timed_lock_shared(TimeDuration const & relative_time) + { + return timed_lock_shared(get_system_time()+relative_time); + } +#endif +#ifdef BOOST_THREAD_USES_CHRONO + template + bool try_lock_shared_for(const chrono::duration& rel_time) + { + return try_lock_shared_until(chrono::steady_clock::now() + rel_time); + } + template + bool try_lock_shared_until(const chrono::time_point& abs_time) + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + boost::this_thread::disable_interruption do_not_disturb; +#endif + boost::unique_lock lk(state_change); + + while(!state.can_lock_shared()) + //while(state.exclusive || state.exclusive_waiting_blocked) + { + if(cv_status::timeout==shared_cond.wait_until(lk,abs_time)) + { + return false; + } + } + state.lock_shared(); + return true; + } +#endif + void unlock_shared() + { + boost::unique_lock lk(state_change); + state.assert_lock_shared(); + state.unlock_shared(); + if (! state.more_shared()) + { + if (state.upgrade) + { + // As there is a thread doing a unlock_upgrade_and_lock that is waiting for ! state.more_shared() + // avoid other threads to lock, lock_upgrade or lock_shared, so only this thread is notified. + state.upgrade=false; + state.exclusive=true; + lk.unlock(); + upgrade_cond.notify_one(); + } + else + { + state.exclusive_waiting_blocked=false; + lk.unlock(); + } + release_waiters(); + } + } + + void lock() + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + boost::this_thread::disable_interruption do_not_disturb; +#endif + boost::unique_lock lk(state_change); + + while (state.shared_count || state.exclusive) + { + state.exclusive_waiting_blocked=true; + exclusive_cond.wait(lk); + } + state.exclusive=true; + } + +#if defined BOOST_THREAD_USES_DATETIME + bool timed_lock(system_time const& timeout) + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + boost::this_thread::disable_interruption do_not_disturb; +#endif + boost::unique_lock lk(state_change); + + while(state.shared_count || state.exclusive) + { + state.exclusive_waiting_blocked=true; + if(!exclusive_cond.timed_wait(lk,timeout)) + { + if(state.shared_count || state.exclusive) + { + state.exclusive_waiting_blocked=false; + release_waiters(); + return false; + } + break; + } + } + state.exclusive=true; + return true; + } + + template + bool timed_lock(TimeDuration const & relative_time) + { + return timed_lock(get_system_time()+relative_time); + } +#endif +#ifdef BOOST_THREAD_USES_CHRONO + template + bool try_lock_for(const chrono::duration& rel_time) + { + return try_lock_until(chrono::steady_clock::now() + rel_time); + } + template + bool try_lock_until(const chrono::time_point& abs_time) + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + boost::this_thread::disable_interruption do_not_disturb; +#endif + boost::unique_lock lk(state_change); + + while(state.shared_count || state.exclusive) + { + state.exclusive_waiting_blocked=true; + if(cv_status::timeout == exclusive_cond.wait_until(lk,abs_time)) + { + if(state.shared_count || state.exclusive) + { + state.exclusive_waiting_blocked=false; + release_waiters(); + return false; + } + break; + } + } + state.exclusive=true; + return true; + } +#endif + + bool try_lock() + { + boost::unique_lock lk(state_change); + + if(state.shared_count || state.exclusive) + { + return false; + } + else + { + state.exclusive=true; + return true; + } + + } + + void unlock() + { + boost::unique_lock lk(state_change); + state.assert_locked(); + state.exclusive=false; + state.exclusive_waiting_blocked=false; + state.assert_free(); + release_waiters(); + } + + void lock_upgrade() + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + boost::this_thread::disable_interruption do_not_disturb; +#endif + boost::unique_lock lk(state_change); + while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) + { + shared_cond.wait(lk); + } + state.lock_shared(); + state.upgrade=true; + } + +#if defined BOOST_THREAD_USES_DATETIME + bool timed_lock_upgrade(system_time const& timeout) + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + boost::this_thread::disable_interruption do_not_disturb; +#endif + boost::unique_lock lk(state_change); + while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) + { + if(!shared_cond.timed_wait(lk,timeout)) + { + if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) + { + return false; + } + break; + } + } + state.lock_shared(); + state.upgrade=true; + return true; + } + + template + bool timed_lock_upgrade(TimeDuration const & relative_time) + { + return timed_lock_upgrade(get_system_time()+relative_time); + } +#endif +#ifdef BOOST_THREAD_USES_CHRONO + template + bool try_lock_upgrade_for(const chrono::duration& rel_time) + { + return try_lock_upgrade_until(chrono::steady_clock::now() + rel_time); + } + template + bool try_lock_upgrade_until(const chrono::time_point& abs_time) + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + boost::this_thread::disable_interruption do_not_disturb; +#endif + boost::unique_lock lk(state_change); + while(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) + { + if(cv_status::timeout == shared_cond.wait_until(lk,abs_time)) + { + if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) + { + return false; + } + break; + } + } + state.lock_shared(); + state.upgrade=true; + return true; + } +#endif + bool try_lock_upgrade() + { + boost::unique_lock lk(state_change); + if(state.exclusive || state.exclusive_waiting_blocked || state.upgrade) + { + return false; + } + else + { + state.lock_shared(); + state.upgrade=true; + state.assert_lock_upgraded(); + return true; + } + } + + void unlock_upgrade() + { + boost::unique_lock lk(state_change); + //state.upgrade=false; + state.unlock_upgrade(); + if(! state.more_shared() ) + { + state.exclusive_waiting_blocked=false; + release_waiters(); + } else { + shared_cond.notify_all(); + } + } + + // Upgrade <-> Exclusive + void unlock_upgrade_and_lock() + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + boost::this_thread::disable_interruption do_not_disturb; +#endif + boost::unique_lock lk(state_change); + state.assert_lock_upgraded(); + state.unlock_shared(); + while (state.more_shared()) + { + upgrade_cond.wait(lk); + } + state.upgrade=false; + state.exclusive=true; + state.assert_locked(); + } + + void unlock_and_lock_upgrade() + { + boost::unique_lock lk(state_change); + state.assert_locked(); + state.exclusive=false; + state.upgrade=true; + state.lock_shared(); + state.exclusive_waiting_blocked=false; + state.assert_lock_upgraded(); + release_waiters(); + } + + bool try_unlock_upgrade_and_lock() + { + boost::unique_lock lk(state_change); + state.assert_lock_upgraded(); + if( !state.exclusive + && !state.exclusive_waiting_blocked + && state.upgrade + && state.shared_count==1) + { + state.shared_count=0; + state.exclusive=true; + state.upgrade=false; + state.assert_locked(); + return true; + } + return false; + } +#ifdef BOOST_THREAD_USES_CHRONO + template + bool + try_unlock_upgrade_and_lock_for( + const chrono::duration& rel_time) + { + return try_unlock_upgrade_and_lock_until( + chrono::steady_clock::now() + rel_time); + } + template + bool + try_unlock_upgrade_and_lock_until( + const chrono::time_point& abs_time) + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + boost::this_thread::disable_interruption do_not_disturb; +#endif + boost::unique_lock lk(state_change); + state.assert_lock_upgraded(); + if (state.shared_count != 1) + { + for (;;) + { + cv_status status = shared_cond.wait_until(lk,abs_time); + if (state.shared_count == 1) + break; + if(status == cv_status::timeout) + return false; + } + } + state.upgrade=false; + state.exclusive=true; + state.exclusive_waiting_blocked=false; + state.shared_count=0; + return true; + } +#endif + + // Shared <-> Exclusive + void unlock_and_lock_shared() + { + boost::unique_lock lk(state_change); + state.assert_locked(); + state.exclusive=false; + state.lock_shared(); + state.exclusive_waiting_blocked=false; + release_waiters(); + } + +#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS + bool try_unlock_shared_and_lock() + { + boost::unique_lock lk(state_change); + state.assert_lock_shared(); + if( !state.exclusive + && !state.exclusive_waiting_blocked + && !state.upgrade + && state.shared_count==1) + { + state.shared_count=0; + state.exclusive=true; + return true; + } + return false; + } +#ifdef BOOST_THREAD_USES_CHRONO + template + bool + try_unlock_shared_and_lock_for( + const chrono::duration& rel_time) + { + return try_unlock_shared_and_lock_until( + chrono::steady_clock::now() + rel_time); + } + template + bool + try_unlock_shared_and_lock_until( + const chrono::time_point& abs_time) + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + boost::this_thread::disable_interruption do_not_disturb; +#endif + boost::unique_lock lk(state_change); + state.assert_lock_shared(); + if (state.shared_count != 1) + { + for (;;) + { + cv_status status = shared_cond.wait_until(lk,abs_time); + if (state.shared_count == 1) + break; + if(status == cv_status::timeout) + return false; + } + } + state.upgrade=false; + state.exclusive=true; + state.exclusive_waiting_blocked=false; + state.shared_count=0; + return true; + } +#endif +#endif + + // Shared <-> Upgrade + void unlock_upgrade_and_lock_shared() + { + boost::unique_lock lk(state_change); + state.assert_lock_upgraded(); + state.upgrade=false; + state.exclusive_waiting_blocked=false; + release_waiters(); + } + +#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS + bool try_unlock_shared_and_lock_upgrade() + { + boost::unique_lock lk(state_change); + state.assert_lock_shared(); + if( !state.exclusive + && !state.exclusive_waiting_blocked + && !state.upgrade + ) + { + state.upgrade=true; + return true; + } + return false; + } +#ifdef BOOST_THREAD_USES_CHRONO + template + bool + try_unlock_shared_and_lock_upgrade_for( + const chrono::duration& rel_time) + { + return try_unlock_shared_and_lock_upgrade_until( + chrono::steady_clock::now() + rel_time); + } + template + bool + try_unlock_shared_and_lock_upgrade_until( + const chrono::time_point& abs_time) + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + boost::this_thread::disable_interruption do_not_disturb; +#endif + boost::unique_lock lk(state_change); + state.assert_lock_shared(); + if( state.exclusive + || state.exclusive_waiting_blocked + || state.upgrade + ) + { + for (;;) + { + cv_status status = exclusive_cond.wait_until(lk,abs_time); + if( ! state.exclusive + && ! state.exclusive_waiting_blocked + && ! state.upgrade + ) + break; + if(status == cv_status::timeout) + return false; + } + } + state.upgrade=true; + return true; + } +#endif +#endif + }; + + typedef shared_mutex upgrade_mutex; +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/pthread/shared_mutex_assert.hpp b/src/third_party/boost-1.60.0/boost/thread/pthread/shared_mutex_assert.hpp new file mode 100644 index 00000000000..186ab7984bd --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/pthread/shared_mutex_assert.hpp @@ -0,0 +1,724 @@ +#ifndef BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP +#define BOOST_THREAD_PTHREAD_SHARED_MUTEX_HPP + +// (C) Copyright 2006-8 Anthony Williams +// (C) Copyright 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS +#include +#endif +#ifdef BOOST_THREAD_USES_CHRONO +#include +#include +#endif +#include +#include + +#include + +namespace boost +{ + class shared_mutex + { + private: + class state_data + { + public: + state_data () : + shared_count(0), + exclusive(false), + upgrade(false), + exclusive_waiting_blocked(false) + {} + + void assert_free() const + { + BOOST_ASSERT( ! exclusive ); + BOOST_ASSERT( ! upgrade ); + BOOST_ASSERT( shared_count==0 ); + } + + void assert_locked() const + { + BOOST_ASSERT( exclusive ); + BOOST_ASSERT( shared_count==0 ); + BOOST_ASSERT( ! upgrade ); + } + + void assert_lock_shared () const + { + BOOST_ASSERT( ! exclusive ); + BOOST_ASSERT( shared_count>0 ); + //BOOST_ASSERT( (! upgrade) || (shared_count>1)); + // if upgraded there are at least 2 threads sharing the mutex, + // except when unlock_upgrade_and_lock has decreased the number of readers but has not taken yet exclusive ownership. + } + + void assert_lock_upgraded () const + { + BOOST_ASSERT( ! exclusive ); + BOOST_ASSERT( upgrade ); + BOOST_ASSERT( shared_count>0 ); + } + + void assert_lock_not_upgraded () const + { + BOOST_ASSERT( ! upgrade ); + } + + bool can_lock () const + { + return ! (shared_count || exclusive); + } + + void exclusive_blocked (bool blocked) + { + exclusive_waiting_blocked = blocked; + } + + void lock () + { + exclusive = true; + } + + void unlock () + { + exclusive = false; + exclusive_waiting_blocked = false; + } + + bool can_lock_shared () const + { + return ! (exclusive || exclusive_waiting_blocked); + } + + bool is_last_shared () const + { + return !shared_count ; + } + unsigned get_shared_count () const + { + return shared_count ; + } + unsigned lock_shared () + { + return ++shared_count; + } + + + void unlock_shared () + { + --shared_count; + } + + bool unlock_shared_downgrades() + { + if (upgrade) { + upgrade=false; + exclusive=true; + return true; + } else { + exclusive_waiting_blocked=false; + return false; + } + } + + void lock_upgrade () + { + lock_shared (); + upgrade=true; + } + bool can_lock_upgrade () const + { + return ! (exclusive || exclusive_waiting_blocked || upgrade); + } + + void unlock_upgrade () + { + upgrade=false; + unlock_shared(); + } + + //private: + unsigned shared_count; + bool exclusive; + bool upgrade; + bool exclusive_waiting_blocked; + }; + + + + state_data state; + boost::mutex state_change; + boost::condition_variable shared_cond; + boost::condition_variable exclusive_cond; + boost::condition_variable upgrade_cond; + + void release_waiters() + { + exclusive_cond.notify_one(); + shared_cond.notify_all(); + } + + public: + BOOST_THREAD_NO_COPYABLE(shared_mutex) + + shared_mutex() + { + } + + ~shared_mutex() + { + } + + void lock_shared() + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + boost::this_thread::disable_interruption do_not_disturb; +#endif + boost::unique_lock lk(state_change); + + while(!state.can_lock_shared()) + { + shared_cond.wait(lk); + } + state.lock_shared(); + } + + bool try_lock_shared() + { + boost::unique_lock lk(state_change); + if(!state.can_lock_shared()) + { + return false; + } + else + { + state.lock_shared(); + return true; + } + } + +#if defined BOOST_THREAD_USES_DATETIME + bool timed_lock_shared(system_time const& timeout) + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + boost::this_thread::disable_interruption do_not_disturb; +#endif + boost::unique_lock lk(state_change); + + while(!state.can_lock_shared()) + { + if(!shared_cond.timed_wait(lk,timeout)) + { + return false; + } + } + state.lock_shared(); + return true; + } + + template + bool timed_lock_shared(TimeDuration const & relative_time) + { + return timed_lock_shared(get_system_time()+relative_time); + } +#endif +#ifdef BOOST_THREAD_USES_CHRONO + template + bool try_lock_shared_for(const chrono::duration& rel_time) + { + return try_lock_shared_until(chrono::steady_clock::now() + rel_time); + } + template + bool try_lock_shared_until(const chrono::time_point& abs_time) + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + boost::this_thread::disable_interruption do_not_disturb; +#endif + boost::unique_lock lk(state_change); + + while(!state.can_lock_shared()) + { + if(cv_status::timeout==shared_cond.wait_until(lk,abs_time)) + { + return false; + } + } + state.lock_shared(); + return true; + } +#endif + void unlock_shared() + { + boost::unique_lock lk(state_change); + state.assert_lock_shared(); + state.unlock_shared(); + if (state.get_shared_count () == 0) + { + if (state.unlock_shared_downgrades()) + { + lk.unlock(); + upgrade_cond.notify_one(); + } else { + lk.unlock(); + } + release_waiters(); + } + } + + void lock() + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + boost::this_thread::disable_interruption do_not_disturb; +#endif + boost::unique_lock lk(state_change); + + while(!state.can_lock()) + { + state.exclusive_blocked(true); + exclusive_cond.wait(lk); + } + state.lock(); + } + +#if defined BOOST_THREAD_USES_DATETIME + bool timed_lock(system_time const& timeout) + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + boost::this_thread::disable_interruption do_not_disturb; +#endif + boost::unique_lock lk(state_change); + + while(!state.can_lock()) + { + state.exclusive_blocked(true); + if(!exclusive_cond.timed_wait(lk,timeout)) + { + if(!state.can_lock()) + { + state.exclusive_blocked(false); + release_waiters(); + return false; + } + break; + } + } + state.exclusive=true; + //state.lock(); + return true; + } + + template + bool timed_lock(TimeDuration const & relative_time) + { + return timed_lock(get_system_time()+relative_time); + } +#endif +#ifdef BOOST_THREAD_USES_CHRONO + template + bool try_lock_for(const chrono::duration& rel_time) + { + return try_lock_until(chrono::steady_clock::now() + rel_time); + } + template + bool try_lock_until(const chrono::time_point& abs_time) + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + boost::this_thread::disable_interruption do_not_disturb; +#endif + boost::unique_lock lk(state_change); + + while(!state.can_lock()) + { + state.exclusive_blocked(true); + if(cv_status::timeout == exclusive_cond.wait_until(lk,abs_time)) + { + if(!state.can_lock()) + { + state.exclusive_blocked(false); + release_waiters(); + return false; + } + break; + } + } + state.exclusive=true; + //state.lock(); + return true; + } +#endif + + bool try_lock() + { + boost::unique_lock lk(state_change); + + if(!state.can_lock()) + { + return false; + } + else + { + state.lock(); + return true; + } + + } + + void unlock() + { + boost::unique_lock lk(state_change); + state.assert_locked(); + state.unlock(); + state.assert_free(); + release_waiters(); + } + + void lock_upgrade() + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + boost::this_thread::disable_interruption do_not_disturb; +#endif + boost::unique_lock lk(state_change); + while(!state.can_lock_upgrade()) + { + shared_cond.wait(lk); + } + state.lock_upgrade(); + } + +#if defined BOOST_THREAD_USES_DATETIME + bool timed_lock_upgrade(system_time const& timeout) + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + boost::this_thread::disable_interruption do_not_disturb; +#endif + boost::unique_lock lk(state_change); + while(!state.can_lock_upgrade()) + { + if(!shared_cond.timed_wait(lk,timeout)) + { + if(!state.can_lock_upgrade()) + { + return false; + } + break; + } + } + state.lock_upgrade(); + return true; + } + + template + bool timed_lock_upgrade(TimeDuration const & relative_time) + { + return timed_lock_upgrade(get_system_time()+relative_time); + } +#endif +#ifdef BOOST_THREAD_USES_CHRONO + template + bool try_lock_upgrade_for(const chrono::duration& rel_time) + { + return try_lock_upgrade_until(chrono::steady_clock::now() + rel_time); + } + template + bool try_lock_upgrade_until(const chrono::time_point& abs_time) + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + boost::this_thread::disable_interruption do_not_disturb; +#endif + boost::unique_lock lk(state_change); + while(!state.can_lock_upgrade()) + { + if(cv_status::timeout == shared_cond.wait_until(lk,abs_time)) + { + if(!state.can_lock_upgrade()) + { + return false; + } + break; + } + } + state.lock_upgrade(); + return true; + } +#endif + bool try_lock_upgrade() + { + boost::unique_lock lk(state_change); + if(!state.can_lock_upgrade()) + { + return false; + } + else + { + state.lock_upgrade(); + state.assert_lock_upgraded(); + return true; + } + } + + void unlock_upgrade() + { + boost::unique_lock lk(state_change); + state.assert_lock_upgraded(); + state.unlock_upgrade(); + state.assert_lock_not_upgraded (); + if(state.get_shared_count () == 0) + { + state.exclusive_blocked(false); + lk.unlock(); + release_waiters(); + } else { + lk.unlock(); + shared_cond.notify_all(); + } + } + + // Upgrade <-> Exclusive + void unlock_upgrade_and_lock() + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + boost::this_thread::disable_interruption do_not_disturb; +#endif + boost::unique_lock lk(state_change); + state.assert_lock_upgraded(); + // assert state.get_shared_count() >=1 + while( + //! state.exclusive_waiting_blocked // Fixme: is this needed? + //&& + state.get_shared_count()!=1) + { + upgrade_cond.wait(lk); + } + state.unlock_upgrade(); + state.lock(); + state.assert_locked(); + } + + void unlock_and_lock_upgrade() + { + boost::unique_lock lk(state_change); + state.assert_locked(); + state.unlock(); + state.lock_upgrade(); + state.assert_lock_upgraded(); + release_waiters(); + } + + bool try_unlock_upgrade_and_lock() + { + boost::unique_lock lk(state_change); + state.assert_lock_upgraded(); + if( //!state.exclusive // this should be removed once the assertion work + ! state.exclusive_waiting_blocked // Fixme: why this is needed? + //&& state.upgrade // this should be removed once the assertion work + && state.get_shared_count()==1) + { + state.unlock_upgrade(); + state.lock(); + state.assert_locked(); + return true; + } + return false; + } +#ifdef BOOST_THREAD_USES_CHRONO + template + bool + try_unlock_upgrade_and_lock_for( + const chrono::duration& rel_time) + { + return try_unlock_upgrade_and_lock_until( + chrono::steady_clock::now() + rel_time); + } + template + bool + try_unlock_upgrade_and_lock_until( + const chrono::time_point& abs_time) + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + boost::this_thread::disable_interruption do_not_disturb; +#endif + boost::unique_lock lk(state_change); + state.assert_lock_upgraded(); + if (//state.exclusive // this should be removed once the assertion work + state.exclusive_waiting_blocked // Fixme: is this needed? + //|| ! state.upgrade // this should be removed once the assertion work + || state.get_shared_count() != 1) + { + for (;;) + { + //cv_status status = shared_cond.wait_until(lk,abs_time); + cv_status status = upgrade_cond.wait_until(lk,abs_time); + if (//!state.exclusive // this should be removed once the assertion work + ! state.exclusive_waiting_blocked // Fixme: is this needed? + //&& ! state.upgrade // this should be removed once the assertion work + && state.get_shared_count() == 1) + break; + if(status == cv_status::timeout) + return false; + } + } + state.unlock_upgrade(); + state.lock(); + return true; + } +#endif + + // Shared <-> Exclusive + void unlock_and_lock_shared() + { + boost::unique_lock lk(state_change); + state.assert_locked(); + state.unlock(); + state.lock_shared(); + release_waiters(); + } + +#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS + bool try_unlock_shared_and_lock() + { + boost::unique_lock lk(state_change); + state.assert_lock_shared(); + if( //!state.exclusive // this should be removed once the assertion work + ! state.exclusive_waiting_blocked // Fixme: why this is needed? + //&& ! state.upgrade // Fixme: why this is needed if state.get_shared_count()==1? + && state.get_shared_count()==1) + { + state.unlock_shared(); + state.lock(); + return true; + } + return false; + } +#ifdef BOOST_THREAD_USES_CHRONO + template + bool + try_unlock_shared_and_lock_for( + const chrono::duration& rel_time) + { + return try_unlock_shared_and_lock_until( + chrono::steady_clock::now() + rel_time); + } + template + bool + try_unlock_shared_and_lock_until( + const chrono::time_point& abs_time) + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + boost::this_thread::disable_interruption do_not_disturb; +#endif + boost::unique_lock lk(state_change); + state.assert_lock_shared(); + if ( // !state.exclusive // this should be removed once the assertion work + state.exclusive_waiting_blocked // Fixme: is this needed? + //|| state.upgrade // Fixme: why this is needed if state.get_shared_count()==1? + || state.get_shared_count() != 1) + { + for (;;) + { + cv_status status = shared_cond.wait_until(lk,abs_time); + if ( //! state.exclusive // this should be removed once the assertion work + ! state.exclusive_waiting_blocked // Fixme: is this needed? + //&& ! state.upgrade + && state.get_shared_count() == 1) + break; + if(status == cv_status::timeout) + return false; + } + } + state.unlock_shared(); + state.lock(); + state.upgrade=false; // Is this absolutely needed? + state.exclusive_waiting_blocked=false; // Is this absolutely needed? + return true; + } +#endif +#endif + + // Shared <-> Upgrade + void unlock_upgrade_and_lock_shared() + { + boost::unique_lock lk(state_change); + state.assert_lock_upgraded(); + //state.unlock_upgrade(); + //state.lock_shared(); // less efficient + state.upgrade=false; + state.exclusive_waiting_blocked=false; // Is this absolutely needed? + release_waiters(); + } + +#ifdef BOOST_THREAD_PROVIDES_SHARED_MUTEX_UPWARDS_CONVERSIONS + bool try_unlock_shared_and_lock_upgrade() + { + boost::unique_lock lk(state_change); + state.assert_lock_shared(); + if( //! state.exclusive // this should be removed once the assertion work + ! state.exclusive_waiting_blocked // Fixme: is this needed? + && ! state.upgrade + ) + { + state.upgrade=true; + return true; + } + return false; + } +#ifdef BOOST_THREAD_USES_CHRONO + template + bool + try_unlock_shared_and_lock_upgrade_for( + const chrono::duration& rel_time) + { + return try_unlock_shared_and_lock_upgrade_until( + chrono::steady_clock::now() + rel_time); + } + template + bool + try_unlock_shared_and_lock_upgrade_until( + const chrono::time_point& abs_time) + { +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + boost::this_thread::disable_interruption do_not_disturb; +#endif + boost::unique_lock lk(state_change); + state.assert_lock_shared(); + if( //state.exclusive // this should be removed once the assertion work + state.exclusive_waiting_blocked // Fixme: is this needed? + || state.upgrade + ) + { + for (;;) + { + cv_status status = exclusive_cond.wait_until(lk,abs_time); + if( //! state.exclusive // this should be removed once the assertion work + ! state.exclusive_waiting_blocked // Fixme: is this needed? + && ! state.upgrade + ) + break; + if(status == cv_status::timeout) + return false; + } + } + //state.unlock_shared(); + //state.lock_upgrade(); // less efficient + state.upgrade=true; + return true; + } +#endif +#endif + }; + + typedef shared_mutex upgrade_mutex; +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/pthread/thread_data.hpp b/src/third_party/boost-1.60.0/boost/thread/pthread/thread_data.hpp new file mode 100644 index 00000000000..dc8ba0fb1ba --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/pthread/thread_data.hpp @@ -0,0 +1,292 @@ +#ifndef BOOST_THREAD_PTHREAD_THREAD_DATA_HPP +#define BOOST_THREAD_PTHREAD_THREAD_DATA_HPP +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#ifdef BOOST_THREAD_USES_CHRONO +#include +#endif + +#include +#include +#include + +#if defined(__ANDROID__) +# ifndef PAGE_SIZE +# define PAGE_SIZE 4096 +# endif +#endif + +#include +#include + +#include + +namespace boost +{ + class thread_attributes { + public: + thread_attributes() BOOST_NOEXCEPT { + int res = pthread_attr_init(&val_); + BOOST_VERIFY(!res && "pthread_attr_init failed"); + } + ~thread_attributes() { + int res = pthread_attr_destroy(&val_); + BOOST_VERIFY(!res && "pthread_attr_destroy failed"); + } + // stack + void set_stack_size(std::size_t size) BOOST_NOEXCEPT { + if (size==0) return; + std::size_t page_size = getpagesize(); +#ifdef PTHREAD_STACK_MIN + if (size func; + void* value; + + tss_data_node(boost::shared_ptr func_, + void* value_): + func(func_),value(value_) + {} + }; + + struct thread_data_base; + typedef boost::shared_ptr thread_data_ptr; + + struct BOOST_THREAD_DECL thread_data_base: + enable_shared_from_this + { + thread_data_ptr self; + pthread_t thread_handle; + boost::mutex data_mutex; + boost::condition_variable done_condition; + boost::mutex sleep_mutex; + boost::condition_variable sleep_condition; + bool done; + bool join_started; + bool joined; + boost::detail::thread_exit_callback_node* thread_exit_callbacks; + std::map tss_data; + +//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + // These data must be at the end so that the access to the other fields doesn't change + // when BOOST_THREAD_PROVIDES_INTERRUPTIONS is defined. + // Another option is to have them always + pthread_mutex_t* cond_mutex; + pthread_cond_t* current_cond; +//#endif + typedef std::vector + //, hidden_allocator > + > notify_list_t; + notify_list_t notify; + + typedef std::vector > async_states_t; + async_states_t async_states_; + +//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + // These data must be at the end so that the access to the other fields doesn't change + // when BOOST_THREAD_PROVIDES_INTERRUPTIONS is defined. + // Another option is to have them always + bool interrupt_enabled; + bool interrupt_requested; +//#endif + thread_data_base(): + thread_handle(0), + done(false),join_started(false),joined(false), + thread_exit_callbacks(0), +//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + cond_mutex(0), + current_cond(0), +//#endif + notify(), + async_states_() +//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + , interrupt_enabled(true) + , interrupt_requested(false) +//#endif + {} + virtual ~thread_data_base(); + + typedef pthread_t native_handle_type; + + virtual void run()=0; + virtual void notify_all_at_thread_exit(condition_variable* cv, mutex* m) + { + notify.push_back(std::pair(cv, m)); + } + + void make_ready_at_thread_exit(shared_ptr as) + { + async_states_.push_back(as); + } + + }; + + BOOST_THREAD_DECL thread_data_base* get_current_thread_data(); + +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + class interruption_checker + { + thread_data_base* const thread_info; + pthread_mutex_t* m; + bool set; + + void check_for_interruption() + { +#ifndef BOOST_NO_EXCEPTIONS + if(thread_info->interrupt_requested) + { + thread_info->interrupt_requested=false; + throw thread_interrupted(); // BOOST_NO_EXCEPTIONS protected + } +#endif + } + + void operator=(interruption_checker&); + public: + explicit interruption_checker(pthread_mutex_t* cond_mutex,pthread_cond_t* cond): + thread_info(detail::get_current_thread_data()),m(cond_mutex), + set(thread_info && thread_info->interrupt_enabled) + { + if(set) + { + lock_guard guard(thread_info->data_mutex); + check_for_interruption(); + thread_info->cond_mutex=cond_mutex; + thread_info->current_cond=cond; + BOOST_VERIFY(!pthread_mutex_lock(m)); + } + else + { + BOOST_VERIFY(!pthread_mutex_lock(m)); + } + } + ~interruption_checker() + { + if(set) + { + BOOST_VERIFY(!pthread_mutex_unlock(m)); + lock_guard guard(thread_info->data_mutex); + thread_info->cond_mutex=NULL; + thread_info->current_cond=NULL; + } + else + { + BOOST_VERIFY(!pthread_mutex_unlock(m)); + } + } + }; +#endif + } + + namespace this_thread + { + namespace hiden + { + void BOOST_THREAD_DECL sleep_for(const timespec& ts); + void BOOST_THREAD_DECL sleep_until(const timespec& ts); + } + +#ifdef BOOST_THREAD_USES_CHRONO +#ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY + + inline + void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) + { + return boost::this_thread::hiden::sleep_for(boost::detail::to_timespec(ns)); + } +#endif +#endif // BOOST_THREAD_USES_CHRONO + + namespace no_interruption_point + { + namespace hiden + { + void BOOST_THREAD_DECL sleep_for(const timespec& ts); + void BOOST_THREAD_DECL sleep_until(const timespec& ts); + } + + #ifdef BOOST_THREAD_USES_CHRONO + #ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY + + inline + void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) + { + return boost::this_thread::no_interruption_point::hiden::sleep_for(boost::detail::to_timespec(ns)); + } + #endif + #endif // BOOST_THREAD_USES_CHRONO + + } // no_interruption_point + + void BOOST_THREAD_DECL yield() BOOST_NOEXCEPT; + +#if defined BOOST_THREAD_USES_DATETIME +#ifdef __DECXXX + /// Workaround of DECCXX issue of incorrect template substitution + template<> +#endif + inline void sleep(system_time const& abs_time) + { + return boost::this_thread::hiden::sleep_until(boost::detail::to_timespec(abs_time)); + } + + template + inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time) + { + this_thread::sleep(get_system_time()+rel_time); + } +#endif // BOOST_THREAD_USES_DATETIME + } // this_thread +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/pthread/thread_heap_alloc.hpp b/src/third_party/boost-1.60.0/boost/thread/pthread/thread_heap_alloc.hpp new file mode 100644 index 00000000000..7828318f05f --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/pthread/thread_heap_alloc.hpp @@ -0,0 +1,242 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2008 Anthony Williams +#ifndef THREAD_HEAP_ALLOC_PTHREAD_HPP +#define THREAD_HEAP_ALLOC_PTHREAD_HPP + +#include + +namespace boost +{ + namespace detail + { + template + inline T* heap_new() + { + return new T(); + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template + inline T* heap_new(A1&& a1) + { + return new T(static_cast(a1)); + } + template + inline T* heap_new(A1&& a1,A2&& a2) + { + return new T(static_cast(a1),static_cast(a2)); + } + template + inline T* heap_new(A1&& a1,A2&& a2,A3&& a3) + { + return new T(static_cast(a1),static_cast(a2), + static_cast(a3)); + } + template + inline T* heap_new(A1&& a1,A2&& a2,A3&& a3,A4&& a4) + { + return new T(static_cast(a1),static_cast(a2), + static_cast(a3),static_cast(a4)); + } +#else + template + inline T* heap_new_impl(A1 a1) + { + return new T(a1); + } + template + inline T* heap_new_impl(A1 a1,A2 a2) + { + return new T(a1,a2); + } + template + inline T* heap_new_impl(A1 a1,A2 a2,A3 a3) + { + return new T(a1,a2,a3); + } + template + inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4) + { + return new T(a1,a2,a3,a4); + } + + template + inline T* heap_new(A1 const& a1) + { + return heap_new_impl(a1); + } + template + inline T* heap_new(A1& a1) + { + return heap_new_impl(a1); + } + + template + inline T* heap_new(A1 const& a1,A2 const& a2) + { + return heap_new_impl(a1,a2); + } + template + inline T* heap_new(A1& a1,A2 const& a2) + { + return heap_new_impl(a1,a2); + } + template + inline T* heap_new(A1 const& a1,A2& a2) + { + return heap_new_impl(a1,a2); + } + template + inline T* heap_new(A1& a1,A2& a2) + { + return heap_new_impl(a1,a2); + } + + template + inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3) + { + return heap_new_impl(a1,a2,a3); + } + template + inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3) + { + return heap_new_impl(a1,a2,a3); + } + template + inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3) + { + return heap_new_impl(a1,a2,a3); + } + template + inline T* heap_new(A1& a1,A2& a2,A3 const& a3) + { + return heap_new_impl(a1,a2,a3); + } + + template + inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3) + { + return heap_new_impl(a1,a2,a3); + } + template + inline T* heap_new(A1& a1,A2 const& a2,A3& a3) + { + return heap_new_impl(a1,a2,a3); + } + template + inline T* heap_new(A1 const& a1,A2& a2,A3& a3) + { + return heap_new_impl(a1,a2,a3); + } + template + inline T* heap_new(A1& a1,A2& a2,A3& a3) + { + return heap_new_impl(a1,a2,a3); + } + + template + inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3,A4 const& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + template + inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3,A4 const& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + template + inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3,A4 const& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + template + inline T* heap_new(A1& a1,A2& a2,A3 const& a3,A4 const& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + + template + inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3,A4 const& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + template + inline T* heap_new(A1& a1,A2 const& a2,A3& a3,A4 const& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + template + inline T* heap_new(A1 const& a1,A2& a2,A3& a3,A4 const& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + template + inline T* heap_new(A1& a1,A2& a2,A3& a3,A4 const& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + template + inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3,A4& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + template + inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3,A4& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + template + inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3,A4& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + template + inline T* heap_new(A1& a1,A2& a2,A3 const& a3,A4& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + + template + inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3,A4& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + template + inline T* heap_new(A1& a1,A2 const& a2,A3& a3,A4& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + template + inline T* heap_new(A1 const& a1,A2& a2,A3& a3,A4& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + template + inline T* heap_new(A1& a1,A2& a2,A3& a3,A4& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + +#endif + template + inline void heap_delete(T* data) + { + delete data; + } + + template + struct do_heap_delete + { + void operator()(T* data) const + { + detail::heap_delete(data); + } + }; + } +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/pthread/timespec.hpp b/src/third_party/boost-1.60.0/boost/thread/pthread/timespec.hpp new file mode 100644 index 00000000000..82f50f6ca74 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/pthread/timespec.hpp @@ -0,0 +1,120 @@ +#ifndef BOOST_THREAD_PTHREAD_TIMESPEC_HPP +#define BOOST_THREAD_PTHREAD_TIMESPEC_HPP +// (C) Copyright 2007-8 Anthony Williams +// (C) Copyright 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#if defined BOOST_THREAD_USES_DATETIME +#include +#endif +#include +#ifndef _WIN32 +#include +#endif +#ifdef BOOST_THREAD_USES_CHRONO +#include +#endif + +#if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) +# define BOOST_THREAD_TIMESPEC_MAC_API +#include //for gettimeofday and timeval +#else +#include // for clock_gettime +#endif + +#include + +namespace boost +{ + namespace detail + { +#if defined BOOST_THREAD_USES_DATETIME + inline struct timespec to_timespec(boost::system_time const& abs_time) + { + struct timespec timeout = { 0,0}; + boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0); + + timeout.tv_sec=time_since_epoch.total_seconds(); + timeout.tv_nsec=(long)(time_since_epoch.fractional_seconds()*(1000000000l/time_since_epoch.ticks_per_second())); + return timeout; + } +#endif +#if defined BOOST_THREAD_USES_CHRONO + inline timespec to_timespec(chrono::nanoseconds const& ns) + { + struct timespec ts; + ts.tv_sec = static_cast(chrono::duration_cast(ns).count()); + ts.tv_nsec = static_cast((ns - chrono::duration_cast(ns)).count()); + return ts; + } + +#endif + + inline timespec to_timespec(boost::intmax_t const& ns) + { + boost::intmax_t s = ns / 1000000000l; + struct timespec ts; + ts.tv_sec = static_cast (s); + ts.tv_nsec = static_cast (ns - s * 1000000000l); + return ts; + } + inline boost::intmax_t to_nanoseconds_int_max(timespec const& ts) + { + return static_cast(ts.tv_sec) * 1000000000l + ts.tv_nsec; + } + inline bool timespec_ge_zero(timespec const& ts) + { + return (ts.tv_sec >= 0) || (ts.tv_nsec >= 0); + } + inline timespec timespec_now() + { + timespec ts; + +#if defined(BOOST_THREAD_TIMESPEC_MAC_API) + timeval tv; + ::gettimeofday(&tv, 0); + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * 1000; +#else + if ( ::clock_gettime( CLOCK_REALTIME, &ts ) ) + { + BOOST_ASSERT(0 && "Boost::Thread - Internal Error"); + } +#endif + return ts; + } + inline timespec timespec_zero() + { + timespec ts; + ts.tv_sec = 0; + ts.tv_nsec = 0; + return ts; + } + inline timespec timespec_plus(timespec const& lhs, timespec const& rhs) + { + return to_timespec(to_nanoseconds_int_max(lhs) + to_nanoseconds_int_max(rhs)); + } + inline timespec timespec_minus(timespec const& lhs, timespec const& rhs) + { + return to_timespec(to_nanoseconds_int_max(lhs) - to_nanoseconds_int_max(rhs)); + } + inline bool timespec_gt(timespec const& lhs, timespec const& rhs) + { + return to_nanoseconds_int_max(lhs) > to_nanoseconds_int_max(rhs); + } + inline bool timespec_ge(timespec const& lhs, timespec const& rhs) + { + return to_nanoseconds_int_max(lhs) >= to_nanoseconds_int_max(rhs); + } + + } +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/recursive_mutex.hpp b/src/third_party/boost-1.60.0/boost/thread/recursive_mutex.hpp new file mode 100644 index 00000000000..e716a190ffb --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/recursive_mutex.hpp @@ -0,0 +1,64 @@ +#ifndef BOOST_THREAD_RECURSIVE_MUTEX_HPP +#define BOOST_THREAD_RECURSIVE_MUTEX_HPP + +// recursive_mutex.hpp +// +// (C) Copyright 2007 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#if defined(BOOST_THREAD_PLATFORM_WIN32) +#include +#elif defined(BOOST_THREAD_PLATFORM_PTHREAD) +#include +#else +#error "Boost threads unavailable on this platform" +#endif + +#include + +namespace boost +{ + namespace sync + { + +#ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES + template<> + struct is_basic_lockable + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + template<> + struct is_lockable + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + template<> + struct is_basic_lockable + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + template<> + struct is_lockable + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; +#endif + + template<> + struct is_recursive_mutex_sur_parolle + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + template<> + struct is_recursive_mutex_sur_parolle + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + + } +} +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/reverse_lock.hpp b/src/third_party/boost-1.60.0/boost/thread/reverse_lock.hpp new file mode 100644 index 00000000000..479c314bdbe --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/reverse_lock.hpp @@ -0,0 +1,59 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2012 Vicente J. Botet Escriba + +#ifndef BOOST_THREAD_REVERSE_LOCK_HPP +#define BOOST_THREAD_REVERSE_LOCK_HPP +#include +#include +#include +#include +#include + +namespace boost +{ + + template + class reverse_lock + { + public: + typedef typename Lock::mutex_type mutex_type; + BOOST_THREAD_NO_COPYABLE(reverse_lock) + + explicit reverse_lock(Lock& m_) + : m(m_), mtx(0) + { + if (m.owns_lock()) + { + m.unlock(); + } + mtx=m.release(); + } + ~reverse_lock() + { + if (mtx) { + mtx->lock(); + m = BOOST_THREAD_MAKE_RV_REF(Lock(*mtx, adopt_lock)); + } + } + + private: + Lock& m; + mutex_type* mtx; + }; + + +#ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES + template + struct is_mutex_type > + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + +#endif + + +} + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/scoped_thread.hpp b/src/third_party/boost-1.60.0/boost/thread/scoped_thread.hpp new file mode 100644 index 00000000000..ae0d1efc53c --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/scoped_thread.hpp @@ -0,0 +1,289 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2009-2012 Anthony Williams +// (C) Copyright 2012 Vicente J. Botet Escriba + +// Based on the Anthony's idea of scoped_thread in CCiA + +#ifndef BOOST_THREAD_SCOPED_THREAD_HPP +#define BOOST_THREAD_SCOPED_THREAD_HPP + +#include +#include +#include +#include +#include + +#include + +namespace boost +{ + + /** + * RAI @c thread wrapper adding a specific destroyer allowing to master what can be done at destruction time. + * + * CallableThread: A callable void(thread&) . + * The default is a join_if_joinable. + * + * thread std/boost::thread destructor terminates the program if the thread is not joinable. + * Having a wrapper that can join the thread before destroying it seems a natural need. + * + * Example: + * + * boost::strict_scoped_thread<> t((boost::thread(F))); + * + */ + template + class strict_scoped_thread + { + thread t_; + struct dummy; + public: + + BOOST_THREAD_NO_COPYABLE( strict_scoped_thread) /// non copyable + + /* + * + */ +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template ::type, thread>, void* >::type> + explicit strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Args)... args) : + t_(boost::forward(f), boost::forward(args)...) {} +#else + template + explicit strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, + typename disable_if::type, thread>, void* >::type=0) : + t_(boost::forward(f)) {} + template + strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1) : + t_(boost::forward(f), boost::forward(a1)) {} + template + strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2) : + t_(boost::forward(f), boost::forward(a1), boost::forward(a2)) {} + template + strict_scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2, BOOST_THREAD_FWD_REF(A3) a3) : + t_(boost::forward(f), boost::forward(a1), boost::forward(a2), boost::forward(a3)) {} +#endif + + /** + * Constructor from the thread to own. + * + * @param t: the thread to own. + * + * Effects: move the thread to own @c t. + */ + explicit strict_scoped_thread(BOOST_THREAD_RV_REF(thread) t) BOOST_NOEXCEPT : + t_(boost::move(t)) + { + } + + /** + * Destructor + * Effects: Call the CallableThread functor before destroying the owned thread. + * Remark: The CallableThread should not throw when joining the thread as the scoped variable is on a scope outside the thread function. + */ + ~strict_scoped_thread() + { + CallableThread on_destructor; + + on_destructor(t_); + } + + }; + + /** + * RAI @c thread wrapper adding a specific destroyer allowing to master what can be done at destruction time. + * + * CallableThread: A callable void(thread&) . + * The default is join_if_joinable. + * + * thread std::thread destructor terminates the program if the thread is not joinable. + * Having a wrapper that can join the thread before destroying it seems a natural need. + * + * Remark: @c scoped_thread is not a @c thread as @c thread is not designed to be derived from as a polymorphic type. + * Anyway @c scoped_thread can be used in most of the contexts a @c thread could be used as it has the + * same non-deprecated interface with the exception of the construction. + * + * Example: + * + * boost::scoped_thread<> t((boost::thread(F))); + * t.interrupt(); + * + */ + template + class scoped_thread + { + thread t_; + struct dummy; + public: + + typedef thread::id id; + + BOOST_THREAD_MOVABLE_ONLY( scoped_thread) /// Movable only + + /** + * Default Constructor. + * + * Effects: wraps a not-a-thread. + */ + scoped_thread() BOOST_NOEXCEPT: + t_() + { + } + + /** + * + */ + +#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template ::type, thread>, void* >::type> + explicit scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(Args)... args) : + t_(boost::forward(f), boost::forward(args)...) {} +#else + template + explicit scoped_thread(BOOST_THREAD_FWD_REF(F) f, + typename disable_if::type, thread>, void* >::type=0) : + t_(boost::forward(f)) {} + template + scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1) : + t_(boost::forward(f), boost::forward(a1)) {} + template + scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2) : + t_(boost::forward(f), boost::forward(a1), boost::forward(a2)) {} + template + scoped_thread(BOOST_THREAD_FWD_REF(F) f, BOOST_THREAD_FWD_REF(A1) a1, BOOST_THREAD_FWD_REF(A2) a2, BOOST_THREAD_FWD_REF(A3) a3) : + t_(boost::forward(f), boost::forward(a1), boost::forward(a2), boost::forward(a3)) {} + +#endif + /** + * Constructor from the thread to own. + * + * @param t: the thread to own. + * + * Effects: move the thread to own @c t. + */ + explicit scoped_thread(BOOST_THREAD_RV_REF(thread) t) BOOST_NOEXCEPT : + t_(boost::move(t)) + { + } + +// explicit operator thread() +// { +// return boost::move(t_); +// } + + /** + * Move constructor. + */ + scoped_thread(BOOST_RV_REF(scoped_thread) x) BOOST_NOEXCEPT : + t_(boost::move(BOOST_THREAD_RV(x).t_)) + {} + + /** + * Destructor + * + * Effects: Call the CallableThread functor before destroying the owned thread. + */ + ~scoped_thread() + { + CallableThread on_destructor; + + on_destructor(t_); + } + + /** + * Move assignment. + */ + scoped_thread& operator=(BOOST_RV_REF(scoped_thread) x) + { + t_ = boost::move(BOOST_THREAD_RV(x).t_); + return *this; + } + + /** + * + */ + void swap(scoped_thread& x) BOOST_NOEXCEPT + { + t_.swap(x.t_); + } + + // forwarded thread functions + inline thread::id get_id() const BOOST_NOEXCEPT + { + return t_.get_id(); + } + + void detach() + { + t_.detach(); + } + + void join() + { + t_.join(); + } + +#ifdef BOOST_THREAD_USES_CHRONO + template + bool try_join_for(const chrono::duration& rel_time) + { + return t_.try_join_for(rel_time); + } + + template + bool try_join_until(const chrono::time_point& abs_time) + { + return t_.try_join_until(abs_time); + } +#endif + + thread::native_handle_type native_handle()BOOST_NOEXCEPT + { + return t_.native_handle(); + } + + bool joinable() const BOOST_NOEXCEPT + { + return t_.joinable(); + } + +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + void interrupt() + { + t_.interrupt(); + } + + bool interruption_requested() const BOOST_NOEXCEPT + { + return t_.interruption_requested(); + } +#endif + + static unsigned hardware_concurrency() BOOST_NOEXCEPT + { + return thread::hardware_concurrency(); + } + +#ifdef BOOST_THREAD_PROVIDES_PHYSICAL_CONCURRENCY + static unsigned physical_concurrency() BOOST_NOEXCEPT + { + return thread::physical_concurrency(); + } +#endif + }; + + /** + * Effects: swaps the contents of two scoped threads. + */ + template + void swap(scoped_thread& lhs, scoped_thread& rhs) +BOOST_NOEXCEPT { + return lhs.swap(rhs); +} + +} +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/shared_lock_guard.hpp b/src/third_party/boost-1.60.0/boost/thread/shared_lock_guard.hpp new file mode 100644 index 00000000000..97a6397c1e6 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/shared_lock_guard.hpp @@ -0,0 +1,53 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2012 Vicente J. Botet Escriba + +#ifndef BOOST_THREAD_SHARED_LOCK_GUARD_HPP +#define BOOST_THREAD_SHARED_LOCK_GUARD_HPP +#include +//#include +#include +#include + +namespace boost +{ + + template + class shared_lock_guard + { + private: + SharedMutex& m; + + public: + typedef SharedMutex mutex_type; + BOOST_THREAD_NO_COPYABLE(shared_lock_guard) + explicit shared_lock_guard(SharedMutex& m_): + m(m_) + { + m.lock_shared(); + } + shared_lock_guard(SharedMutex& m_,adopt_lock_t): + m(m_) + {} + ~shared_lock_guard() + { + m.unlock_shared(); + } + }; + +#ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES + + template + struct is_mutex_type > + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + + +#endif + + +} + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/shared_mutex.hpp b/src/third_party/boost-1.60.0/boost/thread/shared_mutex.hpp new file mode 100644 index 00000000000..ce5d6d1bfbf --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/shared_mutex.hpp @@ -0,0 +1,50 @@ +#ifndef BOOST_THREAD_SHARED_MUTEX_HPP +#define BOOST_THREAD_SHARED_MUTEX_HPP + +// shared_mutex.hpp +// +// (C) Copyright 2007 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#if defined(BOOST_THREAD_PLATFORM_WIN32) +#if defined(BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN) +#include +#else +#include +#endif +#elif defined(BOOST_THREAD_PLATFORM_PTHREAD) +//#include +#include +#else +#error "Boost threads unavailable on this platform" +#endif + +#include + +namespace boost +{ + typedef shared_mutex shared_timed_mutex; + namespace sync + { +#ifdef BOOST_THREAD_NO_AUTO_DETECT_MUTEX_TYPES + template<> + struct is_basic_lockable + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + template<> + struct is_lockable + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; +#endif + + } +} + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/strict_lock.hpp b/src/third_party/boost-1.60.0/boost/thread/strict_lock.hpp new file mode 100644 index 00000000000..93b7b1e71cd --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/strict_lock.hpp @@ -0,0 +1,235 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2008-2009,2012 Vicente J. Botet Escriba + +#ifndef BOOST_THREAD_STRICT_LOCK_HPP +#define BOOST_THREAD_STRICT_LOCK_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost +{ + + + //[strict_lock + template + class strict_lock + { + + BOOST_CONCEPT_ASSERT(( BasicLockable )); + public: + typedef Lockable mutex_type; + + // construct/copy/destroy: + + BOOST_THREAD_NO_COPYABLE( strict_lock) + + /** + * Constructor from a mutex reference. + * + * @param mtx the mutex to lock. + * + * __Effects: Stores a reference to the mutex to lock and locks it. + * __Throws: Any exception BasicMutex::lock() can throw. + */ + explicit strict_lock(mutex_type& mtx) : + mtx_(mtx) + { + mtx.lock(); + } /*< locks on construction >*/ + + +#if ! defined BOOST_THREAD_NO_CXX11_HDR_INITIALIZER_LIST + strict_lock(std::initializer_list > l_) : + mtx_(*(const_cast*>(l_.begin())->m)) + { + mtx_.lock(); + } +#endif + + /** + * Destructor + * + * __Effects: unlocks the stored mutex. + * + * __Throws + */ + ~strict_lock() + { + mtx_.unlock(); + } /*< unlocks on destruction >*/ + + + // observers + + /** + * @return the owned mutex. + */ + mutex_type* mutex() const BOOST_NOEXCEPT + { + return &mtx_; + } + + /** + * @return whether this lock is locking a mutex. + */ + bool owns_lock() const BOOST_NOEXCEPT + { + return true; + } + + /** + * @return whether this lock is locking that mutex. + */ + bool owns_lock(const mutex_type* l) const BOOST_NOEXCEPT + { + return l == mutex(); + } /*< strict locks specific function >*/ + + //BOOST_ADRESS_OF_DELETE(strict_lock) /*< disable aliasing >*/ + //BOOST_HEAP_ALLOCATION_DELETE(strict_lock) /*< disable heap allocation >*/ + + /*< no possibility to unlock >*/ + + private: + mutex_type& mtx_; + }; + //] + template + struct is_strict_lock_sur_parole > : true_type + { + }; + + /** + * A nested strict lock is a scoped lock guard ensuring the mutex is locked on its + * scope, by taking ownership of an nesting lock, locking the mutex on construction if not already locked + * and restoring the ownership to the nesting lock on destruction. + */ + //[nested_strict_lock + template + class nested_strict_lock + { + BOOST_CONCEPT_ASSERT(( BasicLock )); /*< The Lock must be a movable lock >*/ + public: + typedef typename Lock::mutex_type mutex_type; /*< Name the lockable type locked by Lock >*/ + + BOOST_THREAD_NO_COPYABLE( nested_strict_lock) + + /** + * Constructor from a nesting @c Lock. + * + * @param lk the nesting lock + * + * __Requires: lk.mutex() != null_ptr + * __Effects: Stores the reference to the lock parameter and takes ownership on it. + * If the lock doesn't owns the mutex @c mtx lock it. + * __Postconditions: @c owns_lock(lk.mutex()) + * __StrongException + * __Throws: + * + * - lock_error when BOOST_THREAD_THROW_IF_PRECONDITION_NOT_SATISFIED is defined and lk.mutex() == null_ptr + * + * - Any exception that @c lk.lock() can throw. + * + */ + explicit nested_strict_lock(Lock& lk) : + lk_(lk) /*< Store reference to lk >*/ + { + /*< Define BOOST_THREAD_DONT_CHECK_PRECONDITIONS if you don't want to check lk ownership >*/ + BOOST_THREAD_ASSERT_PRECONDITION( lk.mutex() != 0, + lock_error() + ); + if (!lk.owns_lock()) lk.lock(); /*< ensures it is locked >*/ + tmp_lk_ = move(lk); /*< Move ownership to temporary lk >*/ + } + +#if ! defined BOOST_THREAD_NO_CXX11_HDR_INITIALIZER_LIST + nested_strict_lock(std::initializer_list > l_) : + lk_(*(const_cast*>(l_.begin())->m)) + { + /*< Define BOOST_THREAD_DONT_CHECK_PRECONDITIONS if you don't want to check lk ownership >*/ + BOOST_THREAD_ASSERT_PRECONDITION( lk_.mutex() != 0, + lock_error() + ); + if (!lk_.owns_lock()) lk_.lock(); /*< ensures it is locked >*/ + tmp_lk_ = move(lk_); /*< Move ownership to temporary lk >*/ + } +#endif + + /** + * Destructor + * + * __Effects: Restores ownership to the nesting lock. + */ + ~nested_strict_lock()BOOST_NOEXCEPT + { + lk_ = move(tmp_lk_); /*< Move ownership to nesting lock >*/ + } + + // observers + /** + * return @c the owned mutex. + */ + mutex_type* mutex() const BOOST_NOEXCEPT + { + return tmp_lk_.mutex(); + } + + /** + * @return whether this lock is locking a mutex. + */ + bool owns_lock() const BOOST_NOEXCEPT + { + return true; + } + + /** + * @return whether if this lock is locking that mutex. + */ + bool owns_lock(mutex_type const* l) const BOOST_NOEXCEPT + { + return l == mutex(); + } + + //BOOST_ADRESS_OF_DELETE(nested_strict_lock) + //BOOST_HEAP_ALLOCATEION_DELETE(nested_strict_lock) + + private: + Lock& lk_; + Lock tmp_lk_; + }; + //] + + template + struct is_strict_lock_sur_parole > : true_type + { + }; + +#if ! defined BOOST_THREAD_NO_MAKE_STRICT_LOCK + template + strict_lock make_strict_lock(Lockable& mtx) + { + return { thread_detail::lockable_wrapper(mtx) }; + } + template + nested_strict_lock make_nested_strict_lock(Lock& lk) + { + return { thread_detail::lockable_wrapper(lk) }; + } +#endif +} +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/sync_bounded_queue.hpp b/src/third_party/boost-1.60.0/boost/thread/sync_bounded_queue.hpp new file mode 100644 index 00000000000..2024d6602e4 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/sync_bounded_queue.hpp @@ -0,0 +1,16 @@ +#ifndef BOOST_THREAD_SYNC_BOUNDED_QUEUE_HPP +#define BOOST_THREAD_SYNC_BOUNDED_QUEUE_HPP + +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Vicente J. Botet Escriba 2013-2014. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/sync_queue.hpp b/src/third_party/boost-1.60.0/boost/thread/sync_queue.hpp new file mode 100644 index 00000000000..0d9334b4783 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/sync_queue.hpp @@ -0,0 +1,16 @@ +#ifndef BOOST_THREAD_SYNC_QUEUE_HPP +#define BOOST_THREAD_SYNC_QUEUE_HPP + +////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright Vicente J. Botet Escriba 2013-2014. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See http://www.boost.org/libs/thread for documentation. +// +////////////////////////////////////////////////////////////////////////////// + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/synchronized_value.hpp b/src/third_party/boost-1.60.0/boost/thread/synchronized_value.hpp new file mode 100644 index 00000000000..e161063040f --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/synchronized_value.hpp @@ -0,0 +1,1068 @@ +// (C) Copyright 2010 Just Software Solutions Ltd http://www.justsoftwaresolutions.co.uk +// (C) Copyright 2012 Vicente J. Botet Escriba +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#ifndef BOOST_THREAD_SYNCHRONIZED_VALUE_HPP +#define BOOST_THREAD_SYNCHRONIZED_VALUE_HPP + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +//#include +//#if ! defined BOOST_NO_CXX11_HDR_TYPE_TRAITS +//#include +//#endif + +#if ! defined(BOOST_THREAD_NO_SYNCHRONIZE) +#include // todo change to once Boost.Tuple or Boost.Fusion provides Move semantics on C++98 compilers. +#include +#endif + +#include + +#include + +namespace boost +{ + + /** + * strict lock providing a const pointer access to the synchronized value type. + * + * @param T the value type. + * @param Lockable the mutex type protecting the value type. + */ + template + class const_strict_lock_ptr + { + public: + typedef T value_type; + typedef Lockable mutex_type; + protected: + + // this should be a strict_lock, but unique_lock is needed to be able to return it. + boost::unique_lock lk_; + T const& value_; + + public: + BOOST_THREAD_MOVABLE_ONLY( const_strict_lock_ptr ) + + /** + * @param value constant reference of the value to protect. + * @param mtx reference to the mutex used to protect the value. + * @effects locks the mutex @c mtx, stores a reference to it and to the value type @c value. + */ + const_strict_lock_ptr(T const& val, Lockable & mtx) : + lk_(mtx), value_(val) + { + } + const_strict_lock_ptr(T const& val, Lockable & mtx, adopt_lock_t tag) BOOST_NOEXCEPT : + lk_(mtx, tag), value_(val) + { + } + /** + * Move constructor. + * @effects takes ownership of the mutex owned by @c other, stores a reference to the mutex and the value type of @c other. + */ + const_strict_lock_ptr(BOOST_THREAD_RV_REF(const_strict_lock_ptr) other) BOOST_NOEXCEPT + : lk_(boost::move(BOOST_THREAD_RV(other).lk_)),value_(BOOST_THREAD_RV(other).value_) + { + } + + ~const_strict_lock_ptr() + { + } + + /** + * @return a constant pointer to the protected value + */ + const T* operator->() const + { + return &value_; + } + + /** + * @return a constant reference to the protected value + */ + const T& operator*() const + { + return value_; + } + + }; + + /** + * strict lock providing a pointer access to the synchronized value type. + * + * @param T the value type. + * @param Lockable the mutex type protecting the value type. + */ + template + class strict_lock_ptr : public const_strict_lock_ptr + { + typedef const_strict_lock_ptr base_type; + public: + BOOST_THREAD_MOVABLE_ONLY( strict_lock_ptr ) + + /** + * @param value reference of the value to protect. + * @param mtx reference to the mutex used to protect the value. + * @effects locks the mutex @c mtx, stores a reference to it and to the value type @c value. + */ + strict_lock_ptr(T & val, Lockable & mtx) : + base_type(val, mtx) + { + } + strict_lock_ptr(T & val, Lockable & mtx, adopt_lock_t tag) : + base_type(val, mtx, tag) + { + } + + /** + * Move constructor. + * @effects takes ownership of the mutex owned by @c other, stores a reference to the mutex and the value type of @c other. + */ + strict_lock_ptr(BOOST_THREAD_RV_REF(strict_lock_ptr) other) + : base_type(boost::move(static_cast(other))) + { + } + + ~strict_lock_ptr() + { + } + + /** + * @return a pointer to the protected value + */ + T* operator->() + { + return const_cast(&this->value_); + } + + /** + * @return a reference to the protected value + */ + T& operator*() + { + return const_cast(this->value_); + } + + }; + + template + struct synchronized_value_strict_lock_ptr + { + typedef strict_lock_ptr type; + }; + + template + struct synchronized_value_strict_lock_ptr + { + typedef const_strict_lock_ptr type; + }; + /** + * unique_lock providing a const pointer access to the synchronized value type. + * + * An object of type const_unique_lock_ptr is a unique_lock that provides a const pointer access to the synchronized value type. + * As unique_lock controls the ownership of a lockable object within a scope. + * Ownership of the lockable object may be acquired at construction or after construction, + * and may be transferred, after acquisition, to another const_unique_lock_ptr object. + * Objects of type const_unique_lock_ptr are not copyable but are movable. + * The behavior of a program is undefined if the mutex and the value type + * pointed do not exist for the entire remaining lifetime of the const_unique_lock_ptr object. + * The supplied Mutex type shall meet the BasicLockable requirements. + * + * @note const_unique_lock_ptr meets the Lockable requirements. + * If Lockable meets the TimedLockable requirements, const_unique_lock_ptr + * also meets the TimedLockable requirements. + * + * @param T the value type. + * @param Lockable the mutex type protecting the value type. + */ + template + class const_unique_lock_ptr : public unique_lock + { + typedef unique_lock base_type; + public: + typedef T value_type; + typedef Lockable mutex_type; + protected: + T const& value_; + + public: + BOOST_THREAD_MOVABLE_ONLY(const_unique_lock_ptr) + + /** + * @param value reference of the value to protect. + * @param mtx reference to the mutex used to protect the value. + * + * @requires If mutex_type is not a recursive mutex the calling thread does not own the mutex. + * + * @effects locks the mutex @c mtx, stores a reference to it and to the value type @c value. + */ + const_unique_lock_ptr(T const& val, Lockable & mtx) + : base_type(mtx), value_(val) + { + } + /** + * @param value reference of the value to protect. + * @param mtx reference to the mutex used to protect the value. + * @param tag of type adopt_lock_t used to differentiate the constructor. + * @requires The calling thread own the mutex. + * @effects stores a reference to it and to the value type @c value taking ownership. + */ + const_unique_lock_ptr(T const& val, Lockable & mtx, adopt_lock_t) BOOST_NOEXCEPT + : base_type(mtx, adopt_lock), value_(val) + { + } + /** + * @param value reference of the value to protect. + * @param mtx reference to the mutex used to protect the value. + * @param tag of type defer_lock_t used to differentiate the constructor. + * @effects stores a reference to it and to the value type @c value c. + */ + const_unique_lock_ptr(T const& val, Lockable & mtx, defer_lock_t) BOOST_NOEXCEPT + : base_type(mtx, defer_lock), value_(val) + { + } + /** + * @param value reference of the value to protect. + * @param mtx reference to the mutex used to protect the value. + * @param tag of type try_to_lock_t used to differentiate the constructor. + * @requires If mutex_type is not a recursive mutex the calling thread does not own the mutex. + * @effects try to lock the mutex @c mtx, stores a reference to it and to the value type @c value. + */ + const_unique_lock_ptr(T const& val, Lockable & mtx, try_to_lock_t) BOOST_NOEXCEPT + : base_type(mtx, try_to_lock), value_(val) + { + } + /** + * Move constructor. + * @effects takes ownership of the mutex owned by @c other, stores a reference to the mutex and the value type of @c other. + */ + const_unique_lock_ptr(BOOST_THREAD_RV_REF(const_unique_lock_ptr) other) BOOST_NOEXCEPT + : base_type(boost::move(static_cast(other))), value_(BOOST_THREAD_RV(other).value_) + { + } + + /** + * @effects If owns calls unlock() on the owned mutex. + */ + ~const_unique_lock_ptr() + { + } + + /** + * @return a constant pointer to the protected value + */ + const T* operator->() const + { + BOOST_ASSERT (this->owns_lock()); + return &value_; + } + + /** + * @return a constant reference to the protected value + */ + const T& operator*() const + { + BOOST_ASSERT (this->owns_lock()); + return value_; + } + + }; + + /** + * unique lock providing a pointer access to the synchronized value type. + * + * @param T the value type. + * @param Lockable the mutex type protecting the value type. + */ + template + class unique_lock_ptr : public const_unique_lock_ptr + { + typedef const_unique_lock_ptr base_type; + public: + typedef T value_type; + typedef Lockable mutex_type; + + BOOST_THREAD_MOVABLE_ONLY(unique_lock_ptr) + + /** + * @param value reference of the value to protect. + * @param mtx reference to the mutex used to protect the value. + * @effects locks the mutex @c mtx, stores a reference to it and to the value type @c value. + */ + unique_lock_ptr(T & val, Lockable & mtx) + : base_type(val, mtx) + { + } + /** + * @param value reference of the value to protect. + * @param mtx reference to the mutex used to protect the value. + * @param tag of type adopt_lock_t used to differentiate the constructor. + * @effects stores a reference to it and to the value type @c value taking ownership. + */ + unique_lock_ptr(T & value, Lockable & mtx, adopt_lock_t) BOOST_NOEXCEPT + : base_type(value, mtx, adopt_lock) + { + } + /** + * @param value reference of the value to protect. + * @param mtx reference to the mutex used to protect the value. + * @param tag of type defer_lock_t used to differentiate the constructor. + * @effects stores a reference to it and to the value type @c value c. + */ + unique_lock_ptr(T & value, Lockable & mtx, defer_lock_t) BOOST_NOEXCEPT + : base_type(value, mtx, defer_lock) + { + } + /** + * @param value reference of the value to protect. + * @param mtx reference to the mutex used to protect the value. + * @param tag of type try_to_lock_t used to differentiate the constructor. + * @effects try to lock the mutex @c mtx, stores a reference to it and to the value type @c value. + */ + unique_lock_ptr(T & value, Lockable & mtx, try_to_lock_t) BOOST_NOEXCEPT + : base_type(value, mtx, try_to_lock) + { + } + /** + * Move constructor. + * @effects takes ownership of the mutex owned by @c other, stores a reference to the mutex and the value type of @c other. + */ + unique_lock_ptr(BOOST_THREAD_RV_REF(unique_lock_ptr) other) BOOST_NOEXCEPT + : base_type(boost::move(static_cast(other))) + { + } + + ~unique_lock_ptr() + { + } + + /** + * @return a pointer to the protected value + */ + T* operator->() + { + BOOST_ASSERT (this->owns_lock()); + return const_cast(&this->value_); + } + + /** + * @return a reference to the protected value + */ + T& operator*() + { + BOOST_ASSERT (this->owns_lock()); + return const_cast(this->value_); + } + + + }; + + template + struct synchronized_value_unique_lock_ptr + { + typedef unique_lock_ptr type; + }; + + template + struct synchronized_value_unique_lock_ptr + { + typedef const_unique_lock_ptr type; + }; + /** + * cloaks a value type and the mutex used to protect it together. + * @param T the value type. + * @param Lockable the mutex type protecting the value type. + */ + template + class synchronized_value + { + +#if ! defined(BOOST_THREAD_NO_MAKE_UNIQUE_LOCKS) +#if ! defined BOOST_NO_CXX11_VARIADIC_TEMPLATES + template + friend std::tuple::type ...> synchronize(SV& ...sv); +#else + template + friend std::tuple< + typename synchronized_value_strict_lock_ptr::type, + typename synchronized_value_strict_lock_ptr::type + > + synchronize(SV1& sv1, SV2& sv2); + template + friend std::tuple< + typename synchronized_value_strict_lock_ptr::type, + typename synchronized_value_strict_lock_ptr::type, + typename synchronized_value_strict_lock_ptr::type + > + synchronize(SV1& sv1, SV2& sv2, SV3& sv3); +#endif +#endif + + public: + typedef T value_type; + typedef Lockable mutex_type; + private: + T value_; + mutable mutex_type mtx_; + public: + // construction/destruction + /** + * Default constructor. + * + * @Requires: T is DefaultConstructible + */ + synchronized_value() + //BOOST_NOEXCEPT_IF(is_nothrow_default_constructible::value) + : value_() + { + } + + /** + * Constructor from copy constructible value. + * + * Requires: T is CopyConstructible + */ + synchronized_value(T const& other) + //BOOST_NOEXCEPT_IF(is_nothrow_copy_constructible::value) + : value_(other) + { + } + + /** + * Move Constructor. + * + * Requires: T is CopyMovable + */ + synchronized_value(BOOST_THREAD_RV_REF(T) other) + //BOOST_NOEXCEPT_IF(is_nothrow_move_constructible::value) + : value_(boost::move(other)) + { + } + + /** + * Constructor from value type. + * + * Requires: T is DefaultConstructible and Assignable + * Effects: Assigns the value on a scope protected by the mutex of the rhs. The mutex is not copied. + */ + synchronized_value(synchronized_value const& rhs) + { + strict_lock lk(rhs.mtx_); + value_ = rhs.value_; + } + + /** + * Move Constructor from movable value type + * + */ + synchronized_value(BOOST_THREAD_RV_REF(synchronized_value) other) + { + strict_lock lk(BOOST_THREAD_RV(other).mtx_); + value_= boost::move(BOOST_THREAD_RV(other).value_); + } + + // mutation + /** + * Assignment operator. + * + * Effects: Copies the underlying value on a scope protected by the two mutexes. + * The mutex is not copied. The locks are acquired using lock, so deadlock is avoided. + * For example, there is no problem if one thread assigns a = b and the other assigns b = a. + * + * Return: *this + */ + + synchronized_value& operator=(synchronized_value const& rhs) + { + if(&rhs != this) + { + // auto _ = make_unique_locks(mtx_, rhs.mtx_); + unique_lock lk1(mtx_, defer_lock); + unique_lock lk2(rhs.mtx_, defer_lock); + lock(lk1,lk2); + + value_ = rhs.value_; + } + return *this; + } + /** + * Assignment operator from a T const&. + * Effects: The operator copies the value on a scope protected by the mutex. + * Return: *this + */ + synchronized_value& operator=(value_type const& val) + { + { + strict_lock lk(mtx_); + value_ = val; + } + return *this; + } + + //observers + /** + * Explicit conversion to value type. + * + * Requires: T is CopyConstructible + * Return: A copy of the protected value obtained on a scope protected by the mutex. + * + */ + T get() const + { + strict_lock lk(mtx_); + return value_; + } + /** + * Explicit conversion to value type. + * + * Requires: T is CopyConstructible + * Return: A copy of the protected value obtained on a scope protected by the mutex. + * + */ +#if ! defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) + explicit operator T() const + { + return get(); + } +#endif + + /** + * value type getter. + * + * Return: A constant reference to the protected value. + * + * Note: Not thread safe + * + */ + T const& value() const + { + return value_; + } + /** + * mutex getter. + * + * Return: A constant reference to the protecting mutex. + * + * Note: Not thread safe + * + */ + mutex_type const& mutex() const + { + return mtx_; + } + /** + * Swap + * + * Effects: Swaps the data. Again, locks are acquired using lock(). The mutexes are not swapped. + * A swap method accepts a T& and swaps the data inside a critical section. + * This is by far the preferred method of changing the guarded datum wholesale because it keeps the lock only + * for a short time, thus lowering the pressure on the mutex. + */ + void swap(synchronized_value & rhs) + { + if (this == &rhs) { + return; + } + // auto _ = make_unique_locks(mtx_, rhs.mtx_); + unique_lock lk1(mtx_, defer_lock); + unique_lock lk2(rhs.mtx_, defer_lock); + lock(lk1,lk2); + boost::swap(value_, rhs.value_); + } + /** + * Swap with the underlying value type + * + * Effects: Swaps the data on a scope protected by the mutex. + */ + void swap(value_type & rhs) + { + strict_lock lk(mtx_); + boost::swap(value_, rhs); + } + + /** + * Essentially calling a method obj->foo(x, y, z) calls the method foo(x, y, z) inside a critical section as + * long-lived as the call itself. + */ + strict_lock_ptr operator->() + { + return BOOST_THREAD_MAKE_RV_REF((strict_lock_ptr(value_, mtx_))); + } + /** + * If the synchronized_value object involved is const-qualified, then you'll only be able to call const methods + * through operator->. So, for example, vec->push_back("xyz") won't work if vec were const-qualified. + * The locking mechanism capitalizes on the assumption that const methods don't modify their underlying data. + */ + const_strict_lock_ptr operator->() const + { + return BOOST_THREAD_MAKE_RV_REF((const_strict_lock_ptr(value_, mtx_))); + } + + /** + * Call function on a locked block. + * + * @requires fct(value_) is well formed. + * + * Example + * void fun(synchronized_value> & v) { + * v ( [](vector> & vec) + * { + * vec.push_back(42); + * assert(vec.back() == 42); + * } ); + * } + */ + template + inline + typename boost::result_of::type + operator()(BOOST_THREAD_RV_REF(F) fct) + { + strict_lock lk(mtx_); + return fct(value_); + } + template + inline + typename boost::result_of::type + operator()(BOOST_THREAD_RV_REF(F) fct) const + { + strict_lock lk(mtx_); + return fct(value_); + } + + +#if defined BOOST_NO_CXX11_RVALUE_REFERENCES + template + inline + typename boost::result_of::type + operator()(F const & fct) + { + strict_lock lk(mtx_); + return fct(value_); + } + template + inline + typename boost::result_of::type + operator()(F const & fct) const + { + strict_lock lk(mtx_); + return fct(value_); + } + + template + inline + R operator()(R(*fct)(value_type&)) + { + strict_lock lk(mtx_); + return fct(value_); + } + template + inline + R operator()(R(*fct)(value_type const&)) const + { + strict_lock lk(mtx_); + return fct(value_); + } +#endif + + + /** + * The synchronize() factory make easier to lock on a scope. + * As discussed, operator-> can only lock over the duration of a call, so it is insufficient for complex operations. + * With synchronize() you get to lock the object in a scoped and to directly access the object inside that scope. + * + * Example + * void fun(synchronized_value> & v) { + * auto&& vec=v.synchronize(); + * vec.push_back(42); + * assert(vec.back() == 42); + * } + */ + strict_lock_ptr synchronize() + { + return BOOST_THREAD_MAKE_RV_REF((strict_lock_ptr(value_, mtx_))); + } + const_strict_lock_ptr synchronize() const + { + return BOOST_THREAD_MAKE_RV_REF((const_strict_lock_ptr(value_, mtx_))); + } + + unique_lock_ptr unique_synchronize() + { + return BOOST_THREAD_MAKE_RV_REF((unique_lock_ptr(value_, mtx_))); + } + const_unique_lock_ptr unique_synchronize() const + { + return BOOST_THREAD_MAKE_RV_REF((const_unique_lock_ptr(value_, mtx_))); + } + unique_lock_ptr unique_synchronize(defer_lock_t tag) + { + return BOOST_THREAD_MAKE_RV_REF((unique_lock_ptr(value_, mtx_, tag))); + } + const_unique_lock_ptr unique_synchronize(defer_lock_t tag) const + { + return BOOST_THREAD_MAKE_RV_REF((const_unique_lock_ptr(value_, mtx_, tag))); + } + unique_lock_ptr defer_synchronize() BOOST_NOEXCEPT + { + return BOOST_THREAD_MAKE_RV_REF((unique_lock_ptr(value_, mtx_, defer_lock))); + } + const_unique_lock_ptr defer_synchronize() const BOOST_NOEXCEPT + { + return BOOST_THREAD_MAKE_RV_REF((const_unique_lock_ptr(value_, mtx_, defer_lock))); + } + unique_lock_ptr try_to_synchronize() BOOST_NOEXCEPT + { + return BOOST_THREAD_MAKE_RV_REF((unique_lock_ptr(value_, mtx_, try_to_lock))); + } + const_unique_lock_ptr try_to_synchronize() const BOOST_NOEXCEPT + { + return BOOST_THREAD_MAKE_RV_REF((const_unique_lock_ptr(value_, mtx_, try_to_lock))); + } + unique_lock_ptr adopt_synchronize() BOOST_NOEXCEPT + { + return BOOST_THREAD_MAKE_RV_REF((unique_lock_ptr(value_, mtx_, adopt_lock))); + } + const_unique_lock_ptr adopt_synchronize() const BOOST_NOEXCEPT + { + return BOOST_THREAD_MAKE_RV_REF((const_unique_lock_ptr(value_, mtx_, adopt_lock))); + } + + +#if ! defined __IBMCPP__ + private: +#endif + class deref_value + { + private: + friend class synchronized_value; + + boost::unique_lock lk_; + T& value_; + + explicit deref_value(synchronized_value& outer): + lk_(outer.mtx_),value_(outer.value_) + {} + + public: + BOOST_THREAD_MOVABLE_ONLY(deref_value) + + deref_value(BOOST_THREAD_RV_REF(deref_value) other): + lk_(boost::move(BOOST_THREAD_RV(other).lk_)),value_(BOOST_THREAD_RV(other).value_) + {} + operator T&() + { + return value_; + } + + deref_value& operator=(T const& newVal) + { + value_=newVal; + return *this; + } + }; + class const_deref_value + { + private: + friend class synchronized_value; + + boost::unique_lock lk_; + const T& value_; + + explicit const_deref_value(synchronized_value const& outer): + lk_(outer.mtx_), value_(outer.value_) + {} + + public: + BOOST_THREAD_MOVABLE_ONLY(const_deref_value) + + const_deref_value(BOOST_THREAD_RV_REF(const_deref_value) other): + lk_(boost::move(BOOST_THREAD_RV(other).lk_)), value_(BOOST_THREAD_RV(other).value_) + {} + + operator const T&() + { + return value_; + } + }; + + public: + deref_value operator*() + { + return BOOST_THREAD_MAKE_RV_REF(deref_value(*this)); + } + + const_deref_value operator*() const + { + return BOOST_THREAD_MAKE_RV_REF(const_deref_value(*this)); + } + + // io functions + /** + * @requires T is OutputStreamable + * @effects saves the value type on the output stream @c os. + */ + template + void save(OStream& os) const + { + strict_lock lk(mtx_); + os << value_; + } + /** + * @requires T is InputStreamable + * @effects loads the value type from the input stream @c is. + */ + template + void load(IStream& is) const + { + strict_lock lk(mtx_); + is >> value_; + } + + // relational operators + /** + * @requires T is EqualityComparable + * + */ + bool operator==(synchronized_value const& rhs) const + { + unique_lock lk1(mtx_, defer_lock); + unique_lock lk2(rhs.mtx_, defer_lock); + lock(lk1,lk2); + + return value_ == rhs.value_; + } + /** + * @requires T is LessThanComparable + * + */ + bool operator<(synchronized_value const& rhs) const + { + unique_lock lk1(mtx_, defer_lock); + unique_lock lk2(rhs.mtx_, defer_lock); + lock(lk1,lk2); + + return value_ < rhs.value_; + } + /** + * @requires T is GreaterThanComparable + * + */ + bool operator>(synchronized_value const& rhs) const + { + unique_lock lk1(mtx_, defer_lock); + unique_lock lk2(rhs.mtx_, defer_lock); + lock(lk1,lk2); + + return value_ > rhs.value_; + } + bool operator<=(synchronized_value const& rhs) const + { + unique_lock lk1(mtx_, defer_lock); + unique_lock lk2(rhs.mtx_, defer_lock); + lock(lk1,lk2); + + return value_ <= rhs.value_; + } + bool operator>=(synchronized_value const& rhs) const + { + unique_lock lk1(mtx_, defer_lock); + unique_lock lk2(rhs.mtx_, defer_lock); + lock(lk1,lk2); + + return value_ >= rhs.value_; + } + bool operator==(value_type const& rhs) const + { + unique_lock lk1(mtx_); + + return value_ == rhs; + } + bool operator!=(value_type const& rhs) const + { + unique_lock lk1(mtx_); + + return value_ != rhs; + } + bool operator<(value_type const& rhs) const + { + unique_lock lk1(mtx_); + + return value_ < rhs; + } + bool operator<=(value_type const& rhs) const + { + unique_lock lk1(mtx_); + + return value_ <= rhs; + } + bool operator>(value_type const& rhs) const + { + unique_lock lk1(mtx_); + + return value_ > rhs; + } + bool operator>=(value_type const& rhs) const + { + unique_lock lk1(mtx_); + + return value_ >= rhs; + } + + }; + + // Specialized algorithms + /** + * + */ + template + inline void swap(synchronized_value & lhs, synchronized_value & rhs) + { + lhs.swap(rhs); + } + template + inline void swap(synchronized_value & lhs, T & rhs) + { + lhs.swap(rhs); + } + template + inline void swap(T & lhs, synchronized_value & rhs) + { + rhs.swap(lhs); + } + + //Hash support + +// template struct hash; +// template +// struct hash >; + + // Comparison with T + template + bool operator!=(synchronized_value const&lhs, synchronized_value const& rhs) + { + return ! (lhs==rhs); + } + + template + bool operator==(T const& lhs, synchronized_value const&rhs) + { + return rhs==lhs; + } + template + bool operator!=(T const& lhs, synchronized_value const&rhs) + { + return rhs!=lhs; + } + template + bool operator<(T const& lhs, synchronized_value const&rhs) + { + return rhs>=lhs; + } + template + bool operator<=(T const& lhs, synchronized_value const&rhs) + { + return rhs>lhs; + } + template + bool operator>(T const& lhs, synchronized_value const&rhs) + { + return rhs<=lhs; + } + template + bool operator>=(T const& lhs, synchronized_value const&rhs) + { + return rhs + inline OStream& operator<<(OStream& os, synchronized_value const& rhs) + { + rhs.save(os); + return os; + } + template + inline IStream& operator>>(IStream& is, synchronized_value const& rhs) + { + rhs.load(is); + return is; + } + +#if ! defined(BOOST_THREAD_NO_SYNCHRONIZE) +#if ! defined BOOST_NO_CXX11_VARIADIC_TEMPLATES + + template + std::tuple::type ...> synchronize(SV& ...sv) + { + boost::lock(sv.mtx_ ...); + typedef std::tuple::type ...> t_type; + + return t_type(typename synchronized_value_strict_lock_ptr::type(sv.value_, sv.mtx_, adopt_lock) ...); + } +#else + + template + std::tuple< + typename synchronized_value_strict_lock_ptr::type, + typename synchronized_value_strict_lock_ptr::type + > + synchronize(SV1& sv1, SV2& sv2) + { + boost::lock(sv1.mtx_, sv2.mtx_); + typedef std::tuple< + typename synchronized_value_strict_lock_ptr::type, + typename synchronized_value_strict_lock_ptr::type + > t_type; + + return t_type( + typename synchronized_value_strict_lock_ptr::type(sv1.value_, sv1.mtx_, adopt_lock), + typename synchronized_value_strict_lock_ptr::type(sv2.value_, sv2.mtx_, adopt_lock) + ); + + } + template + std::tuple< + typename synchronized_value_strict_lock_ptr::type, + typename synchronized_value_strict_lock_ptr::type, + typename synchronized_value_strict_lock_ptr::type + > + synchronize(SV1& sv1, SV2& sv2, SV3& sv3) + { + boost::lock(sv1.mtx_, sv2.mtx_); + typedef std::tuple< + typename synchronized_value_strict_lock_ptr::type, + typename synchronized_value_strict_lock_ptr::type, + typename synchronized_value_strict_lock_ptr::type + > t_type; + + return t_type( + typename synchronized_value_strict_lock_ptr::type(sv1.value_, sv1.mtx_, adopt_lock), + typename synchronized_value_strict_lock_ptr::type(sv2.value_, sv2.mtx_, adopt_lock), + typename synchronized_value_strict_lock_ptr::type(sv3.value_, sv3.mtx_, adopt_lock) + ); + + } +#endif +#endif +} + +#include + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/testable_mutex.hpp b/src/third_party/boost-1.60.0/boost/thread/testable_mutex.hpp new file mode 100644 index 00000000000..3c87f9349a5 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/testable_mutex.hpp @@ -0,0 +1,152 @@ +// (C) Copyright 2012 Vicente J. Botet Escriba +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#ifndef BOOST_THREAD_TESTABLE_LOCKABLE_HPP +#define BOOST_THREAD_TESTABLE_LOCKABLE_HPP + +#include + +#include + +#include +#include + +#include + +namespace boost +{ + /** + * Based on Associate Mutexes with Data to Prevent Races, By Herb Sutter, May 13, 2010 + * http://www.drdobbs.com/windows/associate-mutexes-with-data-to-prevent-r/224701827?pgno=3 + * + * Make our mutex testable if it isn't already. + * + * Many mutex services (including boost::mutex) don't provide a way to ask, + * "Do I already hold a lock on this mutex?" + * Sometimes it is needed to know if a method like is_locked to be available. + * This wrapper associates an arbitrary lockable type with a thread id that stores the ID of the thread that + * currently holds the lockable. The thread id initially holds an invalid value that means no threads own the mutex. + * 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. + * + */ + template + class testable_mutex + { + Lockable mtx_; + atomic id_; + public: + /// the type of the wrapped lockable + typedef Lockable lockable_type; + + /// Non copyable + BOOST_THREAD_NO_COPYABLE(testable_mutex) + + testable_mutex() : id_(thread::id()) {} + + void lock() + { + BOOST_ASSERT(! is_locked_by_this_thread()); + mtx_.lock(); + id_ = this_thread::get_id(); + } + + void unlock() + { + BOOST_ASSERT(is_locked_by_this_thread()); + id_ = thread::id(); + mtx_.unlock(); + } + + bool try_lock() + { + BOOST_ASSERT(! is_locked_by_this_thread()); + if (mtx_.try_lock()) + { + id_ = this_thread::get_id(); + return true; + } + else + { + return false; + } + } +#ifdef BOOST_THREAD_USES_CHRONO + template + bool try_lock_for(const chrono::duration& rel_time) + { + BOOST_ASSERT(! is_locked_by_this_thread()); + if (mtx_.try_lock_for(rel_time)) + { + id_ = this_thread::get_id(); + return true; + } + else + { + return false; + } + } + template + bool try_lock_until(const chrono::time_point& abs_time) + { + BOOST_ASSERT(! is_locked_by_this_thread()); + if (mtx_.try_lock_until(abs_time)) + { + id_ = this_thread::get_id(); + return true; + } + else + { + return false; + } + } +#endif + + bool is_locked_by_this_thread() const + { + return this_thread::get_id() == id_; + } + bool is_locked() const + { + return ! (thread::id() == id_); + } + + thread::id get_id() const + { + return id_; + } + + // todo add the shared and upgrade mutex functions + }; + + template + struct is_testable_lockable : false_type + {}; + + template + struct is_testable_lockable > : true_type + {}; + +// /** +// * Overloaded function used to check if the mutex is locked when it is testable and do nothing otherwise. +// * +// * This function is used usually to assert the pre-condition when the function can only be called when the mutex +// * must be locked by the current thread. +// */ +// template +// bool is_locked_by_this_thread(testable_mutex const& mtx) +// { +// return mtx.is_locked(); +// } +// template +// bool is_locked_by_this_thread(Lockable const&) +// { +// return true; +// } +} + +#include + +#endif // header diff --git a/src/third_party/boost-1.60.0/boost/thread/thread.hpp b/src/third_party/boost-1.60.0/boost/thread/thread.hpp new file mode 100644 index 00000000000..3e63b42aaa1 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/thread.hpp @@ -0,0 +1,16 @@ +#ifndef BOOST_THREAD_THREAD_HPP +#define BOOST_THREAD_THREAD_HPP + +// thread.hpp +// +// (C) Copyright 2007-8 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/thread_functors.hpp b/src/third_party/boost-1.60.0/boost/thread/thread_functors.hpp new file mode 100644 index 00000000000..f7bd816b178 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/thread_functors.hpp @@ -0,0 +1,57 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2009-2012 Anthony Williams +// (C) Copyright 2012 Vicente J. Botet Escriba + +// Based on the Anthony's idea of scoped_thread in CCiA + +#ifndef BOOST_THREAD_THREAD_FUNCTORS_HPP +#define BOOST_THREAD_THREAD_FUNCTORS_HPP + +#include +#include +#include +#include + +#include + +namespace boost +{ + + struct detach + { + void operator()(thread& t) + { + t.detach(); + } + }; + + struct join_if_joinable + { + void operator()(thread& t) + { + if (t.joinable()) + { + t.join(); + } + } + }; + +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + struct interrupt_and_join_if_joinable + { + void operator()(thread& t) + { + t.interrupt(); + if (t.joinable()) + { + t.join(); + } + } + }; +#endif +} +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/thread_guard.hpp b/src/third_party/boost-1.60.0/boost/thread/thread_guard.hpp new file mode 100644 index 00000000000..85157f101e2 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/thread_guard.hpp @@ -0,0 +1,46 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2009-2012 Anthony Williams +// (C) Copyright 2012 Vicente J. Botet Escriba + +// Based on the Anthony's idea of thread_joiner in CCiA + +#ifndef BOOST_THREAD_THREAD_GUARD_HPP +#define BOOST_THREAD_THREAD_GUARD_HPP + +#include +#include +#include + +#include + +namespace boost +{ + + /** + * Non-copyable RAII scoped thread guard joiner which join the thread if joinable when destroyed. + */ + template + class thread_guard + { + thread& t_; + public: + BOOST_THREAD_NO_COPYABLE( thread_guard) + + explicit thread_guard(thread& t) : + t_(t) + { + } + ~thread_guard() + { + CallableThread on_destructor; + + on_destructor(t_); + } + }; + +} +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/thread_only.hpp b/src/third_party/boost-1.60.0/boost/thread/thread_only.hpp new file mode 100644 index 00000000000..0d0c07061f2 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/thread_only.hpp @@ -0,0 +1,29 @@ +#ifndef BOOST_THREAD_THREAD_ONLY_HPP +#define BOOST_THREAD_THREAD_ONLY_HPP + +// thread.hpp +// +// (C) Copyright 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include + +#if defined(BOOST_THREAD_PLATFORM_WIN32) +#include +#elif defined(BOOST_THREAD_PLATFORM_PTHREAD) +#include +#else +#error "Boost threads unavailable on this platform" +#endif + +#include +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS +#include +#endif +#include + + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/thread_pool.hpp b/src/third_party/boost-1.60.0/boost/thread/thread_pool.hpp new file mode 100644 index 00000000000..4d2dcbea3a7 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/thread_pool.hpp @@ -0,0 +1,15 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// 2013/09 Vicente J. Botet Escriba +// Adapt to boost from CCIA C++11 implementation +// first implementation of a simple pool thread using a vector of threads and a sync_queue. + +#ifndef BOOST_THREAD_THREAD_POOL_HPP +#define BOOST_THREAD_THREAD_POOL_HPP + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/thread_time.hpp b/src/third_party/boost-1.60.0/boost/thread/thread_time.hpp new file mode 100644 index 00000000000..ffdcf850f73 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/thread_time.hpp @@ -0,0 +1,55 @@ +#ifndef BOOST_THREAD_TIME_HPP +#define BOOST_THREAD_TIME_HPP +// (C) Copyright 2007 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include + +#include + +namespace boost +{ + typedef boost::posix_time::ptime system_time; + + inline system_time get_system_time() + { +#if defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK) + return boost::date_time::microsec_clock::universal_time(); +#else // defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK) + return boost::date_time::second_clock::universal_time(); +#endif // defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK) + } + + namespace detail + { + inline system_time get_system_time_sentinel() + { + return system_time(boost::posix_time::pos_infin); + } + + inline unsigned long get_milliseconds_until(system_time const& target_time) + { + if(target_time.is_pos_infinity()) + { + return ~(unsigned long)0; + } + system_time const now=get_system_time(); + if(target_time<=now) + { + return 0; + } + return static_cast((target_time-now).total_milliseconds()+1); + } + + } + +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/tss.hpp b/src/third_party/boost-1.60.0/boost/thread/tss.hpp new file mode 100644 index 00000000000..d798bef558a --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/tss.hpp @@ -0,0 +1,113 @@ +#ifndef BOOST_THREAD_TSS_HPP +#define BOOST_THREAD_TSS_HPP +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2007-8 Anthony Williams + +#include +#include +#include + +#include + +namespace boost +{ + namespace detail + { + struct tss_cleanup_function + { + virtual ~tss_cleanup_function() + {} + + virtual void operator()(void* data)=0; + }; + + BOOST_THREAD_DECL void set_tss_data(void const* key,boost::shared_ptr func,void* tss_data,bool cleanup_existing); + BOOST_THREAD_DECL void* get_tss_data(void const* key); + } + + template + class thread_specific_ptr + { + private: + thread_specific_ptr(thread_specific_ptr&); + thread_specific_ptr& operator=(thread_specific_ptr&); + + struct delete_data: + detail::tss_cleanup_function + { + void operator()(void* data) + { + delete static_cast(data); + } + }; + + struct run_custom_cleanup_function: + detail::tss_cleanup_function + { + void (*cleanup_function)(T*); + + explicit run_custom_cleanup_function(void (*cleanup_function_)(T*)): + cleanup_function(cleanup_function_) + {} + + void operator()(void* data) + { + cleanup_function(static_cast(data)); + } + }; + + + boost::shared_ptr cleanup; + + public: + typedef T element_type; + + thread_specific_ptr(): + cleanup(detail::heap_new(),detail::do_heap_delete()) + {} + explicit thread_specific_ptr(void (*func_)(T*)) + { + if(func_) + { + cleanup.reset(detail::heap_new(func_),detail::do_heap_delete()); + } + } + ~thread_specific_ptr() + { + detail::set_tss_data(this,boost::shared_ptr(),0,true); + } + + T* get() const + { + return static_cast(detail::get_tss_data(this)); + } + T* operator->() const + { + return get(); + } + typename boost::detail::sp_dereference< T >::type operator*() const + { + return *get(); + } + T* release() + { + T* const temp=get(); + detail::set_tss_data(this,boost::shared_ptr(),0,false); + return temp; + } + void reset(T* new_value=0) + { + T* const current_value=get(); + if(current_value!=new_value) + { + detail::set_tss_data(this,cleanup,new_value,true); + } + } + }; +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/user_scheduler.hpp b/src/third_party/boost-1.60.0/boost/thread/user_scheduler.hpp new file mode 100644 index 00000000000..c551d21710d --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/user_scheduler.hpp @@ -0,0 +1,202 @@ +// Copyright (C) 2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// 2013/11 Vicente J. Botet Escriba +// first implementation of a simple serial scheduler. + +#ifndef BOOST_THREAD_USER_SCHEDULER_HPP +#define BOOST_THREAD_USER_SCHEDULER_HPP + +#include +#include +#include +#include +#include + +#include + +namespace boost +{ + + class user_scheduler + { + /// type-erasure to store the works to do + typedef thread_detail::work work; + + /// the thread safe work queue + sync_queue work_queue; + + public: + /** + * Effects: try to execute one task. + * Returns: whether a task has been executed. + * Throws: whatever the current task constructor throws or the task() throws. + */ + bool try_executing_one() + { + work task; + try + { + if (work_queue.try_pull(task) == queue_op_status::success) + { + task(); + return true; + } + return false; + } + catch (std::exception& ) + { + return false; + } + catch (...) + { + return false; + } + } + private: + /** + * Effects: schedule one task or yields + * Throws: whatever the current task constructor throws or the task() throws. + */ + void schedule_one_or_yield() + { + if ( ! try_executing_one()) + { + this_thread::yield(); + } + } + + + /** + * The main loop of the worker thread + */ + void worker_thread() + { + while (!closed()) + { + schedule_one_or_yield(); + } + while (try_executing_one()) + { + } + } + + public: + /// user_scheduler is not copyable. + BOOST_THREAD_NO_COPYABLE(user_scheduler) + + /** + * \b Effects: creates a thread pool that runs closures using one of its closure-executing methods. + * + * \b Throws: Whatever exception is thrown while initializing the needed resources. + */ + user_scheduler() + { + } + /** + * \b Effects: Destroys the thread pool. + * + * \b Synchronization: The completion of all the closures happen before the completion of the \c user_scheduler destructor. + */ + ~user_scheduler() + { + // signal to all the worker thread that there will be no more submissions. + close(); + } + + /** + * loop + */ + void loop() { worker_thread(); } + /** + * \b Effects: close the \c user_scheduler for submissions. + * The loop will work until there is no more closures to run. + */ + void close() + { + work_queue.close(); + } + + /** + * \b Returns: whether the pool is closed for submissions. + */ + bool closed() + { + return work_queue.closed(); + } + + /** + * \b Requires: \c Closure is a model of \c Callable(void()) and a model of \c CopyConstructible/MoveConstructible. + * + * \b Effects: The specified \c closure will be scheduled for execution at some point in the future. + * If invoked closure throws an exception the \c user_scheduler will call \c std::terminate, as is the case with threads. + * + * \b Synchronization: completion of \c closure on a particular thread happens before destruction of thread's thread local variables. + * + * \b Throws: \c sync_queue_is_closed if the thread pool is closed. + * Whatever exception that can be throw while storing the closure. + */ + +#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) + template + void submit(Closure & closure) + { + work w ((closure)); + work_queue.push(boost::move(w)); + //work_queue.push(work(closure)); // todo check why this doesn't work + } +#endif + void submit(void (*closure)()) + { + work w ((closure)); + work_queue.push(boost::move(w)); + //work_queue.push(work(closure)); // todo check why this doesn't work + } + + template + void submit(BOOST_THREAD_RV_REF(Closure) closure) + { + work w =boost::move(closure); + work_queue.push(boost::move(w)); + //work_queue.push(work(boost::move(closure))); // todo check why this doesn't work + } + + /** + * \b Requires: This must be called from an scheduled task. + * + * \b Effects: reschedule functions until pred() + */ + template + bool reschedule_until(Pred const& pred) + { + do { + if ( ! try_executing_one()) + { + return false; + } + } while (! pred()); + return true; + } + /** + * run queued closures + */ + void run_queued_closures() + { + sync_queue::underlying_queue_type q = work_queue.underlying_queue(); + while (q.empty()) + { + work task = q.front(); + q.pop_front(); + task(); + } + } + + }; + +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/v2/shared_mutex.hpp b/src/third_party/boost-1.60.0/boost/thread/v2/shared_mutex.hpp new file mode 100755 index 00000000000..5acab4d8cda --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/v2/shared_mutex.hpp @@ -0,0 +1,1062 @@ +#ifndef BOOST_THREAD_V2_SHARED_MUTEX_HPP +#define BOOST_THREAD_V2_SHARED_MUTEX_HPP + +// shared_mutex.hpp +// +// Copyright Howard Hinnant 2007-2010. +// Copyright Vicente J. Botet Escriba 2012. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +/* + synopsis + +namespace boost +{ +namespace thread_v2 +{ + +class shared_mutex +{ +public: + + shared_mutex(); + ~shared_mutex(); + + shared_mutex(const shared_mutex&) = delete; + shared_mutex& operator=(const shared_mutex&) = delete; + + // Exclusive ownership + + void lock(); + bool try_lock(); + template + bool try_lock_for(const boost::chrono::duration& rel_time); + template + bool + try_lock_until( + const boost::chrono::time_point& abs_time); + void unlock(); + + // Shared ownership + + void lock_shared(); + bool try_lock_shared(); + template + bool + try_lock_shared_for(const boost::chrono::duration& rel_time); + template + bool + try_lock_shared_until( + const boost::chrono::time_point& abs_time); + void unlock_shared(); +}; + +class upgrade_mutex +{ +public: + + upgrade_mutex(); + ~upgrade_mutex(); + + upgrade_mutex(const upgrade_mutex&) = delete; + upgrade_mutex& operator=(const upgrade_mutex&) = delete; + + // Exclusive ownership + + void lock(); + bool try_lock(); + template + bool try_lock_for(const boost::chrono::duration& rel_time); + template + bool + try_lock_until( + const boost::chrono::time_point& abs_time); + void unlock(); + + // Shared ownership + + void lock_shared(); + bool try_lock_shared(); + template + bool + try_lock_shared_for(const boost::chrono::duration& rel_time); + template + bool + try_lock_shared_until( + const boost::chrono::time_point& abs_time); + void unlock_shared(); + + // Upgrade ownership + + void lock_upgrade(); + bool try_lock_upgrade(); + template + bool + try_lock_upgrade_for( + const boost::chrono::duration& rel_time); + template + bool + try_lock_upgrade_until( + const boost::chrono::time_point& abs_time); + void unlock_upgrade(); + + // Shared <-> Exclusive + + bool try_unlock_shared_and_lock(); + template + bool + try_unlock_shared_and_lock_for( + const boost::chrono::duration& rel_time); + template + bool + try_unlock_shared_and_lock_until( + const boost::chrono::time_point& abs_time); + void unlock_and_lock_shared(); + + // Shared <-> Upgrade + + bool try_unlock_shared_and_lock_upgrade(); + template + bool + try_unlock_shared_and_lock_upgrade_for( + const boost::chrono::duration& rel_time); + template + bool + try_unlock_shared_and_lock_upgrade_until( + const boost::chrono::time_point& abs_time); + void unlock_upgrade_and_lock_shared(); + + // Upgrade <-> Exclusive + + void unlock_upgrade_and_lock(); + bool try_unlock_upgrade_and_lock(); + template + bool + try_unlock_upgrade_and_lock_for( + const boost::chrono::duration& rel_time); + template + bool + try_unlock_upgrade_and_lock_until( + const boost::chrono::time_point& abs_time); + void unlock_and_lock_upgrade(); +}; + +} // thread_v2 +} // boost + + */ + +#include +#include +#include +#include +#include +#include +#include +#define BOOST_THREAD_INLINE inline + +namespace boost { + namespace thread_v2 { + + class shared_mutex + { + typedef ::boost::mutex mutex_t; + typedef ::boost::condition_variable cond_t; + typedef unsigned count_t; + + mutex_t mut_; + cond_t gate1_; + cond_t gate2_; + count_t state_; + + static const count_t write_entered_ = 1U << (sizeof(count_t)*CHAR_BIT - 1); + static const count_t n_readers_ = ~write_entered_; + + public: + BOOST_THREAD_INLINE shared_mutex(); + BOOST_THREAD_INLINE ~shared_mutex(); + +#ifndef BOOST_NO_CXX11_DELETED_FUNCTIONS + shared_mutex(shared_mutex const&) = delete; + shared_mutex& operator=(shared_mutex const&) = delete; +#else // BOOST_NO_CXX11_DELETED_FUNCTIONS + private: + shared_mutex(shared_mutex const&); + shared_mutex& operator=(shared_mutex const&); + public: +#endif // BOOST_NO_CXX11_DELETED_FUNCTIONS + + // Exclusive ownership + + BOOST_THREAD_INLINE void lock(); + BOOST_THREAD_INLINE bool try_lock(); + template + bool try_lock_for(const boost::chrono::duration& rel_time) + { + return try_lock_until(boost::chrono::steady_clock::now() + rel_time); + } + template + bool + try_lock_until( + const boost::chrono::time_point& abs_time); + BOOST_THREAD_INLINE void unlock(); + + + // Shared ownership + + BOOST_THREAD_INLINE void lock_shared(); + BOOST_THREAD_INLINE bool try_lock_shared(); + template + bool + try_lock_shared_for(const boost::chrono::duration& rel_time) + { + return try_lock_shared_until(boost::chrono::steady_clock::now() + + rel_time); + } + template + bool + try_lock_shared_until( + const boost::chrono::time_point& abs_time); + BOOST_THREAD_INLINE void unlock_shared(); + +#if defined BOOST_THREAD_USES_DATETIME + bool timed_lock(system_time const& timeout); + template + bool timed_lock(TimeDuration const & relative_time) + { + return timed_lock(get_system_time()+relative_time); + } + bool timed_lock_shared(system_time const& timeout); + template + bool timed_lock_shared(TimeDuration const & relative_time) + { + return timed_lock_shared(get_system_time()+relative_time); + } +#endif + }; + + template + bool + shared_mutex::try_lock_until( + const boost::chrono::time_point& abs_time) + { + boost::unique_lock lk(mut_); + if (state_ & write_entered_) + { + while (true) + { + boost::cv_status status = gate1_.wait_until(lk, abs_time); + if ((state_ & write_entered_) == 0) + break; + if (status == boost::cv_status::timeout) + return false; + } + } + state_ |= write_entered_; + if (state_ & n_readers_) + { + while (true) + { + boost::cv_status status = gate2_.wait_until(lk, abs_time); + if ((state_ & n_readers_) == 0) + break; + if (status == boost::cv_status::timeout) + { + state_ &= ~write_entered_; + return false; + } + } + } + return true; + } + + template + bool + shared_mutex::try_lock_shared_until( + const boost::chrono::time_point& abs_time) + { + boost::unique_lock lk(mut_); + if ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_) + { + while (true) + { + boost::cv_status status = gate1_.wait_until(lk, abs_time); + if ((state_ & write_entered_) == 0 && + (state_ & n_readers_) < n_readers_) + break; + if (status == boost::cv_status::timeout) + return false; + } + } + count_t num_readers = (state_ & n_readers_) + 1; + state_ &= ~n_readers_; + state_ |= num_readers; + return true; + } + +#if defined BOOST_THREAD_USES_DATETIME + bool shared_mutex::timed_lock(system_time const& abs_time) + { + boost::unique_lock lk(mut_); + if (state_ & write_entered_) + { + while (true) + { + bool status = gate1_.timed_wait(lk, abs_time); + if ((state_ & write_entered_) == 0) + break; + if (!status) + return false; + } + } + state_ |= write_entered_; + if (state_ & n_readers_) + { + while (true) + { + bool status = gate2_.timed_wait(lk, abs_time); + if ((state_ & n_readers_) == 0) + break; + if (!status) + { + state_ &= ~write_entered_; + return false; + } + } + } + return true; + } + bool shared_mutex::timed_lock_shared(system_time const& abs_time) + { + boost::unique_lock lk(mut_); + if (state_ & write_entered_) + { + while (true) + { + bool status = gate1_.timed_wait(lk, abs_time); + if ((state_ & write_entered_) == 0) + break; + if (!status ) + return false; + } + } + state_ |= write_entered_; + if (state_ & n_readers_) + { + while (true) + { + bool status = gate2_.timed_wait(lk, abs_time); + if ((state_ & n_readers_) == 0) + break; + if (!status) + { + state_ &= ~write_entered_; + return false; + } + } + } + return true; + } +#endif + class upgrade_mutex + { + typedef boost::mutex mutex_t; + typedef boost::condition_variable cond_t; + typedef unsigned count_t; + + mutex_t mut_; + cond_t gate1_; + cond_t gate2_; + count_t state_; + + static const unsigned write_entered_ = 1U << (sizeof(count_t)*CHAR_BIT - 1); + static const unsigned upgradable_entered_ = write_entered_ >> 1; + static const unsigned n_readers_ = ~(write_entered_ | upgradable_entered_); + + public: + + BOOST_THREAD_INLINE upgrade_mutex(); + BOOST_THREAD_INLINE ~upgrade_mutex(); + +#ifndef BOOST_CXX11_NO_DELETED_FUNCTIONS + upgrade_mutex(const upgrade_mutex&) = delete; + upgrade_mutex& operator=(const upgrade_mutex&) = delete; +#else // BOOST_CXX11_NO_DELETED_FUNCTIONS + private: + upgrade_mutex(const upgrade_mutex&); + upgrade_mutex& operator=(const upgrade_mutex&); + public: +#endif // BOOST_CXX11_NO_DELETED_FUNCTIONS + + // Exclusive ownership + + BOOST_THREAD_INLINE void lock(); + BOOST_THREAD_INLINE bool try_lock(); + template + bool try_lock_for(const boost::chrono::duration& rel_time) + { + return try_lock_until(boost::chrono::steady_clock::now() + rel_time); + } + template + bool + try_lock_until( + const boost::chrono::time_point& abs_time); + BOOST_THREAD_INLINE void unlock(); + + // Shared ownership + + BOOST_THREAD_INLINE void lock_shared(); + BOOST_THREAD_INLINE bool try_lock_shared(); + template + bool + try_lock_shared_for(const boost::chrono::duration& rel_time) + { + return try_lock_shared_until(boost::chrono::steady_clock::now() + + rel_time); + } + template + bool + try_lock_shared_until( + const boost::chrono::time_point& abs_time); + BOOST_THREAD_INLINE void unlock_shared(); + + // Upgrade ownership + + BOOST_THREAD_INLINE void lock_upgrade(); + BOOST_THREAD_INLINE bool try_lock_upgrade(); + template + bool + try_lock_upgrade_for( + const boost::chrono::duration& rel_time) + { + return try_lock_upgrade_until(boost::chrono::steady_clock::now() + + rel_time); + } + template + bool + try_lock_upgrade_until( + const boost::chrono::time_point& abs_time); + BOOST_THREAD_INLINE void unlock_upgrade(); + + // Shared <-> Exclusive + + BOOST_THREAD_INLINE bool try_unlock_shared_and_lock(); + template + bool + try_unlock_shared_and_lock_for( + const boost::chrono::duration& rel_time) + { + return try_unlock_shared_and_lock_until( + boost::chrono::steady_clock::now() + rel_time); + } + template + bool + try_unlock_shared_and_lock_until( + const boost::chrono::time_point& abs_time); + BOOST_THREAD_INLINE void unlock_and_lock_shared(); + + // Shared <-> Upgrade + + BOOST_THREAD_INLINE bool try_unlock_shared_and_lock_upgrade(); + template + bool + try_unlock_shared_and_lock_upgrade_for( + const boost::chrono::duration& rel_time) + { + return try_unlock_shared_and_lock_upgrade_until( + boost::chrono::steady_clock::now() + rel_time); + } + template + bool + try_unlock_shared_and_lock_upgrade_until( + const boost::chrono::time_point& abs_time); + BOOST_THREAD_INLINE void unlock_upgrade_and_lock_shared(); + + // Upgrade <-> Exclusive + + BOOST_THREAD_INLINE void unlock_upgrade_and_lock(); + BOOST_THREAD_INLINE bool try_unlock_upgrade_and_lock(); + template + bool + try_unlock_upgrade_and_lock_for( + const boost::chrono::duration& rel_time) + { + return try_unlock_upgrade_and_lock_until( + boost::chrono::steady_clock::now() + rel_time); + } + template + bool + try_unlock_upgrade_and_lock_until( + const boost::chrono::time_point& abs_time); + BOOST_THREAD_INLINE void unlock_and_lock_upgrade(); + +#if defined BOOST_THREAD_USES_DATETIME + inline bool timed_lock(system_time const& abs_time); + template + bool timed_lock(TimeDuration const & relative_time) + { + return timed_lock(get_system_time()+relative_time); + } + inline bool timed_lock_shared(system_time const& abs_time); + template + bool timed_lock_shared(TimeDuration const & relative_time) + { + return timed_lock_shared(get_system_time()+relative_time); + } + inline bool timed_lock_upgrade(system_time const& abs_time); + template + bool timed_lock_upgrade(TimeDuration const & relative_time) + { + return timed_lock_upgrade(get_system_time()+relative_time); + } +#endif + + }; + + template + bool + upgrade_mutex::try_lock_until( + const boost::chrono::time_point& abs_time) + { + boost::unique_lock lk(mut_); + if (state_ & (write_entered_ | upgradable_entered_)) + { + while (true) + { + boost::cv_status status = gate1_.wait_until(lk, abs_time); + if ((state_ & (write_entered_ | upgradable_entered_)) == 0) + break; + if (status == boost::cv_status::timeout) + return false; + } + } + state_ |= write_entered_; + if (state_ & n_readers_) + { + while (true) + { + boost::cv_status status = gate2_.wait_until(lk, abs_time); + if ((state_ & n_readers_) == 0) + break; + if (status == boost::cv_status::timeout) + { + state_ &= ~write_entered_; + return false; + } + } + } + return true; + } + + template + bool + upgrade_mutex::try_lock_shared_until( + const boost::chrono::time_point& abs_time) + { + boost::unique_lock lk(mut_); + if ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_) + { + while (true) + { + boost::cv_status status = gate1_.wait_until(lk, abs_time); + if ((state_ & write_entered_) == 0 && + (state_ & n_readers_) < n_readers_) + break; + if (status == boost::cv_status::timeout) + return false; + } + } + count_t num_readers = (state_ & n_readers_) + 1; + state_ &= ~n_readers_; + state_ |= num_readers; + return true; + } + + template + bool + upgrade_mutex::try_lock_upgrade_until( + const boost::chrono::time_point& abs_time) + { + boost::unique_lock lk(mut_); + if ((state_ & (write_entered_ | upgradable_entered_)) || + (state_ & n_readers_) == n_readers_) + { + while (true) + { + boost::cv_status status = gate1_.wait_until(lk, abs_time); + if ((state_ & (write_entered_ | upgradable_entered_)) == 0 && + (state_ & n_readers_) < n_readers_) + break; + if (status == boost::cv_status::timeout) + return false; + } + } + count_t num_readers = (state_ & n_readers_) + 1; + state_ &= ~n_readers_; + state_ |= upgradable_entered_ | num_readers; + return true; + } + +#if defined BOOST_THREAD_USES_DATETIME + bool upgrade_mutex::timed_lock(system_time const& abs_time) + { + boost::unique_lock lk(mut_); + if (state_ & (write_entered_ | upgradable_entered_)) + { + while (true) + { + bool status = gate1_.timed_wait(lk, abs_time); + if ((state_ & (write_entered_ | upgradable_entered_)) == 0) + break; + if (!status) + return false; + } + } + state_ |= write_entered_; + if (state_ & n_readers_) + { + while (true) + { + bool status = gate2_.timed_wait(lk, abs_time); + if ((state_ & n_readers_) == 0) + break; + if (!status) + { + state_ &= ~write_entered_; + return false; + } + } + } + return true; + } + bool upgrade_mutex::timed_lock_shared(system_time const& abs_time) + { + boost::unique_lock lk(mut_); + if ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_) + { + while (true) + { + bool status = gate1_.timed_wait(lk, abs_time); + if ((state_ & write_entered_) == 0 && + (state_ & n_readers_) < n_readers_) + break; + if (!status) + return false; + } + } + count_t num_readers = (state_ & n_readers_) + 1; + state_ &= ~n_readers_; + state_ |= num_readers; + return true; + } + bool upgrade_mutex::timed_lock_upgrade(system_time const& abs_time) + { + boost::unique_lock lk(mut_); + if ((state_ & (write_entered_ | upgradable_entered_)) || + (state_ & n_readers_) == n_readers_) + { + while (true) + { + bool status = gate1_.timed_wait(lk, abs_time); + if ((state_ & (write_entered_ | upgradable_entered_)) == 0 && + (state_ & n_readers_) < n_readers_) + break; + if (!status) + return false; + } + } + count_t num_readers = (state_ & n_readers_) + 1; + state_ &= ~n_readers_; + state_ |= upgradable_entered_ | num_readers; + return true; + } + +#endif + template + bool + upgrade_mutex::try_unlock_shared_and_lock_until( + const boost::chrono::time_point& abs_time) + { + boost::unique_lock lk(mut_); + if (state_ != 1) + { + while (true) + { + boost::cv_status status = gate2_.wait_until(lk, abs_time); + if (state_ == 1) + break; + if (status == boost::cv_status::timeout) + return false; + } + } + state_ = write_entered_; + return true; + } + + template + bool + upgrade_mutex::try_unlock_shared_and_lock_upgrade_until( + const boost::chrono::time_point& abs_time) + { + boost::unique_lock lk(mut_); + if ((state_ & (write_entered_ | upgradable_entered_)) != 0) + { + while (true) + { + boost::cv_status status = gate2_.wait_until(lk, abs_time); + if ((state_ & (write_entered_ | upgradable_entered_)) == 0) + break; + if (status == boost::cv_status::timeout) + return false; + } + } + state_ |= upgradable_entered_; + return true; + } + + template + bool + upgrade_mutex::try_unlock_upgrade_and_lock_until( + const boost::chrono::time_point& abs_time) + { + boost::unique_lock lk(mut_); + if ((state_ & n_readers_) != 1) + { + while (true) + { + boost::cv_status status = gate2_.wait_until(lk, abs_time); + if ((state_ & n_readers_) == 1) + break; + if (status == boost::cv_status::timeout) + return false; + } + } + state_ = write_entered_; + return true; + } + + ////// + // shared_mutex + + shared_mutex::shared_mutex() + : state_(0) + { + } + + shared_mutex::~shared_mutex() + { + boost::lock_guard _(mut_); + } + + // Exclusive ownership + + void + shared_mutex::lock() + { + boost::unique_lock lk(mut_); + while (state_ & write_entered_) + gate1_.wait(lk); + state_ |= write_entered_; + while (state_ & n_readers_) + gate2_.wait(lk); + } + + bool + shared_mutex::try_lock() + { + boost::unique_lock lk(mut_); + if (state_ == 0) + { + state_ = write_entered_; + return true; + } + return false; + } + + void + shared_mutex::unlock() + { + boost::lock_guard _(mut_); + state_ = 0; + gate1_.notify_all(); + } + + // Shared ownership + + void + shared_mutex::lock_shared() + { + boost::unique_lock lk(mut_); + while ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_) + gate1_.wait(lk); + count_t num_readers = (state_ & n_readers_) + 1; + state_ &= ~n_readers_; + state_ |= num_readers; + } + + bool + shared_mutex::try_lock_shared() + { + boost::unique_lock lk(mut_); + count_t num_readers = state_ & n_readers_; + if (!(state_ & write_entered_) && num_readers != n_readers_) + { + ++num_readers; + state_ &= ~n_readers_; + state_ |= num_readers; + return true; + } + return false; + } + + void + shared_mutex::unlock_shared() + { + boost::lock_guard _(mut_); + count_t num_readers = (state_ & n_readers_) - 1; + state_ &= ~n_readers_; + state_ |= num_readers; + if (state_ & write_entered_) + { + if (num_readers == 0) + gate2_.notify_one(); + } + else + { + if (num_readers == n_readers_ - 1) + gate1_.notify_one(); + } + } + + // upgrade_mutex + + upgrade_mutex::upgrade_mutex() + : gate1_(), + gate2_(), + state_(0) + { + } + + upgrade_mutex::~upgrade_mutex() + { + boost::lock_guard _(mut_); + } + + // Exclusive ownership + + void + upgrade_mutex::lock() + { + boost::unique_lock lk(mut_); + while (state_ & (write_entered_ | upgradable_entered_)) + gate1_.wait(lk); + state_ |= write_entered_; + while (state_ & n_readers_) + gate2_.wait(lk); + } + + bool + upgrade_mutex::try_lock() + { + boost::unique_lock lk(mut_); + if (state_ == 0) + { + state_ = write_entered_; + return true; + } + return false; + } + + void + upgrade_mutex::unlock() + { + boost::lock_guard _(mut_); + state_ = 0; + gate1_.notify_all(); + } + + // Shared ownership + + void + upgrade_mutex::lock_shared() + { + boost::unique_lock lk(mut_); + while ((state_ & write_entered_) || (state_ & n_readers_) == n_readers_) + gate1_.wait(lk); + count_t num_readers = (state_ & n_readers_) + 1; + state_ &= ~n_readers_; + state_ |= num_readers; + } + + bool + upgrade_mutex::try_lock_shared() + { + boost::unique_lock lk(mut_); + count_t num_readers = state_ & n_readers_; + if (!(state_ & write_entered_) && num_readers != n_readers_) + { + ++num_readers; + state_ &= ~n_readers_; + state_ |= num_readers; + return true; + } + return false; + } + + void + upgrade_mutex::unlock_shared() + { + boost::lock_guard _(mut_); + count_t num_readers = (state_ & n_readers_) - 1; + state_ &= ~n_readers_; + state_ |= num_readers; + if (state_ & write_entered_) + { + if (num_readers == 0) + gate2_.notify_one(); + } + else + { + if (num_readers == n_readers_ - 1) + gate1_.notify_one(); + } + } + + // Upgrade ownership + + void + upgrade_mutex::lock_upgrade() + { + boost::unique_lock lk(mut_); + while ((state_ & (write_entered_ | upgradable_entered_)) || + (state_ & n_readers_) == n_readers_) + gate1_.wait(lk); + count_t num_readers = (state_ & n_readers_) + 1; + state_ &= ~n_readers_; + state_ |= upgradable_entered_ | num_readers; + } + + bool + upgrade_mutex::try_lock_upgrade() + { + boost::unique_lock lk(mut_); + count_t num_readers = state_ & n_readers_; + if (!(state_ & (write_entered_ | upgradable_entered_)) + && num_readers != n_readers_) + { + ++num_readers; + state_ &= ~n_readers_; + state_ |= upgradable_entered_ | num_readers; + return true; + } + return false; + } + + void + upgrade_mutex::unlock_upgrade() + { + { + boost::lock_guard _(mut_); + count_t num_readers = (state_ & n_readers_) - 1; + state_ &= ~(upgradable_entered_ | n_readers_); + state_ |= num_readers; + } + gate1_.notify_all(); + } + + // Shared <-> Exclusive + + bool + upgrade_mutex::try_unlock_shared_and_lock() + { + boost::unique_lock lk(mut_); + if (state_ == 1) + { + state_ = write_entered_; + return true; + } + return false; + } + + void + upgrade_mutex::unlock_and_lock_shared() + { + { + boost::lock_guard _(mut_); + state_ = 1; + } + gate1_.notify_all(); + } + + // Shared <-> Upgrade + + bool + upgrade_mutex::try_unlock_shared_and_lock_upgrade() + { + boost::unique_lock lk(mut_); + if (!(state_ & (write_entered_ | upgradable_entered_))) + { + state_ |= upgradable_entered_; + return true; + } + return false; + } + + void + upgrade_mutex::unlock_upgrade_and_lock_shared() + { + { + boost::lock_guard _(mut_); + state_ &= ~upgradable_entered_; + } + gate1_.notify_all(); + } + + // Upgrade <-> Exclusive + + void + upgrade_mutex::unlock_upgrade_and_lock() + { + boost::unique_lock lk(mut_); + count_t num_readers = (state_ & n_readers_) - 1; + state_ &= ~(upgradable_entered_ | n_readers_); + state_ |= write_entered_ | num_readers; + while (state_ & n_readers_) + gate2_.wait(lk); + } + + bool + upgrade_mutex::try_unlock_upgrade_and_lock() + { + boost::unique_lock lk(mut_); + if (state_ == (upgradable_entered_ | 1)) + { + state_ = write_entered_; + return true; + } + return false; + } + + void + upgrade_mutex::unlock_and_lock_upgrade() + { + { + boost::lock_guard _(mut_); + state_ = upgradable_entered_ | 1; + } + gate1_.notify_all(); + } + + } // thread_v2 +} // boost + +namespace boost { + //using thread_v2::shared_mutex; + using thread_v2::upgrade_mutex; + typedef thread_v2::upgrade_mutex shared_mutex; +} + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/v2/thread.hpp b/src/third_party/boost-1.60.0/boost/thread/v2/thread.hpp new file mode 100644 index 00000000000..53560610e23 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/v2/thread.hpp @@ -0,0 +1,155 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2011 Vicente J. Botet Escriba + +#ifndef BOOST_THREAD_V2_THREAD_HPP +#define BOOST_THREAD_V2_THREAD_HPP + +#include +#ifdef BOOST_THREAD_USES_CHRONO +#include +#include +#endif +#include +#include + +namespace boost +{ + namespace this_thread + { + namespace no_interruption_point + { +#ifdef BOOST_THREAD_USES_CHRONO + + template + void sleep_until(const chrono::time_point& t) + { + using namespace chrono; + mutex mut; + condition_variable cv; + unique_lock lk(mut); + while (Clock::now() < t) + cv.wait_until(lk, t); + } + +#ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY + + template + void sleep_for(const chrono::duration& d) + { + using namespace chrono; + if (d > duration::zero()) + { + duration Max = nanoseconds::max BOOST_PREVENT_MACRO_SUBSTITUTION (); + nanoseconds ns; + if (d < Max) + { + ns = duration_cast(d); + if (ns < d) + ++ns; + } + else + ns = nanoseconds:: max BOOST_PREVENT_MACRO_SUBSTITUTION (); + sleep_for(ns); + } + } + + template + inline BOOST_SYMBOL_VISIBLE + void sleep_until(const chrono::time_point& t) + { + using namespace chrono; + sleep_for(t - steady_clock::now()); + } +#else + template + void sleep_for(const chrono::duration& d) + { + using namespace chrono; + if (d > duration::zero()) + { + steady_clock::time_point c_timeout = steady_clock::now() + ceil(d); + sleep_until(c_timeout); + } + } + +#endif + +#endif + } +#ifdef BOOST_THREAD_USES_CHRONO + + template + void sleep_until(const chrono::time_point& t) + { + using namespace chrono; + mutex mut; + condition_variable cv; + unique_lock lk(mut); + while (Clock::now() < t) + cv.wait_until(lk, t); + } + +#if defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC && defined BOOST_CHRONO_HAS_CLOCK_STEADY + template + void sleep_for(const chrono::duration& d) + { + using namespace chrono; + if (d > duration::zero()) + { + steady_clock::time_point c_timeout = steady_clock::now() + ceil(d); + sleep_until(c_timeout); + } + } + +#elif defined BOOST_THREAD_SLEEP_FOR_IS_STEADY + + template + void sleep_for(const chrono::duration& d) + { + using namespace chrono; + if (d > duration::zero()) + { + duration Max = nanoseconds::max BOOST_PREVENT_MACRO_SUBSTITUTION (); + nanoseconds ns; + if (d < Max) + { + ns = duration_cast(d); + if (ns < d) + ++ns; + } + else + ns = nanoseconds:: max BOOST_PREVENT_MACRO_SUBSTITUTION (); + sleep_for(ns); + } + } + + template + inline BOOST_SYMBOL_VISIBLE + void sleep_until(const chrono::time_point& t) + { + using namespace chrono; + sleep_for(t - steady_clock::now()); + } +#else + template + void sleep_for(const chrono::duration& d) + { + using namespace chrono; + if (d > duration::zero()) + { + //system_clock::time_point c_timeout = time_point_cast(system_clock::now() + ceil(d)); + system_clock::time_point c_timeout = system_clock::now() + ceil(d); + sleep_until(c_timeout); + } + } + +#endif + +#endif + } +} + + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/win32/basic_recursive_mutex.hpp b/src/third_party/boost-1.60.0/boost/thread/win32/basic_recursive_mutex.hpp new file mode 100644 index 00000000000..cfdfa043a3b --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/win32/basic_recursive_mutex.hpp @@ -0,0 +1,164 @@ +#ifndef BOOST_BASIC_RECURSIVE_MUTEX_WIN32_HPP +#define BOOST_BASIC_RECURSIVE_MUTEX_WIN32_HPP + +// basic_recursive_mutex.hpp +// +// (C) Copyright 2006-8 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#ifdef BOOST_THREAD_USES_CHRONO +#include +#include +#endif + +#include + +namespace boost +{ + namespace detail + { + template + struct basic_recursive_mutex_impl + { + long recursion_count; + long locking_thread_id; + underlying_mutex_type mutex; + + void initialize() + { + recursion_count=0; + locking_thread_id=0; + mutex.initialize(); + } + + void destroy() + { + mutex.destroy(); + } + + bool try_lock() BOOST_NOEXCEPT + { + long const current_thread_id=win32::GetCurrentThreadId(); + return try_recursive_lock(current_thread_id) || try_basic_lock(current_thread_id); + } + + void lock() + { + long const current_thread_id=win32::GetCurrentThreadId(); + if(!try_recursive_lock(current_thread_id)) + { + mutex.lock(); + BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id); + recursion_count=1; + } + } +#if defined BOOST_THREAD_USES_DATETIME + bool timed_lock(::boost::system_time const& target) + { + long const current_thread_id=win32::GetCurrentThreadId(); + return try_recursive_lock(current_thread_id) || try_timed_lock(current_thread_id,target); + } + template + bool timed_lock(Duration const& timeout) + { + return timed_lock(get_system_time()+timeout); + } +#endif + +#ifdef BOOST_THREAD_USES_CHRONO + template + bool try_lock_for(const chrono::duration& rel_time) + { + long const current_thread_id=win32::GetCurrentThreadId(); + return try_recursive_lock(current_thread_id) || try_timed_lock_for(current_thread_id,rel_time); + } + template + bool try_lock_until(const chrono::time_point& t) + { + long const current_thread_id=win32::GetCurrentThreadId(); + return try_recursive_lock(current_thread_id) || try_timed_lock_until(current_thread_id,t); + } +#endif + void unlock() + { + if(!--recursion_count) + { + BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,0); + mutex.unlock(); + } + } + + private: + bool try_recursive_lock(long current_thread_id) BOOST_NOEXCEPT + { + if(::boost::detail::interlocked_read_acquire(&locking_thread_id)==current_thread_id) + { + ++recursion_count; + return true; + } + return false; + } + + bool try_basic_lock(long current_thread_id) BOOST_NOEXCEPT + { + if(mutex.try_lock()) + { + BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id); + recursion_count=1; + return true; + } + return false; + } + +#if defined BOOST_THREAD_USES_DATETIME + bool try_timed_lock(long current_thread_id,::boost::system_time const& target) + { + if(mutex.timed_lock(target)) + { + BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id); + recursion_count=1; + return true; + } + return false; + } +#endif + template + bool try_timed_lock_until(long current_thread_id,TP const& target) + { + if(mutex.try_lock_until(target)) + { + BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id); + recursion_count=1; + return true; + } + return false; + } + template + bool try_timed_lock_for(long current_thread_id,D const& target) + { + if(mutex.try_lock_for(target)) + { + BOOST_INTERLOCKED_EXCHANGE(&locking_thread_id,current_thread_id); + recursion_count=1; + return true; + } + return false; + } + }; + + typedef basic_recursive_mutex_impl basic_recursive_mutex; + typedef basic_recursive_mutex_impl basic_recursive_timed_mutex; + } +} + +#define BOOST_BASIC_RECURSIVE_MUTEX_INITIALIZER {0} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/win32/basic_timed_mutex.hpp b/src/third_party/boost-1.60.0/boost/thread/win32/basic_timed_mutex.hpp new file mode 100644 index 00000000000..d20c6589e69 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/win32/basic_timed_mutex.hpp @@ -0,0 +1,279 @@ +#ifndef BOOST_BASIC_TIMED_MUTEX_WIN32_HPP +#define BOOST_BASIC_TIMED_MUTEX_WIN32_HPP + +// basic_timed_mutex_win32.hpp +// +// (C) Copyright 2006-8 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#if defined BOOST_THREAD_USES_DATETIME +#include +#endif +#include +#ifdef BOOST_THREAD_USES_CHRONO +#include +#include +#endif +#include + +namespace boost +{ + namespace detail + { + struct basic_timed_mutex + { + BOOST_STATIC_CONSTANT(unsigned char,lock_flag_bit=31); + BOOST_STATIC_CONSTANT(unsigned char,event_set_flag_bit=30); + BOOST_STATIC_CONSTANT(long,lock_flag_value=1< + bool timed_lock(Duration const& timeout) + { + return timed_lock(get_system_time()+timeout); + } + + bool timed_lock(boost::xtime const& timeout) + { + return timed_lock(system_time(timeout)); + } +#endif +#ifdef BOOST_THREAD_USES_CHRONO + template + bool try_lock_for(const chrono::duration& rel_time) + { + return try_lock_until(chrono::steady_clock::now() + rel_time); + } + template + bool try_lock_until(const chrono::time_point& t) + { + using namespace chrono; + system_clock::time_point s_now = system_clock::now(); + typename Clock::time_point c_now = Clock::now(); + return try_lock_until(s_now + ceil(t - c_now)); + } + template + bool try_lock_until(const chrono::time_point& t) + { + using namespace chrono; + typedef time_point sys_tmpt; + return try_lock_until(sys_tmpt(chrono::ceil(t.time_since_epoch()))); + } + bool try_lock_until(const chrono::time_point& tp) + { + if(try_lock()) + { + return true; + } + long old_count=active_count; + mark_waiting_and_try_lock(old_count); + + if(old_count&lock_flag_value) + { + bool lock_acquired=false; + void* const sem=get_event(); + + do + { + chrono::time_point now = chrono::system_clock::now(); + if (tp<=now) { + BOOST_INTERLOCKED_DECREMENT(&active_count); + return false; + } + chrono::milliseconds rel_time= chrono::ceil(tp-now); + + if(win32::WaitForSingleObjectEx(sem,static_cast(rel_time.count()),0)!=0) + { + BOOST_INTERLOCKED_DECREMENT(&active_count); + return false; + } + clear_waiting_and_try_lock(old_count); + lock_acquired=!(old_count&lock_flag_value); + } + while(!lock_acquired); + } + return true; + } +#endif + + void unlock() + { + long const offset=lock_flag_value; + long const old_count=BOOST_INTERLOCKED_EXCHANGE_ADD(&active_count,lock_flag_value); + if(!(old_count&event_set_flag_value) && (old_count>offset)) + { + if(!win32::interlocked_bit_test_and_set(&active_count,event_set_flag_bit)) + { + win32::SetEvent(get_event()); + } + } + } + + private: + void* get_event() + { + void* current_event=::boost::detail::interlocked_read_acquire(&event); + + if(!current_event) + { + void* const new_event=win32::create_anonymous_event(win32::auto_reset_event,win32::event_initially_reset); +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4311) +#pragma warning(disable:4312) +#endif + void* const old_event=BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(&event,new_event,0); +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + if(old_event!=0) + { + win32::CloseHandle(new_event); + return old_event; + } + else + { + return new_event; + } + } + return current_event; + } + + }; + + } +} + +#define BOOST_BASIC_TIMED_MUTEX_INITIALIZER {0} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/win32/condition_variable.hpp b/src/third_party/boost-1.60.0/boost/thread/win32/condition_variable.hpp new file mode 100644 index 00000000000..23e9e444840 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/win32/condition_variable.hpp @@ -0,0 +1,567 @@ +#ifndef BOOST_THREAD_CONDITION_VARIABLE_WIN32_HPP +#define BOOST_THREAD_CONDITION_VARIABLE_WIN32_HPP +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2007-8 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba + +#include +#include +#include +#include +#include +#if defined BOOST_THREAD_USES_DATETIME +#include +#endif +#include +#include +#include +#include + +#include +#include + +#ifdef BOOST_THREAD_USES_CHRONO +#include +#include +#endif + +#include +#include +#include + +#include + +namespace boost +{ + namespace detail + { + class basic_cv_list_entry; + void intrusive_ptr_add_ref(basic_cv_list_entry * p); + void intrusive_ptr_release(basic_cv_list_entry * p); + + class basic_cv_list_entry + { + private: + detail::win32::handle_manager semaphore; + detail::win32::handle_manager wake_sem; + long waiters; + bool notified; + long references; + + public: + BOOST_THREAD_NO_COPYABLE(basic_cv_list_entry) + explicit basic_cv_list_entry(detail::win32::handle_manager const& wake_sem_): + semaphore(detail::win32::create_anonymous_semaphore(0,LONG_MAX)), + wake_sem(wake_sem_.duplicate()), + waiters(1),notified(false),references(0) + {} + + static bool no_waiters(boost::intrusive_ptr const& entry) + { + return !detail::interlocked_read_acquire(&entry->waiters); + } + + void add_waiter() + { + BOOST_INTERLOCKED_INCREMENT(&waiters); + } + + void remove_waiter() + { + BOOST_INTERLOCKED_DECREMENT(&waiters); + } + + void release(unsigned count_to_release) + { + notified=true; + detail::win32::ReleaseSemaphore(semaphore,count_to_release,0); + } + + void release_waiters() + { + release(detail::interlocked_read_acquire(&waiters)); + } + + bool is_notified() const + { + return notified; + } + + bool wait(timeout abs_time) + { + return this_thread::interruptible_wait(semaphore,abs_time); + } + + bool woken() + { + unsigned long const woken_result=detail::win32::WaitForSingleObjectEx(wake_sem,0,0); + BOOST_ASSERT((woken_result==detail::win32::timeout) || (woken_result==0)); + return woken_result==0; + } + + friend void intrusive_ptr_add_ref(basic_cv_list_entry * p); + friend void intrusive_ptr_release(basic_cv_list_entry * p); + }; + + inline void intrusive_ptr_add_ref(basic_cv_list_entry * p) + { + BOOST_INTERLOCKED_INCREMENT(&p->references); + } + + inline void intrusive_ptr_release(basic_cv_list_entry * p) + { + if(!BOOST_INTERLOCKED_DECREMENT(&p->references)) + { + delete p; + } + } + + class basic_condition_variable + { + boost::mutex internal_mutex; + long total_count; + unsigned active_generation_count; + + typedef basic_cv_list_entry list_entry; + + typedef boost::intrusive_ptr entry_ptr; + typedef std::vector generation_list; + + generation_list generations; + detail::win32::handle_manager wake_sem; + + void wake_waiters(long count_to_wake) + { + detail::interlocked_write_release(&total_count,total_count-count_to_wake); + detail::win32::ReleaseSemaphore(wake_sem,count_to_wake,0); + } + + template + struct relocker + { + BOOST_THREAD_NO_COPYABLE(relocker) + lock_type& lock; + bool unlocked; + + relocker(lock_type& lock_): + lock(lock_),unlocked(false) + {} + void unlock() + { + lock.unlock(); + unlocked=true; + } + ~relocker() + { + if(unlocked) + { + lock.lock(); + } + + } + }; + + + entry_ptr get_wait_entry() + { + boost::lock_guard internal_lock(internal_mutex); + + if(!wake_sem) + { + wake_sem=detail::win32::create_anonymous_semaphore(0,LONG_MAX); + BOOST_ASSERT(wake_sem); + } + + detail::interlocked_write_release(&total_count,total_count+1); + if(generations.empty() || generations.back()->is_notified()) + { + entry_ptr new_entry(new list_entry(wake_sem)); + generations.push_back(new_entry); + return new_entry; + } + else + { + generations.back()->add_waiter(); + return generations.back(); + } + } + + struct entry_manager + { + entry_ptr const entry; + boost::mutex& internal_mutex; + + BOOST_THREAD_NO_COPYABLE(entry_manager) + entry_manager(entry_ptr const& entry_, boost::mutex& mutex_): + entry(entry_), internal_mutex(mutex_) + {} + + ~entry_manager() + { + boost::lock_guard internal_lock(internal_mutex); + entry->remove_waiter(); + } + + list_entry* operator->() + { + return entry.get(); + } + }; + + + protected: + template + bool do_wait(lock_type& lock,timeout abs_time) + { + relocker locker(lock); + + entry_manager entry(get_wait_entry(), internal_mutex); + + locker.unlock(); + + bool woken=false; + while(!woken) + { + if(!entry->wait(abs_time)) + { + return false; + } + + woken=entry->woken(); + } + return woken; + } + + template + bool do_wait(lock_type& m,timeout const& abs_time,predicate_type pred) + { + while (!pred()) + { + if(!do_wait(m, abs_time)) + return pred(); + } + return true; + } + + basic_condition_variable(const basic_condition_variable& other); + basic_condition_variable& operator=(const basic_condition_variable& other); + + public: + basic_condition_variable(): + total_count(0),active_generation_count(0),wake_sem(0) + {} + + ~basic_condition_variable() + {} + + void notify_one() BOOST_NOEXCEPT + { + if(detail::interlocked_read_acquire(&total_count)) + { + boost::lock_guard internal_lock(internal_mutex); + if(!total_count) + { + return; + } + wake_waiters(1); + + for(generation_list::iterator it=generations.begin(), + end=generations.end(); + it!=end;++it) + { + (*it)->release(1); + } + generations.erase(std::remove_if(generations.begin(),generations.end(),&basic_cv_list_entry::no_waiters),generations.end()); + } + } + + void notify_all() BOOST_NOEXCEPT + { + if(detail::interlocked_read_acquire(&total_count)) + { + boost::lock_guard internal_lock(internal_mutex); + if(!total_count) + { + return; + } + wake_waiters(total_count); + for(generation_list::iterator it=generations.begin(), + end=generations.end(); + it!=end;++it) + { + (*it)->release_waiters(); + } + generations.clear(); + wake_sem=detail::win32::handle(0); + } + } + + }; + } + + class condition_variable: + private detail::basic_condition_variable + { + public: + BOOST_THREAD_NO_COPYABLE(condition_variable) + condition_variable() + {} + + using detail::basic_condition_variable::notify_one; + using detail::basic_condition_variable::notify_all; + + void wait(unique_lock& m) + { + do_wait(m,detail::timeout::sentinel()); + } + + template + void wait(unique_lock& m,predicate_type pred) + { + while(!pred()) wait(m); + } + + +#if defined BOOST_THREAD_USES_DATETIME + bool timed_wait(unique_lock& m,boost::system_time const& abs_time) + { + return do_wait(m,abs_time); + } + + bool timed_wait(unique_lock& m,boost::xtime const& abs_time) + { + return do_wait(m,system_time(abs_time)); + } + template + bool timed_wait(unique_lock& m,duration_type const& wait_duration) + { + if (wait_duration.is_pos_infinity()) + { + wait(m); // or do_wait(m,detail::timeout::sentinel()); + return true; + } + if (wait_duration.is_special()) + { + return true; + } + return do_wait(m,wait_duration.total_milliseconds()); + } + + template + bool timed_wait(unique_lock& m,boost::system_time const& abs_time,predicate_type pred) + { + return do_wait(m,abs_time,pred); + } + template + bool timed_wait(unique_lock& m,boost::xtime const& abs_time,predicate_type pred) + { + return do_wait(m,system_time(abs_time),pred); + } + template + bool timed_wait(unique_lock& m,duration_type const& wait_duration,predicate_type pred) + { + if (wait_duration.is_pos_infinity()) + { + while (!pred()) + { + wait(m); // or do_wait(m,detail::timeout::sentinel()); + } + return true; + } + if (wait_duration.is_special()) + { + return pred(); + } + return do_wait(m,wait_duration.total_milliseconds(),pred); + } +#endif +#ifdef BOOST_THREAD_USES_CHRONO + + template + cv_status + wait_until( + unique_lock& lock, + const chrono::time_point& t) + { + using namespace chrono; + chrono::time_point now = Clock::now(); + if (t<=now) { + return cv_status::timeout; + } + do_wait(lock, ceil(t-now).count()); + return Clock::now() < t ? cv_status::no_timeout : + cv_status::timeout; + } + + template + cv_status + wait_for( + unique_lock& lock, + const chrono::duration& d) + { + using namespace chrono; + if (d<=chrono::duration::zero()) { + return cv_status::timeout; + } + + steady_clock::time_point c_now = steady_clock::now(); + do_wait(lock, ceil(d).count()); + return steady_clock::now() - c_now < d ? cv_status::no_timeout : + cv_status::timeout; + } + + template + bool + wait_until( + unique_lock& lock, + const chrono::time_point& t, + Predicate pred) + { + while (!pred()) + { + if (wait_until(lock, t) == cv_status::timeout) + return pred(); + } + return true; + } + template + bool + wait_for( + unique_lock& lock, + const chrono::duration& d, + Predicate pred) + { + return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred)); + } +#endif + }; + + class condition_variable_any: + private detail::basic_condition_variable + { + public: + BOOST_THREAD_NO_COPYABLE(condition_variable_any) + condition_variable_any() + {} + + using detail::basic_condition_variable::notify_one; + using detail::basic_condition_variable::notify_all; + + template + void wait(lock_type& m) + { + do_wait(m,detail::timeout::sentinel()); + } + + template + void wait(lock_type& m,predicate_type pred) + { + while(!pred()) wait(m); + } + +#if defined BOOST_THREAD_USES_DATETIME + template + bool timed_wait(lock_type& m,boost::system_time const& abs_time) + { + return do_wait(m,abs_time); + } + + template + bool timed_wait(lock_type& m,boost::xtime const& abs_time) + { + return do_wait(m,system_time(abs_time)); + } + + template + bool timed_wait(lock_type& m,duration_type const& wait_duration) + { + return do_wait(m,wait_duration.total_milliseconds()); + } + + template + bool timed_wait(lock_type& m,boost::system_time const& abs_time,predicate_type pred) + { + return do_wait(m,abs_time,pred); + } + + template + bool timed_wait(lock_type& m,boost::xtime const& abs_time,predicate_type pred) + { + return do_wait(m,system_time(abs_time),pred); + } + + template + bool timed_wait(lock_type& m,duration_type const& wait_duration,predicate_type pred) + { + return do_wait(m,wait_duration.total_milliseconds(),pred); + } +#endif +#ifdef BOOST_THREAD_USES_CHRONO + + template + cv_status + wait_until( + lock_type& lock, + const chrono::time_point& t) + { + using namespace chrono; + chrono::time_point now = Clock::now(); + if (t<=now) { + return cv_status::timeout; + } + do_wait(lock, ceil(t-now).count()); + return Clock::now() < t ? cv_status::no_timeout : + cv_status::timeout; + } + + template + cv_status + wait_for( + lock_type& lock, + const chrono::duration& d) + { + using namespace chrono; + if (d<=chrono::duration::zero()) { + return cv_status::timeout; + } + steady_clock::time_point c_now = steady_clock::now(); + do_wait(lock, ceil(d).count()); + return steady_clock::now() - c_now < d ? cv_status::no_timeout : + cv_status::timeout; + } + + template + bool + wait_until( + lock_type& lock, + const chrono::time_point& t, + Predicate pred) + { + while (!pred()) + { + if (wait_until(lock, t) == cv_status::timeout) + return pred(); + } + return true; + } + + template + bool + wait_for( + lock_type& lock, + const chrono::duration& d, + Predicate pred) + { + return wait_until(lock, chrono::steady_clock::now() + d, boost::move(pred)); + } +#endif + }; + + BOOST_THREAD_DECL void notify_all_at_thread_exit(condition_variable& cond, unique_lock lk); +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/win32/interlocked_read.hpp b/src/third_party/boost-1.60.0/boost/thread/win32/interlocked_read.hpp new file mode 100644 index 00000000000..2ad3fe9017a --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/win32/interlocked_read.hpp @@ -0,0 +1,77 @@ +#ifndef BOOST_THREAD_DETAIL_INTERLOCKED_READ_WIN32_HPP +#define BOOST_THREAD_DETAIL_INTERLOCKED_READ_WIN32_HPP + +// interlocked_read_win32.hpp +// +// (C) Copyright 2005-8 Anthony Williams +// (C) Copyright 2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +#include + +#ifdef BOOST_MSVC + +namespace boost +{ + namespace detail + { + // Since VS2005 volatile reads always acquire + inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT + { + long const res=*x; + return res; + } + inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT + { + void* const res=*x; + return res; + } + + // Since VS2005 volatile writes always release + inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT + { + *x=value; + } + inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT + { + *x=value; + } + } +} + +#else + +namespace boost +{ + namespace detail + { + inline long interlocked_read_acquire(long volatile* x) BOOST_NOEXCEPT + { + return BOOST_INTERLOCKED_COMPARE_EXCHANGE(x,0,0); + } + inline void* interlocked_read_acquire(void* volatile* x) BOOST_NOEXCEPT + { + return BOOST_INTERLOCKED_COMPARE_EXCHANGE_POINTER(x,0,0); + } + inline void interlocked_write_release(long volatile* x,long value) BOOST_NOEXCEPT + { + BOOST_INTERLOCKED_EXCHANGE(x,value); + } + inline void interlocked_write_release(void* volatile* x,void* value) BOOST_NOEXCEPT + { + BOOST_INTERLOCKED_EXCHANGE_POINTER(x,value); + } + } +} + +#endif + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/win32/mfc_thread_init.hpp b/src/third_party/boost-1.60.0/boost/thread/win32/mfc_thread_init.hpp new file mode 100644 index 00000000000..e866f8949f5 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/win32/mfc_thread_init.hpp @@ -0,0 +1,40 @@ +#ifndef BOOST_THREAD_WIN32_MFC_THREAD_INIT_HPP +#define BOOST_THREAD_WIN32_MFC_THREAD_INIT_HPP +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2008 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba + + +// check if we use MFC +#ifdef _AFXDLL +# if defined(_AFXEXT) + +// can't use ExtRawDllMain from afxdllx.h as it also defines the symbol _pRawDllMain +extern "C" +inline BOOL WINAPI ExtRawDllMain(HINSTANCE, DWORD dwReason, LPVOID) +{ + if (dwReason == DLL_PROCESS_ATTACH) + { + // save critical data pointers before running the constructors + AFX_MODULE_STATE* pModuleState = AfxGetModuleState(); + pModuleState->m_pClassInit = pModuleState->m_classList; + pModuleState->m_pFactoryInit = pModuleState->m_factoryList; + pModuleState->m_classList.m_pHead = NULL; + pModuleState->m_factoryList.m_pHead = NULL; + } + return TRUE; // ok +} + +extern "C" __declspec(selectany) BOOL (WINAPI * const _pRawDllMainOrig)(HANDLE, DWORD, LPVOID) = &ExtRawDllMain; + +# elif defined(_USRDLL) + +extern "C" BOOL WINAPI RawDllMain(HANDLE, DWORD dwReason, LPVOID); +extern "C" __declspec(selectany) BOOL (WINAPI * const _pRawDllMainOrig)(HANDLE, DWORD, LPVOID) = &RawDllMain; + +# endif +#endif + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/win32/mutex.hpp b/src/third_party/boost-1.60.0/boost/thread/win32/mutex.hpp new file mode 100644 index 00000000000..01544784b5b --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/win32/mutex.hpp @@ -0,0 +1,72 @@ +#ifndef BOOST_THREAD_WIN32_MUTEX_HPP +#define BOOST_THREAD_WIN32_MUTEX_HPP +// (C) Copyright 2005-7 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS +#include +#endif +#include + +#include + +namespace boost +{ + namespace detail + { + typedef ::boost::detail::basic_timed_mutex underlying_mutex; + } + + class mutex: + public ::boost::detail::underlying_mutex + { + public: + BOOST_THREAD_NO_COPYABLE(mutex) + mutex() + { + initialize(); + } + ~mutex() + { + destroy(); + } + +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS + typedef unique_lock scoped_lock; + typedef detail::try_lock_wrapper scoped_try_lock; +#endif + }; + + typedef mutex try_mutex; + + class timed_mutex: + public ::boost::detail::basic_timed_mutex + { + public: + BOOST_THREAD_NO_COPYABLE(timed_mutex) + timed_mutex() + { + initialize(); + } + + ~timed_mutex() + { + destroy(); + } + +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS + typedef unique_lock scoped_timed_lock; + typedef detail::try_lock_wrapper scoped_try_lock; + typedef scoped_timed_lock scoped_lock; +#endif + }; +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/win32/once.hpp b/src/third_party/boost-1.60.0/boost/thread/win32/once.hpp new file mode 100644 index 00000000000..24eb0f29d06 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/win32/once.hpp @@ -0,0 +1,1087 @@ +#ifndef BOOST_THREAD_WIN32_ONCE_HPP +#define BOOST_THREAD_WIN32_ONCE_HPP + +// once.hpp +// +// (C) Copyright 2005-7 Anthony Williams +// (C) Copyright 2005 John Maddock +// (C) Copyright 2011-2013 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std +{ + using ::memcpy; + using ::ptrdiff_t; +} +#endif + +namespace boost +{ + struct once_flag; + namespace detail + { + struct once_context; + + inline bool enter_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT; + inline void commit_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT; + inline void rollback_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT; + } + +#ifdef BOOST_THREAD_PROVIDES_ONCE_CXX11 + + struct once_flag + { + BOOST_THREAD_NO_COPYABLE(once_flag) + BOOST_CONSTEXPR once_flag() BOOST_NOEXCEPT + : status(0), count(0) + {} + long status; + long count; + private: + friend inline bool enter_once_region(once_flag& flag, detail::once_context& ctx) BOOST_NOEXCEPT; + friend inline void commit_once_region(once_flag& flag, detail::once_context& ctx) BOOST_NOEXCEPT; + friend inline void rollback_once_region(once_flag& flag, detail::once_context& ctx) BOOST_NOEXCEPT; + }; + +#define BOOST_ONCE_INIT once_flag() +#else // BOOST_THREAD_PROVIDES_ONCE_CXX11 + + struct once_flag + { + long status; + long count; + }; + +#define BOOST_ONCE_INIT {0,0} +#endif // BOOST_THREAD_PROVIDES_ONCE_CXX11 + +#if defined BOOST_THREAD_PROVIDES_INVOKE +#define BOOST_THREAD_INVOKE_RET_VOID detail::invoke +#define BOOST_THREAD_INVOKE_RET_VOID_CALL +#elif defined BOOST_THREAD_PROVIDES_INVOKE_RET +#define BOOST_THREAD_INVOKE_RET_VOID detail::invoke +#define BOOST_THREAD_INVOKE_RET_VOID_CALL +#else +#define BOOST_THREAD_INVOKE_RET_VOID boost::bind +#define BOOST_THREAD_INVOKE_RET_VOID_CALL () +#endif + + namespace detail + { +#ifdef BOOST_NO_ANSI_APIS + typedef wchar_t once_char_type; +#else + typedef char once_char_type; +#endif + unsigned const once_mutex_name_fixed_length=54; + unsigned const once_mutex_name_length=once_mutex_name_fixed_length+ + sizeof(void*)*2+sizeof(unsigned long)*2+1; + + template + void int_to_string(I p, once_char_type* buf) + { + for(unsigned i=0; i < sizeof(I)*2; ++i,++buf) + { +#ifdef BOOST_NO_ANSI_APIS + once_char_type const a=L'A'; +#else + once_char_type const a='A'; +#endif + *buf = a + static_cast((p >> (i*4)) & 0x0f); + } + *buf = 0; + } + + inline void name_once_mutex(once_char_type* mutex_name,void* flag_address) + { +#ifdef BOOST_NO_ANSI_APIS + static const once_char_type fixed_mutex_name[]=L"Local\\{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag"; +#else + static const once_char_type fixed_mutex_name[]="Local\\{C15730E2-145C-4c5e-B005-3BC753F42475}-once-flag"; +#endif + BOOST_STATIC_ASSERT(sizeof(fixed_mutex_name) == + (sizeof(once_char_type)*(once_mutex_name_fixed_length+1))); + + std::memcpy(mutex_name,fixed_mutex_name,sizeof(fixed_mutex_name)); + detail::int_to_string(reinterpret_cast(flag_address), + mutex_name + once_mutex_name_fixed_length); + detail::int_to_string(win32::GetCurrentProcessId(), + mutex_name + once_mutex_name_fixed_length + sizeof(void*)*2); + } + + inline void* open_once_event(once_char_type* mutex_name,void* flag_address) + { + if(!*mutex_name) + { + name_once_mutex(mutex_name,flag_address); + } + +#ifdef BOOST_NO_ANSI_APIS + return ::boost::detail::win32::OpenEventW( +#else + return ::boost::detail::win32::OpenEventA( +#endif + ::boost::detail::win32::synchronize | + ::boost::detail::win32::event_modify_state, + false, + mutex_name); + } + + inline void* create_once_event(once_char_type* mutex_name,void* flag_address) + { + if(!*mutex_name) + { + name_once_mutex(mutex_name,flag_address); + } + + return ::boost::detail::win32::create_event( + mutex_name, + ::boost::detail::win32::manual_reset_event, + ::boost::detail::win32::event_initially_reset); + } + + struct once_context { + long const function_complete_flag_value; + long const running_value; + bool counted; + detail::win32::handle_manager event_handle; + detail::once_char_type mutex_name[once_mutex_name_length]; + once_context() : + function_complete_flag_value(0xc15730e2), + running_value(0x7f0725e3), + counted(false) + { + mutex_name[0]=0; + } + }; + enum once_action {try_, break_, continue_}; + + inline bool enter_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT + { + long status=BOOST_INTERLOCKED_COMPARE_EXCHANGE(&flag.status,ctx.running_value,0); + if(!status) + { + if(!ctx.event_handle) + { + ctx.event_handle=detail::open_once_event(ctx.mutex_name,&flag); + } + if(ctx.event_handle) + { + ::boost::detail::win32::ResetEvent(ctx.event_handle); + } + return true; + } + return false; + } + inline void commit_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT + { + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + } + BOOST_INTERLOCKED_EXCHANGE(&flag.status,ctx.function_complete_flag_value); + if(!ctx.event_handle && + (::boost::detail::interlocked_read_acquire(&flag.count)>1)) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + } + if(ctx.event_handle) + { + ::boost::detail::win32::SetEvent(ctx.event_handle); + } + } + inline void rollback_once_region(once_flag& flag, once_context& ctx) BOOST_NOEXCEPT + { + BOOST_INTERLOCKED_EXCHANGE(&flag.status,0); + if(!ctx.event_handle) + { + ctx.event_handle=detail::open_once_event(ctx.mutex_name,&flag); + } + if(ctx.event_handle) + { + ::boost::detail::win32::SetEvent(ctx.event_handle); + } + } + } + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) +//#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) + inline void call_once(once_flag& flag, void (*f)()) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + f(); + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx( + ctx.event_handle,::boost::detail::win32::infinite, 0)); + } + } +//#endif + template + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + f(); + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx( + ctx.event_handle,::boost::detail::win32::infinite,0)); + } + } + template + inline void call_once(once_flag& flag, BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(A) a, BOOST_THREAD_RV_REF(ArgTypes)... args) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward(f)), + thread_detail::decay_copy(boost::forward(a)), + thread_detail::decay_copy(boost::forward(args))... + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx( + ctx.event_handle,::boost::detail::win32::infinite,0)); + } + } +#else +#if ! defined(BOOST_MSVC) && ! defined(BOOST_INTEL) + template + void call_once(once_flag& flag,Function f) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + f(); + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx( + ctx.event_handle,::boost::detail::win32::infinite,0)); + } + } + template + void call_once(once_flag& flag,Function f, T1 p1) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID(f,p1) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx( + ctx.event_handle,::boost::detail::win32::infinite,0)); + } + } + template + void call_once(once_flag& flag,Function f, T1 p1, T2 p2) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx( + ctx.event_handle,::boost::detail::win32::infinite,0)); + } + } + template + void call_once(once_flag& flag,Function f, T1 p1, T2 p2, T3 p3) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2,p3) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx( + ctx.event_handle,::boost::detail::win32::infinite,0)); + } + } +#elif defined BOOST_NO_CXX11_RVALUE_REFERENCES + + template + void call_once(once_flag& flag,Function const&f) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + f(); + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx( + ctx.event_handle,::boost::detail::win32::infinite,0)); + } + } + template + void call_once(once_flag& flag,Function const&f, T1 const&p1) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID(f,p1) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx( + ctx.event_handle,::boost::detail::win32::infinite,0)); + } + } + template + void call_once(once_flag& flag,Function const&f, T1 const&p1, T2 const&p2) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx( + ctx.event_handle,::boost::detail::win32::infinite,0)); + } + } + template + void call_once(once_flag& flag,Function const&f, T1 const&p1, T2 const&p2, T3 const&p3) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID(f,p1,p2,p3) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx( + ctx.event_handle,::boost::detail::win32::infinite,0)); + } + } +#endif +#if 1 +#if defined(BOOST_THREAD_RVALUE_REFERENCES_DONT_MATCH_FUNTION_PTR) + inline void call_once(once_flag& flag, void (*f)()) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + f(); + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx( + ctx.event_handle,::boost::detail::win32::infinite,0)); + } + } + template + void call_once(once_flag& flag,void (*f)(BOOST_THREAD_RV_REF(T1)), BOOST_THREAD_RV_REF(T1) p1) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + f( + thread_detail::decay_copy(boost::forward(p1)) + ); + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx( + ctx.event_handle,::boost::detail::win32::infinite,0)); + } + } + template + void call_once(once_flag& flag,void (*f)(BOOST_THREAD_RV_REF(T1),BOOST_THREAD_RV_REF(T2)), BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + f( + thread_detail::decay_copy(boost::forward(p1)), + thread_detail::decay_copy(boost::forward(p2)) + ); + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx( + ctx.event_handle,::boost::detail::win32::infinite,0)); + } + } + template + void call_once(once_flag& flag,void (*f)(BOOST_THREAD_RV_REF(T1),BOOST_THREAD_RV_REF(T2)), BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2, BOOST_THREAD_RV_REF(T3) p3) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + f( + thread_detail::decay_copy(boost::forward(p1)), + thread_detail::decay_copy(boost::forward(p2)), + thread_detail::decay_copy(boost::forward(p3)) + ); + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx( + ctx.event_handle,::boost::detail::win32::infinite,0)); + } + } +#endif + template + void call_once(once_flag& flag,BOOST_THREAD_RV_REF(Function) f) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + f(); + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx( + ctx.event_handle,::boost::detail::win32::infinite,0)); + } + } + + template + void call_once(once_flag& flag,BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward(f)), + thread_detail::decay_copy(boost::forward(p1)) + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx( + ctx.event_handle,::boost::detail::win32::infinite,0)); + } + } + template + void call_once(once_flag& flag,BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward(f)), + thread_detail::decay_copy(boost::forward(p1)), + thread_detail::decay_copy(boost::forward(p2)) + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx( + ctx.event_handle,::boost::detail::win32::infinite,0)); + } + } + template + void call_once(once_flag& flag,BOOST_THREAD_RV_REF(Function) f, BOOST_THREAD_RV_REF(T1) p1, BOOST_THREAD_RV_REF(T2) p2, BOOST_THREAD_RV_REF(T3) p3) + { + // Try for a quick win: if the procedure has already been called + // just skip through: + detail::once_context ctx; + while(::boost::detail::interlocked_read_acquire(&flag.status) + !=ctx.function_complete_flag_value) + { + if(detail::enter_once_region(flag, ctx)) + { + BOOST_TRY + { + BOOST_THREAD_INVOKE_RET_VOID( + thread_detail::decay_copy(boost::forward(f)), + thread_detail::decay_copy(boost::forward(p1)), + thread_detail::decay_copy(boost::forward(p2)), + thread_detail::decay_copy(boost::forward(p3)) + ) BOOST_THREAD_INVOKE_RET_VOID_CALL; + + } + BOOST_CATCH(...) + { + detail::rollback_once_region(flag, ctx); + BOOST_RETHROW + } + BOOST_CATCH_END + detail::commit_once_region(flag, ctx); + break; + } + if(!ctx.counted) + { + BOOST_INTERLOCKED_INCREMENT(&flag.count); + ctx.counted=true; + long status=::boost::detail::interlocked_read_acquire(&flag.status); + if(status==ctx.function_complete_flag_value) + { + break; + } + if(!ctx.event_handle) + { + ctx.event_handle=detail::create_once_event(ctx.mutex_name,&flag); + continue; + } + } + BOOST_VERIFY(!::boost::detail::win32::WaitForSingleObjectEx( + ctx.event_handle,::boost::detail::win32::infinite,0)); + } + } + +#endif +#endif +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/win32/recursive_mutex.hpp b/src/third_party/boost-1.60.0/boost/thread/win32/recursive_mutex.hpp new file mode 100644 index 00000000000..1f0f7f5e5fd --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/win32/recursive_mutex.hpp @@ -0,0 +1,70 @@ +#ifndef BOOST_RECURSIVE_MUTEX_WIN32_HPP +#define BOOST_RECURSIVE_MUTEX_WIN32_HPP + +// recursive_mutex.hpp +// +// (C) Copyright 2006-7 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +#include +#include +#include +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS +#include +#endif + +#include + +namespace boost +{ + class recursive_mutex: + public ::boost::detail::basic_recursive_mutex + { + public: + BOOST_THREAD_NO_COPYABLE(recursive_mutex) + recursive_mutex() + { + ::boost::detail::basic_recursive_mutex::initialize(); + } + ~recursive_mutex() + { + ::boost::detail::basic_recursive_mutex::destroy(); + } + +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS + typedef unique_lock scoped_lock; + typedef detail::try_lock_wrapper scoped_try_lock; +#endif + }; + + typedef recursive_mutex recursive_try_mutex; + + class recursive_timed_mutex: + public ::boost::detail::basic_recursive_timed_mutex + { + public: + BOOST_THREAD_NO_COPYABLE(recursive_timed_mutex) + recursive_timed_mutex() + { + ::boost::detail::basic_recursive_timed_mutex::initialize(); + } + ~recursive_timed_mutex() + { + ::boost::detail::basic_recursive_timed_mutex::destroy(); + } + +#if defined BOOST_THREAD_PROVIDES_NESTED_LOCKS + typedef unique_lock scoped_timed_lock; + typedef detail::try_lock_wrapper scoped_try_lock; + typedef scoped_timed_lock scoped_lock; +#endif + }; +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/win32/shared_mutex.hpp b/src/third_party/boost-1.60.0/boost/thread/win32/shared_mutex.hpp new file mode 100644 index 00000000000..b7822d1142f --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/win32/shared_mutex.hpp @@ -0,0 +1,903 @@ +#ifndef BOOST_THREAD_WIN32_SHARED_MUTEX_HPP +#define BOOST_THREAD_WIN32_SHARED_MUTEX_HPP + +// (C) Copyright 2006-8 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include +#include +#ifdef BOOST_THREAD_USES_CHRONO +#include +#include +#endif +#include + +#include + +namespace boost +{ + class shared_mutex + { + private: + struct state_data + { + unsigned shared_count:11, + shared_waiting:11, + exclusive:1, + upgrade:1, + exclusive_waiting:7, + exclusive_waiting_blocked:1; + + friend bool operator==(state_data const& lhs,state_data const& rhs) + { + return *reinterpret_cast(&lhs)==*reinterpret_cast(&rhs); + } + }; + + + template + T interlocked_compare_exchange(T* target,T new_value,T comparand) + { + BOOST_STATIC_ASSERT(sizeof(T)==sizeof(long)); + long const res=BOOST_INTERLOCKED_COMPARE_EXCHANGE(reinterpret_cast(target), + *reinterpret_cast(&new_value), + *reinterpret_cast(&comparand)); + return *reinterpret_cast(&res); + } + + enum + { + unlock_sem = 0, + exclusive_sem = 1 + }; + + state_data state; + detail::win32::handle semaphores[2]; + detail::win32::handle upgrade_sem; + + void release_waiters(state_data old_state) + { + if(old_state.exclusive_waiting) + { + BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[exclusive_sem],1,0)!=0); + } + + if(old_state.shared_waiting || old_state.exclusive_waiting) + { + BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0); + } + } + void release_shared_waiters(state_data old_state) + { + if(old_state.shared_waiting || old_state.exclusive_waiting) + { + BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],old_state.shared_waiting + (old_state.exclusive_waiting?1:0),0)!=0); + } + } + + public: + BOOST_THREAD_NO_COPYABLE(shared_mutex) + shared_mutex() + { + semaphores[unlock_sem]=detail::win32::create_anonymous_semaphore(0,LONG_MAX); + semaphores[exclusive_sem]=detail::win32::create_anonymous_semaphore_nothrow(0,LONG_MAX); + if (!semaphores[exclusive_sem]) + { + detail::win32::release_semaphore(semaphores[unlock_sem],LONG_MAX); + boost::throw_exception(thread_resource_error()); + } + upgrade_sem=detail::win32::create_anonymous_semaphore_nothrow(0,LONG_MAX); + if (!upgrade_sem) + { + detail::win32::release_semaphore(semaphores[unlock_sem],LONG_MAX); + detail::win32::release_semaphore(semaphores[exclusive_sem],LONG_MAX); + boost::throw_exception(thread_resource_error()); + } + state_data state_={0,0,0,0,0,0}; + state=state_; + } + + ~shared_mutex() + { + detail::win32::CloseHandle(upgrade_sem); + detail::win32::CloseHandle(semaphores[unlock_sem]); + detail::win32::CloseHandle(semaphores[exclusive_sem]); + } + + bool try_lock_shared() + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + if(!new_state.exclusive && !new_state.exclusive_waiting_blocked) + { + ++new_state.shared_count; + if(!new_state.shared_count) + { + return false; + } + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + return !(old_state.exclusive| old_state.exclusive_waiting_blocked); + } + + void lock_shared() + { + +#if defined BOOST_THREAD_USES_DATETIME + BOOST_VERIFY(timed_lock_shared(::boost::detail::get_system_time_sentinel())); +#else + BOOST_VERIFY(try_lock_shared_until(chrono::steady_clock::now())); +#endif + } + +#if defined BOOST_THREAD_USES_DATETIME + template + bool timed_lock_shared(TimeDuration const & relative_time) + { + return timed_lock_shared(get_system_time()+relative_time); + } + bool timed_lock_shared(boost::system_time const& wait_until) + { + for(;;) + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + if(new_state.exclusive || new_state.exclusive_waiting_blocked) + { + ++new_state.shared_waiting; + if(!new_state.shared_waiting) + { + boost::throw_exception(boost::lock_error()); + } + } + else + { + ++new_state.shared_count; + if(!new_state.shared_count) + { + boost::throw_exception(boost::lock_error()); + } + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + + if(!(old_state.exclusive| old_state.exclusive_waiting_blocked)) + { + return true; + } + + unsigned long const res=detail::win32::WaitForSingleObjectEx(semaphores[unlock_sem],::boost::detail::get_milliseconds_until(wait_until), 0); + if(res==detail::win32::timeout) + { + for(;;) + { + state_data new_state=old_state; + if(new_state.exclusive || new_state.exclusive_waiting_blocked) + { + if(new_state.shared_waiting) + { + --new_state.shared_waiting; + } + } + else + { + ++new_state.shared_count; + if(!new_state.shared_count) + { + return false; + } + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + + if(!(old_state.exclusive| old_state.exclusive_waiting_blocked)) + { + return true; + } + return false; + } + + BOOST_ASSERT(res==0); + } + } +#endif + +#ifdef BOOST_THREAD_USES_CHRONO + template + bool try_lock_shared_for(const chrono::duration& rel_time) + { + return try_lock_shared_until(chrono::steady_clock::now() + rel_time); + } + template + bool try_lock_shared_until(const chrono::time_point& t) + { + using namespace chrono; + system_clock::time_point s_now = system_clock::now(); + typename Clock::time_point c_now = Clock::now(); + return try_lock_shared_until(s_now + ceil(t - c_now)); + } + template + bool try_lock_shared_until(const chrono::time_point& t) + { + using namespace chrono; + typedef time_point sys_tmpt; + return try_lock_shared_until(sys_tmpt(chrono::ceil(t.time_since_epoch()))); + } + bool try_lock_shared_until(const chrono::time_point& tp) + { + for(;;) + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + if(new_state.exclusive || new_state.exclusive_waiting_blocked) + { + ++new_state.shared_waiting; + if(!new_state.shared_waiting) + { + boost::throw_exception(boost::lock_error()); + } + } + else + { + ++new_state.shared_count; + if(!new_state.shared_count) + { + boost::throw_exception(boost::lock_error()); + } + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + + if(!(old_state.exclusive| old_state.exclusive_waiting_blocked)) + { + return true; + } + + chrono::system_clock::time_point n = chrono::system_clock::now(); + unsigned long res; + if (tp>n) { + chrono::milliseconds rel_time= chrono::ceil(tp-n); + res=detail::win32::WaitForSingleObjectEx(semaphores[unlock_sem], + static_cast(rel_time.count()), 0); + } else { + res=detail::win32::timeout; + } + if(res==detail::win32::timeout) + { + for(;;) + { + state_data new_state=old_state; + if(new_state.exclusive || new_state.exclusive_waiting_blocked) + { + if(new_state.shared_waiting) + { + --new_state.shared_waiting; + } + } + else + { + ++new_state.shared_count; + if(!new_state.shared_count) + { + return false; + } + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + + if(!(old_state.exclusive| old_state.exclusive_waiting_blocked)) + { + return true; + } + return false; + } + + BOOST_ASSERT(res==0); + } + } +#endif + + void unlock_shared() + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + bool const last_reader=!--new_state.shared_count; + + if(last_reader) + { + if(new_state.upgrade) + { + new_state.upgrade=false; + new_state.exclusive=true; + } + else + { + if(new_state.exclusive_waiting) + { + --new_state.exclusive_waiting; + new_state.exclusive_waiting_blocked=false; + } + new_state.shared_waiting=0; + } + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + if(last_reader) + { + if(old_state.upgrade) + { + BOOST_VERIFY(detail::win32::ReleaseSemaphore(upgrade_sem,1,0)!=0); + } + else + { + release_waiters(old_state); + } + } + break; + } + old_state=current_state; + } + } + + void lock() + { + +#if defined BOOST_THREAD_USES_DATETIME + BOOST_VERIFY(timed_lock(::boost::detail::get_system_time_sentinel())); +#else + BOOST_VERIFY(try_lock_until(chrono::steady_clock::now())); +#endif + } + +#if defined BOOST_THREAD_USES_DATETIME + template + bool timed_lock(TimeDuration const & relative_time) + { + return timed_lock(get_system_time()+relative_time); + } +#endif + + bool try_lock() + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + if(new_state.shared_count || new_state.exclusive) + { + return false; + } + else + { + new_state.exclusive=true; + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + return true; + } + + +#if defined BOOST_THREAD_USES_DATETIME + bool timed_lock(boost::system_time const& wait_until) + { + for(;;) + { + state_data old_state=state; + + for(;;) + { + state_data new_state=old_state; + if(new_state.shared_count || new_state.exclusive) + { + ++new_state.exclusive_waiting; + if(!new_state.exclusive_waiting) + { + boost::throw_exception(boost::lock_error()); + } + + new_state.exclusive_waiting_blocked=true; + } + else + { + new_state.exclusive=true; + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + + if(!old_state.shared_count && !old_state.exclusive) + { + return true; + } + #ifndef UNDER_CE + const bool wait_all = true; + #else + const bool wait_all = false; + #endif + unsigned long const wait_res=detail::win32::WaitForMultipleObjectsEx(2,semaphores,wait_all,::boost::detail::get_milliseconds_until(wait_until), 0); + if(wait_res==detail::win32::timeout) + { + for(;;) + { + bool must_notify = false; + state_data new_state=old_state; + if(new_state.shared_count || new_state.exclusive) + { + if(new_state.exclusive_waiting) + { + if(!--new_state.exclusive_waiting) + { + new_state.exclusive_waiting_blocked=false; + must_notify = true; + } + } + } + else + { + new_state.exclusive=true; + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if (must_notify) + { + BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],1,0)!=0); + } + + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + if(!old_state.shared_count && !old_state.exclusive) + { + return true; + } + return false; + } + BOOST_ASSERT(wait_res<2); + } + } +#endif +#ifdef BOOST_THREAD_USES_CHRONO + template + bool try_lock_for(const chrono::duration& rel_time) + { + return try_lock_until(chrono::steady_clock::now() + rel_time); + } + template + bool try_lock_until(const chrono::time_point& t) + { + using namespace chrono; + system_clock::time_point s_now = system_clock::now(); + typename Clock::time_point c_now = Clock::now(); + return try_lock_until(s_now + ceil(t - c_now)); + } + template + bool try_lock_until(const chrono::time_point& t) + { + using namespace chrono; + typedef time_point sys_tmpt; + return try_lock_until(sys_tmpt(chrono::ceil(t.time_since_epoch()))); + } + bool try_lock_until(const chrono::time_point& tp) + { + for(;;) + { + state_data old_state=state; + + for(;;) + { + state_data new_state=old_state; + if(new_state.shared_count || new_state.exclusive) + { + ++new_state.exclusive_waiting; + if(!new_state.exclusive_waiting) + { + boost::throw_exception(boost::lock_error()); + } + + new_state.exclusive_waiting_blocked=true; + } + else + { + new_state.exclusive=true; + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + + if(!old_state.shared_count && !old_state.exclusive) + { + return true; + } + #ifndef UNDER_CE + const bool wait_all = true; + #else + const bool wait_all = false; + #endif + + chrono::system_clock::time_point n = chrono::system_clock::now(); + unsigned long wait_res; + if (tp>n) { + chrono::milliseconds rel_time= chrono::ceil(tp-chrono::system_clock::now()); + wait_res=detail::win32::WaitForMultipleObjectsEx(2,semaphores,wait_all, + static_cast(rel_time.count()), 0); + } else { + wait_res=detail::win32::timeout; + } + if(wait_res==detail::win32::timeout) + { + for(;;) + { + bool must_notify = false; + state_data new_state=old_state; + if(new_state.shared_count || new_state.exclusive) + { + if(new_state.exclusive_waiting) + { + if(!--new_state.exclusive_waiting) + { + new_state.exclusive_waiting_blocked=false; + must_notify = true; + } + } + } + else + { + new_state.exclusive=true; + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if (must_notify) + { + BOOST_VERIFY(detail::win32::ReleaseSemaphore(semaphores[unlock_sem],1,0)!=0); + } + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + if(!old_state.shared_count && !old_state.exclusive) + { + return true; + } + return false; + } + BOOST_ASSERT(wait_res<2); + } + } +#endif + + void unlock() + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + new_state.exclusive=false; + if(new_state.exclusive_waiting) + { + --new_state.exclusive_waiting; + new_state.exclusive_waiting_blocked=false; + } + new_state.shared_waiting=0; + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + release_waiters(old_state); + } + + void lock_upgrade() + { + for(;;) + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgrade) + { + ++new_state.shared_waiting; + if(!new_state.shared_waiting) + { + boost::throw_exception(boost::lock_error()); + } + } + else + { + ++new_state.shared_count; + if(!new_state.shared_count) + { + boost::throw_exception(boost::lock_error()); + } + new_state.upgrade=true; + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + + if(!(old_state.exclusive|| old_state.exclusive_waiting_blocked|| old_state.upgrade)) + { + return; + } + + BOOST_VERIFY(!detail::win32::WaitForSingleObjectEx(semaphores[unlock_sem],detail::win32::infinite, 0)); + } + } + + bool try_lock_upgrade() + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + if(new_state.exclusive || new_state.exclusive_waiting_blocked || new_state.upgrade) + { + return false; + } + else + { + ++new_state.shared_count; + if(!new_state.shared_count) + { + return false; + } + new_state.upgrade=true; + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + return true; + } + + void unlock_upgrade() + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + new_state.upgrade=false; + bool const last_reader=!--new_state.shared_count; + + new_state.shared_waiting=0; + if(last_reader) + { + if(new_state.exclusive_waiting) + { + --new_state.exclusive_waiting; + new_state.exclusive_waiting_blocked=false; + } + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + if(last_reader) + { + release_waiters(old_state); + } + else { + release_shared_waiters(old_state); + } + // #7720 + //else { + // release_waiters(old_state); + //} + break; + } + old_state=current_state; + } + } + + void unlock_upgrade_and_lock() + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + bool const last_reader=!--new_state.shared_count; + + if(last_reader) + { + new_state.upgrade=false; + new_state.exclusive=true; + } + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + if(!last_reader) + { + BOOST_VERIFY(!detail::win32::WaitForSingleObjectEx(upgrade_sem,detail::win32::infinite, 0)); + } + break; + } + old_state=current_state; + } + } + + void unlock_and_lock_upgrade() + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + new_state.exclusive=false; + new_state.upgrade=true; + ++new_state.shared_count; + if(new_state.exclusive_waiting) + { + --new_state.exclusive_waiting; + new_state.exclusive_waiting_blocked=false; + } + new_state.shared_waiting=0; + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + release_waiters(old_state); + } +// bool try_unlock_upgrade_and_lock() +// { +// return false; +// } +//#ifdef BOOST_THREAD_USES_CHRONO +// template +// bool +// try_unlock_upgrade_and_lock_for( +// const chrono::duration& rel_time) +// { +// return try_unlock_upgrade_and_lock_until( +// chrono::steady_clock::now() + rel_time); +// } +// template +// bool +// try_unlock_upgrade_and_lock_until( +// const chrono::time_point& abs_time) +// { +// return false; +// } +//#endif + + void unlock_and_lock_shared() + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + new_state.exclusive=false; + ++new_state.shared_count; + if(new_state.exclusive_waiting) + { + --new_state.exclusive_waiting; + new_state.exclusive_waiting_blocked=false; + } + new_state.shared_waiting=0; + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + release_waiters(old_state); + } + void unlock_upgrade_and_lock_shared() + { + state_data old_state=state; + for(;;) + { + state_data new_state=old_state; + new_state.upgrade=false; + if(new_state.exclusive_waiting) + { + --new_state.exclusive_waiting; + new_state.exclusive_waiting_blocked=false; + } + new_state.shared_waiting=0; + + state_data const current_state=interlocked_compare_exchange(&state,new_state,old_state); + if(current_state==old_state) + { + break; + } + old_state=current_state; + } + release_waiters(old_state); + } + + }; + typedef shared_mutex upgrade_mutex; + +} + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/win32/thread_data.hpp b/src/third_party/boost-1.60.0/boost/thread/win32/thread_data.hpp new file mode 100644 index 00000000000..005f3ba5035 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/win32/thread_data.hpp @@ -0,0 +1,328 @@ +#ifndef BOOST_THREAD_PTHREAD_THREAD_DATA_HPP +#define BOOST_THREAD_PTHREAD_THREAD_DATA_HPP +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2008 Anthony Williams +// (C) Copyright 2011-2012 Vicente J. Botet Escriba + +#include +#include +#include +#include + +#include + +#include +#ifdef BOOST_THREAD_USES_CHRONO +#include +#endif + +#include +#include +#include + +#include + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4251) +#endif + +namespace boost +{ + class condition_variable; + class mutex; + + class thread_attributes { + public: + thread_attributes() BOOST_NOEXCEPT { + val_.stack_size = 0; + //val_.lpThreadAttributes=0; + } + ~thread_attributes() { + } + // stack size + void set_stack_size(std::size_t size) BOOST_NOEXCEPT { + val_.stack_size = size; + } + + std::size_t get_stack_size() const BOOST_NOEXCEPT { + return val_.stack_size; + } + + //void set_security(LPSECURITY_ATTRIBUTES lpThreadAttributes) + //{ + // val_.lpThreadAttributes=lpThreadAttributes; + //} + //LPSECURITY_ATTRIBUTES get_security() + //{ + // return val_.lpThreadAttributes; + //} + + struct win_attrs { + std::size_t stack_size; + //LPSECURITY_ATTRIBUTES lpThreadAttributes; + }; + typedef win_attrs native_handle_type; + native_handle_type* native_handle() {return &val_;} + const native_handle_type* native_handle() const {return &val_;} + + private: + win_attrs val_; + }; + + namespace detail + { + struct shared_state_base; + struct tss_cleanup_function; + struct thread_exit_callback_node; + struct tss_data_node + { + boost::shared_ptr func; + void* value; + + tss_data_node(boost::shared_ptr func_, + void* value_): + func(func_),value(value_) + {} + }; + + struct thread_data_base; + void intrusive_ptr_add_ref(thread_data_base * p); + void intrusive_ptr_release(thread_data_base * p); + + struct BOOST_THREAD_DECL thread_data_base + { + long count; + + // Win32 threading APIs are not available in store apps so + // use abstraction on top of Windows::System::Threading. +#if BOOST_PLAT_WINDOWS_RUNTIME + detail::win32::scoped_winrt_thread thread_handle; +#else + detail::win32::handle_manager thread_handle; +#endif + + boost::detail::thread_exit_callback_node* thread_exit_callbacks; + unsigned id; + std::map tss_data; + typedef std::vector + //, hidden_allocator > + > notify_list_t; + notify_list_t notify; + + typedef std::vector > async_states_t; + async_states_t async_states_; +//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + // These data must be at the end so that the access to the other fields doesn't change + // when BOOST_THREAD_PROVIDES_INTERRUPTIONS is defined + // Another option is to have them always + detail::win32::handle_manager interruption_handle; + bool interruption_enabled; +//#endif + + thread_data_base(): + count(0), + thread_handle(), + thread_exit_callbacks(0), + id(0), + tss_data(), + notify(), + async_states_() +//#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + , interruption_handle(create_anonymous_event(detail::win32::manual_reset_event,detail::win32::event_initially_reset)) + , interruption_enabled(true) +//#endif + {} + virtual ~thread_data_base(); + + friend void intrusive_ptr_add_ref(thread_data_base * p) + { + BOOST_INTERLOCKED_INCREMENT(&p->count); + } + + friend void intrusive_ptr_release(thread_data_base * p) + { + if(!BOOST_INTERLOCKED_DECREMENT(&p->count)) + { + detail::heap_delete(p); + } + } + +#if defined BOOST_THREAD_PROVIDES_INTERRUPTIONS + void interrupt() + { + BOOST_VERIFY(detail::win32::SetEvent(interruption_handle)!=0); + } +#endif + typedef detail::win32::handle native_handle_type; + + virtual void run()=0; + + virtual void notify_all_at_thread_exit(condition_variable* cv, mutex* m) + { + notify.push_back(std::pair(cv, m)); + } + + void make_ready_at_thread_exit(shared_ptr as) + { + async_states_.push_back(as); + } + + }; + BOOST_THREAD_DECL thread_data_base* get_current_thread_data(); + + typedef boost::intrusive_ptr thread_data_ptr; + + struct BOOST_SYMBOL_VISIBLE timeout + { + win32::ticks_type start; + uintmax_t milliseconds; + bool relative; + boost::system_time abs_time; + + static unsigned long const max_non_infinite_wait=0xfffffffe; + + timeout(uintmax_t milliseconds_): + start(win32::GetTickCount64_()()), + milliseconds(milliseconds_), + relative(true) + //, + // abs_time(boost::get_system_time()) + {} + + timeout(boost::system_time const& abs_time_): + start(win32::GetTickCount64_()()), + milliseconds(0), + relative(false), + abs_time(abs_time_) + {} + + struct BOOST_SYMBOL_VISIBLE remaining_time + { + bool more; + unsigned long milliseconds; + + remaining_time(uintmax_t remaining): + more(remaining>max_non_infinite_wait), + milliseconds(more?max_non_infinite_wait:(unsigned long)remaining) + {} + }; + + remaining_time remaining_milliseconds() const + { + if(is_sentinel()) + { + return remaining_time(win32::infinite); + } + else if(relative) + { + win32::ticks_type const now=win32::GetTickCount64_()(); + win32::ticks_type const elapsed=now-start; + return remaining_time((elapsed + inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time) + { + interruptible_wait(detail::pin_to_zero(rel_time.total_milliseconds())); + } + inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time) + { + interruptible_wait(abs_time); + } +// #11322 sleep_for() nanoseconds overload will always return too early on windows +//#ifdef BOOST_THREAD_USES_CHRONO +// inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) +// { +// interruptible_wait(chrono::duration_cast(ns).count()); +// } +//#endif + namespace no_interruption_point + { + bool BOOST_THREAD_DECL non_interruptible_wait(detail::win32::handle handle_to_wait_for,detail::timeout target_time); + inline void non_interruptible_wait(uintmax_t milliseconds) + { + non_interruptible_wait(detail::win32::invalid_handle_value,milliseconds); + } + inline BOOST_SYMBOL_VISIBLE void non_interruptible_wait(system_time const& abs_time) + { + non_interruptible_wait(detail::win32::invalid_handle_value,abs_time); + } + template + inline BOOST_SYMBOL_VISIBLE void sleep(TimeDuration const& rel_time) + { + non_interruptible_wait(detail::pin_to_zero(rel_time.total_milliseconds())); + } + inline BOOST_SYMBOL_VISIBLE void sleep(system_time const& abs_time) + { + non_interruptible_wait(abs_time); + } +// #11322 sleep_for() nanoseconds overload will always return too early on windows +//#ifdef BOOST_THREAD_USES_CHRONO +// inline void BOOST_SYMBOL_VISIBLE sleep_for(const chrono::nanoseconds& ns) +// { +// non_interruptible_wait(chrono::duration_cast(ns).count()); +// } +//#endif + } + } + +} + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#include + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/win32/thread_heap_alloc.hpp b/src/third_party/boost-1.60.0/boost/thread/win32/thread_heap_alloc.hpp new file mode 100644 index 00000000000..610fe3263e1 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/win32/thread_heap_alloc.hpp @@ -0,0 +1,409 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// (C) Copyright 2007 Anthony Williams +#ifndef THREAD_HEAP_ALLOC_HPP +#define THREAD_HEAP_ALLOC_HPP +#include +#include +#include +#include +#include +#include +#include + +#if defined( BOOST_USE_WINDOWS_H ) +# include + +namespace boost +{ + namespace detail + { + namespace win32 + { + using ::GetProcessHeap; + using ::HeapAlloc; + using ::HeapFree; + } + } +} + +#else + +# ifdef HeapAlloc +# undef HeapAlloc +# endif + +namespace boost +{ + namespace detail + { + namespace win32 + { + extern "C" + { + __declspec(dllimport) handle __stdcall GetProcessHeap(); + __declspec(dllimport) void* __stdcall HeapAlloc(handle,unsigned long,ulong_ptr); + __declspec(dllimport) int __stdcall HeapFree(handle,unsigned long,void*); + } + } + } +} + +#endif + +#include + +namespace boost +{ + namespace detail + { + inline void* allocate_raw_heap_memory(unsigned size) + { + void* const heap_memory=detail::win32::HeapAlloc(detail::win32::GetProcessHeap(),0,size); + if(!heap_memory) + { + boost::throw_exception(std::bad_alloc()); + } + return heap_memory; + } + + inline void free_raw_heap_memory(void* heap_memory) + { + BOOST_VERIFY(detail::win32::HeapFree(detail::win32::GetProcessHeap(),0,heap_memory)!=0); + } + + template + inline T* heap_new() + { + void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); + BOOST_TRY + { + T* const data=new (heap_memory) T(); + return data; + } + BOOST_CATCH(...) + { + free_raw_heap_memory(heap_memory); + BOOST_RETHROW + } + BOOST_CATCH_END + } + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + template + inline T* heap_new(A1&& a1) + { + void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); + BOOST_TRY + { + T* const data=new (heap_memory) T(static_cast(a1)); + return data; + } + BOOST_CATCH(...) + { + free_raw_heap_memory(heap_memory); + BOOST_RETHROW + } + BOOST_CATCH_END + } + template + inline T* heap_new(A1&& a1,A2&& a2) + { + void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); + BOOST_TRY + { + T* const data=new (heap_memory) T(static_cast(a1),static_cast(a2)); + return data; + } + BOOST_CATCH(...) + { + free_raw_heap_memory(heap_memory); + BOOST_RETHROW + } + BOOST_CATCH_END + } + template + inline T* heap_new(A1&& a1,A2&& a2,A3&& a3) + { + void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); + BOOST_TRY + { + T* const data=new (heap_memory) T(static_cast(a1),static_cast(a2), + static_cast(a3)); + return data; + } + BOOST_CATCH(...) + { + free_raw_heap_memory(heap_memory); + BOOST_RETHROW + } + BOOST_CATCH_END + } + template + inline T* heap_new(A1&& a1,A2&& a2,A3&& a3,A4&& a4) + { + void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); + BOOST_TRY + { + T* const data=new (heap_memory) T(static_cast(a1),static_cast(a2), + static_cast(a3),static_cast(a4)); + return data; + } + BOOST_CATCH(...) + { + free_raw_heap_memory(heap_memory); + BOOST_RETHROW + } + BOOST_CATCH_END + } +#else + template + inline T* heap_new_impl(A1 a1) + { + void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); + BOOST_TRY + { + T* const data=new (heap_memory) T(a1); + return data; + } + BOOST_CATCH(...) + { + free_raw_heap_memory(heap_memory); + BOOST_RETHROW + } + BOOST_CATCH_END + } + + template + inline T* heap_new_impl(A1 a1,A2 a2) + { + void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); + BOOST_TRY + { + T* const data=new (heap_memory) T(a1,a2); + return data; + } + BOOST_CATCH(...) + { + free_raw_heap_memory(heap_memory); + BOOST_RETHROW + } + BOOST_CATCH_END + } + + template + inline T* heap_new_impl(A1 a1,A2 a2,A3 a3) + { + void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); + BOOST_TRY + { + T* const data=new (heap_memory) T(a1,a2,a3); + return data; + } + BOOST_CATCH(...) + { + free_raw_heap_memory(heap_memory); + BOOST_RETHROW + } + BOOST_CATCH_END + } + + template + inline T* heap_new_impl(A1 a1,A2 a2,A3 a3,A4 a4) + { + void* const heap_memory=allocate_raw_heap_memory(sizeof(T)); + BOOST_TRY + { + T* const data=new (heap_memory) T(a1,a2,a3,a4); + return data; + } + BOOST_CATCH(...) + { + free_raw_heap_memory(heap_memory); + BOOST_RETHROW + } + BOOST_CATCH_END + } + + + template + inline T* heap_new(A1 const& a1) + { + return heap_new_impl(a1); + } + template + inline T* heap_new(A1& a1) + { + return heap_new_impl(a1); + } + + template + inline T* heap_new(A1 const& a1,A2 const& a2) + { + return heap_new_impl(a1,a2); + } + template + inline T* heap_new(A1& a1,A2 const& a2) + { + return heap_new_impl(a1,a2); + } + template + inline T* heap_new(A1 const& a1,A2& a2) + { + return heap_new_impl(a1,a2); + } + template + inline T* heap_new(A1& a1,A2& a2) + { + return heap_new_impl(a1,a2); + } + + template + inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3) + { + return heap_new_impl(a1,a2,a3); + } + template + inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3) + { + return heap_new_impl(a1,a2,a3); + } + template + inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3) + { + return heap_new_impl(a1,a2,a3); + } + template + inline T* heap_new(A1& a1,A2& a2,A3 const& a3) + { + return heap_new_impl(a1,a2,a3); + } + + template + inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3) + { + return heap_new_impl(a1,a2,a3); + } + template + inline T* heap_new(A1& a1,A2 const& a2,A3& a3) + { + return heap_new_impl(a1,a2,a3); + } + template + inline T* heap_new(A1 const& a1,A2& a2,A3& a3) + { + return heap_new_impl(a1,a2,a3); + } + template + inline T* heap_new(A1& a1,A2& a2,A3& a3) + { + return heap_new_impl(a1,a2,a3); + } + + template + inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3,A4 const& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + template + inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3,A4 const& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + template + inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3,A4 const& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + template + inline T* heap_new(A1& a1,A2& a2,A3 const& a3,A4 const& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + + template + inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3,A4 const& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + template + inline T* heap_new(A1& a1,A2 const& a2,A3& a3,A4 const& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + template + inline T* heap_new(A1 const& a1,A2& a2,A3& a3,A4 const& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + template + inline T* heap_new(A1& a1,A2& a2,A3& a3,A4 const& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + template + inline T* heap_new(A1 const& a1,A2 const& a2,A3 const& a3,A4& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + template + inline T* heap_new(A1& a1,A2 const& a2,A3 const& a3,A4& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + template + inline T* heap_new(A1 const& a1,A2& a2,A3 const& a3,A4& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + template + inline T* heap_new(A1& a1,A2& a2,A3 const& a3,A4& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + + template + inline T* heap_new(A1 const& a1,A2 const& a2,A3& a3,A4& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + template + inline T* heap_new(A1& a1,A2 const& a2,A3& a3,A4& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + template + inline T* heap_new(A1 const& a1,A2& a2,A3& a3,A4& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + template + inline T* heap_new(A1& a1,A2& a2,A3& a3,A4& a4) + { + return heap_new_impl(a1,a2,a3,a4); + } + +#endif + template + inline void heap_delete(T* data) + { + data->~T(); + free_raw_heap_memory(data); + } + + template + struct do_heap_delete + { + void operator()(T* data) const + { + detail::heap_delete(data); + } + }; + } +} + +#include + + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/win32/thread_primitives.hpp b/src/third_party/boost-1.60.0/boost/thread/win32/thread_primitives.hpp new file mode 100644 index 00000000000..b63503ad52b --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/win32/thread_primitives.hpp @@ -0,0 +1,669 @@ +#ifndef BOOST_WIN32_THREAD_PRIMITIVES_HPP +#define BOOST_WIN32_THREAD_PRIMITIVES_HPP + +// win32_thread_primitives.hpp +// +// (C) Copyright 2005-7 Anthony Williams +// (C) Copyright 2007 David Deakins +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include +#include +#include +#include +//#include +#include + +#if BOOST_PLAT_WINDOWS_RUNTIME +#include +#endif + +#if defined( BOOST_USE_WINDOWS_H ) +# include + +namespace boost +{ + namespace detail + { + namespace win32 + { + typedef HANDLE handle; + typedef SYSTEM_INFO system_info; + typedef unsigned __int64 ticks_type; + typedef FARPROC farproc_t; + unsigned const infinite=INFINITE; + unsigned const timeout=WAIT_TIMEOUT; + handle const invalid_handle_value=INVALID_HANDLE_VALUE; + unsigned const event_modify_state=EVENT_MODIFY_STATE; + unsigned const synchronize=SYNCHRONIZE; + unsigned const wait_abandoned=WAIT_ABANDONED; + unsigned const create_event_initial_set = 0x00000002; + unsigned const create_event_manual_reset = 0x00000001; + unsigned const event_all_access = EVENT_ALL_ACCESS; + unsigned const semaphore_all_access = SEMAPHORE_ALL_ACCESS; + + +# ifdef BOOST_NO_ANSI_APIS +# if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA + using ::CreateMutexW; + using ::CreateEventW; + using ::CreateSemaphoreW; +# else + using ::CreateMutexExW; + using ::CreateEventExW; + using ::CreateSemaphoreExW; +# endif + using ::OpenEventW; + using ::GetModuleHandleW; +# else + using ::CreateMutexA; + using ::CreateEventA; + using ::OpenEventA; + using ::CreateSemaphoreA; + using ::GetModuleHandleA; +# endif +#if BOOST_PLAT_WINDOWS_RUNTIME + using ::GetNativeSystemInfo; + using ::GetTickCount64; +#else + using ::GetSystemInfo; + using ::GetTickCount; +#endif + using ::CloseHandle; + using ::ReleaseMutex; + using ::ReleaseSemaphore; + using ::SetEvent; + using ::ResetEvent; + using ::WaitForMultipleObjectsEx; + using ::WaitForSingleObjectEx; + using ::GetCurrentProcessId; + using ::GetCurrentThreadId; + using ::GetCurrentThread; + using ::GetCurrentProcess; + using ::DuplicateHandle; +#if !BOOST_PLAT_WINDOWS_RUNTIME + using ::SleepEx; + using ::Sleep; + using ::QueueUserAPC; + using ::GetProcAddress; +#endif + } + } +} +#elif defined( WIN32 ) || defined( _WIN32 ) || defined( __WIN32__ ) + +# ifdef UNDER_CE +# ifndef WINAPI +# ifndef _WIN32_WCE_EMULATION +# define WINAPI __cdecl // Note this doesn't match the desktop definition +# else +# define WINAPI __stdcall +# endif +# endif + +# ifdef __cplusplus +extern "C" { +# endif +typedef int BOOL; +typedef unsigned long DWORD; +typedef void* HANDLE; +# include +# ifdef __cplusplus +} +# endif +# endif + +# ifdef __cplusplus +extern "C" { +# endif +struct _SYSTEM_INFO; +# ifdef __cplusplus +} +#endif + +namespace boost +{ + namespace detail + { + namespace win32 + { +# ifdef _WIN64 + typedef unsigned __int64 ulong_ptr; +# else + typedef unsigned long ulong_ptr; +# endif + typedef void* handle; + typedef _SYSTEM_INFO system_info; + typedef unsigned __int64 ticks_type; + typedef int (__stdcall *farproc_t)(); + unsigned const infinite=~0U; + unsigned const timeout=258U; + handle const invalid_handle_value=(handle)(-1); + unsigned const event_modify_state=2; + unsigned const synchronize=0x100000u; + unsigned const wait_abandoned=0x00000080u; + unsigned const create_event_initial_set = 0x00000002; + unsigned const create_event_manual_reset = 0x00000001; + unsigned const event_all_access = 0x1F0003; + unsigned const semaphore_all_access = 0x1F0003; + + extern "C" + { + struct _SECURITY_ATTRIBUTES; +# ifdef BOOST_NO_ANSI_APIS +# if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA + __declspec(dllimport) void* __stdcall CreateMutexW(_SECURITY_ATTRIBUTES*,int,wchar_t const*); + __declspec(dllimport) void* __stdcall CreateSemaphoreW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*); + __declspec(dllimport) void* __stdcall CreateEventW(_SECURITY_ATTRIBUTES*,int,int,wchar_t const*); +# else + __declspec(dllimport) void* __stdcall CreateMutexExW(_SECURITY_ATTRIBUTES*,wchar_t const*,unsigned long,unsigned long); + __declspec(dllimport) void* __stdcall CreateEventExW(_SECURITY_ATTRIBUTES*,wchar_t const*,unsigned long,unsigned long); + __declspec(dllimport) void* __stdcall CreateSemaphoreExW(_SECURITY_ATTRIBUTES*,long,long,wchar_t const*,unsigned long,unsigned long); +# endif + __declspec(dllimport) void* __stdcall OpenEventW(unsigned long,int,wchar_t const*); + __declspec(dllimport) void* __stdcall GetModuleHandleW(wchar_t const*); +# else + __declspec(dllimport) void* __stdcall CreateMutexA(_SECURITY_ATTRIBUTES*,int,char const*); + __declspec(dllimport) void* __stdcall CreateSemaphoreA(_SECURITY_ATTRIBUTES*,long,long,char const*); + __declspec(dllimport) void* __stdcall CreateEventA(_SECURITY_ATTRIBUTES*,int,int,char const*); + __declspec(dllimport) void* __stdcall OpenEventA(unsigned long,int,char const*); + __declspec(dllimport) void* __stdcall GetModuleHandleA(char const*); +# endif +#if BOOST_PLAT_WINDOWS_RUNTIME + __declspec(dllimport) void __stdcall GetNativeSystemInfo(_SYSTEM_INFO*); + __declspec(dllimport) ticks_type __stdcall GetTickCount64(); +#else + __declspec(dllimport) void __stdcall GetSystemInfo(_SYSTEM_INFO*); + __declspec(dllimport) unsigned long __stdcall GetTickCount(); +#endif + __declspec(dllimport) int __stdcall CloseHandle(void*); + __declspec(dllimport) int __stdcall ReleaseMutex(void*); + __declspec(dllimport) unsigned long __stdcall WaitForSingleObjectEx(void*,unsigned long,int); + __declspec(dllimport) unsigned long __stdcall WaitForMultipleObjectsEx(unsigned long nCount,void* const * lpHandles,int bWaitAll,unsigned long dwMilliseconds,int bAlertable); + __declspec(dllimport) int __stdcall ReleaseSemaphore(void*,long,long*); + __declspec(dllimport) int __stdcall DuplicateHandle(void*,void*,void*,void**,unsigned long,int,unsigned long); +#if !BOOST_PLAT_WINDOWS_RUNTIME + __declspec(dllimport) unsigned long __stdcall SleepEx(unsigned long,int); + __declspec(dllimport) void __stdcall Sleep(unsigned long); + typedef void (__stdcall *queue_user_apc_callback_function)(ulong_ptr); + __declspec(dllimport) unsigned long __stdcall QueueUserAPC(queue_user_apc_callback_function,void*,ulong_ptr); + __declspec(dllimport) farproc_t __stdcall GetProcAddress(void *, const char *); +#endif + +# ifndef UNDER_CE + __declspec(dllimport) unsigned long __stdcall GetCurrentProcessId(); + __declspec(dllimport) unsigned long __stdcall GetCurrentThreadId(); + __declspec(dllimport) void* __stdcall GetCurrentThread(); + __declspec(dllimport) void* __stdcall GetCurrentProcess(); + __declspec(dllimport) int __stdcall SetEvent(void*); + __declspec(dllimport) int __stdcall ResetEvent(void*); +# else + using ::GetCurrentProcessId; + using ::GetCurrentThreadId; + using ::GetCurrentThread; + using ::GetCurrentProcess; + using ::SetEvent; + using ::ResetEvent; +# endif + } + } + } +} +#else +# error "Win32 functions not available" +#endif + +#include + +namespace boost +{ + namespace detail + { + namespace win32 + { + namespace detail { typedef ticks_type (__stdcall *gettickcount64_t)(); } +#if !BOOST_PLAT_WINDOWS_RUNTIME + extern "C" + { +#ifdef _MSC_VER + long _InterlockedCompareExchange(long volatile *, long, long); +#pragma intrinsic(_InterlockedCompareExchange) +#elif defined(__MINGW64_VERSION_MAJOR) + long _InterlockedCompareExchange(long volatile *, long, long); +#else + // Mingw doesn't provide intrinsics +#define _InterlockedCompareExchange InterlockedCompareExchange +#endif + } + // Borrowed from https://stackoverflow.com/questions/8211820/userland-interrupt-timer-access-such-as-via-kequeryinterrupttime-or-similar + inline ticks_type __stdcall GetTickCount64emulation() + { + static volatile long count = 0xFFFFFFFF; + unsigned long previous_count, current_tick32, previous_count_zone, current_tick32_zone; + ticks_type current_tick64; + + previous_count = (unsigned long) _InterlockedCompareExchange(&count, 0, 0); + current_tick32 = GetTickCount(); + + if(previous_count == 0xFFFFFFFF) + { + // count has never been written + unsigned long initial_count; + initial_count = current_tick32 >> 28; + previous_count = (unsigned long) _InterlockedCompareExchange(&count, initial_count, 0xFFFFFFFF); + + current_tick64 = initial_count; + current_tick64 <<= 28; + current_tick64 += current_tick32 & 0x0FFFFFFF; + return current_tick64; + } + + previous_count_zone = previous_count & 15; + current_tick32_zone = current_tick32 >> 28; + + if(current_tick32_zone == previous_count_zone) + { + // The top four bits of the 32-bit tick count haven't changed since count was last written. + current_tick64 = previous_count; + current_tick64 <<= 28; + current_tick64 += current_tick32 & 0x0FFFFFFF; + return current_tick64; + } + + if(current_tick32_zone == previous_count_zone + 1 || (current_tick32_zone == 0 && previous_count_zone == 15)) + { + // The top four bits of the 32-bit tick count have been incremented since count was last written. + _InterlockedCompareExchange(&count, previous_count + 1, previous_count); + current_tick64 = previous_count + 1; + current_tick64 <<= 28; + current_tick64 += current_tick32 & 0x0FFFFFFF; + return current_tick64; + } + + // Oops, we weren't called often enough, we're stuck + return 0xFFFFFFFF; + } +#else +#endif + inline detail::gettickcount64_t GetTickCount64_() + { + static detail::gettickcount64_t gettickcount64impl; + if(gettickcount64impl) + return gettickcount64impl; + + // GetTickCount and GetModuleHandle are not allowed in the Windows Runtime, + // and kernel32 isn't used in Windows Phone. +#if BOOST_PLAT_WINDOWS_RUNTIME + gettickcount64impl = &GetTickCount64; +#else + farproc_t addr=GetProcAddress( +#if !defined(BOOST_NO_ANSI_APIS) + GetModuleHandleA("KERNEL32.DLL"), +#else + GetModuleHandleW(L"KERNEL32.DLL"), +#endif + "GetTickCount64"); + if(addr) + gettickcount64impl=(detail::gettickcount64_t) addr; + else + gettickcount64impl=&GetTickCount64emulation; +#endif + return gettickcount64impl; + } + + enum event_type + { + auto_reset_event=false, + manual_reset_event=true + }; + + enum initial_event_state + { + event_initially_reset=false, + event_initially_set=true + }; + + inline handle create_event( +#if !defined(BOOST_NO_ANSI_APIS) + const char *mutex_name, +#else + const wchar_t *mutex_name, +#endif + event_type type, + initial_event_state state) + { +#if !defined(BOOST_NO_ANSI_APIS) + handle const res = win32::CreateEventA(0, type, state, mutex_name); +#elif BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA + handle const res = win32::CreateEventW(0, type, state, mutex_name); +#else + handle const res = win32::CreateEventExW( + 0, + mutex_name, + type ? create_event_manual_reset : 0 | state ? create_event_initial_set : 0, + event_all_access); +#endif + return res; + } + + inline handle create_anonymous_event(event_type type,initial_event_state state) + { + handle const res = create_event(0, type, state); + if(!res) + { + boost::throw_exception(thread_resource_error()); + } + return res; + } + + inline handle create_anonymous_semaphore_nothrow(long initial_count,long max_count) + { +#if !defined(BOOST_NO_ANSI_APIS) + handle const res=win32::CreateSemaphoreA(0,initial_count,max_count,0); +#else +#if BOOST_USE_WINAPI_VERSION < BOOST_WINAPI_VERSION_VISTA + handle const res=win32::CreateSemaphoreEx(0,initial_count,max_count,0,0); +#else + handle const res=win32::CreateSemaphoreExW(0,initial_count,max_count,0,0,semaphore_all_access); +#endif +#endif + return res; + } + + inline handle create_anonymous_semaphore(long initial_count,long max_count) + { + handle const res=create_anonymous_semaphore_nothrow(initial_count,max_count); + if(!res) + { + boost::throw_exception(thread_resource_error()); + } + return res; + } + + inline handle duplicate_handle(handle source) + { + handle const current_process=GetCurrentProcess(); + long const same_access_flag=2; + handle new_handle=0; + bool const success=DuplicateHandle(current_process,source,current_process,&new_handle,0,false,same_access_flag)!=0; + if(!success) + { + boost::throw_exception(thread_resource_error()); + } + return new_handle; + } + + inline void release_semaphore(handle semaphore,long count) + { + BOOST_VERIFY(ReleaseSemaphore(semaphore,count,0)!=0); + } + + inline void get_system_info(system_info *info) + { +#if BOOST_PLAT_WINDOWS_RUNTIME + win32::GetNativeSystemInfo(info); +#else + win32::GetSystemInfo(info); +#endif + } + + inline void sleep(unsigned long milliseconds) + { + if(milliseconds == 0) + { +#if BOOST_PLAT_WINDOWS_RUNTIME + std::this_thread::yield(); +#else + ::boost::detail::win32::Sleep(0); +#endif + } + else + { +#if BOOST_PLAT_WINDOWS_RUNTIME + ::boost::detail::win32::WaitForSingleObjectEx(::boost::detail::win32::GetCurrentThread(), milliseconds, 0); +#else + ::boost::detail::win32::Sleep(milliseconds); +#endif + } + } + +#if BOOST_PLAT_WINDOWS_RUNTIME + class BOOST_THREAD_DECL scoped_winrt_thread + { + public: + scoped_winrt_thread() : m_completionHandle(invalid_handle_value) + {} + + ~scoped_winrt_thread() + { + if (m_completionHandle != ::boost::detail::win32::invalid_handle_value) + { + CloseHandle(m_completionHandle); + } + } + + typedef unsigned(__stdcall * thread_func)(void *); + bool start(thread_func address, void *parameter, unsigned int *thrdId); + + handle waitable_handle() const + { + BOOST_ASSERT(m_completionHandle != ::boost::detail::win32::invalid_handle_value); + return m_completionHandle; + } + + private: + handle m_completionHandle; + }; +#endif + class BOOST_THREAD_DECL handle_manager + { + private: + handle handle_to_manage; + handle_manager(handle_manager&); + handle_manager& operator=(handle_manager&); + + void cleanup() + { + if(handle_to_manage && handle_to_manage!=invalid_handle_value) + { + BOOST_VERIFY(CloseHandle(handle_to_manage)); + } + } + + public: + explicit handle_manager(handle handle_to_manage_): + handle_to_manage(handle_to_manage_) + {} + handle_manager(): + handle_to_manage(0) + {} + + handle_manager& operator=(handle new_handle) + { + cleanup(); + handle_to_manage=new_handle; + return *this; + } + + operator handle() const + { + return handle_to_manage; + } + + handle duplicate() const + { + return duplicate_handle(handle_to_manage); + } + + void swap(handle_manager& other) + { + std::swap(handle_to_manage,other.handle_to_manage); + } + + handle release() + { + handle const res=handle_to_manage; + handle_to_manage=0; + return res; + } + + bool operator!() const + { + return !handle_to_manage; + } + + ~handle_manager() + { + cleanup(); + } + }; + } + } +} + +#if defined(BOOST_MSVC) && (_MSC_VER>=1400) && !defined(UNDER_CE) + +namespace boost +{ + namespace detail + { + namespace win32 + { +#if _MSC_VER==1400 + extern "C" unsigned char _interlockedbittestandset(long *a,long b); + extern "C" unsigned char _interlockedbittestandreset(long *a,long b); +#else + extern "C" unsigned char _interlockedbittestandset(volatile long *a,long b); + extern "C" unsigned char _interlockedbittestandreset(volatile long *a,long b); +#endif + +#pragma intrinsic(_interlockedbittestandset) +#pragma intrinsic(_interlockedbittestandreset) + + inline bool interlocked_bit_test_and_set(long* x,long bit) + { + return _interlockedbittestandset(x,bit)!=0; + } + + inline bool interlocked_bit_test_and_reset(long* x,long bit) + { + return _interlockedbittestandreset(x,bit)!=0; + } + + } + } +} +#define BOOST_THREAD_BTS_DEFINED +#elif (defined(BOOST_MSVC) || defined(BOOST_INTEL_WIN)) && defined(_M_IX86) +namespace boost +{ + namespace detail + { + namespace win32 + { + inline bool interlocked_bit_test_and_set(long* x,long bit) + { +#ifndef BOOST_INTEL_CXX_VERSION + __asm { + mov eax,bit; + mov edx,x; + lock bts [edx],eax; + setc al; + }; +#else + bool ret; + __asm { + mov eax,bit + mov edx,x + lock bts [edx],eax + setc al + mov ret, al + }; + return ret; + +#endif + } + + inline bool interlocked_bit_test_and_reset(long* x,long bit) + { +#ifndef BOOST_INTEL_CXX_VERSION + __asm { + mov eax,bit; + mov edx,x; + lock btr [edx],eax; + setc al; + }; +#else + bool ret; + __asm { + mov eax,bit + mov edx,x + lock btr [edx],eax + setc al + mov ret, al + }; + return ret; + +#endif + } + + } + } +} +#define BOOST_THREAD_BTS_DEFINED +#endif + +#ifndef BOOST_THREAD_BTS_DEFINED + +namespace boost +{ + namespace detail + { + namespace win32 + { + inline bool interlocked_bit_test_and_set(long* x,long bit) + { + long const value=1< + +#endif diff --git a/src/third_party/boost-1.60.0/boost/thread/with_lock_guard.hpp b/src/third_party/boost-1.60.0/boost/thread/with_lock_guard.hpp new file mode 100644 index 00000000000..5d99b36f2e4 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/with_lock_guard.hpp @@ -0,0 +1,234 @@ +// (C) Copyright 2013 Ruslan Baratov +// Copyright (C) 2014 Vicente J. Botet Escriba +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// See www.boost.org/libs/thread for documentation. + +#ifndef BOOST_THREAD_WITH_LOCK_GUARD_HPP +#define BOOST_THREAD_WITH_LOCK_GUARD_HPP + +#include +#include +//#include + +namespace boost { + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \ + !defined(BOOST_NO_CXX11_DECLTYPE) && \ + !defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) + +/** + * Utility to run functions in scope protected by mutex. + * + * Examples: + * + * int func(int, int&); + * boost::mutex m; + * int a; + * int result = boost::with_lock_guard(m, func, 1, boost::ref(a)); + * + * // using boost::bind + * int result = boost::with_lock_guard( + * m, boost::bind(func, 2, boost::ref(a)) + * ); + * + * // using lambda + * int a; + * int result = boost::with_lock_guard( + * m, + * [&a](int x) { + * a = 3; + * return x + 4; + * }, + * 5 + * ); + */ +template +typename boost::result_of::type with_lock_guard( + Lockable& m, + BOOST_FWD_REF(Function) func, + BOOST_FWD_REF(Args)... args +) //-> decltype(func(boost::forward(args)...)) +{ + boost::lock_guard lock(m); + return func(boost::forward(args)...); +} + +#else + +// Workaround versions for compilers without c++11 variadic templates support. +// (function arguments limit: 4) +// (for lambda support define BOOST_RESULT_OF_USE_DECLTYPE may be needed) + +template +typename boost::result_of::type with_lock_guard( + Lockable& m, + BOOST_FWD_REF(Func) func +) { + boost::lock_guard lock(m); + return func(); +} + +template +typename boost::result_of::type with_lock_guard( + Lockable& m, + BOOST_FWD_REF(Func) func, + BOOST_FWD_REF(Arg) arg +) { + boost::lock_guard lock(m); + return func( + boost::forward(arg) + ); +} + +template +typename boost::result_of::type with_lock_guard( + Lockable& m, + BOOST_FWD_REF(Func) func, + BOOST_FWD_REF(Arg1) arg1, + BOOST_FWD_REF(Arg2) arg2 +) { + boost::lock_guard lock(m); + return func( + boost::forward(arg1), + boost::forward(arg2) + ); +} + +template +typename boost::result_of::type with_lock_guard( + Lockable& m, + BOOST_FWD_REF(Func) func, + BOOST_FWD_REF(Arg1) arg1, + BOOST_FWD_REF(Arg2) arg2, + BOOST_FWD_REF(Arg3) arg3 +) { + boost::lock_guard lock(m); + return func( + boost::forward(arg1), + boost::forward(arg2), + boost::forward(arg3) + ); +} + +template < + class Lockable, class Func, class Arg1, class Arg2, class Arg3, class Arg4 +> +typename boost::result_of::type with_lock_guard( + Lockable& m, + BOOST_FWD_REF(Func) func, + BOOST_FWD_REF(Arg1) arg1, + BOOST_FWD_REF(Arg2) arg2, + BOOST_FWD_REF(Arg3) arg3, + BOOST_FWD_REF(Arg4) arg4 +) { + boost::lock_guard lock(m); + return func( + boost::forward(arg1), + boost::forward(arg2), + boost::forward(arg3), + boost::forward(arg4) + ); +} + +// overloads for function pointer +// (if argument is not function pointer, static assert will trigger) +template +typename boost::result_of< + typename boost::add_pointer::type() +>::type with_lock_guard( + Lockable& m, + Func* func +) { + BOOST_STATIC_ASSERT(boost::is_function::value); + + boost::lock_guard lock(m); + return func(); +} + +template +typename boost::result_of< + typename boost::add_pointer::type(Arg) +>::type with_lock_guard( + Lockable& m, + Func* func, + BOOST_FWD_REF(Arg) arg +) { + BOOST_STATIC_ASSERT(boost::is_function::value); + + boost::lock_guard lock(m); + return func( + boost::forward(arg) + ); +} + +template +typename boost::result_of< + typename boost::add_pointer::type(Arg1, Arg2) +>::type with_lock_guard( + Lockable& m, + Func* func, + BOOST_FWD_REF(Arg1) arg1, + BOOST_FWD_REF(Arg2) arg2 +) { + BOOST_STATIC_ASSERT(boost::is_function::value); + + boost::lock_guard lock(m); + return func( + boost::forward(arg1), + boost::forward(arg2) + ); +} + +template +typename boost::result_of< + typename boost::add_pointer::type(Arg1, Arg2, Arg3) +>::type with_lock_guard( + Lockable& m, + Func* func, + BOOST_FWD_REF(Arg1) arg1, + BOOST_FWD_REF(Arg2) arg2, + BOOST_FWD_REF(Arg3) arg3 +) { + BOOST_STATIC_ASSERT(boost::is_function::value); + + boost::lock_guard lock(m); + return func( + boost::forward(arg1), + boost::forward(arg2), + boost::forward(arg3) + ); +} + +template < + class Lockable, class Func, class Arg1, class Arg2, class Arg3, class Arg4 +> +typename boost::result_of< + typename boost::add_pointer::type(Arg1, Arg2, Arg3, Arg4) +>::type with_lock_guard( + Lockable& m, + Func* func, + BOOST_FWD_REF(Arg1) arg1, + BOOST_FWD_REF(Arg2) arg2, + BOOST_FWD_REF(Arg3) arg3, + BOOST_FWD_REF(Arg4) arg4 +) { + BOOST_STATIC_ASSERT(boost::is_function::value); + + boost::lock_guard lock(m); + return func( + boost::forward(arg1), + boost::forward(arg2), + boost::forward(arg3), + boost::forward(arg4) + ); +} + +#endif + +} // namespace boost + +#endif // BOOST_THREAD_WITH_LOCK_GUARD_HPP + diff --git a/src/third_party/boost-1.60.0/boost/thread/xtime.hpp b/src/third_party/boost-1.60.0/boost/thread/xtime.hpp new file mode 100644 index 00000000000..9c6a3596400 --- /dev/null +++ b/src/third_party/boost-1.60.0/boost/thread/xtime.hpp @@ -0,0 +1,93 @@ +// Copyright (C) 2001-2003 +// William E. Kempf +// Copyright (C) 2007-8 Anthony Williams +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_XTIME_WEK070601_HPP +#define BOOST_XTIME_WEK070601_HPP + +#include +#if defined BOOST_THREAD_USES_DATETIME + +#include +#include +#include + +#include + +namespace boost { + +enum xtime_clock_types +{ + TIME_UTC_=1 +// TIME_TAI, +// TIME_MONOTONIC, +// TIME_PROCESS, +// TIME_THREAD, +// TIME_LOCAL, +// TIME_SYNC, +// TIME_RESOLUTION +}; + +struct xtime +{ +#if defined(BOOST_NO_INT64_T) + typedef int_fast32_t xtime_sec_t; //INT_FAST32_MIN <= sec <= INT_FAST32_MAX +#else + typedef int_fast64_t xtime_sec_t; //INT_FAST64_MIN <= sec <= INT_FAST64_MAX +#endif + + typedef int_fast32_t xtime_nsec_t; //0 <= xtime.nsec < NANOSECONDS_PER_SECOND + + xtime_sec_t sec; + xtime_nsec_t nsec; + + operator system_time() const + { + return boost::posix_time::from_time_t(0)+ + boost::posix_time::seconds(static_cast(sec))+ +#ifdef BOOST_DATE_TIME_HAS_NANOSECONDS + boost::posix_time::nanoseconds(nsec); +#else + boost::posix_time::microseconds((nsec+500)/1000); +#endif + } + +}; + +inline xtime get_xtime(boost::system_time const& abs_time) +{ + xtime res; + boost::posix_time::time_duration const time_since_epoch=abs_time-boost::posix_time::from_time_t(0); + + res.sec=static_cast(time_since_epoch.total_seconds()); + res.nsec=static_cast(time_since_epoch.fractional_seconds()*(1000000000/time_since_epoch.ticks_per_second())); + return res; +} + +inline int xtime_get(struct xtime* xtp, int clock_type) +{ + if (clock_type == TIME_UTC_) + { + *xtp=get_xtime(get_system_time()); + return clock_type; + } + return 0; +} + + +inline int xtime_cmp(const xtime& xt1, const xtime& xt2) +{ + if (xt1.sec == xt2.sec) + return (int)(xt1.nsec - xt2.nsec); + else + return (xt1.sec > xt2.sec) ? 1 : -1; +} + +} // namespace boost + +#include +#endif +#endif //BOOST_XTIME_WEK070601_HPP -- cgit v1.2.1