From 2e296dc8d366206247a459266c32ac85cdacb2c5 Mon Sep 17 00:00:00 2001 From: Kyle Schwarz Date: Fri, 9 Sep 2022 15:46:46 -0400 Subject: [PATCH] ConcurrentQueue: Update to HEAD --- .../third-party/concurrentqueue/.gitignore | 3 + .../concurrentqueue/CMakeLists.txt | 74 + .../third-party/concurrentqueue/LICENSE.md | 1 + .../third-party/concurrentqueue/README.md | 26 +- .../concurrentqueue/benchmarks/benchmarks.cpp | 305 +- .../concurrentqueue/benchmarks/dlib/algs.h | 1158 ++++++++ .../concurrentqueue/benchmarks/dlib/array.h | 10 + .../benchmarks/dlib/array/array_kernel.h | 809 +++++ .../dlib/array/array_kernel_abstract.h | 360 +++ .../benchmarks/dlib/array/array_tools.h | 38 + .../dlib/array/array_tools_abstract.h | 33 + .../concurrentqueue/benchmarks/dlib/assert.h | 217 ++ .../benchmarks/dlib/binary_search_tree.h | 50 + .../binary_search_tree_kernel_1.h | 2064 +++++++++++++ .../binary_search_tree_kernel_2.h | 1897 ++++++++++++ .../binary_search_tree_kernel_abstract.h | 311 ++ .../binary_search_tree_kernel_c.h | 235 ++ .../benchmarks/dlib/bound_function_pointer.h | 10 + .../bound_function_pointer_kernel_1.h | 774 +++++ .../bound_function_pointer_kernel_abstract.h | 456 +++ .../benchmarks/dlib/byte_orderer.h | 10 + .../dlib/byte_orderer/byte_orderer_kernel_1.h | 176 ++ .../byte_orderer_kernel_abstract.h | 149 + .../concurrentqueue/benchmarks/dlib/cassert | 1 + .../concurrentqueue/benchmarks/dlib/config.h | 34 + .../dlib/console_progress_indicator.h | 207 ++ .../concurrentqueue/benchmarks/dlib/cstring | 1 + .../dlib/dlib_basic_cpp_build_tutorial.txt | 13 + .../dlib/dlib_include_path_tutorial.txt | 20 + .../benchmarks/dlib/enable_if.h | 62 + .../concurrentqueue/benchmarks/dlib/error.h | 449 +++ .../benchmarks/dlib/float_details.h | 161 + .../concurrentqueue/benchmarks/dlib/fstream | 1 + .../concurrentqueue/benchmarks/dlib/hash.h | 14 + .../dlib/interfaces/cmd_line_parser_option.h | 107 + .../benchmarks/dlib/interfaces/enumerable.h | 130 + .../benchmarks/dlib/interfaces/map_pair.h | 74 + .../benchmarks/dlib/interfaces/remover.h | 220 ++ .../concurrentqueue/benchmarks/dlib/iomanip | 1 + .../concurrentqueue/benchmarks/dlib/iosfwd | 1 + .../concurrentqueue/benchmarks/dlib/iostream | 1 + .../concurrentqueue/benchmarks/dlib/is_kind.h | 162 + .../concurrentqueue/benchmarks/dlib/istream | 1 + .../concurrentqueue/benchmarks/dlib/locale | 1 + .../concurrentqueue/benchmarks/dlib/logger.h | 11 + .../dlib/logger/extra_logger_headers.h | 41 + .../dlib/logger/logger_config_file.h | 135 + .../benchmarks/dlib/logger/logger_kernel_1.h | 687 +++++ .../dlib/logger/logger_kernel_abstract.h | 429 +++ .../concurrentqueue/benchmarks/dlib/map.h | 59 + .../benchmarks/dlib/map/map_kernel_1.h | 436 +++ .../benchmarks/dlib/map/map_kernel_abstract.h | 235 ++ .../benchmarks/dlib/map/map_kernel_c.h | 248 ++ .../benchmarks/dlib/member_function_pointer.h | 10 + .../dlib/member_function_pointer/make_mfp.h | 179 ++ .../make_mfp_abstract.h | 207 ++ .../member_function_pointer_kernel_1.h | 509 ++++ .../member_function_pointer_kernel_abstract.h | 483 +++ .../benchmarks/dlib/memory_manager.h | 73 + .../memory_manager/memory_manager_kernel_1.h | 305 ++ .../memory_manager/memory_manager_kernel_2.h | 253 ++ .../memory_manager/memory_manager_kernel_3.h | 385 +++ .../memory_manager_kernel_abstract.h | 146 + .../benchmarks/dlib/memory_manager_global.h | 38 + .../memory_manager_global_kernel_1.h | 113 + .../memory_manager_global_kernel_abstract.h | 181 ++ .../dlib/memory_manager_stateless.h | 72 + .../memory_manager_stateless_kernel_1.h | 101 + .../memory_manager_stateless_kernel_2.h | 119 + ...memory_manager_stateless_kernel_abstract.h | 173 ++ .../benchmarks/dlib/metaprogramming.h | 111 + .../benchmarks/dlib/misc_api.h | 20 + .../dlib/misc_api/misc_api_kernel_1.h | 110 + .../dlib/misc_api/misc_api_kernel_2.h | 81 + .../dlib/misc_api/misc_api_kernel_abstract.h | 159 + .../dlib/misc_api/misc_api_shared.h | 57 + .../benchmarks/dlib/misc_api/posix.h | 6 + .../benchmarks/dlib/misc_api/windows.h | 6 + .../benchmarks/dlib/noncopyable.h | 32 + .../benchmarks/dlib/numeric_constants.h | 53 + .../benchmarks/dlib/numerical_integration.h | 8 + .../integrate_function_adapt_simpson.h | 93 + ...ntegrate_function_adapt_simpson_abstract.h | 34 + .../concurrentqueue/benchmarks/dlib/ostream | 1 + .../concurrentqueue/benchmarks/dlib/pipe.h | 10 + .../benchmarks/dlib/pipe/pipe_kernel_1.h | 756 +++++ .../dlib/pipe/pipe_kernel_abstract.h | 323 ++ .../benchmarks/dlib/platform.h | 65 + .../concurrentqueue/benchmarks/dlib/queue.h | 84 + .../benchmarks/dlib/queue/queue_kernel_1.h | 554 ++++ .../benchmarks/dlib/queue/queue_kernel_2.h | 600 ++++ .../dlib/queue/queue_kernel_abstract.h | 196 ++ .../benchmarks/dlib/queue/queue_kernel_c.h | 187 ++ .../benchmarks/dlib/queue/queue_sort_1.h | 165 ++ .../dlib/queue/queue_sort_abstract.h | 74 + .../concurrentqueue/benchmarks/dlib/ref.h | 84 + .../benchmarks/dlib/revision.h | 6 + .../benchmarks/dlib/serialize.h | 2606 +++++++++++++++++ .../concurrentqueue/benchmarks/dlib/set.h | 74 + .../benchmarks/dlib/set/set_compare_1.h | 122 + .../dlib/set/set_compare_abstract.h | 96 + .../benchmarks/dlib/set/set_kernel_1.h | 372 +++ .../benchmarks/dlib/set/set_kernel_abstract.h | 192 ++ .../benchmarks/dlib/set/set_kernel_c.h | 194 ++ .../benchmarks/dlib/sliding_buffer.h | 38 + .../dlib/sliding_buffer/circular_buffer.h | 235 ++ .../sliding_buffer/circular_buffer_abstract.h | 257 ++ .../sliding_buffer/sliding_buffer_kernel_1.h | 227 ++ .../sliding_buffer_kernel_abstract.h | 205 ++ .../sliding_buffer/sliding_buffer_kernel_c.h | 222 ++ .../concurrentqueue/benchmarks/dlib/sockets.h | 20 + .../benchmarks/dlib/sockets/posix.h | 6 + .../dlib/sockets/sockets_extensions.h | 151 + .../sockets/sockets_extensions_abstract.h | 300 ++ .../dlib/sockets/sockets_kernel_1.h | 351 +++ .../dlib/sockets/sockets_kernel_2.h | 396 +++ .../dlib/sockets/sockets_kernel_abstract.h | 495 ++++ .../benchmarks/dlib/sockets/windows.h | 6 + .../concurrentqueue/benchmarks/dlib/sort.h | 490 ++++ .../benchmarks/dlib/sparse_vector.h | 10 + .../concurrentqueue/benchmarks/dlib/sstream | 1 + .../concurrentqueue/benchmarks/dlib/stack.h | 34 + .../benchmarks/dlib/stack/stack_kernel_1.h | 504 ++++ .../dlib/stack/stack_kernel_abstract.h | 180 ++ .../benchmarks/dlib/stack/stack_kernel_c.h | 189 ++ .../benchmarks/dlib/stack_trace.h | 118 + .../benchmarks/dlib/std_allocator.h | 199 ++ .../benchmarks/dlib/stl_checked.h | 10 + .../dlib/stl_checked/std_vector_c.h | 333 +++ .../dlib/stl_checked/std_vector_c_abstract.h | 470 +++ .../concurrentqueue/benchmarks/dlib/string.h | 9 + .../benchmarks/dlib/string/cassert | 1 + .../benchmarks/dlib/string/iomanip | 1 + .../benchmarks/dlib/string/iosfwd | 1 + .../benchmarks/dlib/string/iostream | 1 + .../benchmarks/dlib/string/locale | 1 + .../benchmarks/dlib/string/string.h | 1004 +++++++ .../benchmarks/dlib/string/string_abstract.h | 652 +++++ .../dlib/test_for_odr_violations.cpp | 47 + .../benchmarks/dlib/test_for_odr_violations.h | 54 + .../concurrentqueue/benchmarks/dlib/threads.h | 28 + .../benchmarks/dlib/threads/async.h | 118 + .../benchmarks/dlib/threads/async_abstract.h | 67 + .../dlib/threads/auto_mutex_extension.h | 180 ++ .../threads/auto_mutex_extension_abstract.h | 185 ++ .../dlib/threads/auto_unlock_extension.h | 116 + .../threads/auto_unlock_extension_abstract.h | 116 + .../threads/create_new_thread_extension.h | 46 + .../create_new_thread_extension_abstract.h | 33 + .../threads/multithreaded_object_extension.h | 153 + .../multithreaded_object_extension_abstract.h | 186 ++ .../dlib/threads/parallel_for_extension.h | 676 +++++ .../threads/parallel_for_extension_abstract.h | 469 +++ .../benchmarks/dlib/threads/posix.h | 6 + .../dlib/threads/read_write_mutex_extension.h | 177 ++ .../read_write_mutex_extension_abstract.h | 146 + .../dlib/threads/rmutex_extension.h | 109 + .../dlib/threads/rmutex_extension_abstract.h | 107 + .../dlib/threads/rsignaler_extension.h | 90 + .../threads/rsignaler_extension_abstract.h | 123 + .../dlib/threads/thread_function_extension.h | 215 ++ .../thread_function_extension_abstract.h | 146 + .../dlib/threads/thread_pool_extension.h | 1392 +++++++++ .../threads/thread_pool_extension_abstract.h | 842 ++++++ .../threads/thread_specific_data_extension.h | 141 + .../thread_specific_data_extension_abstract.h | 87 + .../dlib/threads/threaded_object_extension.h | 123 + .../threaded_object_extension_abstract.h | 199 ++ .../benchmarks/dlib/threads/threads_kernel.h | 18 + .../dlib/threads/threads_kernel_1.h | 158 + .../dlib/threads/threads_kernel_2.h | 180 ++ .../dlib/threads/threads_kernel_abstract.h | 302 ++ .../dlib/threads/threads_kernel_shared.h | 274 ++ .../benchmarks/dlib/threads/windows.h | 6 + .../benchmarks/dlib/time_this.h | 36 + .../concurrentqueue/benchmarks/dlib/timeout.h | 10 + .../benchmarks/dlib/timeout/timeout.h | 200 ++ .../dlib/timeout/timeout_abstract.h | 188 ++ .../concurrentqueue/benchmarks/dlib/timer.h | 10 + .../benchmarks/dlib/timer/timer.h | 427 +++ .../benchmarks/dlib/timer/timer_abstract.h | 190 ++ .../benchmarks/dlib/timer/timer_heavy.h | 392 +++ .../concurrentqueue/benchmarks/dlib/timing.h | 196 ++ .../benchmarks/dlib/tokenizer.h | 33 + .../dlib/tokenizer/tokenizer_kernel_1.h | 155 + .../tokenizer/tokenizer_kernel_abstract.h | 289 ++ .../dlib/tokenizer/tokenizer_kernel_c.h | 167 ++ .../concurrentqueue/benchmarks/dlib/uintn.h | 96 + .../concurrentqueue/benchmarks/dlib/unicode.h | 9 + .../benchmarks/dlib/unicode/unicode.h | 622 ++++ .../dlib/unicode/unicode_abstract.h | 233 ++ .../benchmarks/dlib/unordered_pair.h | 176 ++ .../benchmarks/dlib/vectorstream.h | 11 + .../dlib/vectorstream/unserialize.h | 98 + .../dlib/vectorstream/unserialize_abstract.h | 58 + .../dlib/vectorstream/vectorstream.h | 159 + .../dlib/vectorstream/vectorstream_abstract.h | 62 + .../benchmarks/dlib/windows_magic.h | 50 + .../concurrentqueue/benchmarks/dlibqueue.h | 39 + .../concurrentqueue/blockingconcurrentqueue.h | 6 +- .../c_api/blockingconcurrentqueue.cpp | 40 + .../concurrentqueue/c_api/concurrentqueue.cpp | 39 + .../concurrentqueue/c_api/concurrentqueue.h | 41 + .../concurrentqueue/concurrentqueue.h | 179 +- .../concurrentqueueConfig.cmake.in | 3 + .../concurrentqueue/lightweightsemaphore.h | 22 +- .../third-party/concurrentqueue/samples.md | 2 +- .../tests/unittests/unittests.cpp | 210 +- 208 files changed, 42592 insertions(+), 274 deletions(-) create mode 100644 include/icsneo/third-party/concurrentqueue/CMakeLists.txt create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/algs.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/array.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/array/array_kernel.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/array/array_kernel_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/array/array_tools.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/array/array_tools_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/assert.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/binary_search_tree.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/binary_search_tree/binary_search_tree_kernel_1.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/binary_search_tree/binary_search_tree_kernel_2.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/binary_search_tree/binary_search_tree_kernel_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/binary_search_tree/binary_search_tree_kernel_c.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/bound_function_pointer.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/bound_function_pointer/bound_function_pointer_kernel_1.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/bound_function_pointer/bound_function_pointer_kernel_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/byte_orderer.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/byte_orderer/byte_orderer_kernel_1.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/byte_orderer/byte_orderer_kernel_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/cassert create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/config.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/console_progress_indicator.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/cstring create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/dlib_basic_cpp_build_tutorial.txt create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/dlib_include_path_tutorial.txt create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/enable_if.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/error.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/float_details.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/fstream create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/hash.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/interfaces/cmd_line_parser_option.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/interfaces/enumerable.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/interfaces/map_pair.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/interfaces/remover.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/iomanip create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/iosfwd create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/iostream create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/is_kind.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/istream create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/locale create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/logger.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/logger/extra_logger_headers.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/logger/logger_config_file.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/logger/logger_kernel_1.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/logger/logger_kernel_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/map.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/map/map_kernel_1.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/map/map_kernel_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/map/map_kernel_c.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/member_function_pointer.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/member_function_pointer/make_mfp.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/member_function_pointer/make_mfp_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/member_function_pointer/member_function_pointer_kernel_1.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/member_function_pointer/member_function_pointer_kernel_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager/memory_manager_kernel_1.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager/memory_manager_kernel_2.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager/memory_manager_kernel_3.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager/memory_manager_kernel_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager_global.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager_global/memory_manager_global_kernel_1.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager_global/memory_manager_global_kernel_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager_stateless.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager_stateless/memory_manager_stateless_kernel_1.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager_stateless/memory_manager_stateless_kernel_2.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager_stateless/memory_manager_stateless_kernel_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/metaprogramming.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/misc_api.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/misc_api/misc_api_kernel_1.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/misc_api/misc_api_kernel_2.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/misc_api/misc_api_kernel_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/misc_api/misc_api_shared.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/misc_api/posix.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/misc_api/windows.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/noncopyable.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/numeric_constants.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/numerical_integration.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/numerical_integration/integrate_function_adapt_simpson.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/numerical_integration/integrate_function_adapt_simpson_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/ostream create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/pipe.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/pipe/pipe_kernel_1.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/pipe/pipe_kernel_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/platform.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/queue.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/queue/queue_kernel_1.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/queue/queue_kernel_2.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/queue/queue_kernel_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/queue/queue_kernel_c.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/queue/queue_sort_1.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/queue/queue_sort_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/ref.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/revision.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/serialize.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/set.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/set/set_compare_1.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/set/set_compare_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/set/set_kernel_1.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/set/set_kernel_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/set/set_kernel_c.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sliding_buffer.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sliding_buffer/circular_buffer.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sliding_buffer/circular_buffer_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sliding_buffer/sliding_buffer_kernel_1.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sliding_buffer/sliding_buffer_kernel_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sliding_buffer/sliding_buffer_kernel_c.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets/posix.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets/sockets_extensions.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets/sockets_extensions_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets/sockets_kernel_1.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets/sockets_kernel_2.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets/sockets_kernel_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets/windows.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sort.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sparse_vector.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sstream create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stack.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stack/stack_kernel_1.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stack/stack_kernel_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stack/stack_kernel_c.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stack_trace.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/std_allocator.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stl_checked.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stl_checked/std_vector_c.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stl_checked/std_vector_c_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string/cassert create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string/iomanip create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string/iosfwd create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string/iostream create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string/locale create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string/string.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string/string_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/test_for_odr_violations.cpp create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/test_for_odr_violations.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/async.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/async_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/auto_mutex_extension.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/auto_mutex_extension_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/auto_unlock_extension.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/auto_unlock_extension_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/create_new_thread_extension.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/create_new_thread_extension_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/multithreaded_object_extension.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/multithreaded_object_extension_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/parallel_for_extension.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/parallel_for_extension_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/posix.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/read_write_mutex_extension.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/read_write_mutex_extension_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/rmutex_extension.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/rmutex_extension_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/rsignaler_extension.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/rsignaler_extension_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/thread_function_extension.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/thread_function_extension_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/thread_pool_extension.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/thread_pool_extension_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/thread_specific_data_extension.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/thread_specific_data_extension_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/threaded_object_extension.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/threaded_object_extension_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/threads_kernel.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/threads_kernel_1.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/threads_kernel_2.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/threads_kernel_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/threads_kernel_shared.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/windows.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/time_this.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timeout.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timeout/timeout.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timeout/timeout_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timer.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timer/timer.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timer/timer_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timer/timer_heavy.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timing.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/tokenizer.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/tokenizer/tokenizer_kernel_1.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/tokenizer/tokenizer_kernel_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/tokenizer/tokenizer_kernel_c.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/uintn.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/unicode.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/unicode/unicode.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/unicode/unicode_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/unordered_pair.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/vectorstream.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/vectorstream/unserialize.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/vectorstream/unserialize_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/vectorstream/vectorstream.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/vectorstream/vectorstream_abstract.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlib/windows_magic.h create mode 100644 include/icsneo/third-party/concurrentqueue/benchmarks/dlibqueue.h create mode 100644 include/icsneo/third-party/concurrentqueue/c_api/blockingconcurrentqueue.cpp create mode 100644 include/icsneo/third-party/concurrentqueue/c_api/concurrentqueue.cpp create mode 100644 include/icsneo/third-party/concurrentqueue/c_api/concurrentqueue.h create mode 100644 include/icsneo/third-party/concurrentqueue/concurrentqueueConfig.cmake.in diff --git a/include/icsneo/third-party/concurrentqueue/.gitignore b/include/icsneo/third-party/concurrentqueue/.gitignore index 6f9e6ec..6a3596e 100644 --- a/include/icsneo/third-party/concurrentqueue/.gitignore +++ b/include/icsneo/third-party/concurrentqueue/.gitignore @@ -8,6 +8,7 @@ *.vs *.VC.db build/bin/ +build/*.o build/*.log build/msvc16/*.log build/msvc16/obj/ @@ -20,6 +21,8 @@ build/msvc12/obj/ build/msvc11/*.log build/msvc11/obj/ build/xcode/build/ +.idea/ +cmake-build*/ tests/fuzztests/fuzztests.log benchmarks/benchmarks.log tests/CDSChecker/*.o diff --git a/include/icsneo/third-party/concurrentqueue/CMakeLists.txt b/include/icsneo/third-party/concurrentqueue/CMakeLists.txt new file mode 100644 index 0000000..ea80135 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/CMakeLists.txt @@ -0,0 +1,74 @@ +cmake_minimum_required(VERSION 3.9) +project(concurrentqueue VERSION 1.0.0) + +include(GNUInstallDirs) +include(CMakePackageConfigHelpers) + +add_library(${PROJECT_NAME} INTERFACE) + +target_include_directories(${PROJECT_NAME} + INTERFACE + $ + $ +) + +install(TARGETS ${PROJECT_NAME} + EXPORT ${PROJECT_NAME}Targets +) + +write_basic_package_version_file( + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake + VERSION + ${PROJECT_VERSION} + COMPATIBILITY AnyNewerVersion +) + +configure_package_config_file(${PROJECT_NAME}Config.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake + INSTALL_DESTINATION + ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}/ +) + +install(EXPORT + ${PROJECT_NAME}Targets + FILE + ${PROJECT_NAME}Targets.cmake + NAMESPACE + "${PROJECT_NAME}::" + DESTINATION + ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} + COMPONENT + Devel +) + +install( + FILES + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake + ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake + DESTINATION + ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} + COMPONENT + Devel +) + +install( + FILES + blockingconcurrentqueue.h + concurrentqueue.h + lightweightsemaphore.h + LICENSE.md + DESTINATION + ${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/moodycamel +) + +set(CPACK_PACKAGE_NAME ${PROJECT_NAME}) +set(CPACK_PACKAGE_VENDOR "Cameron Desrochers ") +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "An industrial-strength lock-free queue for C++.") +set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}") +set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}") +set(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}") +set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}") +set(CPACK_DEBIAN_PACKAGE_MAINTAINER ${CPACK_PACKAGE_VENDOR}) +set(CPACK_GENERATOR "RPM;DEB") + +include(CPack) \ No newline at end of file diff --git a/include/icsneo/third-party/concurrentqueue/LICENSE.md b/include/icsneo/third-party/concurrentqueue/LICENSE.md index 47efd43..5193389 100644 --- a/include/icsneo/third-party/concurrentqueue/LICENSE.md +++ b/include/icsneo/third-party/concurrentqueue/LICENSE.md @@ -1,6 +1,7 @@ This license file applies to everything in this repository except that which is explicitly annotated as being written by other authors, i.e. the Boost queue (included in the benchmarks for comparison), Intel's TBB library (ditto), +dlib::pipe (ditto), the CDSChecker tool (used for verification), the Relacy model checker (ditto), and Jeff Preshing's semaphore implementation (used in the blocking queue) which has a zlib license (embedded in lightweightsempahore.h). diff --git a/include/icsneo/third-party/concurrentqueue/README.md b/include/icsneo/third-party/concurrentqueue/README.md index 016fedb..b710475 100644 --- a/include/icsneo/third-party/concurrentqueue/README.md +++ b/include/icsneo/third-party/concurrentqueue/README.md @@ -91,7 +91,7 @@ The entire queue's implementation is contained in **one header**, [`concurrentqu Simply download and include that to use the queue. The blocking version is in a separate header, [`blockingconcurrentqueue.h`][blockingconcurrentqueue.h], that depends on [`concurrentqueue.h`][concurrentqueue.h] and [`lightweightsemaphore.h`][lightweightsemaphore.h]. The implementation makes use of certain key C++11 features, -so it requires a fairly recent compiler (e.g. VS2012+ or g++ 4.8; note that g++ 4.6 has a known bug with `std::atomic` +so it requires a relatively recent compiler (e.g. VS2012+ or g++ 4.8; note that g++ 4.6 has a known bug with `std::atomic` and is thus not supported). The algorithm implementations themselves are platform independent. Use it like you would any other templated queue, with the exception that you can use @@ -128,8 +128,12 @@ There's usually two versions of each method, one "explicit" version that takes a per-consumer token, and one "implicit" version that works without tokens. Using the explicit methods is almost always faster (though not necessarily by a huge factor). Apart from performance, the primary distinction between them is their sub-queue allocation behaviour for enqueue operations: Using the implicit enqueue methods causes an -automatically-allocated thread-local producer sub-queue to be allocated (it is marked for reuse once the thread exits). -Explicit producers, on the other hand, are tied directly to their tokens' lifetimes (and are also recycled as needed). +automatically-allocated thread-local producer sub-queue to be allocated. +Explicit producers, on the other hand, are tied directly to their tokens' lifetimes (but are recycled internally). + +In order to avoid the number of sub-queues growing without bound, implicit producers are marked for reuse once +their thread exits. However, this is not supported on all platforms. If using the queue from short-lived threads, +it is recommended to use explicit producer tokens instead. Full API (pseudocode): @@ -272,7 +276,7 @@ in order to obtain an effective number of pre-allocated element slots is non-obv First, be aware that the count passed is rounded up to the next multiple of the block size. Note that the default block size is 32 (this can be changed via the traits). Second, once a slot in a block has been -enqueued to, that slot cannot be re-used until the rest of the block has completely been completely filled +enqueued to, that slot cannot be re-used until the rest of the block has been completely filled up and then completely emptied. This affects the number of blocks you need in order to account for the overhead of partially-filled blocks. Third, each producer (whether implicit or explicit) claims and recycles blocks in a different manner, which again affects the number of blocks you need to account for a desired number of @@ -320,7 +324,7 @@ so be sure to reserve enough capacity in the target container first if you do th The guarantees are presently as follows: - Enqueue operations are rolled back completely if an exception is thrown from an element's constructor. For bulk enqueue operations, this means that elements are copied instead of moved (in order to avoid - having only some of the objects be moved in the event of an exception). Non-bulk enqueues always use + having only some objects moved in the event of an exception). Non-bulk enqueues always use the move constructor if one is available. - If the assignment operator throws during a dequeue operation (both single and bulk), the element(s) are considered dequeued regardless. In such a case, the dequeued elements are all properly destructed before @@ -426,6 +430,17 @@ written to be platform-independent, however, and should work across all processo Due to the complexity of the implementation and the difficult-to-test nature of lock-free code in general, there may still be bugs. If anyone is seeing buggy behaviour, I'd like to hear about it! (Especially if a unit test for it can be cooked up.) Just open an issue on GitHub. + +## Using vcpkg +You can download and install `moodycamel::ConcurrentQueue` using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager: + + git clone https://github.com/Microsoft/vcpkg.git + cd vcpkg + ./bootstrap-vcpkg.sh + ./vcpkg integrate install + vcpkg install concurrentqueue + +The `moodycamel::ConcurrentQueue` port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. ## License @@ -474,6 +489,7 @@ of the queue itself, followed lastly by the free-standing swap functions. [source]: https://github.com/cameron314/concurrentqueue [concurrentqueue.h]: https://github.com/cameron314/concurrentqueue/blob/master/concurrentqueue.h [blockingconcurrentqueue.h]: https://github.com/cameron314/concurrentqueue/blob/master/blockingconcurrentqueue.h +[lightweightsemaphore.h]: https://github.com/cameron314/concurrentqueue/blob/master/lightweightsemaphore.h [unittest-src]: https://github.com/cameron314/concurrentqueue/tree/master/tests/unittests [benchmarks]: http://moodycamel.com/blog/2014/a-fast-general-purpose-lock-free-queue-for-c++#benchmarks [benchmark-src]: https://github.com/cameron314/concurrentqueue/tree/master/benchmarks diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/benchmarks.cpp b/include/icsneo/third-party/concurrentqueue/benchmarks/benchmarks.cpp index 69c08a4..e551c95 100644 --- a/include/icsneo/third-party/concurrentqueue/benchmarks/benchmarks.cpp +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/benchmarks.cpp @@ -28,6 +28,7 @@ #include "boostqueue.h" #include "tbbqueue.h" #include "stdqueue.h" +#include "dlibqueue.h" #include "../tests/common/simplethread.h" #include "../tests/common/systemtime.h" #include "cpuid.h" @@ -192,7 +193,7 @@ enum queue_id_t queue_simplelockfree, queue_lockbased, queue_std, - + queue_dlib, QUEUE_COUNT }; @@ -204,6 +205,7 @@ const char QUEUE_NAMES[QUEUE_COUNT][64] = { "SimpleLockFreeQueue", "LockBasedQueue", "std::queue", + "dlib::pipe" }; const char QUEUE_SUMMARY_NOTES[QUEUE_COUNT][128] = { @@ -214,6 +216,7 @@ const char QUEUE_SUMMARY_NOTES[QUEUE_COUNT][128] = { "", "", "single thread only", + "" }; const bool QUEUE_TOKEN_SUPPORT[QUEUE_COUNT] = { @@ -224,6 +227,7 @@ const bool QUEUE_TOKEN_SUPPORT[QUEUE_COUNT] = { false, false, false, + false }; const int QUEUE_MAX_THREADS[QUEUE_COUNT] = { @@ -234,6 +238,7 @@ const int QUEUE_MAX_THREADS[QUEUE_COUNT] = { -1, -1, 1, + -1 }; const bool QUEUE_BENCH_SUPPORT[QUEUE_COUNT][BENCHMARK_TYPE_COUNT] = { @@ -244,6 +249,7 @@ const bool QUEUE_BENCH_SUPPORT[QUEUE_COUNT][BENCHMARK_TYPE_COUNT] = { { 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1 }, { 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 }, + { 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1 } }; @@ -254,6 +260,9 @@ struct Traits : public moodycamel::ConcurrentQueueDefaultTraits // block size will improve throughput (which is mostly what // we're after with these benchmarks). static const size_t BLOCK_SIZE = 64; + + // Reuse blocks once allocated. + static const bool RECYCLE_ALLOCATED_BLOCKS = true; }; @@ -295,7 +304,7 @@ counter_t adjustForThreads(counter_t suggestedOps, int nthreads) } -template +template counter_t determineMaxOpsForBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, unsigned int randSeed) { switch (benchmark) { @@ -306,9 +315,10 @@ counter_t determineMaxOpsForBenchmark(benchmark_type_t benchmark, int nthreads, std::uniform_int_distribution rand(0, 20); double total = 0; SystemTime start; + item_t item = 1; for (counter_t i = 0; i != ops; ++i) { start = getSystemTime(); - q.enqueue(i); + q.enqueue(item); total += getTimeDelta(start); } return total; @@ -319,9 +329,10 @@ counter_t determineMaxOpsForBenchmark(benchmark_type_t benchmark, int nthreads, case bench_mostly_enqueue: { return adjustForThreads(rampUpToMeasurableNumberOfMaxOps([](counter_t ops) { TQueue q; + item_t item = 1; auto start = getSystemTime(); for (counter_t i = 0; i != ops; ++i) { - q.enqueue(i); + q.enqueue(item); } return getTimeDelta(start); }), nthreads); @@ -333,13 +344,14 @@ counter_t determineMaxOpsForBenchmark(benchmark_type_t benchmark, int nthreads, case bench_mpsc: { return adjustForThreads(rampUpToMeasurableNumberOfMaxOps([](counter_t ops) { TQueue q; + item_t item = 1; for (counter_t i = 0; i != ops; ++i) { - q.enqueue(i); + q.enqueue(item); } - int item; + item_t item_rec; auto start = getSystemTime(); for (counter_t i = 0; i != ops; ++i) { - q.try_dequeue(item); + q.try_dequeue(item_rec); } return getTimeDelta(start); }), nthreads); @@ -347,7 +359,7 @@ counter_t determineMaxOpsForBenchmark(benchmark_type_t benchmark, int nthreads, case bench_only_enqueue_bulk: case bench_only_enqueue_bulk_prealloc: case bench_mostly_enqueue_bulk: { - std::vector data; + std::vector data; for (counter_t i = 0; i != BULK_BATCH_SIZE; ++i) { data.push_back(i); } @@ -364,7 +376,7 @@ counter_t determineMaxOpsForBenchmark(benchmark_type_t benchmark, int nthreads, case bench_mostly_dequeue_bulk: { return adjustForThreads(rampUpToMeasurableNumberOfMaxOps([](counter_t ops) { TQueue q; - std::vector data(BULK_BATCH_SIZE); + std::vector data(BULK_BATCH_SIZE); for (counter_t i = 0; i != ops; ++i) { q.enqueue_bulk(data.cbegin(), data.size()); } @@ -379,10 +391,10 @@ counter_t determineMaxOpsForBenchmark(benchmark_type_t benchmark, int nthreads, case bench_empty_dequeue: { return adjustForThreads(rampUpToMeasurableNumberOfMaxOps([](counter_t ops) { TQueue q; - int item; + item_t item_rec; auto start = getSystemTime(); for (counter_t i = 0; i != ops; ++i) { - q.try_dequeue(item); + q.try_dequeue(item_rec); } return getTimeDelta(start); }), nthreads); @@ -390,11 +402,12 @@ counter_t determineMaxOpsForBenchmark(benchmark_type_t benchmark, int nthreads, case bench_enqueue_dequeue_pairs: { return adjustForThreads(rampUpToMeasurableNumberOfMaxOps([](counter_t ops) { TQueue q; - int item; + item_t item = 1; + item_t item_rec; auto start = getSystemTime(); for (counter_t i = 0; i != ops; ++i) { - q.enqueue(i); - q.try_dequeue(item); + q.enqueue(item); + q.try_dequeue(item_rec); } return getTimeDelta(start); }), nthreads); @@ -403,11 +416,12 @@ counter_t determineMaxOpsForBenchmark(benchmark_type_t benchmark, int nthreads, case bench_heavy_concurrent: { return adjustForThreads(rampUpToMeasurableNumberOfMaxOps([](counter_t ops) { TQueue q; - int item; + item_t item=1; + item_t item_rec; auto start = getSystemTime(); for (counter_t i = 0; i != ops; ++i) { - q.enqueue(i); - q.try_dequeue(item); + q.enqueue(item); + q.try_dequeue(item_rec); } return getTimeDelta(start); }), nthreads); @@ -421,7 +435,7 @@ counter_t determineMaxOpsForBenchmark(benchmark_type_t benchmark, int nthreads, // Returns time elapsed, in (fractional) milliseconds -template +template double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, unsigned int randSeed, counter_t maxOps, int maxThreads, counter_t& out_opCount) { double result = 0; @@ -435,13 +449,14 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un std::vector ops(nthreads); std::vector times(nthreads); std::atomic ready(0); + item_t item_rec; + item_t item = 1; for (int tid = 0; tid != nthreads; ++tid) { threads[tid] = SimpleThread([&](int id) { ready.fetch_add(1, std::memory_order_relaxed); while (ready.load(std::memory_order_relaxed) != nthreads) continue; - int item; SystemTime start; RNG_t rng(randSeed * (id + 1)); std::uniform_int_distribution rand(0, 20); @@ -449,24 +464,25 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un times[id] = 0; typename TQueue::consumer_token_t consTok(q); typename TQueue::producer_token_t prodTok(q); - + + for (counter_t i = 0; i != maxOps; ++i) { if (rand(rng) == 0) { start = getSystemTime(); if ((i & 1) == 0) { if (useTokens) { - q.try_dequeue(consTok, item); + q.try_dequeue(consTok, item_rec); } else { - q.try_dequeue(item); + q.try_dequeue(item_rec); } } else { if (useTokens) { - q.enqueue(prodTok, i); + q.enqueue(prodTok, item); } else { - q.enqueue(i); + q.enqueue(item); } } times[id] += getTimeDelta(start); @@ -482,8 +498,7 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un out_opCount += ops[tid]; result += times[tid]; } - int item; - forceNoOptimizeDummy = q.try_dequeue(item) ? 1 : 0; + forceNoOptimizeDummy = q.try_dequeue(item_rec) ? 1 : 0; break; } @@ -491,23 +506,26 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un out_opCount = maxOps * nthreads; TQueue q; + item_t item = 1; + item_t item_rec; { // Enqueue opcount elements first, then dequeue them; this // will "stretch out" the queue, letting implementatations // that re-use memory internally avoid having to allocate // more later during the timed enqueue operations. std::vector threads(nthreads); + for (int tid = 0; tid != nthreads; ++tid) { threads[tid] = SimpleThread([&](int id) { if (useTokens) { typename TQueue::producer_token_t tok(q); for (counter_t i = 0; i != maxOps; ++i) { - q.enqueue(tok, i); + q.enqueue(tok, item); } } else { for (counter_t i = 0; i != maxOps; ++i) { - q.enqueue(i); + q.enqueue(item); } } }, tid); @@ -517,8 +535,8 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un } // Now empty the queue - int item; - while (q.try_dequeue(item)) + + while (q.try_dequeue(item_rec)) continue; } @@ -528,12 +546,12 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un if (useTokens) { typename TQueue::producer_token_t tok(q); for (counter_t i = 0; i != maxOps; ++i) { - q.enqueue(tok, i); + q.enqueue(tok, item); } } else { for (counter_t i = 0; i != maxOps; ++i) { - q.enqueue(i); + q.enqueue(item); } } result = getTimeDelta(start); @@ -552,12 +570,12 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un if (useTokens) { typename TQueue::producer_token_t tok(q); for (counter_t i = 0; i != maxOps; ++i) { - q.enqueue(tok, i); + q.enqueue(tok, item); } } else { for (counter_t i = 0; i != maxOps; ++i) { - q.enqueue(i); + q.enqueue(item); } } timings[id] = getTimeDelta(start); @@ -569,8 +587,7 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un result += timings[tid]; } } - int item; - forceNoOptimizeDummy = q.try_dequeue(item) ? 1 : 0; + forceNoOptimizeDummy = q.try_dequeue(item_rec) ? 1 : 0; break; } @@ -578,18 +595,20 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un out_opCount = maxOps * nthreads; TQueue q; + item_t item = 1; + item_t item_rec; if (nthreads == 1) { // No contention -- measures raw single-item enqueue speed auto start = getSystemTime(); if (useTokens) { typename TQueue::producer_token_t tok(q); for (counter_t i = 0; i != maxOps; ++i) { - q.enqueue(tok, i); + q.enqueue(tok, item); } } else { for (counter_t i = 0; i != maxOps; ++i) { - q.enqueue(i); + q.enqueue(item); } } result = getTimeDelta(start); @@ -608,12 +627,12 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un if (useTokens) { typename TQueue::producer_token_t tok(q); for (counter_t i = 0; i != maxOps; ++i) { - q.enqueue(tok, i); + q.enqueue(tok, item); } } else { for (counter_t i = 0; i != maxOps; ++i) { - q.enqueue(i); + q.enqueue(item); } } timings[id] = getTimeDelta(start); @@ -625,8 +644,7 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un result += timings[tid]; } } - int item; - forceNoOptimizeDummy = q.try_dequeue(item) ? 1 : 0; + forceNoOptimizeDummy = q.try_dequeue(item_rec) ? 1 : 0; break; } @@ -635,6 +653,8 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un out_opCount = maxOps * nthreads; TQueue q; + item_t item = 1; + item_t item_rec; { // Fill up the queue first std::vector threads(benchmark == bench_spmc_preproduced ? 1 : nthreads); @@ -644,12 +664,12 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un if (useTokens) { typename TQueue::producer_token_t tok(q); for (counter_t i = 0; i != itemsPerThread; ++i) { - q.enqueue(tok, i); + q.enqueue(tok, item); } } else { for (counter_t i = 0; i != itemsPerThread; ++i) { - q.enqueue(i); + q.enqueue(item); } } }, tid); @@ -661,17 +681,16 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un if (nthreads == 1) { // No contention -- measures raw single-item dequeue speed - int item; auto start = getSystemTime(); if (useTokens) { typename TQueue::consumer_token_t tok(q); for (counter_t i = 0; i != maxOps; ++i) { - q.try_dequeue(tok, item); + q.try_dequeue(tok, item_rec); } } else { for (counter_t i = 0; i != maxOps; ++i) { - q.try_dequeue(item); + q.try_dequeue(item_rec); } } result = getTimeDelta(start); @@ -686,17 +705,16 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un while (ready.load(std::memory_order_relaxed) != nthreads) continue; - int item; auto start = getSystemTime(); if (useTokens) { typename TQueue::consumer_token_t tok(q); for (counter_t i = 0; i != maxOps; ++i) { - q.try_dequeue(tok, item); + q.try_dequeue(tok, item_rec); } } else { for (counter_t i = 0; i != maxOps; ++i) { - q.try_dequeue(item); + q.try_dequeue(item_rec); } } timings[id] = getTimeDelta(start); @@ -708,14 +726,15 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un result += timings[tid]; } } - int item; - forceNoOptimizeDummy = q.try_dequeue(item) ? 1 : 0; + forceNoOptimizeDummy = q.try_dequeue(item_rec) ? 1 : 0; break; } case bench_mostly_enqueue: { // Measures the average operation speed when most threads are enqueueing TQueue q; + item_t item = 1; + item_t item_rec; out_opCount = maxOps * nthreads; std::vector threads(nthreads); std::vector timings(nthreads); @@ -731,12 +750,12 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un if (useTokens) { typename TQueue::producer_token_t tok(q); for (counter_t i = 0; i != maxOps; ++i) { - q.enqueue(tok, i); + q.enqueue(tok, item); } } else { for (counter_t i = 0; i != maxOps; ++i) { - q.enqueue(i); + q.enqueue(item); } } timings[id] = getTimeDelta(start); @@ -748,17 +767,16 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un while (ready.load(std::memory_order_relaxed) != nthreads) continue; - int item; auto start = getSystemTime(); if (useTokens) { typename TQueue::consumer_token_t tok(q); for (counter_t i = 0; i != maxOps; ++i) { - q.try_dequeue(tok, item); + q.try_dequeue(tok, item_rec); } } else { for (counter_t i = 0; i != maxOps; ++i) { - q.try_dequeue(item); + q.try_dequeue(item_rec); } } timings[id] = getTimeDelta(start); @@ -769,14 +787,15 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un threads[tid].join(); result += timings[tid]; } - int item; - forceNoOptimizeDummy = q.try_dequeue(item) ? 1 : 0; + forceNoOptimizeDummy = q.try_dequeue(item_rec) ? 1 : 0; break; } case bench_mostly_dequeue: { // Measures the average operation speed when most threads are dequeueing TQueue q; + item_t item = 1; + item_t item_rec; out_opCount = maxOps * nthreads; std::vector threads(nthreads); std::vector timings(nthreads); @@ -789,12 +808,12 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un if (useTokens) { typename TQueue::producer_token_t tok(q); for (counter_t i = 0; i != maxOps; ++i) { - q.enqueue(tok, i); + q.enqueue(tok, item); } } else { for (counter_t i = 0; i != maxOps; ++i) { - q.enqueue(i); + q.enqueue(item); } } }, tid); @@ -810,17 +829,16 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un while (ready.load(std::memory_order_relaxed) != nthreads) continue; - int item; auto start = getSystemTime(); if (useTokens) { typename TQueue::consumer_token_t tok(q); for (counter_t i = 0; i != maxOps; ++i) { - q.try_dequeue(tok, item); + q.try_dequeue(tok, item_rec); } } else { for (counter_t i = 0; i != maxOps; ++i) { - q.try_dequeue(item); + q.try_dequeue(item_rec); } } timings[id] = getTimeDelta(start); @@ -836,12 +854,12 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un if (useTokens) { typename TQueue::producer_token_t tok(q); for (counter_t i = 0; i != maxOps; ++i) { - q.enqueue(tok, i); + q.enqueue(tok, item); } } else { for (counter_t i = 0; i != maxOps; ++i) { - q.enqueue(i); + q.enqueue(item); } } timings[id] = getTimeDelta(start); @@ -852,13 +870,14 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un threads[tid].join(); result += timings[tid]; } - int item; - forceNoOptimizeDummy = q.try_dequeue(item) ? 1 : 0; + forceNoOptimizeDummy = q.try_dequeue(item_rec) ? 1 : 0; break; } case bench_only_enqueue_bulk_prealloc: { TQueue q; + item_t item = 1; + item_t item_rec; { // Enqueue opcount elements first, then dequeue them; this // will "stretch out" the queue, letting implementatations @@ -870,12 +889,12 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un if (useTokens) { typename TQueue::producer_token_t tok(q); for (counter_t i = 0; i != maxOps; ++i) { - q.enqueue(tok, i); + q.enqueue(tok, item); } } else { for (counter_t i = 0; i != maxOps; ++i) { - q.enqueue(i); + q.enqueue(item); } } }, tid); @@ -885,8 +904,7 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un } // Now empty the queue - int item; - while (q.try_dequeue(item)) + while (q.try_dequeue(item_rec)) continue; } @@ -942,13 +960,14 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un result += timings[tid]; } } - int item; - forceNoOptimizeDummy = q.try_dequeue(item) ? 1 : 0; + forceNoOptimizeDummy = q.try_dequeue(item_rec) ? 1 : 0; break; } case bench_only_enqueue_bulk: { TQueue q; + item_t item = 1; + item_t item_rec; std::vector data; for (counter_t i = 0; i != BULK_BATCH_SIZE; ++i) { data.push_back(i); @@ -1001,14 +1020,15 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un result += timings[tid]; } } - int item; - forceNoOptimizeDummy = q.try_dequeue(item) ? 1 : 0; + forceNoOptimizeDummy = q.try_dequeue(item_rec) ? 1 : 0; break; } case bench_mostly_enqueue_bulk: { // Measures the average speed of enqueueing in bulk under light contention TQueue q; + item_t item = 1; + item_t item_rec; std::vector data; for (counter_t i = 0; i != BULK_BATCH_SIZE; ++i) { data.push_back(i); @@ -1076,14 +1096,15 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un out_opCount += ops[tid]; } } - int item; - forceNoOptimizeDummy = q.try_dequeue(item) ? 1 : 0; + forceNoOptimizeDummy = q.try_dequeue(item_rec) ? 1 : 0; break; } case bench_only_dequeue_bulk: { // Measures the average speed of dequeueing in bulk when all threads are consumers TQueue q; + item_t item = 1; + item_t item_rec; { // Fill up the queue first std::vector data(BULK_BATCH_SIZE); @@ -1166,14 +1187,15 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un out_opCount += ops[tid]; } } - int item; - forceNoOptimizeDummy = q.try_dequeue(item) ? 1 : 0; + forceNoOptimizeDummy = q.try_dequeue(item_rec) ? 1 : 0; break; } case bench_mostly_dequeue_bulk: { // Measures the average speed of dequeueing in bulk under light contention TQueue q; + item_t item = 1; + item_t item_rec; auto enqueueThreads = std::max(1, nthreads / 4); out_opCount = maxOps * BULK_BATCH_SIZE * enqueueThreads; std::vector threads(nthreads); @@ -1260,8 +1282,7 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un out_opCount += ops[tid]; } } - int item; - forceNoOptimizeDummy = q.try_dequeue(item) ? 1 : 0; + forceNoOptimizeDummy = q.try_dequeue(item_rec) ? 1 : 0; break; } @@ -1269,6 +1290,8 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un counter_t elementsToDequeue = maxOps * (nthreads - 1); TQueue q; + item_t item = 1; + item_t item_rec; std::vector threads(nthreads - 1); std::vector timings(nthreads - 1); std::vector ops(nthreads - 1); @@ -1297,7 +1320,7 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un } else { while (true) { - if (q.try_dequeue(item)) { + if (q.try_dequeue(item_rec)) { totalDequeued.fetch_add(1, std::memory_order_relaxed); } else if (totalDequeued.load(std::memory_order_relaxed) == elementsToDequeue) { @@ -1313,7 +1336,7 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un lynchpin.store(true, std::memory_order_seq_cst); for (counter_t i = 0; i != elementsToDequeue; ++i) { - q.enqueue(i); + q.enqueue(item); } result = 0; @@ -1323,13 +1346,14 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un result += timings[tid]; out_opCount += ops[tid]; } - int item; - forceNoOptimizeDummy = q.try_dequeue(item) ? 1 : 0; + forceNoOptimizeDummy = q.try_dequeue(item_rec) ? 1 : 0; break; } case bench_mpsc: { TQueue q; + item_t item = 1; + item_t item_rec; counter_t elementsToDequeue = maxOps * (nthreads - 1); std::vector threads(nthreads); std::atomic ready(0); @@ -1353,7 +1377,7 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un } else { for (counter_t i = 0; i != elementsToDequeue;) { - i += q.try_dequeue(item) ? 1 : 0; + i += q.try_dequeue(item_rec) ? 1 : 0; ++out_opCount; } } @@ -1369,12 +1393,12 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un if (useTokens) { typename TQueue::producer_token_t tok(q); for (counter_t i = 0; i != maxOps; ++i) { - q.enqueue(tok, i); + q.enqueue(tok, item); } } else { for (counter_t i = 0; i != maxOps; ++i) { - q.enqueue(i); + q.enqueue(item); } } }, tid); @@ -1384,14 +1408,15 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un for (int tid = 0; tid != nthreads; ++tid) { threads[tid].join(); } - int item; - forceNoOptimizeDummy = q.try_dequeue(item) ? 1 : 0; + forceNoOptimizeDummy = q.try_dequeue(item_rec) ? 1 : 0; break; } case bench_empty_dequeue: { // Measures the average speed of attempting to dequeue from an empty queue TQueue q; + item_t item = 1; + item_t item_rec; // Fill up then empty the queue first { std::vector threads(maxThreads > 0 ? maxThreads : 8); @@ -1400,12 +1425,12 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un if (useTokens) { typename TQueue::producer_token_t tok(q); for (counter_t i = 0; i != 10000; ++i) { - q.enqueue(tok, i); + q.enqueue(tok, item); } } else { for (counter_t i = 0; i != 10000; ++i) { - q.enqueue(i); + q.enqueue(item); } } }, tid); @@ -1415,8 +1440,7 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un } // Empty the queue - int item; - while (q.try_dequeue(item)) + while (q.try_dequeue(item_rec)) continue; } @@ -1433,11 +1457,11 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un } else { for (counter_t i = 0; i != maxOps; ++i) { - q.try_dequeue(item); + q.try_dequeue(item_rec); } } result = getTimeDelta(start); - forceNoOptimizeDummy = q.try_dequeue(item) ? 1 : 0; + forceNoOptimizeDummy = q.try_dequeue(item_rec) ? 1 : 0; } else { out_opCount = maxOps * nthreads; @@ -1460,7 +1484,7 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un } else { for (counter_t i = 0; i != maxOps; ++i) { - q.try_dequeue(item); + q.try_dequeue(item_rec); } } timings[id] = getTimeDelta(start); @@ -1471,8 +1495,7 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un threads[tid].join(); result += timings[tid]; } - int item; - forceNoOptimizeDummy = q.try_dequeue(item) ? 1 : 0; + forceNoOptimizeDummy = q.try_dequeue(item_rec) ? 1 : 0; } break; } @@ -1482,26 +1505,28 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un // (that eight separate threads had at one point enqueued to) out_opCount = maxOps * 2 * nthreads; TQueue q; + item_t item = 1; + item_t item_rec; if (nthreads == 1) { // No contention -- measures speed of immediately dequeueing the item that was just enqueued int item; auto start = getSystemTime(); if (useTokens) { - typename TQueue::producer_token_t ptok(q); - typename TQueue::consumer_token_t ctok(q); + typename TQueue::producer_token_t prodTok(q); + typename TQueue::consumer_token_t consTok(q); for (counter_t i = 0; i != maxOps; ++i) { - q.enqueue(ptok, i); - q.try_dequeue(ctok, item); + q.enqueue(prodTok, item); + q.try_dequeue(consTok, item); } } else { for (counter_t i = 0; i != maxOps; ++i) { - q.enqueue(i); - q.try_dequeue(item); + q.enqueue(item); + q.try_dequeue(item_rec); } } result = getTimeDelta(start); - forceNoOptimizeDummy = q.try_dequeue(item) ? 1 : 0; + forceNoOptimizeDummy = q.try_dequeue(item_rec) ? 1 : 0; } else { std::vector threads(nthreads); @@ -1516,17 +1541,17 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un int item; auto start = getSystemTime(); if (useTokens) { - typename TQueue::producer_token_t ptok(q); - typename TQueue::consumer_token_t ctok(q); + typename TQueue::producer_token_t prodTok(q); + typename TQueue::consumer_token_t consTok(q); for (counter_t i = 0; i != maxOps; ++i) { - q.enqueue(ptok, i); - q.try_dequeue(ctok, item); + q.enqueue(prodTok, item); + q.try_dequeue(consTok, item); } } else { for (counter_t i = 0; i != maxOps; ++i) { - q.enqueue(i); - q.try_dequeue(item); + q.enqueue(item); + q.try_dequeue(item_rec); } } timings[id] = getTimeDelta(start); @@ -1537,8 +1562,7 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un threads[tid].join(); result += timings[tid]; } - int item; - forceNoOptimizeDummy = q.try_dequeue(item) ? 1 : 0; + forceNoOptimizeDummy = q.try_dequeue(item_rec) ? 1 : 0; } break; } @@ -1547,6 +1571,8 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un // Measures the average operation speed with many threads under heavy load out_opCount = maxOps * nthreads; TQueue q; + item_t item = 1; + item_t item_rec; std::vector threads(nthreads); std::vector timings(nthreads); std::atomic ready(0); @@ -1566,13 +1592,13 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un for (counter_t i = 0; i != maxOps / 2; ++i) { q.try_dequeue(consTok, item); - q.enqueue(prodTok, i); + q.enqueue(prodTok, item); } } else { for (counter_t i = 0; i != maxOps / 2; ++i) { - q.try_dequeue(item); - q.enqueue(i); + q.try_dequeue(item_rec); + q.enqueue(item); } } } @@ -1582,12 +1608,12 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un if (useTokens) { typename TQueue::producer_token_t prodTok(q); for (counter_t i = 0; i != maxOps; ++i) { - q.enqueue(prodTok, i); + q.enqueue(prodTok, item); } } else { for (counter_t i = 0; i != maxOps; ++i) { - q.enqueue(i); + q.enqueue(item); } } } @@ -1602,7 +1628,7 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un } else { for (counter_t i = 0; i != maxOps; ++i) { - q.try_dequeue(item); + q.try_dequeue(item_rec); } } } @@ -1615,8 +1641,7 @@ double runBenchmark(benchmark_type_t benchmark, int nthreads, bool useTokens, un threads[tid].join(); result += timings[tid]; } - int item; - forceNoOptimizeDummy = q.try_dequeue(item) ? 1 : 0; + forceNoOptimizeDummy = q.try_dequeue(item_rec) ? 1 : 0; break; } @@ -1964,25 +1989,28 @@ int main(int argc, char** argv) counter_t maxOps; switch ((queue_id_t)queue) { case queue_moodycamel_ConcurrentQueue: - maxOps = determineMaxOpsForBenchmark>((benchmark_type_t)benchmark, nthreads, (bool)useTokens, seed); + maxOps = determineMaxOpsForBenchmark, int>((benchmark_type_t)benchmark, nthreads, (bool)useTokens, seed); break; case queue_moodycamel_BlockingConcurrentQueue: - maxOps = determineMaxOpsForBenchmark>((benchmark_type_t)benchmark, nthreads, (bool)useTokens, seed); + maxOps = determineMaxOpsForBenchmark, int>((benchmark_type_t)benchmark, nthreads, (bool)useTokens, seed); break; case queue_lockbased: - maxOps = determineMaxOpsForBenchmark>((benchmark_type_t)benchmark, nthreads, (bool)useTokens, seed); + maxOps = determineMaxOpsForBenchmark, int>((benchmark_type_t)benchmark, nthreads, (bool)useTokens, seed); break; case queue_simplelockfree: - maxOps = determineMaxOpsForBenchmark>((benchmark_type_t)benchmark, nthreads, (bool)useTokens, seed); + maxOps = determineMaxOpsForBenchmark, int>((benchmark_type_t)benchmark, nthreads, (bool)useTokens, seed); break; case queue_boost: - maxOps = determineMaxOpsForBenchmark>((benchmark_type_t)benchmark, nthreads, (bool)useTokens, seed); + maxOps = determineMaxOpsForBenchmark, int>((benchmark_type_t)benchmark, nthreads, (bool)useTokens, seed); break; case queue_tbb: - maxOps = determineMaxOpsForBenchmark>((benchmark_type_t)benchmark, nthreads, (bool)useTokens, seed); + maxOps = determineMaxOpsForBenchmark, int>((benchmark_type_t)benchmark, nthreads, (bool)useTokens, seed); break; case queue_std: - maxOps = determineMaxOpsForBenchmark>((benchmark_type_t)benchmark, nthreads, (bool)useTokens, seed); + maxOps = determineMaxOpsForBenchmark, int>((benchmark_type_t)benchmark, nthreads, (bool)useTokens, seed); + break; + case queue_dlib: + maxOps = determineMaxOpsForBenchmark, int>((benchmark_type_t)benchmark, nthreads, (bool)useTokens, seed); break; default: assert(false && "There should be a case here for every queue in the benchmarks!"); @@ -1997,25 +2025,28 @@ int main(int argc, char** argv) switch ((queue_id_t)queue) { case queue_moodycamel_ConcurrentQueue: - elapsed = runBenchmark>((benchmark_type_t)benchmark, nthreads, (bool)useTokens, seed, maxOps, maxThreads, ops); + elapsed = runBenchmark, int>((benchmark_type_t)benchmark, nthreads, (bool)useTokens, seed, maxOps, maxThreads, ops); break; case queue_moodycamel_BlockingConcurrentQueue: - elapsed = runBenchmark>((benchmark_type_t)benchmark, nthreads, (bool)useTokens, seed, maxOps, maxThreads, ops); + elapsed = runBenchmark, int>((benchmark_type_t)benchmark, nthreads, (bool)useTokens, seed, maxOps, maxThreads, ops); break; case queue_lockbased: - elapsed = runBenchmark>((benchmark_type_t)benchmark, nthreads, (bool)useTokens, seed, maxOps, maxThreads, ops); + elapsed = runBenchmark, int>((benchmark_type_t)benchmark, nthreads, (bool)useTokens, seed, maxOps, maxThreads, ops); break; case queue_simplelockfree: - elapsed = runBenchmark>((benchmark_type_t)benchmark, nthreads, (bool)useTokens, seed, maxOps, maxThreads, ops); + elapsed = runBenchmark, int>((benchmark_type_t)benchmark, nthreads, (bool)useTokens, seed, maxOps, maxThreads, ops); break; case queue_boost: - elapsed = runBenchmark>((benchmark_type_t)benchmark, nthreads, (bool)useTokens, seed, maxOps, maxThreads, ops); + elapsed = runBenchmark, int>((benchmark_type_t)benchmark, nthreads, (bool)useTokens, seed, maxOps, maxThreads, ops); break; case queue_tbb: - elapsed = runBenchmark>((benchmark_type_t)benchmark, nthreads, (bool)useTokens, seed, maxOps, maxThreads, ops); + elapsed = runBenchmark, int>((benchmark_type_t)benchmark, nthreads, (bool)useTokens, seed, maxOps, maxThreads, ops); break; case queue_std: - elapsed = runBenchmark>((benchmark_type_t)benchmark, nthreads, (bool)useTokens, seed, maxOps, maxThreads, ops); + elapsed = runBenchmark, int>((benchmark_type_t)benchmark, nthreads, (bool)useTokens, seed, maxOps, maxThreads, ops); + break; + case queue_dlib: + elapsed = runBenchmark, int>((benchmark_type_t)benchmark, nthreads, (bool)useTokens, seed, maxOps, maxThreads, ops); break; default: assert(false && "There should be a case here for every queue in the benchmarks!"); diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/algs.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/algs.h new file mode 100644 index 0000000..f387fc3 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/algs.h @@ -0,0 +1,1158 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. + +#ifdef DLIB_ALL_SOURCE_END +#include "dlib_basic_cpp_build_tutorial.txt" +#endif + +#ifndef DLIB_ALGs_ +#define DLIB_ALGs_ + +// this file contains miscellaneous stuff + +// Give people who forget the -std=c++11 option a reminder +#if (defined(__GNUC__) && ((__GNUC__ >= 4 && __GNUC_MINOR__ >= 8) || (__GNUC__ > 4))) || \ + (defined(__clang__) && ((__clang_major__ >= 3 && __clang_minor__ >= 4) || (__clang_major__ >= 3))) + #if __cplusplus < 201103 + #error "Dlib requires C++11 support. Give your compiler the -std=c++11 option to enable it." + #endif +#endif + +#if defined __NVCC__ + // Disable the "statement is unreachable" message since it will go off on code that is + // actually reachable but just happens to not be reachable sometimes during certain + // template instantiations. + #pragma diag_suppress code_is_unreachable +#endif + + +#ifdef _MSC_VER + +#if _MSC_VER < 1900 +#error "dlib versions newer than v19.1 use C++11 and therefore require Visual Studio 2015 or newer." +#endif + +// Disable the following warnings for Visual Studio + +// this is to disable the "'this' : used in base member initializer list" +// warning you get from some of the GUI objects since all the objects +// require that their parent class be passed into their constructor. +// In this case though it is totally safe so it is ok to disable this warning. +#pragma warning(disable : 4355) + +// This is a warning you get sometimes when Visual Studio performs a Koenig Lookup. +// This is a bug in visual studio. It is a totally legitimate thing to +// expect from a compiler. +#pragma warning(disable : 4675) + +// This is a warning you get from visual studio 2005 about things in the standard C++ +// library being "deprecated." I checked the C++ standard and it doesn't say jack +// about any of them (I checked the searchable PDF). So this warning is total Bunk. +#pragma warning(disable : 4996) + +// This is a warning you get from visual studio 2003: +// warning C4345: behavior change: an object of POD type constructed with an initializer +// of the form () will be default-initialized. +// I love it when this compiler gives warnings about bugs in previous versions of itself. +#pragma warning(disable : 4345) + + +// Disable warnings about conversion from size_t to unsigned long and long. +#pragma warning(disable : 4267) + +// Disable warnings about conversion from double to float +#pragma warning(disable : 4244) +#pragma warning(disable : 4305) + +// Disable "warning C4180: qualifier applied to function type has no meaning; ignored". +// This warning happens often in generic code that works with functions and isn't useful. +#pragma warning(disable : 4180) + +// Disable "warning C4290: C++ exception specification ignored except to indicate a function is not __declspec(nothrow)" +#pragma warning(disable : 4290) + + +// DNN module uses template-based network declaration that leads to very long +// type names. Visual Studio will produce Warning C4503 in such cases. https://msdn.microsoft.com/en-us/library/074af4b6.aspx says +// that correct binaries are still produced even when this warning happens, but linker errors from visual studio, if they occur could be confusing. +#pragma warning( disable: 4503 ) + + +#endif + +#ifdef __BORLANDC__ +// Disable the following warnings for the Borland Compilers +// +// These warnings just say that the compiler is refusing to inline functions with +// loops or try blocks in them. +// +#pragma option -w-8027 +#pragma option -w-8026 +#endif + +#include // for the exceptions + +#ifdef __CYGWIN__ +namespace std +{ + typedef std::basic_string wstring; +} +#endif + +#include "platform.h" +#include "windows_magic.h" + + +#include // for std::swap +#include // for std::bad_alloc +#include +#include +#include // for std::numeric_limits for is_finite() +#include "assert.h" +#include "error.h" +#include "noncopyable.h" +#include "enable_if.h" +#include "uintn.h" +#include "numeric_constants.h" +#include "memory_manager_stateless/memory_manager_stateless_kernel_1.h" // for the default memory manager + + + +// ---------------------------------------------------------------------------------------- +/*!A _dT !*/ + +template +inline charT _dTcast (const char a, const wchar_t b); +template <> +inline char _dTcast (const char a, const wchar_t ) { return a; } +template <> +inline wchar_t _dTcast (const char , const wchar_t b) { return b; } + +template +inline const charT* _dTcast ( const char* a, const wchar_t* b); +template <> +inline const char* _dTcast ( const char* a, const wchar_t* ) { return a; } +template <> +inline const wchar_t* _dTcast ( const char* , const wchar_t* b) { return b; } + + +#define _dT(charT,str) _dTcast(str,L##str) +/*! + requires + - charT == char or wchar_t + - str == a string or character literal + ensures + - returns the literal in the form of a charT type literal. +!*/ + +// ---------------------------------------------------------------------------------------- + + + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + /*!A default_memory_manager + + This memory manager just calls new and delete directly. + + !*/ + typedef memory_manager_stateless_kernel_1 default_memory_manager; + +// ---------------------------------------------------------------------------------------- + + /*!A swap !*/ + // make swap available in the dlib namespace + using std::swap; + +// ---------------------------------------------------------------------------------------- + + /*! + Here is where I define my return codes. It is + important that they all be < 0. + !*/ + + enum general_return_codes + { + TIMEOUT = -1, + WOULDBLOCK = -2, + OTHER_ERROR = -3, + SHUTDOWN = -4, + PORTINUSE = -5 + }; + +// ---------------------------------------------------------------------------------------- + + inline unsigned long square_root ( + unsigned long value + ) + /*! + requires + - value <= 2^32 - 1 + ensures + - returns the square root of value. if the square root is not an + integer then it will be rounded up to the nearest integer. + !*/ + { + unsigned long x; + + // set the initial guess for what the root is depending on + // how big value is + if (value < 3) + return value; + else if (value < 4096) // 12 + x = 45; + else if (value < 65536) // 16 + x = 179; + else if (value < 1048576) // 20 + x = 717; + else if (value < 16777216) // 24 + x = 2867; + else if (value < 268435456) // 28 + x = 11469; + else // 32 + x = 45875; + + + + // find the root + x = (x + value/x)>>1; + x = (x + value/x)>>1; + x = (x + value/x)>>1; + x = (x + value/x)>>1; + + + + if (x*x < value) + return x+1; + else + return x; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void median ( + T& one, + T& two, + T& three + ); + /*! + requires + - T implements operator< + - T is swappable by a global swap() + ensures + - #one is the median + - #one, #two, and #three is some permutation of one, two, and three. + !*/ + + + template < + typename T + > + void median ( + T& one, + T& two, + T& three + ) + { + using std::swap; + using dlib::swap; + + if ( one < two ) + { + // one < two + if ( two < three ) + { + // one < two < three : two + swap(one,two); + + } + else + { + // one < two >= three + if ( one < three) + { + // three + swap(three,one); + } + } + + } + else + { + // one >= two + if ( three < one ) + { + // three <= one >= two + if ( three < two ) + { + // two + swap(two,one); + } + else + { + // three + swap(three,one); + } + } + } + } + +// ---------------------------------------------------------------------------------------- + + namespace relational_operators + { + template < + typename A, + typename B + > + constexpr bool operator> ( + const A& a, + const B& b + ) { return b < a; } + + // --------------------------------- + + template < + typename A, + typename B + > + constexpr bool operator!= ( + const A& a, + const B& b + ) { return !(a == b); } + + // --------------------------------- + + template < + typename A, + typename B + > + constexpr bool operator<= ( + const A& a, + const B& b + ) { return !(b < a); } + + // --------------------------------- + + template < + typename A, + typename B + > + constexpr bool operator>= ( + const A& a, + const B& b + ) { return !(a < b); } + + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void exchange ( + T& a, + T& b + ) + /*! + This function does the exact same thing that global swap does and it does it by + just calling swap. But a lot of compilers have problems doing a Koenig Lookup + and the fact that this has a different name (global swap has the same name as + the member functions called swap) makes them compile right. + + So this is a workaround but not too ugly of one. But hopefully I get get + rid of this in a few years. So this function is already deprecated. + + This also means you should NOT use this function in your own code unless + you have to support an old buggy compiler that benefits from this hack. + !*/ + { + using std::swap; + using dlib::swap; + swap(a,b); + } + +// ---------------------------------------------------------------------------------------- + + /*!A is_pointer_type + + This is a template where is_pointer_type::value == true when T is a pointer + type and false otherwise. + !*/ + + template < + typename T + > + class is_pointer_type + { + public: + enum { value = false }; + private: + is_pointer_type(); + }; + + template < + typename T + > + class is_pointer_type + { + public: + enum { value = true }; + private: + is_pointer_type(); + }; + +// ---------------------------------------------------------------------------------------- + + /*!A is_const_type + + This is a template where is_const_type::value == true when T is a const + type and false otherwise. + !*/ + + template + struct is_const_type + { + static const bool value = false; + }; + template + struct is_const_type + { + static const bool value = true; + }; + template + struct is_const_type + { + static const bool value = true; + }; + +// ---------------------------------------------------------------------------------------- + + /*!A is_reference_type + + This is a template where is_reference_type::value == true when T is a reference + type and false otherwise. + !*/ + + template + struct is_reference_type + { + static const bool value = false; + }; + + template struct is_reference_type { static const bool value = true; }; + template struct is_reference_type { static const bool value = true; }; + +// ---------------------------------------------------------------------------------------- + + /*!A is_same_type + + This is a template where is_same_type::value == true when T and U are the + same type and false otherwise. + !*/ + + template < + typename T, + typename U + > + class is_same_type + { + public: + enum {value = false}; + private: + is_same_type(); + }; + + template + class is_same_type + { + public: + enum {value = true}; + private: + is_same_type(); + }; + +// ---------------------------------------------------------------------------------------- + + /*!A is_float_type + + This is a template that can be used to determine if a type is one of the built + int floating point types (i.e. float, double, or long double). + !*/ + + template < typename T > struct is_float_type { const static bool value = false; }; + template <> struct is_float_type { const static bool value = true; }; + template <> struct is_float_type { const static bool value = true; }; + template <> struct is_float_type { const static bool value = true; }; + +// ---------------------------------------------------------------------------------------- + + /*!A is_convertible + + This is a template that can be used to determine if one type is convertible + into another type. + + For example: + is_convertible::value == true // because ints are convertible to floats + is_convertible::value == false // because int pointers are NOT convertible to floats + !*/ + + template + struct is_convertible + { + struct yes_type { char a; }; + struct no_type { yes_type a[2]; }; + static const from& from_helper(); + static yes_type test(to); + static no_type test(...); + const static bool value = sizeof(test(from_helper())) == sizeof(yes_type); + }; + +// ---------------------------------------------------------------------------------------- + + struct general_ {}; + struct special_ : general_ {}; + template struct int_ { typedef int type; }; + +// ---------------------------------------------------------------------------------------- + + + /*!A is_same_object + + This is a templated function which checks if both of its arguments are actually + references to the same object. It returns true if they are and false otherwise. + + !*/ + + // handle the case where T and U are unrelated types. + template < typename T, typename U > + typename disable_if_c::value || is_convertible::value, bool>::type + is_same_object ( + const T& a, + const U& b + ) + { + return ((void*)&a == (void*)&b); + } + + // handle the case where T and U are related types because their pointers can be + // implicitly converted into one or the other. E.g. a derived class and its base class. + // Or where both T and U are just the same type. This way we make sure that if there is a + // valid way to convert between these two pointer types then we will take that route rather + // than the void* approach used otherwise. + template < typename T, typename U > + typename enable_if_c::value || is_convertible::value, bool>::type + is_same_object ( + const T& a, + const U& b + ) + { + return (&a == &b); + } + +// ---------------------------------------------------------------------------------------- + + /*!A is_unsigned_type + + This is a template where is_unsigned_type::value == true when T is an unsigned + scalar type and false when T is a signed scalar type. + !*/ + template < + typename T + > + struct is_unsigned_type + { + static const bool value = static_cast((static_cast(0)-static_cast(1))) > 0; + }; + template <> struct is_unsigned_type { static const bool value = false; }; + template <> struct is_unsigned_type { static const bool value = false; }; + template <> struct is_unsigned_type { static const bool value = false; }; + +// ---------------------------------------------------------------------------------------- + + /*!A is_signed_type + + This is a template where is_signed_type::value == true when T is a signed + scalar type and false when T is an unsigned scalar type. + !*/ + template < + typename T + > + struct is_signed_type + { + static const bool value = !is_unsigned_type::value; + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + class copy_functor + { + public: + void operator() ( + const T& source, + T& destination + ) const + { + destination = source; + } + }; + +// ---------------------------------------------------------------------------------------- + + /*!A static_switch + + To use this template you give it some number of boolean expressions and it + tells you which one of them is true. If more than one of them is true then + it causes a compile time error. + + for example: + static_switch<1 + 1 == 2, 4 - 1 == 4>::value == 1 // because the first expression is true + static_switch<1 + 1 == 3, 4 == 4>::value == 2 // because the second expression is true + static_switch<1 + 1 == 3, 4 == 5>::value == 0 // 0 here because none of them are true + static_switch<1 + 1 == 2, 4 == 4>::value == compiler error // because more than one expression is true + !*/ + + template < bool v1 = 0, bool v2 = 0, bool v3 = 0, bool v4 = 0, bool v5 = 0, + bool v6 = 0, bool v7 = 0, bool v8 = 0, bool v9 = 0, bool v10 = 0, + bool v11 = 0, bool v12 = 0, bool v13 = 0, bool v14 = 0, bool v15 = 0 > + struct static_switch; + + template <> struct static_switch<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0> { const static int value = 0; }; + template <> struct static_switch<1,0,0,0,0,0,0,0,0,0,0,0,0,0,0> { const static int value = 1; }; + template <> struct static_switch<0,1,0,0,0,0,0,0,0,0,0,0,0,0,0> { const static int value = 2; }; + template <> struct static_switch<0,0,1,0,0,0,0,0,0,0,0,0,0,0,0> { const static int value = 3; }; + template <> struct static_switch<0,0,0,1,0,0,0,0,0,0,0,0,0,0,0> { const static int value = 4; }; + template <> struct static_switch<0,0,0,0,1,0,0,0,0,0,0,0,0,0,0> { const static int value = 5; }; + template <> struct static_switch<0,0,0,0,0,1,0,0,0,0,0,0,0,0,0> { const static int value = 6; }; + template <> struct static_switch<0,0,0,0,0,0,1,0,0,0,0,0,0,0,0> { const static int value = 7; }; + template <> struct static_switch<0,0,0,0,0,0,0,1,0,0,0,0,0,0,0> { const static int value = 8; }; + template <> struct static_switch<0,0,0,0,0,0,0,0,1,0,0,0,0,0,0> { const static int value = 9; }; + template <> struct static_switch<0,0,0,0,0,0,0,0,0,1,0,0,0,0,0> { const static int value = 10; }; + template <> struct static_switch<0,0,0,0,0,0,0,0,0,0,1,0,0,0,0> { const static int value = 11; }; + template <> struct static_switch<0,0,0,0,0,0,0,0,0,0,0,1,0,0,0> { const static int value = 12; }; + template <> struct static_switch<0,0,0,0,0,0,0,0,0,0,0,0,1,0,0> { const static int value = 13; }; + template <> struct static_switch<0,0,0,0,0,0,0,0,0,0,0,0,0,1,0> { const static int value = 14; }; + template <> struct static_switch<0,0,0,0,0,0,0,0,0,0,0,0,0,0,1> { const static int value = 15; }; + +// ---------------------------------------------------------------------------------------- + /*!A is_built_in_scalar_type + + This is a template that allows you to determine if the given type is a built + in scalar type such as an int, char, float, short, etc. + + For example, is_built_in_scalar_type::value == true + For example, is_built_in_scalar_type::value == false + !*/ + + template struct is_built_in_scalar_type { const static bool value = false; }; + + template <> struct is_built_in_scalar_type { const static bool value = true; }; + template <> struct is_built_in_scalar_type { const static bool value = true; }; + template <> struct is_built_in_scalar_type { const static bool value = true; }; + template <> struct is_built_in_scalar_type { const static bool value = true; }; + template <> struct is_built_in_scalar_type { const static bool value = true; }; + template <> struct is_built_in_scalar_type { const static bool value = true; }; + template <> struct is_built_in_scalar_type { const static bool value = true; }; + template <> struct is_built_in_scalar_type { const static bool value = true; }; + template <> struct is_built_in_scalar_type { const static bool value = true; }; + template <> struct is_built_in_scalar_type { const static bool value = true; }; + template <> struct is_built_in_scalar_type { const static bool value = true; }; + template <> struct is_built_in_scalar_type { const static bool value = true; }; + template <> struct is_built_in_scalar_type { const static bool value = true; }; + template <> struct is_built_in_scalar_type { const static bool value = true; }; + // Don't define one for wchar_t when using a version of visual studio + // older than 8.0 (visual studio 2005) since before then they improperly set + // wchar_t to be a typedef rather than its own type as required by the C++ + // standard. +#if !defined(_MSC_VER) || _NATIVE_WCHAR_T_DEFINED + template <> struct is_built_in_scalar_type { const static bool value = true; }; +#endif + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + typename enable_if,bool>::type is_finite ( + const T& value + ) + /*! + requires + - value must be some kind of scalar type such as int or double + ensures + - returns true if value is a finite value (e.g. not infinity or NaN) and false + otherwise. + !*/ + { + if (is_float_type::value) + return -std::numeric_limits::infinity() < value && value < std::numeric_limits::infinity(); + else + return true; + } + +// ---------------------------------------------------------------------------------------- + + /*!A promote + + This is a template that takes one of the built in scalar types and gives you another + scalar type that should be big enough to hold sums of values from the original scalar + type. The new scalar type will also always be signed. + + For example, promote::type == int32 + !*/ + + template struct promote; + template struct promote { typedef int32 type; }; + template struct promote { typedef int32 type; }; + template struct promote { typedef int64 type; }; + template struct promote { typedef int64 type; }; + + template <> struct promote { typedef double type; }; + template <> struct promote { typedef double type; }; + template <> struct promote { typedef long double type; }; + +// ---------------------------------------------------------------------------------------- + + /*!A assign_zero_if_built_in_scalar_type + + This function assigns its argument the value of 0 if it is a built in scalar + type according to the is_built_in_scalar_type<> template. If it isn't a + built in scalar type then it does nothing. + !*/ + + template inline typename disable_if,void>::type assign_zero_if_built_in_scalar_type (T&){} + template inline typename enable_if,void>::type assign_zero_if_built_in_scalar_type (T& a){a=0;} + +// ---------------------------------------------------------------------------------------- + + /*!A basic_type + + This is a template that takes a type and strips off any const, volatile, or reference + qualifiers and gives you back the basic underlying type. So for example: + + basic_type::type == int + !*/ + + template struct basic_type { typedef T type; }; + template struct basic_type { typedef T type; }; + template struct basic_type { typedef T type; }; + template struct basic_type { typedef T type; }; + template struct basic_type { typedef T type; }; + template struct basic_type { typedef T type; }; + template struct basic_type { typedef T type; }; + template struct basic_type { typedef T type; }; + +// ---------------------------------------------------------------------------------------- + + template + T put_in_range ( + const T& a, + const T& b, + const T& val + ) + /*! + requires + - T is a type that looks like double, float, int, or so forth + ensures + - if (val is within the range [a,b]) then + - returns val + - else + - returns the end of the range [a,b] that is closest to val + !*/ + { + if (a < b) + { + if (val < a) + return a; + else if (val > b) + return b; + } + else + { + if (val < b) + return b; + else if (val > a) + return a; + } + + return val; + } + + // overload for double + inline double put_in_range(const double& a, const double& b, const double& val) + { return put_in_range(a,b,val); } + +// ---------------------------------------------------------------------------------------- + + /*!A tabs + + This is a template to compute the absolute value a number at compile time. + + For example, + abs<-4>::value == 4 + abs<4>::value == 4 + !*/ + + template + struct tabs { const static long value = x; }; + template + struct tabs::type> { const static long value = -x; }; + +// ---------------------------------------------------------------------------------------- + + /*!A tmax + + This is a template to compute the max of two values at compile time + + For example, + abs<4,7>::value == 7 + !*/ + + template + struct tmax { const static long value = x; }; + template + struct tmax x)>::type> { const static long value = y; }; + +// ---------------------------------------------------------------------------------------- + + /*!A tmin + + This is a template to compute the min of two values at compile time + + For example, + abs<4,7>::value == 4 + !*/ + + template + struct tmin { const static long value = x; }; + template + struct tmin::type> { const static long value = y; }; + +// ---------------------------------------------------------------------------------------- + +#define DLIB_MAKE_HAS_MEMBER_FUNCTION_TEST(testname, returnT, funct_name, args) \ + struct _two_bytes_##testname { char a[2]; }; \ + template < typename T, returnT (T::*funct)args > \ + struct _helper_##testname { typedef char type; }; \ + template \ + static char _has_##testname##_helper( typename _helper_##testname::type ) { return 0;} \ + template \ + static _two_bytes_##testname _has_##testname##_helper(int) { return _two_bytes_##testname();} \ + template struct _##testname##workaroundbug { \ + const static unsigned long U = sizeof(_has_##testname##_helper('a')); }; \ + template ::U > \ + struct testname { static const bool value = false; }; \ + template \ + struct testname { static const bool value = true; }; + /*!A DLIB_MAKE_HAS_MEMBER_FUNCTION_TEST + + The DLIB_MAKE_HAS_MEMBER_FUNCTION_TEST() macro is used to define traits templates + that tell you if a class has a certain member function. For example, to make a + test to see if a class has a public method with the signature void print(int) you + would say: + DLIB_MAKE_HAS_MEMBER_FUNCTION_TEST(has_print, void, print, (int)) + + Then you can check if a class, T, has this method by looking at the boolean value: + has_print::value + which will be true if the member function is in the T class. + + Note that you can test for member functions taking no arguments by simply passing + in empty () like so: + DLIB_MAKE_HAS_MEMBER_FUNCTION_TEST(has_print, void, print, ()) + This would test for a member of the form: + void print(). + + To test for const member functions you would use a statement such as this: + DLIB_MAKE_HAS_MEMBER_FUNCTION_TEST(has_print, void, print, ()const) + This would test for a member of the form: + void print() const. + + To test for const templated member functions you would use a statement such as this: + DLIB_MAKE_HAS_MEMBER_FUNCTION_TEST(has_print, void, template print, ()) + This would test for a member of the form: + template void print(). + !*/ + +// ---------------------------------------------------------------------------------------- + + /*!A is_function + + This is a template that allows you to determine if the given type is a function. + + For example, + void funct(); + + is_built_in_scalar_type::value == true + is_built_in_scalar_type::value == false + !*/ + + template struct is_function { static const bool value = false; }; + template + struct is_function { static const bool value = true; }; + template + struct is_function { static const bool value = true; }; + template + struct is_function { static const bool value = true; }; + template + struct is_function { static const bool value = true; }; + template + struct is_function { static const bool value = true; }; + template + struct is_function { static const bool value = true; }; + template + struct is_function { static const bool value = true; }; + template + struct is_function { static const bool value = true; }; + template + struct is_function { static const bool value = true; }; + template + struct is_function { static const bool value = true; }; + template + struct is_function { static const bool value = true; }; + + + template class funct_wrap0 + { + public: + funct_wrap0(T (&f_)()):f(f_){} + T operator()() const { return f(); } + private: + T (&f)(); + }; + template class funct_wrap1 + { + public: + funct_wrap1(T (&f_)(A0)):f(f_){} + T operator()(A0 a0) const { return f(a0); } + private: + T (&f)(A0); + }; + template class funct_wrap2 + { + public: + funct_wrap2(T (&f_)(A0,A1)):f(f_){} + T operator()(A0 a0, A1 a1) const { return f(a0,a1); } + private: + T (&f)(A0,A1); + }; + template class funct_wrap3 + { + public: + funct_wrap3(T (&f_)(A0,A1,A2)):f(f_){} + T operator()(A0 a0, A1 a1, A2 a2) const { return f(a0,a1,a2); } + private: + T (&f)(A0,A1,A2); + }; + template class funct_wrap4 + { + public: + funct_wrap4(T (&f_)(A0,A1,A2,A3)):f(f_){} + T operator()(A0 a0, A1 a1, A2 a2, A3 a3) const { return f(a0,a1,a2,a3); } + private: + T (&f)(A0,A1,A2,A3); + }; + template class funct_wrap5 + { + public: + funct_wrap5(T (&f_)(A0,A1,A2,A3,A4)):f(f_){} + T operator()(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) const { return f(a0,a1,a2,a3,a4); } + private: + T (&f)(A0,A1,A2,A3,A4); + }; + + /*!A wrap_function + + This is a template that allows you to turn a global function into a + function object. The reason for this template's existence is so you can + do stuff like this: + + template + void call_funct(const T& funct) + { cout << funct(); } + + std::string test() { return "asdfasf"; } + + int main() + { + call_funct(wrap_function(test)); + } + + The above code doesn't work right on some compilers if you don't + use wrap_function. + !*/ + + template + funct_wrap0 wrap_function(T (&f)()) { return funct_wrap0(f); } + template + funct_wrap1 wrap_function(T (&f)(A0)) { return funct_wrap1(f); } + template + funct_wrap2 wrap_function(T (&f)(A0, A1)) { return funct_wrap2(f); } + template + funct_wrap3 wrap_function(T (&f)(A0, A1, A2)) { return funct_wrap3(f); } + template + funct_wrap4 wrap_function(T (&f)(A0, A1, A2, A3)) { return funct_wrap4(f); } + template + funct_wrap5 wrap_function(T (&f)(A0, A1, A2, A3, A4)) { return funct_wrap5(f); } + +// ---------------------------------------------------------------------------------------- + + template + class stack_based_memory_block : noncopyable + { + /*! + WHAT THIS OBJECT REPRESENTS + This object is a simple container for a block of memory + of bSIZE bytes. This memory block is located on the stack + and properly aligned to hold any kind of object. + !*/ + public: + static const unsigned long size = bSIZE; + + stack_based_memory_block(): data(mem.data) {} + + void* get () { return data; } + /*! + ensures + - returns a pointer to the block of memory contained in this object + !*/ + + const void* get () const { return data; } + /*! + ensures + - returns a pointer to the block of memory contained in this object + !*/ + + private: + + // You obviously can't have a block of memory that has zero bytes in it. + COMPILE_TIME_ASSERT(bSIZE > 0); + + union mem_block + { + // All of this garbage is to make sure this union is properly aligned + // (a union is always aligned such that everything in it would be properly + // aligned. So the assumption here is that one of these objects has + // a large enough alignment requirement to satisfy any object this + // block of memory might be cast into). + void* void_ptr; + int integer; + struct { + void (stack_based_memory_block::*callback)(); + stack_based_memory_block* o; + } stuff; + long double more_stuff; + + uint64 var1; + uint32 var2; + double var3; + + char data[size]; + } mem; + + // The reason for having this variable is that doing it this way avoids + // warnings from gcc about violations of strict-aliasing rules. + void* const data; + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename F + > + auto max_scoring_element( + const T& container, + F score_func + ) -> decltype(std::make_pair(*container.begin(), 0.0)) + /*! + requires + - container has .begin() and .end(), allowing it to be enumerated. + - score_func() is a function that takes an element of the container and returns a double. + ensures + - This function finds the element of container that has the largest score, + according to score_func(), and returns a std::pair containing that maximal + element along with the score. + - If the container is empty then make_pair(a default initialized object, -infinity) is returned. + !*/ + { + double best_score = -std::numeric_limits::infinity(); + auto best_i = container.begin(); + for (auto i = container.begin(); i != container.end(); ++i) + { + auto score = score_func(*i); + if (score > best_score) + { + best_score = score; + best_i = i; + } + } + + using item_type = typename std::remove_reference::type; + + if (best_i == container.end()) + return std::make_pair(item_type(), best_score); + else + return std::make_pair(*best_i, best_score); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename F + > + auto min_scoring_element( + const T& container, + F score_func + ) -> decltype(std::make_pair(*container.begin(), 0.0)) + /*! + requires + - container has .begin() and .end(), allowing it to be enumerated. + - score_func() is a function that takes an element of the container and returns a double. + ensures + - This function finds the element of container that has the smallest score, + according to score_func(), and returns a std::pair containing that minimal + element along with the score. + - If the container is empty then make_pair(a default initialized object, infinity) is returned. + !*/ + { + double best_score = std::numeric_limits::infinity(); + auto best_i = container.begin(); + for (auto i = container.begin(); i != container.end(); ++i) + { + auto score = score_func(*i); + if (score < best_score) + { + best_score = score; + best_i = i; + } + } + + using item_type = typename std::remove_reference::type; + + if (best_i == container.end()) + return std::make_pair(item_type(), best_score); + else + return std::make_pair(*best_i, best_score); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_ALGs_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/array.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/array.h new file mode 100644 index 0000000..ecdafc4 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/array.h @@ -0,0 +1,10 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_ARRAy_ +#define DLIB_ARRAy_ + +#include "array/array_kernel.h" +#include "array/array_tools.h" + +#endif // DLIB_ARRAy_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/array/array_kernel.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/array/array_kernel.h new file mode 100644 index 0000000..0d18d1f --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/array/array_kernel.h @@ -0,0 +1,809 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_ARRAY_KERNEl_2_ +#define DLIB_ARRAY_KERNEl_2_ + +#include "array_kernel_abstract.h" +#include "../interfaces/enumerable.h" +#include "../algs.h" +#include "../serialize.h" +#include "../sort.h" +#include "../is_kind.h" + +namespace dlib +{ + + template < + typename T, + typename mem_manager = default_memory_manager + > + class array : public enumerable + { + + /*! + INITIAL VALUE + - array_size == 0 + - max_array_size == 0 + - array_elements == 0 + - pos == 0 + - last_pos == 0 + - _at_start == true + + CONVENTION + - array_size == size() + - max_array_size == max_size() + - if (max_array_size > 0) + - array_elements == pointer to max_array_size elements of type T + - else + - array_elements == 0 + + - if (array_size > 0) + - last_pos == array_elements + array_size - 1 + - else + - last_pos == 0 + + + - at_start() == _at_start + - current_element_valid() == pos != 0 + - if (current_element_valid()) then + - *pos == element() + !*/ + + public: + + // These typedefs are here for backwards compatibility with old versions of dlib. + typedef array kernel_1a; + typedef array kernel_1a_c; + typedef array kernel_2a; + typedef array kernel_2a_c; + typedef array sort_1a; + typedef array sort_1a_c; + typedef array sort_1b; + typedef array sort_1b_c; + typedef array sort_2a; + typedef array sort_2a_c; + typedef array sort_2b; + typedef array sort_2b_c; + typedef array expand_1a; + typedef array expand_1a_c; + typedef array expand_1b; + typedef array expand_1b_c; + typedef array expand_1c; + typedef array expand_1c_c; + typedef array expand_1d; + typedef array expand_1d_c; + + + + + typedef T type; + typedef T value_type; + typedef mem_manager mem_manager_type; + + array ( + ) : + array_size(0), + max_array_size(0), + array_elements(0), + pos(0), + last_pos(0), + _at_start(true) + {} + + array(const array&) = delete; + array& operator=(array&) = delete; + + array( + array&& item + ) : array() + { + swap(item); + } + + array& operator=( + array&& item + ) + { + swap(item); + return *this; + } + + explicit array ( + size_t new_size + ) : + array_size(0), + max_array_size(0), + array_elements(0), + pos(0), + last_pos(0), + _at_start(true) + { + resize(new_size); + } + + ~array ( + ); + + void clear ( + ); + + inline const T& operator[] ( + size_t pos + ) const; + + inline T& operator[] ( + size_t pos + ); + + void set_size ( + size_t size + ); + + inline size_t max_size( + ) const; + + void set_max_size( + size_t max + ); + + void swap ( + array& item + ); + + // functions from the enumerable interface + inline size_t size ( + ) const; + + inline bool at_start ( + ) const; + + inline void reset ( + ) const; + + bool current_element_valid ( + ) const; + + inline const T& element ( + ) const; + + inline T& element ( + ); + + bool move_next ( + ) const; + + void sort ( + ); + + void resize ( + size_t new_size + ); + + const T& back ( + ) const; + + T& back ( + ); + + void pop_back ( + ); + + void pop_back ( + T& item + ); + + void push_back ( + T& item + ); + + void push_back ( + T&& item + ); + + typedef T* iterator; + typedef const T* const_iterator; + iterator begin() { return array_elements; } + const_iterator begin() const { return array_elements; } + iterator end() { return array_elements+array_size; } + const_iterator end() const { return array_elements+array_size; } + + private: + + typename mem_manager::template rebind::other pool; + + // data members + size_t array_size; + size_t max_array_size; + T* array_elements; + + mutable T* pos; + T* last_pos; + mutable bool _at_start; + + }; + + template < + typename T, + typename mem_manager + > + inline void swap ( + array& a, + array& b + ) { a.swap(b); } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + void serialize ( + const array& item, + std::ostream& out + ) + { + try + { + serialize(item.max_size(),out); + serialize(item.size(),out); + + for (size_t i = 0; i < item.size(); ++i) + serialize(item[i],out); + } + catch (serialization_error& e) + { + throw serialization_error(e.info + "\n while serializing object of type array"); + } + } + + template < + typename T, + typename mem_manager + > + void deserialize ( + array& item, + std::istream& in + ) + { + try + { + size_t max_size, size; + deserialize(max_size,in); + deserialize(size,in); + item.set_max_size(max_size); + item.set_size(size); + for (size_t i = 0; i < size; ++i) + deserialize(item[i],in); + } + catch (serialization_error& e) + { + item.clear(); + throw serialization_error(e.info + "\n while deserializing object of type array"); + } + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + array:: + ~array ( + ) + { + if (array_elements) + { + pool.deallocate_array(array_elements); + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + void array:: + clear ( + ) + { + reset(); + last_pos = 0; + array_size = 0; + if (array_elements) + { + pool.deallocate_array(array_elements); + } + array_elements = 0; + max_array_size = 0; + + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + const T& array:: + operator[] ( + size_t pos + ) const + { + // make sure requires clause is not broken + DLIB_ASSERT( pos < this->size() , + "\tconst T& array::operator[]" + << "\n\tpos must < size()" + << "\n\tpos: " << pos + << "\n\tsize(): " << this->size() + << "\n\tthis: " << this + ); + + return array_elements[pos]; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + T& array:: + operator[] ( + size_t pos + ) + { + // make sure requires clause is not broken + DLIB_ASSERT( pos < this->size() , + "\tT& array::operator[]" + << "\n\tpos must be < size()" + << "\n\tpos: " << pos + << "\n\tsize(): " << this->size() + << "\n\tthis: " << this + ); + + return array_elements[pos]; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + void array:: + set_size ( + size_t size + ) + { + // make sure requires clause is not broken + DLIB_CASSERT(( size <= this->max_size() ), + "\tvoid array::set_size" + << "\n\tsize must be <= max_size()" + << "\n\tsize: " << size + << "\n\tmax size: " << this->max_size() + << "\n\tthis: " << this + ); + + reset(); + array_size = size; + if (size > 0) + last_pos = array_elements + size - 1; + else + last_pos = 0; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + size_t array:: + size ( + ) const + { + return array_size; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + void array:: + set_max_size( + size_t max + ) + { + reset(); + array_size = 0; + last_pos = 0; + if (max != 0) + { + // if new max size is different + if (max != max_array_size) + { + if (array_elements) + { + pool.deallocate_array(array_elements); + } + // try to get more memroy + try { array_elements = pool.allocate_array(max); } + catch (...) { array_elements = 0; max_array_size = 0; throw; } + max_array_size = max; + } + + } + // if the array is being made to be zero + else + { + if (array_elements) + pool.deallocate_array(array_elements); + max_array_size = 0; + array_elements = 0; + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + size_t array:: + max_size ( + ) const + { + return max_array_size; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + void array:: + swap ( + array& item + ) + { + auto array_size_temp = item.array_size; + auto max_array_size_temp = item.max_array_size; + T* array_elements_temp = item.array_elements; + + item.array_size = array_size; + item.max_array_size = max_array_size; + item.array_elements = array_elements; + + array_size = array_size_temp; + max_array_size = max_array_size_temp; + array_elements = array_elements_temp; + + exchange(_at_start,item._at_start); + exchange(pos,item.pos); + exchange(last_pos,item.last_pos); + pool.swap(item.pool); + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// enumerable function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + bool array:: + at_start ( + ) const + { + return _at_start; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + void array:: + reset ( + ) const + { + _at_start = true; + pos = 0; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + bool array:: + current_element_valid ( + ) const + { + return pos != 0; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + const T& array:: + element ( + ) const + { + // make sure requires clause is not broken + DLIB_ASSERT(this->current_element_valid(), + "\tconst T& array::element()" + << "\n\tThe current element must be valid if you are to access it." + << "\n\tthis: " << this + ); + + return *pos; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + T& array:: + element ( + ) + { + // make sure requires clause is not broken + DLIB_ASSERT(this->current_element_valid(), + "\tT& array::element()" + << "\n\tThe current element must be valid if you are to access it." + << "\n\tthis: " << this + ); + + return *pos; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + bool array:: + move_next ( + ) const + { + if (!_at_start) + { + if (pos < last_pos) + { + ++pos; + return true; + } + else + { + pos = 0; + return false; + } + } + else + { + _at_start = false; + if (array_size > 0) + { + pos = array_elements; + return true; + } + else + { + return false; + } + } + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// Yet more functions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + void array:: + sort ( + ) + { + if (this->size() > 1) + { + // call the quick sort function for arrays that is in algs.h + dlib::qsort_array(*this,0,this->size()-1); + } + this->reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + void array:: + resize ( + size_t new_size + ) + { + if (this->max_size() < new_size) + { + array temp; + temp.set_max_size(new_size); + temp.set_size(new_size); + for (size_t i = 0; i < this->size(); ++i) + { + exchange((*this)[i],temp[i]); + } + temp.swap(*this); + } + else + { + this->set_size(new_size); + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + T& array:: + back ( + ) + { + // make sure requires clause is not broken + DLIB_ASSERT( this->size() > 0 , + "\tT& array::back()" + << "\n\tsize() must be bigger than 0" + << "\n\tsize(): " << this->size() + << "\n\tthis: " << this + ); + + return (*this)[this->size()-1]; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + const T& array:: + back ( + ) const + { + // make sure requires clause is not broken + DLIB_ASSERT( this->size() > 0 , + "\tconst T& array::back()" + << "\n\tsize() must be bigger than 0" + << "\n\tsize(): " << this->size() + << "\n\tthis: " << this + ); + + return (*this)[this->size()-1]; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + void array:: + pop_back ( + T& item + ) + { + // make sure requires clause is not broken + DLIB_ASSERT( this->size() > 0 , + "\tvoid array::pop_back()" + << "\n\tsize() must be bigger than 0" + << "\n\tsize(): " << this->size() + << "\n\tthis: " << this + ); + + exchange(item,(*this)[this->size()-1]); + this->set_size(this->size()-1); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + void array:: + pop_back ( + ) + { + // make sure requires clause is not broken + DLIB_ASSERT( this->size() > 0 , + "\tvoid array::pop_back()" + << "\n\tsize() must be bigger than 0" + << "\n\tsize(): " << this->size() + << "\n\tthis: " << this + ); + + this->set_size(this->size()-1); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + void array:: + push_back ( + T& item + ) + { + if (this->max_size() == this->size()) + { + // double the size of the array + array temp; + temp.set_max_size(this->size()*2 + 1); + temp.set_size(this->size()+1); + for (size_t i = 0; i < this->size(); ++i) + { + exchange((*this)[i],temp[i]); + } + exchange(item,temp[temp.size()-1]); + temp.swap(*this); + } + else + { + this->set_size(this->size()+1); + exchange(item,(*this)[this->size()-1]); + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + void array:: + push_back ( + T&& item + ) { push_back(item); } + +// ---------------------------------------------------------------------------------------- + + template + struct is_array > + { + const static bool value = true; + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_ARRAY_KERNEl_2_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/array/array_kernel_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/array/array_kernel_abstract.h new file mode 100644 index 0000000..5cfdd48 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/array/array_kernel_abstract.h @@ -0,0 +1,360 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_ARRAY_KERNEl_ABSTRACT_ +#ifdef DLIB_ARRAY_KERNEl_ABSTRACT_ + +#include "../interfaces/enumerable.h" +#include "../serialize.h" +#include "../algs.h" + +namespace dlib +{ + + template < + typename T, + typename mem_manager = default_memory_manager + > + class array : public enumerable + { + + /*! + REQUIREMENTS ON T + T must have a default constructor. + + REQUIREMENTS ON mem_manager + must be an implementation of memory_manager/memory_manager_kernel_abstract.h or + must be an implementation of memory_manager_global/memory_manager_global_kernel_abstract.h or + must be an implementation of memory_manager_stateless/memory_manager_stateless_kernel_abstract.h + mem_manager::type can be set to anything. + + POINTERS AND REFERENCES TO INTERNAL DATA + front(), back(), swap(), max_size(), set_size(), and operator[] + functions do not invalidate pointers or references to internal data. + All other functions have no such guarantee. + + INITIAL VALUE + size() == 0 + max_size() == 0 + + ENUMERATION ORDER + The enumerator will iterate over the elements of the array in the + order (*this)[0], (*this)[1], (*this)[2], ... + + WHAT THIS OBJECT REPRESENTS + This object represents an ordered 1-dimensional array of items, + each item is associated with an integer value. The items are + numbered from 0 though size() - 1 and the operator[] functions + run in constant time. + + Also note that unless specified otherwise, no member functions + of this object throw exceptions. + !*/ + + public: + + typedef T type; + typedef T value_type; + typedef mem_manager mem_manager_type; + + array ( + ); + /*! + ensures + - #*this is properly initialized + throws + - std::bad_alloc or any exception thrown by T's constructor + !*/ + + explicit array ( + size_t new_size + ); + /*! + ensures + - #*this is properly initialized + - #size() == new_size + - #max_size() == new_size + - All elements of the array will have initial values for their type. + throws + - std::bad_alloc or any exception thrown by T's constructor + !*/ + + ~array ( + ); + /*! + ensures + - all memory associated with *this has been released + !*/ + + array( + array&& item + ); + /*! + ensures + - move constructs *this from item. Therefore, the state of item is + moved into *this and #item has a valid but unspecified state. + !*/ + + array& operator=( + array&& item + ); + /*! + ensures + - move assigns *this from item. Therefore, the state of item is + moved into *this and #item has a valid but unspecified state. + - returns a reference to #*this + !*/ + + void clear ( + ); + /*! + ensures + - #*this has its initial value + throws + - std::bad_alloc or any exception thrown by T's constructor + if this exception is thrown then the array object is unusable + until clear() is called and succeeds + !*/ + + const T& operator[] ( + size_t pos + ) const; + /*! + requires + - pos < size() + ensures + - returns a const reference to the element at position pos + !*/ + + T& operator[] ( + size_t pos + ); + /*! + requires + - pos < size() + ensures + - returns a non-const reference to the element at position pos + !*/ + + void set_size ( + size_t size + ); + /*! + requires + - size <= max_size() + ensures + - #size() == size + - any element with index between 0 and size - 1 which was in the + array before the call to set_size() retains its value and index. + All other elements have undetermined (but valid for their type) + values. (e.g. this object might buffer old T objects and reuse + them without reinitializing them between calls to set_size()) + - #at_start() == true + throws + - std::bad_alloc or any exception thrown by T's constructor + may throw this exception if there is not enough memory and + if it does throw then the call to set_size() has no effect + !*/ + + size_t max_size( + ) const; + /*! + ensures + - returns the maximum size of *this + !*/ + + void set_max_size( + size_t max + ); + /*! + ensures + - #max_size() == max + - #size() == 0 + - #at_start() == true + throws + - std::bad_alloc or any exception thrown by T's constructor + may throw this exception if there is not enough + memory and if it does throw then max_size() == 0 + !*/ + + void swap ( + array& item + ); + /*! + ensures + - swaps *this and item + !*/ + + void sort ( + ); + /*! + requires + - T must be a type with that is comparable via operator< + ensures + - for all elements in #*this the ith element is <= the i+1 element + - #at_start() == true + throws + - std::bad_alloc or any exception thrown by T's constructor + data may be lost if sort() throws + !*/ + + void resize ( + size_t new_size + ); + /*! + ensures + - #size() == new_size + - #max_size() == max(new_size,max_size()) + - for all i < size() && i < new_size: + - #(*this)[i] == (*this)[i] + (i.e. All the original elements of *this which were at index + values less than new_size are unmodified.) + - for all valid i >= size(): + - #(*this)[i] has an undefined value + (i.e. any new elements of the array have an undefined value) + throws + - std::bad_alloc or any exception thrown by T's constructor. + If an exception is thrown then it has no effect on *this. + !*/ + + + const T& back ( + ) const; + /*! + requires + - size() != 0 + ensures + - returns a const reference to (*this)[size()-1] + !*/ + + T& back ( + ); + /*! + requires + - size() != 0 + ensures + - returns a non-const reference to (*this)[size()-1] + !*/ + + void pop_back ( + T& item + ); + /*! + requires + - size() != 0 + ensures + - #size() == size() - 1 + - swaps (*this)[size()-1] into item + - All elements with an index less than size()-1 are + unmodified by this operation. + !*/ + + void pop_back ( + ); + /*! + requires + - size() != 0 + ensures + - #size() == size() - 1 + - All elements with an index less than size()-1 are + unmodified by this operation. + !*/ + + void push_back ( + T& item + ); + /*! + ensures + - #size() == size()+1 + - swaps item into (*this)[#size()-1] + - #back() == item + - #item has some undefined value (whatever happens to + get swapped out of the array) + throws + - std::bad_alloc or any exception thrown by T's constructor. + If an exception is thrown then it has no effect on *this. + !*/ + + void push_back (T&& item) { push_back(item); } + /*! + enable push_back from rvalues + !*/ + + typedef T* iterator; + typedef const T* const_iterator; + + iterator begin( + ); + /*! + ensures + - returns an iterator that points to the first element in this array or + end() if the array is empty. + !*/ + + const_iterator begin( + ) const; + /*! + ensures + - returns a const iterator that points to the first element in this + array or end() if the array is empty. + !*/ + + iterator end( + ); + /*! + ensures + - returns an iterator that points to one past the end of the array. + !*/ + + const_iterator end( + ) const; + /*! + ensures + - returns a const iterator that points to one past the end of the + array. + !*/ + + private: + + // restricted functions + array(array&); // copy constructor + array& operator=(array&); // assignment operator + + }; + + template < + typename T + > + inline void swap ( + array& a, + array& b + ) { a.swap(b); } + /*! + provides a global swap function + !*/ + + template < + typename T + > + void serialize ( + const array& item, + std::ostream& out + ); + /*! + provides serialization support + !*/ + + template < + typename T + > + void deserialize ( + array& item, + std::istream& in + ); + /*! + provides deserialization support + !*/ + +} + +#endif // DLIB_ARRAY_KERNEl_ABSTRACT_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/array/array_tools.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/array/array_tools.h new file mode 100644 index 0000000..fce6343 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/array/array_tools.h @@ -0,0 +1,38 @@ +// Copyright (C) 2013 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_ARRAY_tOOLS_H_ +#define DLIB_ARRAY_tOOLS_H_ + +#include "../assert.h" +#include "array_tools_abstract.h" + +namespace dlib +{ + template + void split_array ( + T& a, + T& b, + double frac + ) + { + // make sure requires clause is not broken + DLIB_ASSERT(0 <= frac && frac <= 1, + "\t void split_array()" + << "\n\t frac must be between 0 and 1." + << "\n\t frac: " << frac + ); + + const unsigned long asize = static_cast(a.size()*frac); + const unsigned long bsize = a.size()-asize; + + b.resize(bsize); + for (unsigned long i = 0; i < b.size(); ++i) + { + swap(b[i], a[i+asize]); + } + a.resize(asize); + } +} + +#endif // DLIB_ARRAY_tOOLS_H_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/array/array_tools_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/array/array_tools_abstract.h new file mode 100644 index 0000000..e9b9575 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/array/array_tools_abstract.h @@ -0,0 +1,33 @@ +// Copyright (C) 2013 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_ARRAY_tOOLS_ABSTRACT_H_ +#ifdef DLIB_ARRAY_tOOLS_ABSTRACT_H_ + +#include "array_kernel_abstract.h" + +namespace dlib +{ + template + void split_array ( + T& a, + T& b, + double frac + ); + /*! + requires + - 0 <= frac <= 1 + - T must be an array type such as dlib::array or std::vector + ensures + - This function takes the elements of a and splits them into two groups. The + first group remains in a and the second group is put into b. The ordering of + elements in a is preserved. In particular, concatenating #a with #b will + reproduce the original contents of a. + - The elements in a are moved around using global swap(). So they must be + swappable, but do not need to be copyable. + - #a.size() == floor(a.size()*frac) + - #b.size() == a.size()-#a.size() + !*/ +} + +#endif // DLIB_ARRAY_tOOLS_ABSTRACT_H_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/assert.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/assert.h new file mode 100644 index 0000000..67dc634 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/assert.h @@ -0,0 +1,217 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_ASSERt_ +#define DLIB_ASSERt_ + +#include "config.h" +#include +#include +#include "error.h" + +// ----------------------------- + +// Use some stuff from boost here +// (C) Copyright John Maddock 2001 - 2003. +// (C) Copyright Darin Adler 2001. +// (C) Copyright Peter Dimov 2001. +// (C) Copyright Bill Kempf 2002. +// (C) Copyright Jens Maurer 2002. +// (C) Copyright David Abrahams 2002 - 2003. +// (C) Copyright Gennaro Prota 2003. +// (C) Copyright Eric Friedman 2003. +// License: Boost Software License See LICENSE.txt for the full license. +// +#ifndef DLIB_BOOST_JOIN +#define DLIB_BOOST_JOIN( X, Y ) DLIB_BOOST_DO_JOIN( X, Y ) +#define DLIB_BOOST_DO_JOIN( X, Y ) DLIB_BOOST_DO_JOIN2(X,Y) +#define DLIB_BOOST_DO_JOIN2( X, Y ) X##Y +#endif + +// figure out if the compiler has rvalue references. +#if defined(__clang__) +# if __has_feature(cxx_rvalue_references) +# define DLIB_HAS_RVALUE_REFERENCES +# endif +# if __has_feature(cxx_generalized_initializers) +# define DLIB_HAS_INITIALIZER_LISTS +# endif +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) && defined(__GXX_EXPERIMENTAL_CXX0X__) +# define DLIB_HAS_RVALUE_REFERENCES +# define DLIB_HAS_INITIALIZER_LISTS +#elif defined(_MSC_VER) && _MSC_VER >= 1800 +# define DLIB_HAS_INITIALIZER_LISTS +# define DLIB_HAS_RVALUE_REFERENCES +#elif defined(_MSC_VER) && _MSC_VER >= 1600 +# define DLIB_HAS_RVALUE_REFERENCES +#elif defined(__INTEL_COMPILER) && defined(BOOST_INTEL_STDCXX0X) +# define DLIB_HAS_RVALUE_REFERENCES +# define DLIB_HAS_INITIALIZER_LISTS +#endif + +#if defined(__APPLE__) && defined(__GNUC_LIBSTD__) && ((__GNUC_LIBSTD__-0) * 100 + __GNUC_LIBSTD_MINOR__-0 <= 402) + // Apple has not updated libstdc++ in some time and anything under 4.02 does not have for sure. +# undef DLIB_HAS_INITIALIZER_LISTS +#endif + +// figure out if the compiler has static_assert. +#if defined(__clang__) +# if __has_feature(cxx_static_assert) +# define DLIB_HAS_STATIC_ASSERT +# endif +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) && defined(__GXX_EXPERIMENTAL_CXX0X__) +# define DLIB_HAS_STATIC_ASSERT +#elif defined(_MSC_VER) && _MSC_VER >= 1600 +# define DLIB_HAS_STATIC_ASSERT +#elif defined(__INTEL_COMPILER) && defined(BOOST_INTEL_STDCXX0X) +# define DLIB_HAS_STATIC_ASSERT +#endif + + +// ----------------------------- + +namespace dlib +{ + template struct compile_time_assert; + template <> struct compile_time_assert { enum {value=1}; }; + + template struct assert_are_same_type; + template struct assert_are_same_type {enum{value=1};}; + template struct assert_are_not_same_type {enum{value=1}; }; + template struct assert_are_not_same_type {}; + + template struct assert_types_match {enum{value=0};}; + template struct assert_types_match {enum{value=1};}; +} + + +// gcc 4.8 will warn about unused typedefs. But we use typedefs in some of the compile +// time assert macros so we need to make it not complain about them "not being used". +#ifdef __GNUC__ +#define DLIB_NO_WARN_UNUSED __attribute__ ((unused)) +#else +#define DLIB_NO_WARN_UNUSED +#endif + +// Use the newer static_assert if it's available since it produces much more readable error +// messages. +#ifdef DLIB_HAS_STATIC_ASSERT + #define COMPILE_TIME_ASSERT(expression) static_assert(expression, "Failed assertion") + #define ASSERT_ARE_SAME_TYPE(type1, type2) static_assert(::dlib::assert_types_match::value, "These types should be the same but aren't.") + #define ASSERT_ARE_NOT_SAME_TYPE(type1, type2) static_assert(!::dlib::assert_types_match::value, "These types should NOT be the same.") +#else + #define COMPILE_TIME_ASSERT(expression) \ + DLIB_NO_WARN_UNUSED typedef char DLIB_BOOST_JOIN(DLIB_CTA, __LINE__)[::dlib::compile_time_assert<(bool)(expression)>::value] + + #define ASSERT_ARE_SAME_TYPE(type1, type2) \ + DLIB_NO_WARN_UNUSED typedef char DLIB_BOOST_JOIN(DLIB_AAST, __LINE__)[::dlib::assert_are_same_type::value] + + #define ASSERT_ARE_NOT_SAME_TYPE(type1, type2) \ + DLIB_NO_WARN_UNUSED typedef char DLIB_BOOST_JOIN(DLIB_AANST, __LINE__)[::dlib::assert_are_not_same_type::value] +#endif + +// ----------------------------- + +#if defined DLIB_DISABLE_ASSERTS + // if DLIB_DISABLE_ASSERTS is on then never enable DLIB_ASSERT no matter what. + #undef ENABLE_ASSERTS +#endif + +#if !defined(DLIB_DISABLE_ASSERTS) && ( defined DEBUG || defined _DEBUG) + // make sure ENABLE_ASSERTS is defined if we are indeed using them. + #ifndef ENABLE_ASSERTS + #define ENABLE_ASSERTS + #endif +#endif + +// ----------------------------- + +#ifdef __GNUC__ +// There is a bug in version 4.4.5 of GCC on Ubuntu which causes GCC to segfault +// when __PRETTY_FUNCTION__ is used within certain templated functions. So just +// don't use it with this version of GCC. +# if !(__GNUC__ == 4 && __GNUC_MINOR__ == 4 && __GNUC_PATCHLEVEL__ == 5) +# define DLIB_FUNCTION_NAME __PRETTY_FUNCTION__ +# else +# define DLIB_FUNCTION_NAME "unknown function" +# endif +#elif defined(_MSC_VER) +#define DLIB_FUNCTION_NAME __FUNCSIG__ +#else +#define DLIB_FUNCTION_NAME "unknown function" +#endif + +#define DLIBM_CASSERT(_exp,_message) \ + {if ( !(_exp) ) \ + { \ + dlib_assert_breakpoint(); \ + std::ostringstream dlib_o_out; \ + dlib_o_out << "\n\nError detected at line " << __LINE__ << ".\n"; \ + dlib_o_out << "Error detected in file " << __FILE__ << ".\n"; \ + dlib_o_out << "Error detected in function " << DLIB_FUNCTION_NAME << ".\n\n"; \ + dlib_o_out << "Failing expression was " << #_exp << ".\n"; \ + dlib_o_out << std::boolalpha << _message << "\n"; \ + throw dlib::fatal_error(dlib::EBROKEN_ASSERT,dlib_o_out.str()); \ + }} + +// This macro is not needed if you have a real C++ compiler. It's here to work around bugs in Visual Studio's preprocessor. +#define DLIB_WORKAROUND_VISUAL_STUDIO_BUGS(x) x +// Make it so the 2nd argument of DLIB_CASSERT is optional. That is, you can call it like +// DLIB_CASSERT(exp) or DLIB_CASSERT(exp,message). +#define DLIBM_CASSERT_1_ARGS(exp) DLIBM_CASSERT(exp,"") +#define DLIBM_CASSERT_2_ARGS(exp,message) DLIBM_CASSERT(exp,message) +#define DLIBM_GET_3TH_ARG(arg1, arg2, arg3, ...) arg3 +#define DLIBM_CASSERT_CHOOSER(...) DLIB_WORKAROUND_VISUAL_STUDIO_BUGS(DLIBM_GET_3TH_ARG(__VA_ARGS__, DLIBM_CASSERT_2_ARGS, DLIBM_CASSERT_1_ARGS, DLIB_CASSERT_NEVER_USED)) +#define DLIB_CASSERT(...) DLIB_WORKAROUND_VISUAL_STUDIO_BUGS(DLIBM_CASSERT_CHOOSER(__VA_ARGS__)(__VA_ARGS__)) + + +#ifdef ENABLE_ASSERTS + #define DLIB_ASSERT(...) DLIB_CASSERT(__VA_ARGS__) + #define DLIB_IF_ASSERT(exp) exp +#else + #define DLIB_ASSERT(...) {} + #define DLIB_IF_ASSERT(exp) +#endif + +// ---------------------------------------------------------------------------------------- + + /*!A DLIB_ASSERT_HAS_STANDARD_LAYOUT + + This macro is meant to cause a compiler error if a type doesn't have a simple + memory layout (like a C struct). In particular, types with simple layouts are + ones which can be copied via memcpy(). + + + This was called a POD type in C++03 and in C++0x we are looking to check if + it is a "standard layout type". Once we can use C++0x we can change this macro + to something that uses the std::is_standard_layout type_traits class. + See: http://www2.research.att.com/~bs/C++0xFAQ.html#PODs + !*/ + // Use the fact that in C++03 you can't put non-PODs into a union. +#define DLIB_ASSERT_HAS_STANDARD_LAYOUT(type) \ + union DLIB_BOOST_JOIN(DAHSL_,__LINE__) { type TYPE_NOT_STANDARD_LAYOUT; }; \ + DLIB_NO_WARN_UNUSED typedef char DLIB_BOOST_JOIN(DAHSL2_,__LINE__)[sizeof(DLIB_BOOST_JOIN(DAHSL_,__LINE__))]; + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + +// breakpoints +extern "C" +{ + inline void dlib_assert_breakpoint( + ) {} + /*! + ensures + - this function does nothing + It exists just so you can put breakpoints on it in a debugging tool. + It is called only when an DLIB_ASSERT or DLIB_CASSERT fails and is about to + throw an exception. + !*/ +} + +// ----------------------------- + +#include "stack_trace.h" + +#endif // DLIB_ASSERt_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/binary_search_tree.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/binary_search_tree.h new file mode 100644 index 0000000..5273e8c --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/binary_search_tree.h @@ -0,0 +1,50 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_BINARY_SEARCH_TREe_ +#define DLIB_BINARY_SEARCH_TREe_ + + +#include "binary_search_tree/binary_search_tree_kernel_1.h" +#include "binary_search_tree/binary_search_tree_kernel_2.h" +#include "binary_search_tree/binary_search_tree_kernel_c.h" + + +#include "algs.h" +#include + + +namespace dlib +{ + + template < + typename domain, + typename range, + typename mem_manager = default_memory_manager, + typename compare = std::less + > + class binary_search_tree + { + binary_search_tree() {} + + public: + + //----------- kernels --------------- + + // kernel_1a + typedef binary_search_tree_kernel_1 + kernel_1a; + typedef binary_search_tree_kernel_c + kernel_1a_c; + + + // kernel_2a + typedef binary_search_tree_kernel_2 + kernel_2a; + typedef binary_search_tree_kernel_c + kernel_2a_c; + + }; +} + +#endif // DLIB_BINARY_SEARCH_TREe_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/binary_search_tree/binary_search_tree_kernel_1.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/binary_search_tree/binary_search_tree_kernel_1.h new file mode 100644 index 0000000..f0a0cfb --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/binary_search_tree/binary_search_tree_kernel_1.h @@ -0,0 +1,2064 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_BINARY_SEARCH_TREE_KERNEl_1_ +#define DLIB_BINARY_SEARCH_TREE_KERNEl_1_ + +#include "binary_search_tree_kernel_abstract.h" +#include "../algs.h" +#include "../interfaces/map_pair.h" +#include "../interfaces/enumerable.h" +#include "../interfaces/remover.h" +#include "../serialize.h" +#include +#include + +namespace dlib +{ + + template < + typename domain, + typename range, + typename mem_manager, + typename compare = std::less + > + class binary_search_tree_kernel_1 : public enumerable >, + public asc_pair_remover + { + + /*! + INITIAL VALUE + tree_size == 0 + tree_root == 0 + tree_height == 0 + at_start_ == true + current_element == 0 + stack == array of 50 node pointers + stack_pos == 0 + + + CONVENTION + tree_size == size() + tree_height == height() + + stack[stack_pos-1] == pop() + + current_element_valid() == (current_element != 0) + if (current_element_valid()) then + element() == current_element->d and current_element->r + at_start_ == at_start() + if (current_element != 0 && current_element != tree_root) then + stack[stack_pos-1] == the parent of the node pointed to by current_element + + if (tree_size != 0) + tree_root == pointer to the root node of the binary search tree + else + tree_root == 0 + + + for all nodes: + { + left points to the left subtree or 0 if there is no left subtree and + right points to the right subtree or 0 if there is no right subtree and + all elements in a left subtree are <= the root and + all elements in a right subtree are >= the root and + d is the item in the domain of *this contained in the node + r is the item in the range of *this contained in the node + balance: + balance == 0 if both subtrees have the same height + balance == -1 if the left subtree has a height that is greater + than the height of the right subtree by 1 + balance == 1 if the right subtree has a height that is greater + than the height of the left subtree by 1 + for all trees: + the height of the left and right subtrees differ by at most one + } + + !*/ + + class node + { + public: + node* left; + node* right; + domain d; + range r; + signed char balance; + }; + + class mpair : public map_pair + { + public: + const domain* d; + range* r; + + const domain& key( + ) const { return *d; } + + const range& value( + ) const { return *r; } + + range& value( + ) { return *r; } + }; + + + public: + + typedef domain domain_type; + typedef range range_type; + typedef compare compare_type; + typedef mem_manager mem_manager_type; + + binary_search_tree_kernel_1( + ) : + tree_size(0), + tree_root(0), + current_element(0), + tree_height(0), + at_start_(true), + stack_pos(0), + stack(ppool.allocate_array(50)) + { + } + + virtual ~binary_search_tree_kernel_1( + ); + + inline void clear( + ); + + inline short height ( + ) const; + + inline unsigned long count ( + const domain& item + ) const; + + inline void add ( + domain& d, + range& r + ); + + void remove ( + const domain& d, + domain& d_copy, + range& r + ); + + void destroy ( + const domain& item + ); + + inline const range* operator[] ( + const domain& item + ) const; + + inline range* operator[] ( + const domain& item + ); + + inline void swap ( + binary_search_tree_kernel_1& item + ); + + // function from the asc_pair_remover interface + void remove_any ( + domain& d, + range& r + ); + + // functions from the enumerable interface + inline size_t size ( + ) const; + + bool at_start ( + ) const; + + inline void reset ( + ) const; + + bool current_element_valid ( + ) const; + + const map_pair& element ( + ) const; + + map_pair& element ( + ); + + bool move_next ( + ) const; + + void remove_last_in_order ( + domain& d, + range& r + ); + + void remove_current_element ( + domain& d, + range& r + ); + + void position_enumerator ( + const domain& d + ) const; + + private: + + + inline void rotate_left ( + node*& t + ); + /*! + requires + - t->balance == 2 + - t->right->balance == 0 or 1 + - t == reference to the pointer in t's parent node that points to t + ensures + - #t is still a binary search tree + - #t->balance is between 1 and -1 + - #t now has a height smaller by 1 if #t->balance == 0 + !*/ + + inline void rotate_right ( + node*& t + ); + /*! + requires + - t->balance == -2 + - t->left->balance == 0 or -1 + - t == reference to the pointer in t's parent node that points to t + ensures + - #t is still a binary search tree + - #t->balance is between 1 and -1 + - #t now has a height smaller by 1 if #t->balance == 0 + + !*/ + + inline void double_rotate_right ( + node*& t + ); + /*! + requires + - t->balance == -2 + - t->left->balance == 1 + - t == reference to the pointer in t's parent node that points to t + ensures + - #t is still a binary search tree + - #t now has a balance of 0 + - #t now has a height smaller by 1 + !*/ + + inline void double_rotate_left ( + node*& t + ); + /*! + requires + - t->balance == 2 + - t->right->balance == -1 + - t == reference to the pointer in t's parent node that points to t + ensures + - #t is still a binary search tree + - #t now has a balance of 0 + - #t now has a height smaller by 1 + !*/ + + bool remove_biggest_element_in_tree ( + node*& t, + domain& d, + range& r + ); + /*! + requires + - t != 0 (i.e. there must be something in the tree to remove) + - t == reference to the pointer in t's parent node that points to t + ensures + - the biggest node in t has been removed + - the biggest node domain element in t has been put into #d + - the biggest node range element in t has been put into #r + - #t is still a binary search tree + - returns false if the height of the tree has not changed + - returns true if the height of the tree has shrunk by one + !*/ + + bool remove_least_element_in_tree ( + node*& t, + domain& d, + range& r + ); + /*! + requires + - t != 0 (i.e. there must be something in the tree to remove) + - t == reference to the pointer in t's parent node that points to t + ensures + - the least node in t has been removed + - the least node domain element in t has been put into #d + - the least node range element in t has been put into #r + - #t is still a binary search tree + - returns false if the height of the tree has not changed + - returns true if the height of the tree has shrunk by one + !*/ + + bool add_to_tree ( + node*& t, + domain& d, + range& r + ); + /*! + requires + - t == reference to the pointer in t's parent node that points to t + ensures + - the mapping (d --> r) has been added to #t + - #d and #r have initial values for their types + - #t is still a binary search tree + - returns false if the height of the tree has not changed + - returns true if the height of the tree has grown by one + !*/ + + bool remove_from_tree ( + node*& t, + const domain& d, + domain& d_copy, + range& r + ); + /*! + requires + - return_reference(t,d) != 0 + - t == reference to the pointer in t's parent node that points to t + ensures + - #d_copy is equivalent to d + - an element in t equivalent to d has been removed and swapped + into #d_copy and its associated range object has been + swapped into #r + - #t is still a binary search tree + - returns false if the height of the tree has not changed + - returns true if the height of the tree has shrunk by one + !*/ + + bool remove_from_tree ( + node*& t, + const domain& item + ); + /*! + requires + - return_reference(t,item) != 0 + - t == reference to the pointer in t's parent node that points to t + ensures + - an element in t equivalent to item has been removed + - #t is still a binary search tree + - returns false if the height of the tree has not changed + - returns true if the height of the tree has shrunk by one + !*/ + + const range* return_reference ( + const node* t, + const domain& d + ) const; + /*! + ensures + - if (there is a domain element equivalent to d in t) then + - returns a pointer to the element in the range equivalent to d + - else + - returns 0 + !*/ + + range* return_reference ( + node* t, + const domain& d + ); + /*! + ensures + - if (there is a domain element equivalent to d in t) then + - returns a pointer to the element in the range equivalent to d + - else + - returns 0 + !*/ + + + inline bool keep_node_balanced ( + node*& t + ); + /*! + requires + - t != 0 + - t == reference to the pointer in t's parent node that points to t + ensures + - if (t->balance is < 1 or > 1) then + - keep_node_balanced() will ensure that #t->balance == 0, -1, or 1 + - #t is still a binary search tree + - returns true if it made the tree one height shorter + - returns false if it didn't change the height + !*/ + + + unsigned long get_count ( + const domain& item, + node* tree_root + ) const; + /*! + requires + - tree_root == the root of a binary search tree or 0 + ensures + - if (tree_root == 0) then + - returns 0 + - else + - returns the number of elements in tree_root that are + equivalent to item + !*/ + + + void delete_tree ( + node* t + ); + /*! + requires + - t != 0 + ensures + - deallocates the node pointed to by t and all of t's left and right children + !*/ + + + void push ( + node* n + ) const { stack[stack_pos] = n; ++stack_pos; } + /*! + ensures + - pushes n onto the stack + !*/ + + + node* pop ( + ) const { --stack_pos; return stack[stack_pos]; } + /*! + ensures + - pops the top of the stack and returns it + !*/ + + + + bool fix_stack ( + node* t, + unsigned char depth = 0 + ); + /*! + requires + - current_element != 0 + - depth == 0 + - t == tree_root + ensures + - makes the stack contain the correct set of parent pointers. + also adjusts stack_pos so it is correct. + - #t is still a binary search tree + !*/ + + bool remove_current_element_from_tree ( + node*& t, + domain& d, + range& r, + unsigned long cur_stack_pos = 1 + ); + /*! + requires + - t == tree_root + - cur_stack_pos == 1 + - current_element != 0 + ensures + - removes the data in the node given by current_element and swaps it into + #d and #r. + - #t is still a binary search tree + - the enumerator is advances on to the next element but its stack is + potentially corrupted. so you must call fix_stack(tree_root) to fix + it. + - returns false if the height of the tree has not changed + - returns true if the height of the tree has shrunk by one + !*/ + + + // data members + + mutable mpair p; + unsigned long tree_size; + node* tree_root; + mutable node* current_element; + typename mem_manager::template rebind::other pool; + typename mem_manager::template rebind::other ppool; + short tree_height; + mutable bool at_start_; + mutable unsigned char stack_pos; + mutable node** stack; + compare comp; + + // restricted functions + binary_search_tree_kernel_1(binary_search_tree_kernel_1&); + binary_search_tree_kernel_1& operator=(binary_search_tree_kernel_1&); + + + }; + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + inline void swap ( + binary_search_tree_kernel_1& a, + binary_search_tree_kernel_1& b + ) { a.swap(b); } + + + + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void deserialize ( + binary_search_tree_kernel_1& item, + std::istream& in + ) + { + try + { + item.clear(); + unsigned long size; + deserialize(size,in); + domain d; + range r; + for (unsigned long i = 0; i < size; ++i) + { + deserialize(d,in); + deserialize(r,in); + item.add(d,r); + } + } + catch (serialization_error& e) + { + item.clear(); + throw serialization_error(e.info + "\n while deserializing object of type binary_search_tree_kernel_1"); + } + } + + + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + binary_search_tree_kernel_1:: + ~binary_search_tree_kernel_1 ( + ) + { + ppool.deallocate_array(stack); + if (tree_size != 0) + { + delete_tree(tree_root); + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_1:: + clear ( + ) + { + if (tree_size > 0) + { + delete_tree(tree_root); + tree_root = 0; + tree_size = 0; + tree_height = 0; + } + // reset the enumerator + reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + size_t binary_search_tree_kernel_1:: + size ( + ) const + { + return tree_size; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + short binary_search_tree_kernel_1:: + height ( + ) const + { + return tree_height; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + unsigned long binary_search_tree_kernel_1:: + count ( + const domain& item + ) const + { + return get_count(item,tree_root); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_1:: + add ( + domain& d, + range& r + ) + { + tree_height += add_to_tree(tree_root,d,r); + ++tree_size; + // reset the enumerator + reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_1:: + remove ( + const domain& d, + domain& d_copy, + range& r + ) + { + tree_height -= remove_from_tree(tree_root,d,d_copy,r); + --tree_size; + // reset the enumerator + reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_1:: + destroy ( + const domain& item + ) + { + tree_height -= remove_from_tree(tree_root,item); + --tree_size; + // reset the enumerator + reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_1:: + remove_any ( + domain& d, + range& r + ) + { + tree_height -= remove_least_element_in_tree(tree_root,d,r); + --tree_size; + // reset the enumerator + reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + range* binary_search_tree_kernel_1:: + operator[] ( + const domain& item + ) + { + return return_reference(tree_root,item); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + const range* binary_search_tree_kernel_1:: + operator[] ( + const domain& item + ) const + { + return return_reference(tree_root,item); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_1:: + swap ( + binary_search_tree_kernel_1& item + ) + { + pool.swap(item.pool); + ppool.swap(item.ppool); + exchange(p,item.p); + exchange(stack,item.stack); + exchange(stack_pos,item.stack_pos); + exchange(comp,item.comp); + + + node* tree_root_temp = item.tree_root; + unsigned long tree_size_temp = item.tree_size; + short tree_height_temp = item.tree_height; + node* current_element_temp = item.current_element; + bool at_start_temp = item.at_start_; + + item.tree_root = tree_root; + item.tree_size = tree_size; + item.tree_height = tree_height; + item.current_element = current_element; + item.at_start_ = at_start_; + + tree_root = tree_root_temp; + tree_size = tree_size_temp; + tree_height = tree_height_temp; + current_element = current_element_temp; + at_start_ = at_start_temp; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_1:: + remove_last_in_order ( + domain& d, + range& r + ) + { + tree_height -= remove_biggest_element_in_tree(tree_root,d,r); + --tree_size; + // reset the enumerator + reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_1:: + remove_current_element ( + domain& d, + range& r + ) + { + tree_height -= remove_current_element_from_tree(tree_root,d,r); + --tree_size; + + // fix the enumerator stack if we need to + if (current_element) + fix_stack(tree_root); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_1:: + position_enumerator ( + const domain& d + ) const + { + // clear the enumerator state and make sure the stack is empty + reset(); + at_start_ = false; + node* t = tree_root; + bool went_left = false; + while (t != 0) + { + if ( comp(d , t->d) ) + { + push(t); + // if item is on the left then look in left + t = t->left; + went_left = true; + } + else if (comp(t->d , d)) + { + push(t); + // if item is on the right then look in right + t = t->right; + went_left = false; + } + else + { + current_element = t; + return; + } + } + + // if we didn't find any matches but there might be something after the + // d in this tree. + if (stack_pos > 0) + { + current_element = pop(); + // if we went left from this node then this node is the next + // biggest. + if (went_left) + { + return; + } + else + { + move_next(); + } + } + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // enumerable function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + bool binary_search_tree_kernel_1:: + at_start ( + ) const + { + return at_start_; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_1:: + reset ( + ) const + { + at_start_ = true; + current_element = 0; + stack_pos = 0; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + bool binary_search_tree_kernel_1:: + current_element_valid ( + ) const + { + return (current_element != 0); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + const map_pair& binary_search_tree_kernel_1:: + element ( + ) const + { + p.d = &(current_element->d); + p.r = &(current_element->r); + return p; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + map_pair& binary_search_tree_kernel_1:: + element ( + ) + { + p.d = &(current_element->d); + p.r = &(current_element->r); + return p; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + bool binary_search_tree_kernel_1:: + move_next ( + ) const + { + // if we haven't started iterating yet + if (at_start_) + { + at_start_ = false; + if (tree_size == 0) + { + return false; + } + else + { + // find the first element in the tree + current_element = tree_root; + node* temp = current_element->left; + while (temp != 0) + { + push(current_element); + current_element = temp; + temp = current_element->left; + } + return true; + } + } + else + { + if (current_element == 0) + { + return false; + } + else + { + node* temp; + bool went_up; // true if we went up the tree from a child node to parent + bool from_left = false; // true if we went up and were coming from a left child node + // find the next element in the tree + if (current_element->right != 0) + { + // go right and down + temp = current_element; + push(current_element); + current_element = temp->right; + went_up = false; + } + else + { + // go up to the parent if we can + if (current_element == tree_root) + { + // in this case we have iterated over all the element of the tree + current_element = 0; + return false; + } + went_up = true; + node* parent = pop(); + + + from_left = (parent->left == current_element); + // go up to parent + current_element = parent; + } + + + while (true) + { + if (went_up) + { + if (from_left) + { + // in this case we have found the next node + break; + } + else + { + if (current_element == tree_root) + { + // in this case we have iterated over all the elements + // in the tree + current_element = 0; + return false; + } + // we should go up + node* parent = pop(); + from_left = (parent->left == current_element); + current_element = parent; + } + } + else + { + // we just went down to a child node + if (current_element->left != 0) + { + // go left + went_up = false; + temp = current_element; + push(current_element); + current_element = temp->left; + } + else + { + // if there is no left child then we have found the next node + break; + } + } + } + + return true; + } + } + + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // private member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_1:: + delete_tree ( + node* t + ) + { + if (t->left != 0) + delete_tree(t->left); + if (t->right != 0) + delete_tree(t->right); + pool.deallocate(t); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_1:: + rotate_left ( + node*& t + ) + { + + // set the new balance numbers + if (t->right->balance == 1) + { + t->balance = 0; + t->right->balance = 0; + } + else + { + t->balance = 1; + t->right->balance = -1; + } + + // perform the rotation + node* temp = t->right; + t->right = temp->left; + temp->left = t; + t = temp; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_1:: + rotate_right ( + node*& t + ) + { + // set the new balance numbers + if (t->left->balance == -1) + { + t->balance = 0; + t->left->balance = 0; + } + else + { + t->balance = -1; + t->left->balance = 1; + } + + // preform the rotation + node* temp = t->left; + t->left = temp->right; + temp->right = t; + t = temp; + + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_1:: + double_rotate_right ( + node*& t + ) + { + + node* temp = t; + t = t->left->right; + + temp->left->right = t->left; + t->left = temp->left; + + temp->left = t->right; + t->right = temp; + + if (t->balance < 0) + { + t->left->balance = 0; + t->right->balance = 1; + } + else if (t->balance > 0) + { + t->left->balance = -1; + t->right->balance = 0; + } + else + { + t->left->balance = 0; + t->right->balance = 0; + } + t->balance = 0; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_1:: + double_rotate_left ( + node*& t + ) + { + node* temp = t; + t = t->right->left; + + temp->right->left = t->right; + t->right = temp->right; + + temp->right = t->left; + t->left = temp; + + if (t->balance < 0) + { + t->left->balance = 0; + t->right->balance = 1; + } + else if (t->balance > 0) + { + t->left->balance = -1; + t->right->balance = 0; + } + else + { + t->left->balance = 0; + t->right->balance = 0; + } + + t->balance = 0; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + bool binary_search_tree_kernel_1:: + remove_biggest_element_in_tree ( + node*& t, + domain& d, + range& r + ) + { + // make a reference to the current node so we don't have to dereference a + // pointer a bunch of times + node& tree = *t; + + // if the right tree is an empty tree + if ( tree.right == 0) + { + // swap nodes domain and range elements into d and r + exchange(d,tree.d); + exchange(r,tree.r); + + // plug hole left by removing this node + t = tree.left; + + // delete the node that was just removed + pool.deallocate(&tree); + + // return that the height of this part of the tree has decreased + return true; + } + else + { + + // keep going right + + // if remove made the tree one height shorter + if ( remove_biggest_element_in_tree(tree.right,d,r) ) + { + // if this caused the current tree to strink then report that + if ( tree.balance == 1) + { + --tree.balance; + return true; + } + else + { + --tree.balance; + return keep_node_balanced(t); + } + } + + return false; + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + bool binary_search_tree_kernel_1:: + remove_least_element_in_tree ( + node*& t, + domain& d, + range& r + ) + { + // make a reference to the current node so we don't have to dereference a + // pointer a bunch of times + node& tree = *t; + + // if the left tree is an empty tree + if ( tree.left == 0) + { + // swap nodes domain and range elements into d and r + exchange(d,tree.d); + exchange(r,tree.r); + + // plug hole left by removing this node + t = tree.right; + + // delete the node that was just removed + pool.deallocate(&tree); + + // return that the height of this part of the tree has decreased + return true; + } + else + { + + // keep going left + + // if remove made the tree one height shorter + if ( remove_least_element_in_tree(tree.left,d,r) ) + { + // if this caused the current tree to strink then report that + if ( tree.balance == -1) + { + ++tree.balance; + return true; + } + else + { + ++tree.balance; + return keep_node_balanced(t); + } + } + + return false; + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + bool binary_search_tree_kernel_1:: + add_to_tree ( + node*& t, + domain& d, + range& r + ) + { + + // if found place to add + if (t == 0) + { + // create a node to add new item into + t = pool.allocate(); + + // make a reference to the current node so we don't have to dereference a + // pointer a bunch of times + node& tree = *t; + + + // set left and right pointers to NULL to indicate that there are no + // left or right subtrees + tree.left = 0; + tree.right = 0; + tree.balance = 0; + + // put d and r into t + exchange(tree.d,d); + exchange(tree.r,r); + + // indicate that the height of this tree has increased + return true; + } + else // keep looking for a place to add the new item + { + // make a reference to the current node so we don't have to dereference + // a pointer a bunch of times + node& tree = *t; + signed char old_balance = tree.balance; + + // add the new item to whatever subtree it should go into + if (comp( d , tree.d) ) + tree.balance -= add_to_tree(tree.left,d,r); + else + tree.balance += add_to_tree(tree.right,d,r); + + + // if the tree was balanced to start with + if (old_balance == 0) + { + // if its not balanced anymore then it grew in height + if (tree.balance != 0) + return true; + else + return false; + } + else + { + // if the tree is now balanced then it didn't grow + if (tree.balance == 0) + { + return false; + } + else + { + // if the tree needs to be balanced + if (tree.balance != old_balance) + { + return !keep_node_balanced(t); + } + // if there has been no change in the heights + else + { + return false; + } + } + } + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + bool binary_search_tree_kernel_1:: + fix_stack ( + node* t, + unsigned char depth + ) + { + // if we found the node we were looking for + if (t == current_element) + { + stack_pos = depth; + return true; + } + else if (t == 0) + { + return false; + } + + if (!( comp(t->d , current_element->d))) + { + // go left + if (fix_stack(t->left,depth+1)) + { + stack[depth] = t; + return true; + } + } + if (!(comp(current_element->d , t->d))) + { + // go right + if (fix_stack(t->right,depth+1)) + { + stack[depth] = t; + return true; + } + } + return false; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + bool binary_search_tree_kernel_1:: + remove_current_element_from_tree ( + node*& t, + domain& d, + range& r, + unsigned long cur_stack_pos + ) + { + // make a reference to the current node so we don't have to dereference + // a pointer a bunch of times + node& tree = *t; + + // if we found the node we were looking for + if (t == current_element) + { + + // swap nodes domain and range elements into d_copy and r + exchange(d,tree.d); + exchange(r,tree.r); + + // if there is no left node + if (tree.left == 0) + { + // move the enumerator on to the next element before we mess with the + // tree + move_next(); + + // plug hole left by removing this node and free memory + t = tree.right; // plug hole with right subtree + + // delete old node + pool.deallocate(&tree); + + // indicate that the height has changed + return true; + } + // if there is no right node + else if (tree.right == 0) + { + // move the enumerator on to the next element before we mess with the + // tree + move_next(); + + // plug hole left by removing this node and free memory + t = tree.left; // plug hole with left subtree + + // delete old node + pool.deallocate(&tree); + + // indicate that the height of this tree has changed + return true; + } + // if there are both a left and right sub node + else + { + + // in this case the next current element is going to get swapped back + // into this t node. + current_element = t; + + // get an element that can replace the one being removed and do this + // if it made the right subtree shrink by one + if (remove_least_element_in_tree(tree.right,tree.d,tree.r)) + { + // adjust the tree height + --tree.balance; + + // if the height of the current tree has dropped by one + if (tree.balance == 0) + { + return true; + } + else + { + return keep_node_balanced(t); + } + } + // else this remove did not effect the height of this tree + else + { + return false; + } + + } + + } + else if ( (cur_stack_pos < stack_pos && stack[cur_stack_pos] == tree.left) || + tree.left == current_element ) + { + // go left + if (tree.balance == -1) + { + int balance = tree.balance; + balance += remove_current_element_from_tree(tree.left,d,r,cur_stack_pos+1); + tree.balance = balance; + return !tree.balance; + } + else + { + int balance = tree.balance; + balance += remove_current_element_from_tree(tree.left,d,r,cur_stack_pos+1); + tree.balance = balance; + return keep_node_balanced(t); + } + } + else if ( (cur_stack_pos < stack_pos && stack[cur_stack_pos] == tree.right) || + tree.right == current_element ) + { + // go right + if (tree.balance == 1) + { + int balance = tree.balance; + balance -= remove_current_element_from_tree(tree.right,d,r,cur_stack_pos+1); + tree.balance = balance; + return !tree.balance; + } + else + { + int balance = tree.balance; + balance -= remove_current_element_from_tree(tree.right,d,r,cur_stack_pos+1); + tree.balance = balance; + return keep_node_balanced(t); + } + } + + // this return should never happen but do it anyway to suppress compiler warnings + return false; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + bool binary_search_tree_kernel_1:: + remove_from_tree ( + node*& t, + const domain& d, + domain& d_copy, + range& r + ) + { + // make a reference to the current node so we don't have to dereference + // a pointer a bunch of times + node& tree = *t; + + // if item is on the left + if (comp(d , tree.d)) + { + // if the left side of the tree has the greatest height + if (tree.balance == -1) + { + int balance = tree.balance; + balance += remove_from_tree(tree.left,d,d_copy,r); + tree.balance = balance; + return !tree.balance; + } + else + { + int balance = tree.balance; + balance += remove_from_tree(tree.left,d,d_copy,r); + tree.balance = balance; + return keep_node_balanced(t); + } + + } + // if item is on the right + else if (comp(tree.d , d)) + { + + // if the right side of the tree has the greatest height + if (tree.balance == 1) + { + int balance = tree.balance; + balance -= remove_from_tree(tree.right,d,d_copy,r); + tree.balance = balance; + return !tree.balance; + } + else + { + int balance = tree.balance; + balance -= remove_from_tree(tree.right,d,d_copy,r); + tree.balance = balance; + return keep_node_balanced(t); + } + } + // if item is found + else + { + + // swap nodes domain and range elements into d_copy and r + exchange(d_copy,tree.d); + exchange(r,tree.r); + + // if there is no left node + if (tree.left == 0) + { + + // plug hole left by removing this node and free memory + t = tree.right; // plug hole with right subtree + + // delete old node + pool.deallocate(&tree); + + // indicate that the height has changed + return true; + } + // if there is no right node + else if (tree.right == 0) + { + + // plug hole left by removing this node and free memory + t = tree.left; // plug hole with left subtree + + // delete old node + pool.deallocate(&tree); + + // indicate that the height of this tree has changed + return true; + } + // if there are both a left and right sub node + else + { + + // get an element that can replace the one being removed and do this + // if it made the right subtree shrink by one + if (remove_least_element_in_tree(tree.right,tree.d,tree.r)) + { + // adjust the tree height + --tree.balance; + + // if the height of the current tree has dropped by one + if (tree.balance == 0) + { + return true; + } + else + { + return keep_node_balanced(t); + } + } + // else this remove did not effect the height of this tree + else + { + return false; + } + + } + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + bool binary_search_tree_kernel_1:: + remove_from_tree ( + node*& t, + const domain& d + ) + { + // make a reference to the current node so we don't have to dereference + // a pointer a bunch of times + node& tree = *t; + + // if item is on the left + if (comp(d , tree.d)) + { + // if the left side of the tree has the greatest height + if (tree.balance == -1) + { + int balance = tree.balance; + balance += remove_from_tree(tree.left,d); + tree.balance = balance; + return !tree.balance; + } + else + { + int balance = tree.balance; + balance += remove_from_tree(tree.left,d); + tree.balance = balance; + return keep_node_balanced(t); + } + + } + // if item is on the right + else if (comp(tree.d , d)) + { + + // if the right side of the tree has the greatest height + if (tree.balance == 1) + { + int balance = tree.balance; + balance -= remove_from_tree(tree.right,d); + tree.balance = balance; + return !tree.balance; + } + else + { + int balance = tree.balance; + balance -= remove_from_tree(tree.right,d); + tree.balance = balance; + return keep_node_balanced(t); + } + } + // if item is found + else + { + + // if there is no left node + if (tree.left == 0) + { + + // plug hole left by removing this node and free memory + t = tree.right; // plug hole with right subtree + + // delete old node + pool.deallocate(&tree); + + // indicate that the height has changed + return true; + } + // if there is no right node + else if (tree.right == 0) + { + + // plug hole left by removing this node and free memory + t = tree.left; // plug hole with left subtree + + // delete old node + pool.deallocate(&tree); + + // indicate that the height of this tree has changed + return true; + } + // if there are both a left and right sub node + else + { + + // get an element that can replace the one being removed and do this + // if it made the right subtree shrink by one + if (remove_least_element_in_tree(tree.right,tree.d,tree.r)) + { + // adjust the tree height + --tree.balance; + + // if the height of the current tree has dropped by one + if (tree.balance == 0) + { + return true; + } + else + { + return keep_node_balanced(t); + } + } + // else this remove did not effect the height of this tree + else + { + return false; + } + + } + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + range* binary_search_tree_kernel_1:: + return_reference ( + node* t, + const domain& d + ) + { + while (t != 0) + { + + if ( comp(d , t->d )) + { + // if item is on the left then look in left + t = t->left; + } + else if (comp(t->d , d)) + { + // if item is on the right then look in right + t = t->right; + } + else + { + // if it's found then return a reference to it + return &(t->r); + } + } + return 0; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + const range* binary_search_tree_kernel_1:: + return_reference ( + const node* t, + const domain& d + ) const + { + while (t != 0) + { + + if ( comp(d , t->d) ) + { + // if item is on the left then look in left + t = t->left; + } + else if (comp(t->d , d)) + { + // if item is on the right then look in right + t = t->right; + } + else + { + // if it's found then return a reference to it + return &(t->r); + } + } + return 0; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + bool binary_search_tree_kernel_1:: + keep_node_balanced ( + node*& t + ) + { + // make a reference to the current node so we don't have to dereference + // a pointer a bunch of times + node& tree = *t; + + // if tree does not need to be balanced then return false + if (tree.balance == 0) + return false; + + + // if tree needs to be rotated left + if (tree.balance == 2) + { + if (tree.right->balance >= 0) + rotate_left(t); + else + double_rotate_left(t); + } + // else if the tree needs to be rotated right + else if (tree.balance == -2) + { + if (tree.left->balance <= 0) + rotate_right(t); + else + double_rotate_right(t); + } + + + if (t->balance == 0) + return true; + else + return false; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + unsigned long binary_search_tree_kernel_1:: + get_count ( + const domain& d, + node* tree_root + ) const + { + if (tree_root != 0) + { + if (comp(d , tree_root->d)) + { + // go left + return get_count(d,tree_root->left); + } + else if (comp(tree_root->d , d)) + { + // go right + return get_count(d,tree_root->right); + } + else + { + // go left and right to look for more matches + return get_count(d,tree_root->left) + + get_count(d,tree_root->right) + + 1; + } + } + return 0; + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_BINARY_SEARCH_TREE_KERNEl_1_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/binary_search_tree/binary_search_tree_kernel_2.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/binary_search_tree/binary_search_tree_kernel_2.h new file mode 100644 index 0000000..83866f2 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/binary_search_tree/binary_search_tree_kernel_2.h @@ -0,0 +1,1897 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_BINARY_SEARCH_TREE_KERNEl_2_ +#define DLIB_BINARY_SEARCH_TREE_KERNEl_2_ + +#include "binary_search_tree_kernel_abstract.h" +#include "../algs.h" +#include "../interfaces/map_pair.h" +#include "../interfaces/enumerable.h" +#include "../interfaces/remover.h" +#include "../serialize.h" +#include + +namespace dlib +{ + + template < + typename domain, + typename range, + typename mem_manager, + typename compare = std::less + > + class binary_search_tree_kernel_2 : public enumerable >, + public asc_pair_remover + { + + /*! + INITIAL VALUE + NIL == pointer to a node that represents a leaf + tree_size == 0 + tree_root == NIL + at_start == true + current_element == 0 + + + CONVENTION + current_element_valid() == (current_element != 0) + if (current_element_valid()) then + element() == current_element->d and current_element->r + at_start_ == at_start() + + + tree_size == size() + + NIL == pointer to a node that represents a leaf + + if (tree_size != 0) + tree_root == pointer to the root node of the binary search tree + else + tree_root == NIL + + tree_root->color == black + Every leaf is black and all leafs are the NIL node. + The number of black nodes in any path from the root to a leaf is the + same. + + for all nodes: + { + - left points to the left subtree or NIL if there is no left subtree + - right points to the right subtree or NIL if there is no right + subtree + - parent points to the parent node or NIL if the node is the root + - ordering of nodes is determined by comparing each node's d member + - all elements in a left subtree are <= the node + - all elements in a right subtree are >= the node + - color == red or black + - if (color == red) + - the node's children are black + } + + !*/ + + class node + { + public: + node* left; + node* right; + node* parent; + domain d; + range r; + char color; + }; + + class mpair : public map_pair + { + public: + const domain* d; + range* r; + + const domain& key( + ) const { return *d; } + + const range& value( + ) const { return *r; } + + range& value( + ) { return *r; } + }; + + + const static char red = 0; + const static char black = 1; + + + public: + + typedef domain domain_type; + typedef range range_type; + typedef compare compare_type; + typedef mem_manager mem_manager_type; + + binary_search_tree_kernel_2( + ) : + NIL(pool.allocate()), + tree_size(0), + tree_root(NIL), + current_element(0), + at_start_(true) + { + NIL->color = black; + NIL->left = 0; + NIL->right = 0; + NIL->parent = 0; + } + + virtual ~binary_search_tree_kernel_2( + ); + + inline void clear( + ); + + inline short height ( + ) const; + + inline unsigned long count ( + const domain& d + ) const; + + inline void add ( + domain& d, + range& r + ); + + void remove ( + const domain& d, + domain& d_copy, + range& r + ); + + void destroy ( + const domain& d + ); + + void remove_any ( + domain& d, + range& r + ); + + inline const range* operator[] ( + const domain& item + ) const; + + inline range* operator[] ( + const domain& item + ); + + inline void swap ( + binary_search_tree_kernel_2& item + ); + + // functions from the enumerable interface + inline size_t size ( + ) const; + + bool at_start ( + ) const; + + inline void reset ( + ) const; + + bool current_element_valid ( + ) const; + + const map_pair& element ( + ) const; + + map_pair& element ( + ); + + bool move_next ( + ) const; + + void remove_last_in_order ( + domain& d, + range& r + ); + + void remove_current_element ( + domain& d, + range& r + ); + + void position_enumerator ( + const domain& d + ) const; + + private: + + inline void rotate_left ( + node* t + ); + /*! + requires + - t != NIL + - t->right != NIL + ensures + - performs a left rotation around t and its right child + !*/ + + inline void rotate_right ( + node* t + ); + /*! + requires + - t != NIL + - t->left != NIL + ensures + - performs a right rotation around t and its left child + !*/ + + inline void double_rotate_right ( + node* t + ); + /*! + requires + - t != NIL + - t->left != NIL + - t->left->right != NIL + - double_rotate_right() is only called in fix_after_add() + ensures + - performs a left rotation around t->left + - then performs a right rotation around t + !*/ + + inline void double_rotate_left ( + node* t + ); + /*! + requires + - t != NIL + - t->right != NIL + - t->right->left != NIL + - double_rotate_left() is only called in fix_after_add() + ensures + - performs a right rotation around t->right + - then performs a left rotation around t + !*/ + + void remove_biggest_element_in_tree ( + node* t, + domain& d, + range& r + ); + /*! + requires + - t != NIL (i.e. there must be something in the tree to remove) + ensures + - the biggest node in t has been removed + - the biggest node element in t has been put into #d and #r + - #t is still a binary search tree + !*/ + + bool remove_least_element_in_tree ( + node* t, + domain& d, + range& r + ); + /*! + requires + - t != NIL (i.e. there must be something in the tree to remove) + ensures + - the least node in t has been removed + - the least node element in t has been put into #d and #r + - #t is still a binary search tree + - if (the node that was removed was the one pointed to by current_element) then + - returns true + - else + - returns false + !*/ + + void add_to_tree ( + node* t, + domain& d, + range& r + ); + /*! + requires + - t != NIL + ensures + - d and r are now in #t + - there is a mapping from d to r in #t + - #d and #r have initial values for their types + - #t is still a binary search tree + !*/ + + void remove_from_tree ( + node* t, + const domain& d, + domain& d_copy, + range& r + ); + /*! + requires + - return_reference(t,d) != 0 + ensures + - #d_copy is equivalent to d + - the first element in t equivalent to d that is encountered when searching down the tree + from t has been removed and swapped into #d_copy. Also, the associated range element + has been removed and swapped into #r. + - if (the node that got removed wasn't current_element) then + - adjusts the current_element pointer if the data in the node that it points to gets moved. + - else + - the value of current_element is now invalid + - #t is still a binary search tree + !*/ + + void remove_from_tree ( + node* t, + const domain& d + ); + /*! + requires + - return_reference(t,d) != 0 + ensures + - an element in t equivalent to d has been removed + - #t is still a binary search tree + !*/ + + const range* return_reference ( + const node* t, + const domain& d + ) const; + /*! + ensures + - if (there is a domain element equivalent to d in t) then + - returns a pointer to the element in the range equivalent to d + - else + - returns 0 + !*/ + + range* return_reference ( + node* t, + const domain& d + ); + /*! + ensures + - if (there is a domain element equivalent to d in t) then + - returns a pointer to the element in the range equivalent to d + - else + - returns 0 + !*/ + + void fix_after_add ( + node* t + ); + /*! + requires + - t == pointer to the node just added + - t->color == red + - t->parent != NIL (t must not be the root) + - fix_after_add() is only called after a new node has been added + to t + ensures + - fixes any deviations from the CONVENTION caused by adding a node + !*/ + + void fix_after_remove ( + node* t + ); + /*! + requires + - t == pointer to the only child of the node that was spliced out + - fix_after_remove() is only called after a node has been removed + from t + - the color of the spliced out node was black + ensures + - fixes any deviations from the CONVENTION causes by removing a node + !*/ + + + short tree_height ( + node* t + ) const; + /*! + ensures + - returns the number of nodes in the longest path from the root of the + tree to a leaf + !*/ + + void delete_tree ( + node* t + ); + /*! + requires + - t == root of binary search tree + - t != NIL + ensures + - deletes all nodes in t except for NIL + !*/ + + unsigned long get_count ( + const domain& item, + node* tree_root + ) const; + /*! + requires + - tree_root == the root of a binary search tree or NIL + ensures + - if (tree_root == NIL) then + - returns 0 + - else + - returns the number of elements in tree_root that are + equivalent to item + !*/ + + + + // data members + typename mem_manager::template rebind::other pool; + node* NIL; + unsigned long tree_size; + node* tree_root; + mutable node* current_element; + mutable bool at_start_; + mutable mpair p; + compare comp; + + + + // restricted functions + binary_search_tree_kernel_2(binary_search_tree_kernel_2&); + binary_search_tree_kernel_2& operator=(binary_search_tree_kernel_2&); + + + }; + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + inline void swap ( + binary_search_tree_kernel_2& a, + binary_search_tree_kernel_2& b + ) { a.swap(b); } + + + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void deserialize ( + binary_search_tree_kernel_2& item, + std::istream& in + ) + { + try + { + item.clear(); + unsigned long size; + deserialize(size,in); + domain d; + range r; + for (unsigned long i = 0; i < size; ++i) + { + deserialize(d,in); + deserialize(r,in); + item.add(d,r); + } + } + catch (serialization_error& e) + { + item.clear(); + throw serialization_error(e.info + "\n while deserializing object of type binary_search_tree_kernel_2"); + } + } + + + + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + binary_search_tree_kernel_2:: + ~binary_search_tree_kernel_2 ( + ) + { + if (tree_root != NIL) + delete_tree(tree_root); + pool.deallocate(NIL); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2:: + clear ( + ) + { + if (tree_size > 0) + { + delete_tree(tree_root); + tree_root = NIL; + tree_size = 0; + } + // reset the enumerator + reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + size_t binary_search_tree_kernel_2:: + size ( + ) const + { + return tree_size; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + short binary_search_tree_kernel_2:: + height ( + ) const + { + return tree_height(tree_root); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + unsigned long binary_search_tree_kernel_2:: + count ( + const domain& item + ) const + { + return get_count(item,tree_root); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2:: + add ( + domain& d, + range& r + ) + { + if (tree_size == 0) + { + tree_root = pool.allocate(); + tree_root->color = black; + tree_root->left = NIL; + tree_root->right = NIL; + tree_root->parent = NIL; + exchange(tree_root->d,d); + exchange(tree_root->r,r); + } + else + { + add_to_tree(tree_root,d,r); + } + ++tree_size; + // reset the enumerator + reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2:: + remove ( + const domain& d, + domain& d_copy, + range& r + ) + { + remove_from_tree(tree_root,d,d_copy,r); + --tree_size; + // reset the enumerator + reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2:: + destroy ( + const domain& item + ) + { + remove_from_tree(tree_root,item); + --tree_size; + // reset the enumerator + reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2:: + remove_any ( + domain& d, + range& r + ) + { + remove_least_element_in_tree(tree_root,d,r); + --tree_size; + // reset the enumerator + reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + range* binary_search_tree_kernel_2:: + operator[] ( + const domain& d + ) + { + return return_reference(tree_root,d); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + const range* binary_search_tree_kernel_2:: + operator[] ( + const domain& d + ) const + { + return return_reference(tree_root,d); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2:: + swap ( + binary_search_tree_kernel_2& item + ) + { + pool.swap(item.pool); + + exchange(p,item.p); + exchange(comp,item.comp); + + node* tree_root_temp = item.tree_root; + unsigned long tree_size_temp = item.tree_size; + node* const NIL_temp = item.NIL; + node* current_element_temp = item.current_element; + bool at_start_temp = item.at_start_; + + item.tree_root = tree_root; + item.tree_size = tree_size; + item.NIL = NIL; + item.current_element = current_element; + item.at_start_ = at_start_; + + tree_root = tree_root_temp; + tree_size = tree_size_temp; + NIL = NIL_temp; + current_element = current_element_temp; + at_start_ = at_start_temp; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2:: + remove_last_in_order ( + domain& d, + range& r + ) + { + remove_biggest_element_in_tree(tree_root,d,r); + --tree_size; + // reset the enumerator + reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2:: + remove_current_element ( + domain& d, + range& r + ) + { + node* t = current_element; + move_next(); + remove_from_tree(t,t->d,d,r); + --tree_size; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2:: + position_enumerator ( + const domain& d + ) const + { + // clear the enumerator state and make sure the stack is empty + reset(); + at_start_ = false; + node* t = tree_root; + node* parent = NIL; + bool went_left = false; + while (t != NIL) + { + if ( comp(d , t->d )) + { + // if item is on the left then look in left + parent = t; + t = t->left; + went_left = true; + } + else if (comp(t->d , d)) + { + // if item is on the right then look in right + parent = t; + t = t->right; + went_left = false; + } + else + { + current_element = t; + return; + } + } + + // if we didn't find any matches but there might be something after the + // d in this tree. + if (parent != NIL) + { + current_element = parent; + // if we went left from this node then this node is the next + // biggest. + if (went_left) + { + return; + } + else + { + move_next(); + } + } + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // enumerable function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + bool binary_search_tree_kernel_2:: + at_start ( + ) const + { + return at_start_; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2:: + reset ( + ) const + { + at_start_ = true; + current_element = 0; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + bool binary_search_tree_kernel_2:: + current_element_valid ( + ) const + { + return (current_element != 0); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + const map_pair& binary_search_tree_kernel_2:: + element ( + ) const + { + p.d = &(current_element->d); + p.r = &(current_element->r); + return p; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + map_pair& binary_search_tree_kernel_2:: + element ( + ) + { + p.d = &(current_element->d); + p.r = &(current_element->r); + return p; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + bool binary_search_tree_kernel_2:: + move_next ( + ) const + { + // if we haven't started iterating yet + if (at_start_) + { + at_start_ = false; + if (tree_size == 0) + { + return false; + } + else + { + // find the first element in the tree + current_element = tree_root; + node* temp = current_element->left; + while (temp != NIL) + { + current_element = temp; + temp = current_element->left; + } + return true; + } + } + else + { + if (current_element == 0) + { + return false; + } + else + { + bool went_up; // true if we went up the tree from a child node to parent + bool from_left = false; // true if we went up and were coming from a left child node + // find the next element in the tree + if (current_element->right != NIL) + { + // go right and down + current_element = current_element->right; + went_up = false; + } + else + { + went_up = true; + node* parent = current_element->parent; + if (parent == NIL) + { + // in this case we have iterated over all the element of the tree + current_element = 0; + return false; + } + + from_left = (parent->left == current_element); + // go up to parent + current_element = parent; + } + + + while (true) + { + if (went_up) + { + if (from_left) + { + // in this case we have found the next node + break; + } + else + { + // we should go up + node* parent = current_element->parent; + from_left = (parent->left == current_element); + current_element = parent; + if (current_element == NIL) + { + // in this case we have iterated over all the elements + // in the tree + current_element = 0; + return false; + } + } + } + else + { + // we just went down to a child node + if (current_element->left != NIL) + { + // go left + went_up = false; + current_element = current_element->left; + } + else + { + // if there is no left child then we have found the next node + break; + } + } + } + + return true; + } + } + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // private member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2:: + delete_tree ( + node* t + ) + { + if (t->left != NIL) + delete_tree(t->left); + if (t->right != NIL) + delete_tree(t->right); + pool.deallocate(t); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2:: + rotate_left ( + node* t + ) + { + + // perform the rotation + node* temp = t->right; + t->right = temp->left; + if (temp->left != NIL) + temp->left->parent = t; + temp->left = t; + temp->parent = t->parent; + + + if (t == tree_root) + tree_root = temp; + else + { + // if t was on the left + if (t->parent->left == t) + t->parent->left = temp; + else + t->parent->right = temp; + } + + t->parent = temp; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2:: + rotate_right ( + node* t + ) + { + // perform the rotation + node* temp = t->left; + t->left = temp->right; + if (temp->right != NIL) + temp->right->parent = t; + temp->right = t; + temp->parent = t->parent; + + if (t == tree_root) + tree_root = temp; + else + { + // if t is a left child + if (t->parent->left == t) + t->parent->left = temp; + else + t->parent->right = temp; + } + + t->parent = temp; + } + + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2:: + double_rotate_right ( + node* t + ) + { + + // preform the rotation + node& temp = *(t->left->right); + t->left = temp.right; + temp.right->parent = t; + temp.left->parent = temp.parent; + temp.parent->right = temp.left; + temp.parent->parent = &temp; + temp.right = t; + temp.left = temp.parent; + temp.parent = t->parent; + + + if (tree_root == t) + tree_root = &temp; + else + { + // t is a left child + if (t->parent->left == t) + t->parent->left = &temp; + else + t->parent->right = &temp; + } + t->parent = &temp; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2:: + double_rotate_left ( + node* t + ) + { + + + // preform the rotation + node& temp = *(t->right->left); + t->right = temp.left; + temp.left->parent = t; + temp.right->parent = temp.parent; + temp.parent->left = temp.right; + temp.parent->parent = &temp; + temp.left = t; + temp.right = temp.parent; + temp.parent = t->parent; + + + if (tree_root == t) + tree_root = &temp; + else + { + // t is a left child + if (t->parent->left == t) + t->parent->left = &temp; + else + t->parent->right = &temp; + } + t->parent = &temp; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2:: + remove_biggest_element_in_tree ( + node* t, + domain& d, + range& r + ) + { + + node* next = t->right; + node* child; // the child node of the one we will slice out + + if (next == NIL) + { + // need to determine if t is a right or left child + if (t->parent->right == t) + child = t->parent->right = t->left; + else + child = t->parent->left = t->left; + + // update tree_root if necessary + if (t == tree_root) + tree_root = child; + } + else + { + // find the least node + do + { + t = next; + next = next->right; + } while (next != NIL); + // t is a right child + child = t->parent->right = t->left; + + } + + // swap the item from this node into d and r + exchange(d,t->d); + exchange(r,t->r); + + // plug hole right by removing this node + child->parent = t->parent; + + // keep the red-black properties true + if (t->color == black) + fix_after_remove(child); + + // free the memory for this removed node + pool.deallocate(t); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + bool binary_search_tree_kernel_2:: + remove_least_element_in_tree ( + node* t, + domain& d, + range& r + ) + { + + node* next = t->left; + node* child; // the child node of the one we will slice out + + if (next == NIL) + { + // need to determine if t is a left or right child + if (t->parent->left == t) + child = t->parent->left = t->right; + else + child = t->parent->right = t->right; + + // update tree_root if necessary + if (t == tree_root) + tree_root = child; + } + else + { + // find the least node + do + { + t = next; + next = next->left; + } while (next != NIL); + // t is a left child + child = t->parent->left = t->right; + + } + + // swap the item from this node into d and r + exchange(d,t->d); + exchange(r,t->r); + + // plug hole left by removing this node + child->parent = t->parent; + + // keep the red-black properties true + if (t->color == black) + fix_after_remove(child); + + bool rvalue = (t == current_element); + // free the memory for this removed node + pool.deallocate(t); + return rvalue; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2:: + add_to_tree ( + node* t, + domain& d, + range& r + ) + { + // parent of the current node + node* parent; + + // find a place to add node + while (true) + { + parent = t; + // if item should be put on the left then go left + if (comp(d , t->d)) + { + t = t->left; + if (t == NIL) + { + t = parent->left = pool.allocate(); + break; + } + } + // if item should be put on the right then go right + else + { + t = t->right; + if (t == NIL) + { + t = parent->right = pool.allocate(); + break; + } + } + } + + // t is now the node where we will add item and + // parent is the parent of t + + t->parent = parent; + t->left = NIL; + t->right = NIL; + t->color = red; + exchange(t->d,d); + exchange(t->r,r); + + + // keep the red-black properties true + fix_after_add(t); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2:: + remove_from_tree ( + node* t, + const domain& d, + domain& d_copy, + range& r + ) + { + while (true) + { + if ( comp(d , t->d) ) + { + // if item is on the left then look in left + t = t->left; + } + else if (comp(t->d , d)) + { + // if item is on the right then look in right + t = t->right; + } + else + { + // found the node we want to remove + + // swap out the item into d_copy and r + exchange(d_copy,t->d); + exchange(r,t->r); + + if (t->left == NIL) + { + // if there is no left subtree + + node* parent = t->parent; + + // plug hole with right subtree + + + // if t is on the left + if (parent->left == t) + parent->left = t->right; + else + parent->right = t->right; + t->right->parent = parent; + + // update tree_root if necessary + if (t == tree_root) + tree_root = t->right; + + if (t->color == black) + fix_after_remove(t->right); + + // delete old node + pool.deallocate(t); + } + else if (t->right == NIL) + { + // if there is no right subtree + + node* parent = t->parent; + + // plug hole with left subtree + if (parent->left == t) + parent->left = t->left; + else + parent->right = t->left; + t->left->parent = parent; + + // update tree_root if necessary + if (t == tree_root) + tree_root = t->left; + + if (t->color == black) + fix_after_remove(t->left); + + // delete old node + pool.deallocate(t); + } + else + { + // if there is both a left and right subtree + // get an element to fill this node now that its been swapped into + // item_copy + if (remove_least_element_in_tree(t->right,t->d,t->r)) + { + // the node removed was the one pointed to by current_element so we + // need to update it so that it points to the right spot. + current_element = t; + } + } + + // quit loop + break; + } + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2:: + remove_from_tree ( + node* t, + const domain& d + ) + { + while (true) + { + if ( comp(d , t->d) ) + { + // if item is on the left then look in left + t = t->left; + } + else if (comp(t->d , d)) + { + // if item is on the right then look in right + t = t->right; + } + else + { + // found the node we want to remove + + + if (t->left == NIL) + { + // if there is no left subtree + + node* parent = t->parent; + + // plug hole with right subtree + + + if (parent->left == t) + parent->left = t->right; + else + parent->right = t->right; + t->right->parent = parent; + + // update tree_root if necessary + if (t == tree_root) + tree_root = t->right; + + if (t->color == black) + fix_after_remove(t->right); + + // delete old node + pool.deallocate(t); + } + else if (t->right == NIL) + { + // if there is no right subtree + + node* parent = t->parent; + + // plug hole with left subtree + if (parent->left == t) + parent->left = t->left; + else + parent->right = t->left; + t->left->parent = parent; + + // update tree_root if necessary + if (t == tree_root) + tree_root = t->left; + + if (t->color == black) + fix_after_remove(t->left); + + // delete old node + pool.deallocate(t); + } + else + { + // if there is both a left and right subtree + // get an element to fill this node now that its been swapped into + // item_copy + remove_least_element_in_tree(t->right,t->d,t->r); + + } + + // quit loop + break; + } + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + range* binary_search_tree_kernel_2:: + return_reference ( + node* t, + const domain& d + ) + { + while (t != NIL) + { + if ( comp(d , t->d )) + { + // if item is on the left then look in left + t = t->left; + } + else if (comp(t->d , d)) + { + // if item is on the right then look in right + t = t->right; + } + else + { + // if it's found then return a reference to it + return &(t->r); + } + } + return 0; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + const range* binary_search_tree_kernel_2:: + return_reference ( + const node* t, + const domain& d + ) const + { + while (t != NIL) + { + if ( comp(d , t->d) ) + { + // if item is on the left then look in left + t = t->left; + } + else if (comp(t->d , d)) + { + // if item is on the right then look in right + t = t->right; + } + else + { + // if it's found then return a reference to it + return &(t->r); + } + } + return 0; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2:: + fix_after_add ( + node* t + ) + { + + while (t->parent->color == red) + { + node& grandparent = *(t->parent->parent); + + // if both t's parent and its sibling are red + if (grandparent.left->color == grandparent.right->color) + { + grandparent.color = red; + grandparent.left->color = black; + grandparent.right->color = black; + t = &grandparent; + } + else + { + // if t is a left child + if (t == t->parent->left) + { + // if t's parent is a left child + if (t->parent == grandparent.left) + { + grandparent.color = red; + grandparent.left->color = black; + rotate_right(&grandparent); + } + // if t's parent is a right child + else + { + t->color = black; + grandparent.color = red; + double_rotate_left(&grandparent); + } + } + // if t is a right child + else + { + // if t's parent is a left child + if (t->parent == grandparent.left) + { + t->color = black; + grandparent.color = red; + double_rotate_right(&grandparent); + } + // if t's parent is a right child + else + { + grandparent.color = red; + grandparent.right->color = black; + rotate_left(&grandparent); + } + } + break; + } + } + tree_root->color = black; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void binary_search_tree_kernel_2:: + fix_after_remove ( + node* t + ) + { + + while (t != tree_root && t->color == black) + { + if (t->parent->left == t) + { + node* sibling = t->parent->right; + if (sibling->color == red) + { + sibling->color = black; + t->parent->color = red; + rotate_left(t->parent); + sibling = t->parent->right; + } + + if (sibling->left->color == black && sibling->right->color == black) + { + sibling->color = red; + t = t->parent; + } + else + { + if (sibling->right->color == black) + { + sibling->left->color = black; + sibling->color = red; + rotate_right(sibling); + sibling = t->parent->right; + } + + sibling->color = t->parent->color; + t->parent->color = black; + sibling->right->color = black; + rotate_left(t->parent); + t = tree_root; + + } + + + } + else + { + + node* sibling = t->parent->left; + if (sibling->color == red) + { + sibling->color = black; + t->parent->color = red; + rotate_right(t->parent); + sibling = t->parent->left; + } + + if (sibling->left->color == black && sibling->right->color == black) + { + sibling->color = red; + t = t->parent; + } + else + { + if (sibling->left->color == black) + { + sibling->right->color = black; + sibling->color = red; + rotate_left(sibling); + sibling = t->parent->left; + } + + sibling->color = t->parent->color; + t->parent->color = black; + sibling->left->color = black; + rotate_right(t->parent); + t = tree_root; + + } + + + } + + } + t->color = black; + + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + short binary_search_tree_kernel_2:: + tree_height ( + node* t + ) const + { + if (t == NIL) + return 0; + + short height1 = tree_height(t->left); + short height2 = tree_height(t->right); + if (height1 > height2) + return height1 + 1; + else + return height2 + 1; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + unsigned long binary_search_tree_kernel_2:: + get_count ( + const domain& d, + node* tree_root + ) const + { + if (tree_root != NIL) + { + if (comp(d , tree_root->d)) + { + // go left + return get_count(d,tree_root->left); + } + else if (comp(tree_root->d , d)) + { + // go right + return get_count(d,tree_root->right); + } + else + { + // go left and right to look for more matches + return get_count(d,tree_root->left) + + get_count(d,tree_root->right) + + 1; + } + } + return 0; + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_BINARY_SEARCH_TREE_KERNEl_2_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/binary_search_tree/binary_search_tree_kernel_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/binary_search_tree/binary_search_tree_kernel_abstract.h new file mode 100644 index 0000000..2abfe7e --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/binary_search_tree/binary_search_tree_kernel_abstract.h @@ -0,0 +1,311 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_BINARY_SEARCH_TREE_KERNEl_ABSTRACT_ +#ifdef DLIB_BINARY_SEARCH_TREE_KERNEl_ABSTRACT_ + +#include "../interfaces/map_pair.h" +#include "../interfaces/enumerable.h" +#include "../interfaces/remover.h" +#include "../serialize.h" +#include "../algs.h" +#include + +namespace dlib +{ + + template < + typename domain, + typename range, + typename mem_manager = default_memory_manager, + typename compare = std::less + > + class binary_search_tree : public enumerable >, + public asc_pair_remover + { + + /*! + REQUIREMENTS ON domain + domain must be comparable by compare where compare is a functor compatible with std::less and + domain is swappable by a global swap() and + domain must have a default constructor + + REQUIREMENTS ON range + range is swappable by a global swap() and + range must have a default constructor + + REQUIREMENTS ON mem_manager + must be an implementation of memory_manager/memory_manager_kernel_abstract.h or + must be an implementation of memory_manager_global/memory_manager_global_kernel_abstract.h or + must be an implementation of memory_manager_stateless/memory_manager_stateless_kernel_abstract.h + mem_manager::type can be set to anything. + + + POINTERS AND REFERENCES TO INTERNAL DATA + swap(), count(), height(), and operator[] functions + do not invalidate pointers or references to internal data. + + position_enumerator() invalidates pointers or references to + data returned by element() and only by element() (i.e. pointers and + references returned by operator[] are still valid). + + All other functions have no such guarantees. + + INITIAL VALUE + size() == 0 + height() == 0 + + ENUMERATION ORDER + The enumerator will iterate over the domain (and each associated + range element) elements in ascending order according to the compare functor. + (i.e. the elements are enumerated in sorted order) + + WHAT THIS OBJECT REPRESENTS + this object represents a data dictionary that is built on top of some + kind of binary search tree. It maps objects of type domain to objects + of type range. + + Also note that unless specified otherwise, no member functions + of this object throw exceptions. + + NOTE: + definition of equivalent: + a is equivalent to b if + a < b == false and + b < a == false + !*/ + + + public: + + typedef domain domain_type; + typedef range range_type; + typedef compare compare_type; + typedef mem_manager mem_manager_type; + + binary_search_tree( + ); + /*! + ensures + - #*this is properly initialized + throws + - std::bad_alloc or any exception thrown by domain's or range's + constructor. + !*/ + + virtual ~binary_search_tree( + ); + /*! + ensures + - all memory associated with *this has been released + !*/ + + void clear( + ); + /*! + ensures + - #*this has its initial value + throws + - std::bad_alloc or any exception thrown by domain's or range's + constructor. + if this exception is thrown then *this is unusable + until clear() is called and succeeds + !*/ + + short height ( + ) const; + /*! + ensures + - returns the number of elements in the longest path from the root + of the tree to a leaf + !*/ + + unsigned long count ( + const domain& d + ) const; + /*! + ensures + - returns the number of elements in the domain of *this that are + equivalent to d + !*/ + + void add ( + domain& d, + range& r + ); + /*! + requires + - &d != &r (i.e. d and r cannot be the same variable) + ensures + - adds a mapping between d and r to *this + - if (count(d) == 0) then + - #*(*this)[d] == r + - else + - #(*this)[d] != 0 + - #d and #r have initial values for their types + - #count(d) == count(d) + 1 + - #at_start() == true + - #size() == size() + 1 + throws + - std::bad_alloc or any exception thrown by domain's or range's + constructor. + if add() throws then it has no effect + !*/ + + void remove ( + const domain& d, + domain& d_copy, + range& r + ); + /*! + requires + - (*this)[d] != 0 + - &d != &r (i.e. d and r cannot be the same variable) + - &d != &d_copy (i.e. d and d_copy cannot be the same variable) + - &r != &d_copy (i.e. r and d_copy cannot be the same variable) + ensures + - some element in the domain of *this that is equivalent to d has + been removed and swapped into #d_copy. Additionally, its + associated range element has been removed and swapped into #r. + - #count(d) == count(d) - 1 + - #size() == size() - 1 + - #at_start() == true + !*/ + + void destroy ( + const domain& d + ); + /*! + requires + - (*this)[d] != 0 + ensures + - an element in the domain of *this equivalent to d has been removed. + The element in the range of *this associated with d has also been + removed. + - #count(d) == count(d) - 1 + - #size() == size() - 1 + - #at_start() == true + !*/ + + void remove_last_in_order ( + domain& d, + range& r + ); + /*! + requires + - size() > 0 + ensures + - the last/biggest (according to the compare functor) element in the domain of *this has + been removed and swapped into #d. The element in the range of *this + associated with #d has also been removed and swapped into #r. + - #count(#d) == count(#d) - 1 + - #size() == size() - 1 + - #at_start() == true + !*/ + + void remove_current_element ( + domain& d, + range& r + ); + /*! + requires + - current_element_valid() == true + ensures + - the current element given by element() has been removed and swapped into d and r. + - #d == element().key() + - #r == element().value() + - #count(#d) == count(#d) - 1 + - #size() == size() - 1 + - moves the enumerator to the next element. If element() was the last + element in enumeration order then #current_element_valid() == false + and #at_start() == false. + !*/ + + void position_enumerator ( + const domain& d + ) const; + /*! + ensures + - #at_start() == false + - if (count(d) > 0) then + - #element().key() == d + - else if (there are any items in the domain of *this that are bigger than + d according to the compare functor) then + - #element().key() == the smallest item in the domain of *this that is + bigger than d according to the compare functor. + - else + - #current_element_valid() == false + !*/ + + const range* operator[] ( + const domain& d + ) const; + /*! + ensures + - if (there is an element in the domain equivalent to d) then + - returns a pointer to an element in the range of *this that + is associated with an element in the domain of *this + equivalent to d. + - else + - returns 0 + !*/ + + range* operator[] ( + const domain& d + ); + /*! + ensures + - if (there is an element in the domain equivalent to d) then + - returns a pointer to an element in the range of *this that + is associated with an element in the domain of *this + equivalent to d. + - else + - returns 0 + !*/ + + void swap ( + binary_search_tree& item + ); + /*! + ensures + - swaps *this and item + !*/ + + private: + + // restricted functions + binary_search_tree(binary_search_tree&); + binary_search_tree& operator=(binary_search_tree&); + + }; + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + inline void swap ( + binary_search_tree& a, + binary_search_tree& b + ) { a.swap(b); } + /*! + provides a global swap function + !*/ + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void deserialize ( + binary_search_tree& item, + std::istream& in + ); + /*! + provides deserialization support + !*/ +} + +#endif // DLIB_BINARY_SEARCH_TREE_KERNEl_ABSTRACT_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/binary_search_tree/binary_search_tree_kernel_c.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/binary_search_tree/binary_search_tree_kernel_c.h new file mode 100644 index 0000000..0dc1539 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/binary_search_tree/binary_search_tree_kernel_c.h @@ -0,0 +1,235 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_BINARY_SEARCH_TREE_KERNEl_C_ +#define DLIB_BINARY_SEARCH_TREE_KERNEl_C_ + +#include "../interfaces/map_pair.h" +#include "binary_search_tree_kernel_abstract.h" +#include "../algs.h" +#include "../assert.h" + +namespace dlib +{ + + template < + typename bst_base + > + class binary_search_tree_kernel_c : public bst_base + { + typedef typename bst_base::domain_type domain; + typedef typename bst_base::range_type range; + + public: + + binary_search_tree_kernel_c () {} + + void remove ( + const domain& d, + domain& d_copy, + range& r + ); + + void destroy ( + const domain& d + ); + + void add ( + domain& d, + range& r + ); + + void remove_any ( + domain& d, + range& r + ); + + const map_pair& element( + ) const + { + DLIB_CASSERT(this->current_element_valid() == true, + "\tconst map_pair& binary_search_tree::element() const" + << "\n\tyou can't access the current element if it doesn't exist" + << "\n\tthis: " << this + ); + + return bst_base::element(); + } + + map_pair& element( + ) + { + DLIB_CASSERT(this->current_element_valid() == true, + "\tmap_pair& binary_search_tree::element()" + << "\n\tyou can't access the current element if it doesn't exist" + << "\n\tthis: " << this + ); + + return bst_base::element(); + } + + void remove_last_in_order ( + domain& d, + range& r + ); + + void remove_current_element ( + domain& d, + range& r + ); + + + }; + + + template < + typename bst_base + > + inline void swap ( + binary_search_tree_kernel_c& a, + binary_search_tree_kernel_c& b + ) { a.swap(b); } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename bst_base + > + void binary_search_tree_kernel_c:: + add ( + domain& d, + range& r + ) + { + DLIB_CASSERT( static_cast(&d) != static_cast(&r), + "\tvoid binary_search_tree::add" + << "\n\tyou can't call add() and give the same object to both parameters." + << "\n\tthis: " << this + << "\n\t&d: " << &d + << "\n\t&r: " << &r + << "\n\tsize(): " << this->size() + ); + + bst_base::add(d,r); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename bst_base + > + void binary_search_tree_kernel_c:: + destroy ( + const domain& d + ) + { + DLIB_CASSERT(this->operator[](d) != 0, + "\tvoid binary_search_tree::destroy" + << "\n\tthe element must be in the tree for it to be removed" + << "\n\tthis: " << this + << "\n\t&d: " << &d + ); + + bst_base::destroy(d); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename bst_base + > + void binary_search_tree_kernel_c:: + remove ( + const domain& d, + domain& d_copy, + range& r + ) + { + DLIB_CASSERT(this->operator[](d) != 0 && + (static_cast(&d) != static_cast(&d_copy)) && + (static_cast(&d) != static_cast(&r)) && + (static_cast(&r) != static_cast(&d_copy)), + "\tvoid binary_search_tree::remove" + << "\n\tthe element must be in the tree for it to be removed" + << "\n\tthis: " << this + << "\n\t&d: " << &d + << "\n\t&d_copy: " << &d_copy + << "\n\t&r: " << &r + ); + + bst_base::remove(d,d_copy,r); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename bst_base + > + void binary_search_tree_kernel_c:: + remove_any( + domain& d, + range& r + ) + { + DLIB_CASSERT(this->size() != 0 && + (static_cast(&d) != static_cast(&r)), + "\tvoid binary_search_tree::remove_any" + << "\n\ttree must not be empty if something is going to be removed" + << "\n\tthis: " << this + << "\n\t&d: " << &d + << "\n\t&r: " << &r + ); + + bst_base::remove_any(d,r); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename bst_base + > + void binary_search_tree_kernel_c:: + remove_last_in_order ( + domain& d, + range& r + ) + { + DLIB_CASSERT(this->size() > 0, + "\tvoid binary_search_tree::remove_last_in_order()" + << "\n\tyou can't remove an element if it doesn't exist" + << "\n\tthis: " << this + ); + + bst_base::remove_last_in_order(d,r); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename bst_base + > + void binary_search_tree_kernel_c:: + remove_current_element ( + domain& d, + range& r + ) + { + DLIB_CASSERT(this->current_element_valid() == true, + "\tvoid binary_search_tree::remove_current_element()" + << "\n\tyou can't remove the current element if it doesn't exist" + << "\n\tthis: " << this + ); + + bst_base::remove_current_element(d,r); + } + + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_BINARY_SEARCH_TREE_KERNEl_C_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/bound_function_pointer.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/bound_function_pointer.h new file mode 100644 index 0000000..a482919 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/bound_function_pointer.h @@ -0,0 +1,10 @@ +// Copyright (C) 2008 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_BOUND_FUNCTION_POINTEr_ +#define DLIB_BOUND_FUNCTION_POINTEr_ + +#include "bound_function_pointer/bound_function_pointer_kernel_1.h" + +#endif // DLIB_BOUND_FUNCTION_POINTEr_ + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/bound_function_pointer/bound_function_pointer_kernel_1.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/bound_function_pointer/bound_function_pointer_kernel_1.h new file mode 100644 index 0000000..a395927 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/bound_function_pointer/bound_function_pointer_kernel_1.h @@ -0,0 +1,774 @@ +// Copyright (C) 2008 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_BOUND_FUNCTION_POINTER_KERNEl_1_ +#define DLIB_BOUND_FUNCTION_POINTER_KERNEl_1_ + +#include "../algs.h" +#include "../member_function_pointer.h" +#include "bound_function_pointer_kernel_abstract.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + namespace bfp1_helpers + { + template struct strip { typedef T type; }; + template struct strip { typedef T type; }; + + // ------------------------------------------------------------------------------------ + + class bound_function_helper_base_base + { + public: + virtual ~bound_function_helper_base_base(){} + virtual void call() const = 0; + virtual bool is_set() const = 0; + virtual void clone(void* ptr) const = 0; + }; + + // ------------------------------------------------------------------------------------ + + template + class bound_function_helper_base : public bound_function_helper_base_base + { + public: + bound_function_helper_base():arg1(0), arg2(0), arg3(0), arg4(0) {} + + typename strip::type* arg1; + typename strip::type* arg2; + typename strip::type* arg3; + typename strip::type* arg4; + + + member_function_pointer mfp; + }; + + // ---------------- + + template + class bound_function_helper : public bound_function_helper_base + { + public: + void call() const + { + (*fp)(*this->arg1, *this->arg2, *this->arg3, *this->arg4); + } + + typename strip::type* fp; + }; + + template + class bound_function_helper : public bound_function_helper_base + { + public: + void call() const + { + if (this->mfp) this->mfp(*this->arg1, *this->arg2, *this->arg3, *this->arg4); + else if (fp) fp(*this->arg1, *this->arg2, *this->arg3, *this->arg4); + } + + void (*fp)(T1, T2, T3, T4); + }; + + // ---------------- + + template + class bound_function_helper : public bound_function_helper_base + { + public: + void call() const + { + (*fp)(); + } + + typename strip::type* fp; + }; + + template <> + class bound_function_helper : public bound_function_helper_base + { + public: + void call() const + { + if (this->mfp) this->mfp(); + else if (fp) fp(); + } + + void (*fp)(); + }; + + // ---------------- + + template + class bound_function_helper : public bound_function_helper_base + { + public: + void call() const + { + (*fp)(*this->arg1); + } + + typename strip::type* fp; + }; + + template + class bound_function_helper : public bound_function_helper_base + { + public: + void call() const + { + if (this->mfp) this->mfp(*this->arg1); + else if (fp) fp(*this->arg1); + } + + void (*fp)(T1); + }; + + // ---------------- + + template + class bound_function_helper : public bound_function_helper_base + { + public: + void call() const + { + (*fp)(*this->arg1, *this->arg2); + } + + typename strip::type* fp; + }; + + template + class bound_function_helper : public bound_function_helper_base + { + public: + void call() const + { + if (this->mfp) this->mfp(*this->arg1, *this->arg2); + else if (fp) fp(*this->arg1, *this->arg2); + } + + void (*fp)(T1, T2); + }; + + // ---------------- + + template + class bound_function_helper : public bound_function_helper_base + { + public: + void call() const + { + (*fp)(*this->arg1, *this->arg2, *this->arg3); + } + + typename strip::type* fp; + }; + + template + class bound_function_helper : public bound_function_helper_base + { + public: + + void call() const + { + if (this->mfp) this->mfp(*this->arg1, *this->arg2, *this->arg3); + else if (fp) fp(*this->arg1, *this->arg2, *this->arg3); + } + + void (*fp)(T1, T2, T3); + }; + + // ------------------------------------------------------------------------------------ + // ------------------------------------------------------------------------------------ + + template + class bound_function_helper_T : public T + { + public: + bound_function_helper_T(){ this->fp = 0;} + + bool is_set() const + { + return this->fp != 0 || this->mfp.is_set(); + } + + template + void safe_clone(stack_based_memory_block& buf) + { + // This is here just to validate the assumption that our block of memory we have made + // in bf_memory is the right size to store the data for this object. If you + // get a compiler error on this line then email me :) + COMPILE_TIME_ASSERT(sizeof(bound_function_helper_T) <= mem_size); + clone(buf.get()); + } + + void clone (void* ptr) const + { + bound_function_helper_T* p = new(ptr) bound_function_helper_T(); + p->arg1 = this->arg1; + p->arg2 = this->arg2; + p->arg3 = this->arg3; + p->arg4 = this->arg4; + p->fp = this->fp; + p->mfp = this->mfp; + } + }; + + } + +// ---------------------------------------------------------------------------------------- + + class bound_function_pointer + { + typedef bfp1_helpers::bound_function_helper_T > bf_null_type; + + public: + + // These typedefs are here for backwards compatibility with previous versions of + // dlib. + typedef bound_function_pointer kernel_1a; + typedef bound_function_pointer kernel_1a_c; + + + bound_function_pointer ( + ) { bf_null_type().safe_clone(bf_memory); } + + bound_function_pointer ( + const bound_function_pointer& item + ) { item.bf()->clone(bf_memory.get()); } + + ~bound_function_pointer() + { destroy_bf_memory(); } + + bound_function_pointer& operator= ( + const bound_function_pointer& item + ) { bound_function_pointer(item).swap(*this); return *this; } + + void clear ( + ) { bound_function_pointer().swap(*this); } + + bool is_set ( + ) const + { + return bf()->is_set(); + } + + void swap ( + bound_function_pointer& item + ) + { + // make a temp copy of item + bound_function_pointer temp(item); + + // destory the stuff in item + item.destroy_bf_memory(); + // copy *this into item + bf()->clone(item.bf_memory.get()); + + // destory the stuff in this + destroy_bf_memory(); + // copy temp into *this + temp.bf()->clone(bf_memory.get()); + } + + void operator() ( + ) const + { + // make sure requires clause is not broken + DLIB_ASSERT(is_set() == true , + "\tvoid bound_function_pointer::operator()" + << "\n\tYou must call set() before you can use this function" + << "\n\tthis: " << this + ); + + bf()->call(); + } + + private: + struct dummy{ void nonnull() {}}; + typedef void (dummy::*safe_bool)(); + + public: + operator safe_bool () const { return is_set() ? &dummy::nonnull : 0; } + bool operator!() const { return !is_set(); } + + // ------------------------------------------- + // set function object overloads + // ------------------------------------------- + + template + void set ( + F& function_object + ) + { + COMPILE_TIME_ASSERT(is_function::value == false); + COMPILE_TIME_ASSERT(is_pointer_type::value == false); + + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T > bf_helper_type; + + bf_helper_type temp; + temp.fp = &function_object; + + temp.safe_clone(bf_memory); + } + + template + void set ( + F& function_object, + A1& arg1 + ) + { + COMPILE_TIME_ASSERT(is_function::value == false); + COMPILE_TIME_ASSERT(is_pointer_type::value == false); + + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.fp = &function_object; + + temp.safe_clone(bf_memory); + } + + template + void set ( + F& function_object, + A1& arg1, + A2& arg2 + ) + { + COMPILE_TIME_ASSERT(is_function::value == false); + COMPILE_TIME_ASSERT(is_pointer_type::value == false); + + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.arg2 = &arg2; + temp.fp = &function_object; + + temp.safe_clone(bf_memory); + } + + template + void set ( + F& function_object, + A1& arg1, + A2& arg2, + A3& arg3 + ) + { + COMPILE_TIME_ASSERT(is_function::value == false); + COMPILE_TIME_ASSERT(is_pointer_type::value == false); + + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.arg2 = &arg2; + temp.arg3 = &arg3; + temp.fp = &function_object; + + temp.safe_clone(bf_memory); + } + + template + void set ( + F& function_object, + A1& arg1, + A2& arg2, + A3& arg3, + A4& arg4 + ) + { + COMPILE_TIME_ASSERT(is_function::value == false); + COMPILE_TIME_ASSERT(is_pointer_type::value == false); + + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.arg2 = &arg2; + temp.arg3 = &arg3; + temp.arg4 = &arg4; + temp.fp = &function_object; + + temp.safe_clone(bf_memory); + } + + // ------------------------------------------- + // set mfp overloads + // ------------------------------------------- + + template + void set ( + T& object, + void (T::*funct)() + ) + { + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T > bf_helper_type; + + bf_helper_type temp; + temp.mfp.set(object,funct); + + temp.safe_clone(bf_memory); + } + + template + void set ( + const T& object, + void (T::*funct)()const + ) + { + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T > bf_helper_type; + + bf_helper_type temp; + temp.mfp.set(object,funct); + + temp.safe_clone(bf_memory); + } + + // ------------------------------------------- + + template + void set ( + T& object, + void (T::*funct)(T1), + A1& arg1 + ) + { + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.mfp.set(object,funct); + + temp.safe_clone(bf_memory); + } + + template + void set ( + const T& object, + void (T::*funct)(T1)const, + A1& arg1 + ) + { + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.mfp.set(object,funct); + + temp.safe_clone(bf_memory); + } + + // ---------------- + + template + void set ( + T& object, + void (T::*funct)(T1, T2), + A1& arg1, + A2& arg2 + ) + { + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.arg2 = &arg2; + temp.mfp.set(object,funct); + + temp.safe_clone(bf_memory); + } + + template + void set ( + const T& object, + void (T::*funct)(T1, T2)const, + A1& arg1, + A2& arg2 + ) + { + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.arg2 = &arg2; + temp.mfp.set(object,funct); + + temp.safe_clone(bf_memory); + } + + // ---------------- + + template + void set ( + T& object, + void (T::*funct)(T1, T2, T3), + A1& arg1, + A2& arg2, + A3& arg3 + ) + { + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.arg2 = &arg2; + temp.arg3 = &arg3; + temp.mfp.set(object,funct); + + temp.safe_clone(bf_memory); + } + + template + void set ( + const T& object, + void (T::*funct)(T1, T2, T3)const, + A1& arg1, + A2& arg2, + A3& arg3 + ) + { + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.arg2 = &arg2; + temp.arg3 = &arg3; + temp.mfp.set(object,funct); + + temp.safe_clone(bf_memory); + } + + // ---------------- + + template + void set ( + T& object, + void (T::*funct)(T1, T2, T3, T4), + A1& arg1, + A2& arg2, + A3& arg3, + A4& arg4 + ) + { + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.arg2 = &arg2; + temp.arg3 = &arg3; + temp.arg4 = &arg4; + temp.mfp.set(object,funct); + + temp.safe_clone(bf_memory); + } + + template + void set ( + const T& object, + void (T::*funct)(T1, T2, T3, T4)const, + A1& arg1, + A2& arg2, + A3& arg3, + A4& arg4 + ) + { + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.arg2 = &arg2; + temp.arg3 = &arg3; + temp.arg4 = &arg4; + temp.mfp.set(object,funct); + + temp.safe_clone(bf_memory); + } + + // ------------------------------------------- + // set fp overloads + // ------------------------------------------- + + void set ( + void (*funct)() + ) + { + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T > bf_helper_type; + + bf_helper_type temp; + temp.fp = funct; + + temp.safe_clone(bf_memory); + } + + template + void set ( + void (*funct)(T1), + A1& arg1 + ) + { + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.fp = funct; + + temp.safe_clone(bf_memory); + } + + template + void set ( + void (*funct)(T1, T2), + A1& arg1, + A2& arg2 + ) + { + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.arg2 = &arg2; + temp.fp = funct; + + temp.safe_clone(bf_memory); + } + + template + void set ( + void (*funct)(T1, T2, T3), + A1& arg1, + A2& arg2, + A3& arg3 + ) + { + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.arg2 = &arg2; + temp.arg3 = &arg3; + temp.fp = funct; + + temp.safe_clone(bf_memory); + } + + template + void set ( + void (*funct)(T1, T2, T3, T4), + A1& arg1, + A2& arg2, + A3& arg3, + A4& arg4 + ) + { + using namespace bfp1_helpers; + destroy_bf_memory(); + typedef bound_function_helper_T > bf_helper_type; + + bf_helper_type temp; + temp.arg1 = &arg1; + temp.arg2 = &arg2; + temp.arg3 = &arg3; + temp.arg4 = &arg4; + temp.fp = funct; + + temp.safe_clone(bf_memory); + } + + // ------------------------------------------- + + private: + + stack_based_memory_block bf_memory; + + void destroy_bf_memory ( + ) + { + // Honestly, this probably doesn't even do anything but I'm putting + // it here just for good measure. + bf()->~bound_function_helper_base_base(); + } + + bfp1_helpers::bound_function_helper_base_base* bf () + { return static_cast(bf_memory.get()); } + + const bfp1_helpers::bound_function_helper_base_base* bf () const + { return static_cast(bf_memory.get()); } + + }; + +// ---------------------------------------------------------------------------------------- + + inline void swap ( + bound_function_pointer& a, + bound_function_pointer& b + ) { a.swap(b); } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_BOUND_FUNCTION_POINTER_KERNEl_1_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/bound_function_pointer/bound_function_pointer_kernel_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/bound_function_pointer/bound_function_pointer_kernel_abstract.h new file mode 100644 index 0000000..b5356d6 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/bound_function_pointer/bound_function_pointer_kernel_abstract.h @@ -0,0 +1,456 @@ +// Copyright (C) 2008 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_BOUND_FUNCTION_POINTER_KERNEl_ABSTRACT_ +#ifdef DLIB_BOUND_FUNCTION_POINTER_KERNEl_ABSTRACT_ + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class bound_function_pointer + { + /*! + INITIAL VALUE + is_set() == false + + WHAT THIS OBJECT REPRESENTS + This object represents a function with all its arguments bound to + specific objects. For example: + + void test(int& var) { var = var+1; } + + bound_function_pointer funct; + + int a = 4; + funct.set(test,a); // bind the variable a to the first argument of the test() function + + // at this point a == 4 + funct(); + // after funct() is called a == 5 + !*/ + + public: + + bound_function_pointer ( + ); + /*! + ensures + - #*this is properly initialized + !*/ + + bound_function_pointer( + const bound_function_pointer& item + ); + /*! + ensures + - *this == item + !*/ + + ~bound_function_pointer ( + ); + /*! + ensures + - any resources associated with *this have been released + !*/ + + bound_function_pointer& operator=( + const bound_function_pointer& item + ); + /*! + ensures + - *this == item + !*/ + + void clear( + ); + /*! + ensures + - #*this has its initial value + !*/ + + bool is_set ( + ) const; + /*! + ensures + - if (this->set() has been called) then + - returns true + - else + - returns false + !*/ + + operator some_undefined_pointer_type ( + ) const; + /*! + ensures + - if (is_set()) then + - returns a non 0 value + - else + - returns a 0 value + !*/ + + bool operator! ( + ) const; + /*! + ensures + - returns !is_set() + !*/ + + void operator () ( + ) const; + /*! + requires + - is_set() == true + ensures + - calls the bound function on the object(s) specified by the last + call to this->set() + throws + - any exception thrown by the function specified by + the previous call to this->set(). + If any of these exceptions are thrown then the call to this + function will have no effect on *this. + !*/ + + void swap ( + bound_function_pointer& item + ); + /*! + ensures + - swaps *this and item + !*/ + + // ---------------------- + + template + void set ( + F& function_object + ); + /*! + requires + - function_object() is a valid expression + ensures + - #is_set() == true + - calls to this->operator() will call function_object() + (This seems pointless but it is a useful base case) + !*/ + + template < typename T> + void set ( + T& object, + void (T::*funct)() + ); + /*! + requires + - funct == a valid member function pointer for class T + ensures + - #is_set() == true + - calls to this->operator() will call (object.*funct)() + !*/ + + template < typename T> + void set ( + const T& object, + void (T::*funct)()const + ); + /*! + requires + - funct == a valid bound function pointer for class T + ensures + - #is_set() == true + - calls to this->operator() will call (object.*funct)() + !*/ + + void set ( + void (*funct)() + ); + /*! + requires + - funct == a valid function pointer + ensures + - #is_set() == true + - calls to this->operator() will call funct() + !*/ + + // ---------------------- + + template + void set ( + F& function_object, + A1& arg1 + ); + /*! + requires + - function_object(arg1) is a valid expression + ensures + - #is_set() == true + - calls to this->operator() will call function_object(arg1) + !*/ + + template < typename T, typename T1, typename A1 > + void set ( + T& object, + void (T::*funct)(T1), + A1& arg1 + ); + /*! + requires + - funct == a valid member function pointer for class T + ensures + - #is_set() == true + - calls to this->operator() will call (object.*funct)(arg1) + !*/ + + template < typename T, typename T1, typename A1 > + void set ( + const T& object, + void (T::*funct)(T1)const, + A1& arg1 + ); + /*! + requires + - funct == a valid bound function pointer for class T + ensures + - #is_set() == true + - calls to this->operator() will call (object.*funct)(arg1) + !*/ + + template + void set ( + void (*funct)(T1), + A1& arg1 + ); + /*! + requires + - funct == a valid function pointer + ensures + - #is_set() == true + - calls to this->operator() will call funct(arg1) + !*/ + + // ---------------------- + template + void set ( + F& function_object, + A1& arg1, + A2& arg2 + ); + /*! + requires + - function_object(arg1,arg2) is a valid expression + ensures + - #is_set() == true + - calls to this->operator() will call function_object(arg1,arg2) + !*/ + + template < typename T, typename T1, typename A1, + typename T2, typename A2> + void set ( + T& object, + void (T::*funct)(T1,T2), + A1& arg1, + A2& arg2 + ); + /*! + requires + - funct == a valid member function pointer for class T + ensures + - #is_set() == true + - calls to this->operator() will call (object.*funct)(arg1,arg2) + !*/ + + template < typename T, typename T1, typename A1, + typename T2, typename A2> + void set ( + const T& object, + void (T::*funct)(T1,T2)const, + A1& arg1, + A2& arg2 + ); + /*! + requires + - funct == a valid bound function pointer for class T + ensures + - #is_set() == true + - calls to this->operator() will call (object.*funct)(arg1,arg2) + !*/ + + template + void set ( + void (*funct)(T1,T2), + A1& arg1, + A2& arg2 + ); + /*! + requires + - funct == a valid function pointer + ensures + - #is_set() == true + - calls to this->operator() will call funct(arg1,arg2) + !*/ + + // ---------------------- + + template + void set ( + F& function_object, + A1& arg1, + A2& arg2, + A3& arg3 + ); + /*! + requires + - function_object(arg1,arg2,arg3) is a valid expression + ensures + - #is_set() == true + - calls to this->operator() will call function_object(arg1,arg2,arg3) + !*/ + + template < typename T, typename T1, typename A1, + typename T2, typename A2, + typename T3, typename A3> + void set ( + T& object, + void (T::*funct)(T1,T2,T3), + A1& arg1, + A2& arg2, + A3& arg3 + ); + /*! + requires + - funct == a valid member function pointer for class T + ensures + - #is_set() == true + - calls to this->operator() will call (object.*funct)(arg1,arg2,arg3) + !*/ + + template < typename T, typename T1, typename A1, + typename T2, typename A2, + typename T3, typename A3> + void set ( + const T& object, + void (T::*funct)(T1,T2,T3)const, + A1& arg1, + A2& arg2, + A3& arg3 + ); + /*! + requires + - funct == a valid bound function pointer for class T + ensures + - #is_set() == true + - calls to this->operator() will call (object.*funct)(arg1,arg2,arg3) + !*/ + + template + void set ( + void (*funct)(T1,T2,T3), + A1& arg1, + A2& arg2, + A3& arg3 + ); + /*! + requires + - funct == a valid function pointer + ensures + - #is_set() == true + - calls to this->operator() will call funct(arg1,arg2,arg3) + !*/ + + // ---------------------- + + template + void set ( + F& function_object, + A1& arg1, + A2& arg2, + A3& arg3, + A4& arg4 + ); + /*! + requires + - function_object(arg1,arg2,arg3,arg4) is a valid expression + ensures + - #is_set() == true + - calls to this->operator() will call function_object(arg1,arg2,arg3,arg4) + !*/ + + template < typename T, typename T1, typename A1, + typename T2, typename A2, + typename T3, typename A3, + typename T4, typename A4> + void set ( + T& object, + void (T::*funct)(T1,T2,T3,T4), + A1& arg1, + A2& arg2, + A3& arg3, + A4& arg4 + ); + /*! + requires + - funct == a valid member function pointer for class T + ensures + - #is_set() == true + - calls to this->operator() will call (object.*funct)(arg1,arg2,arg3,arg4) + !*/ + + template < typename T, typename T1, typename A1, + typename T2, typename A2, + typename T3, typename A3, + typename T4, typename A4> + void set ( + const T& object, + void (T::*funct)(T1,T2,T3,T4)const, + A1& arg1, + A2& arg2, + A3& arg3, + A4& arg4 + ); + /*! + requires + - funct == a valid bound function pointer for class T + ensures + - #is_set() == true + - calls to this->operator() will call (object.*funct)(arg1,arg2,arg3,arg4) + !*/ + + template + void set ( + void (*funct)(T1,T2,T3,T4), + A1& arg1, + A2& arg2, + A3& arg3, + A4& arg4 + ); + /*! + requires + - funct == a valid function pointer + ensures + - #is_set() == true + - calls to this->operator() will call funct(arg1,arg2,arg3,arg4) + !*/ + + }; + +// ---------------------------------------------------------------------------------------- + + inline void swap ( + bound_function_pointer& a, + bound_function_pointer& b + ) { a.swap(b); } + /*! + provides a global swap function + !*/ + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_BOUND_FUNCTION_POINTER_KERNEl_ABSTRACT_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/byte_orderer.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/byte_orderer.h new file mode 100644 index 0000000..bc8f610 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/byte_orderer.h @@ -0,0 +1,10 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_BYTE_ORDEREr_ +#define DLIB_BYTE_ORDEREr_ + + +#include "byte_orderer/byte_orderer_kernel_1.h" + +#endif // DLIB_BYTE_ORDEREr_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/byte_orderer/byte_orderer_kernel_1.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/byte_orderer/byte_orderer_kernel_1.h new file mode 100644 index 0000000..9f8e834 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/byte_orderer/byte_orderer_kernel_1.h @@ -0,0 +1,176 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_BYTE_ORDEREr_KERNEL_1_ +#define DLIB_BYTE_ORDEREr_KERNEL_1_ + +#include "byte_orderer_kernel_abstract.h" +#include "../algs.h" +#include "../assert.h" + +namespace dlib +{ + + class byte_orderer + { + /*! + INITIAL VALUE + - if (this machine is little endian) then + - little_endian == true + - else + - little_endian == false + + CONVENTION + - host_is_big_endian() == !little_endian + - host_is_little_endian() == little_endian + + - if (this machine is little endian) then + - little_endian == true + - else + - little_endian == false + + + !*/ + + + public: + + // this is here for backwards compatibility with older versions of dlib. + typedef byte_orderer kernel_1a; + + byte_orderer ( + ) + { + // This will probably never be false but if it is then it means chars are not 8bits + // on this system. Which is a problem for this object. + COMPILE_TIME_ASSERT(sizeof(short) >= 2); + + unsigned long temp = 1; + unsigned char* ptr = reinterpret_cast(&temp); + if (*ptr == 1) + little_endian = true; + else + little_endian = false; + } + + virtual ~byte_orderer ( + ){} + + bool host_is_big_endian ( + ) const { return !little_endian; } + + bool host_is_little_endian ( + ) const { return little_endian; } + + template < + typename T + > + inline void host_to_network ( + T& item + ) const + { if (little_endian) flip(item); } + + template < + typename T + > + inline void network_to_host ( + T& item + ) const { if (little_endian) flip(item); } + + template < + typename T + > + void host_to_big ( + T& item + ) const { if (little_endian) flip(item); } + + template < + typename T + > + void big_to_host ( + T& item + ) const { if (little_endian) flip(item); } + + template < + typename T + > + void host_to_little ( + T& item + ) const { if (!little_endian) flip(item); } + + template < + typename T + > + void little_to_host ( + T& item + ) const { if (!little_endian) flip(item); } + + + private: + + template < + typename T, + size_t size + > + inline void flip ( + T (&array)[size] + ) const + /*! + ensures + - flips the bytes in every element of this array + !*/ + { + for (size_t i = 0; i < size; ++i) + { + flip(array[i]); + } + } + + template < + typename T + > + inline void flip ( + T& item + ) const + /*! + ensures + - reverses the byte ordering in item + !*/ + { + DLIB_ASSERT_HAS_STANDARD_LAYOUT(T); + + T value; + + // If you are getting this as an error then you are probably using + // this object wrong. If you think you aren't then send me (Davis) an + // email and I'll either set you straight or change/remove this check so + // your stuff works :) + COMPILE_TIME_ASSERT(sizeof(T) <= sizeof(long double)); + + // If you are getting a compile error on this line then it means T is + // a pointer type. It doesn't make any sense to byte swap pointers + // since they have no meaning outside the context of their own process. + // So you probably just forgot to dereference that pointer before passing + // it to this function :) + COMPILE_TIME_ASSERT(is_pointer_type::value == false); + + + const size_t size = sizeof(T); + unsigned char* const ptr = reinterpret_cast(&item); + unsigned char* const ptr_temp = reinterpret_cast(&value); + for (size_t i = 0; i < size; ++i) + ptr_temp[size-i-1] = ptr[i]; + + item = value; + } + + bool little_endian; + }; + + // make flip not do anything at all for chars + template <> inline void byte_orderer::flip ( char& ) const {} + template <> inline void byte_orderer::flip ( unsigned char& ) const {} + template <> inline void byte_orderer::flip ( signed char& ) const {} +} + +#endif // DLIB_BYTE_ORDEREr_KERNEL_1_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/byte_orderer/byte_orderer_kernel_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/byte_orderer/byte_orderer_kernel_abstract.h new file mode 100644 index 0000000..f7ea151 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/byte_orderer/byte_orderer_kernel_abstract.h @@ -0,0 +1,149 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_BYTE_ORDEREr_ABSTRACT_ +#ifdef DLIB_BYTE_ORDEREr_ABSTRACT_ + +#include "../algs.h" + +namespace dlib +{ + + class byte_orderer + { + /*! + INITIAL VALUE + This object has no state. + + WHAT THIS OBJECT REPRESENTS + This object simply provides a mechanism to convert data from a + host machine's own byte ordering to big or little endian and to + also do the reverse. + + It also provides a pair of functions to convert to/from network byte + order where network byte order is big endian byte order. This pair of + functions does the exact same thing as the host_to_big() and big_to_host() + functions and is provided simply so that client code can use the most + self documenting name appropriate. + + Also note that this object is capable of correctly flipping the contents + of arrays when the arrays are declared on the stack. e.g. You can + say things like: + int array[10]; + bo.host_to_network(array); + !*/ + + public: + + byte_orderer ( + ); + /*! + ensures + - #*this is properly initialized + throws + - std::bad_alloc + !*/ + + virtual ~byte_orderer ( + ); + /*! + ensures + - any resources associated with *this have been released + !*/ + + bool host_is_big_endian ( + ) const; + /*! + ensures + - if (the host computer is a big endian machine) then + - returns true + - else + - returns false + !*/ + + bool host_is_little_endian ( + ) const; + /*! + ensures + - if (the host computer is a little endian machine) then + - returns true + - else + - returns false + !*/ + + template < + typename T + > + void host_to_network ( + T& item + ) const; + /*! + ensures + - #item == the value of item converted from host byte order + to network byte order. + !*/ + + template < + typename T + > + void network_to_host ( + T& item + ) const; + /*! + ensures + - #item == the value of item converted from network byte order + to host byte order. + !*/ + + template < + typename T + > + void host_to_big ( + T& item + ) const; + /*! + ensures + - #item == the value of item converted from host byte order + to big endian byte order. + !*/ + + template < + typename T + > + void big_to_host ( + T& item + ) const; + /*! + ensures + - #item == the value of item converted from big endian byte order + to host byte order. + !*/ + + template < + typename T + > + void host_to_little ( + T& item + ) const; + /*! + ensures + - #item == the value of item converted from host byte order + to little endian byte order. + !*/ + + template < + typename T + > + void little_to_host ( + T& item + ) const; + /*! + ensures + - #item == the value of item converted from little endian byte order + to host byte order. + !*/ + + }; +} + +#endif // DLIB_BYTE_ORDEREr_ABSTRACT_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/cassert b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/cassert new file mode 100644 index 0000000..eb0e59e --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/cassert @@ -0,0 +1 @@ +#include "dlib_include_path_tutorial.txt" diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/config.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/config.h new file mode 100644 index 0000000..142f5ff --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/config.h @@ -0,0 +1,34 @@ + + +// If you are compiling dlib as a shared library and installing it somewhere on your system +// then it is important that any programs that use dlib agree on the state of the +// DLIB_ASSERT statements (i.e. they are either always on or always off). Therefore, +// uncomment one of the following lines to force all DLIB_ASSERTs to either always on or +// always off. If you don't define one of these two macros then DLIB_ASSERT will toggle +// automatically depending on the state of certain other macros, which is not what you want +// when creating a shared library. +// #define ENABLE_ASSERTS // asserts always enabled +/* #undef DLIB_DISABLE_ASSERTS */ + +/* #undef DLIB_ISO_CPP_ONLY */ +/* #undef DLIB_NO_GUI_SUPPORT */ +#define DLIB_ENABLE_STACK_TRACE + +#define LAPACK_FORCE_UNDERSCORE +/* #undef LAPACK_FORCE_NOUNDERSCORE */ + +// You should also consider telling dlib to link against libjpeg, libpng, libgif, fftw, CUDA, +// and a BLAS and LAPACK library. To do this you need to uncomment the following #defines. +#define DLIB_JPEG_SUPPORT +#define DLIB_PNG_SUPPORT +/* #undef DLIB_GIF_SUPPORT */ +/* #undef DLIB_USE_FFTW */ +#define DLIB_USE_BLAS +#define DLIB_USE_LAPACK +/* #undef DLIB_USE_CUDA */ +/* #undef DLIB_USE_MKL_FFT */ + +// This variable allows dlib/test_for_odr_violations.h to catch people who mistakenly use +// headers from one version of dlib with a compiled dlib binary from a different dlib version. +// #define DLIB_CHECK_FOR_VERSION_MISMATCH DLIB_VERSION_MISMATCH_CHECK__EXPECTED_VERSION_19_21_99 + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/console_progress_indicator.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/console_progress_indicator.h new file mode 100644 index 0000000..8e61c75 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/console_progress_indicator.h @@ -0,0 +1,207 @@ +// Copyright (C) 2010 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_CONSOLE_PROGRESS_INDiCATOR_Hh_ +#define DLIB_CONSOLE_PROGRESS_INDiCATOR_Hh_ + +#include +#include +#include +#include + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class console_progress_indicator + { + /*! + WHAT THIS OBJECT REPRESENTS + This object is a tool for reporting how long a task will take + to complete. + + For example, consider the following bit of code: + + console_progress_indicator pbar(100) + for (int i = 1; i <= 100; ++i) + { + pbar.print_status(i); + long_running_operation(); + } + + The above code will print a message to the console each iteration + which shows how much time is remaining until the loop terminates. + !*/ + + public: + + inline explicit console_progress_indicator ( + double target_value + ); + /*! + ensures + - #target() == target_value + !*/ + + inline void reset ( + double target_value + ); + /*! + ensures + - #target() == target_value + - performs the equivalent of: + *this = console_progress_indicator(target_value) + (i.e. resets this object with a new target value) + + !*/ + + inline double target ( + ) const; + /*! + ensures + - This object attempts to measure how much time is + left until we reach a certain targeted value. This + function returns that targeted value. + !*/ + + inline bool print_status ( + double cur, + bool always_print = false + ); + /*! + ensures + - print_status() assumes it is called with values which are linearly + approaching target(). It will attempt to predict how much time is + remaining until cur becomes equal to target(). + - prints a status message to the screen which indicates how much + more time is left until cur is equal to target() + - if (always_print) then + - This function prints to the screen each time it is called. + - else + - This function throttles the printing so that at most 1 message is + printed each second. Note that it won't print anything to the screen + until about one second has elapsed. This means that the first call + to print_status() never prints to the screen. + - This function returns true if it prints to the screen and false + otherwise. + !*/ + + private: + + double target_val; + + time_t start_time; + double first_val; + double seen_first_val; + time_t last_time; + + }; + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// IMPLEMENTATION DETAILS +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + console_progress_indicator:: + console_progress_indicator ( + double target_value + ) : + target_val(target_value), + start_time(0), + first_val(0), + seen_first_val(false), + last_time(0) + { + } + +// ---------------------------------------------------------------------------------------- + + bool console_progress_indicator:: + print_status ( + double cur, + bool always_print + ) + { + const time_t cur_time = std::time(0); + + // if this is the first time print_status has been called + // then collect some information and exit. We will print status + // on the next call. + if (!seen_first_val) + { + start_time = cur_time; + last_time = cur_time; + first_val = cur; + seen_first_val = true; + return false; + } + + if (cur_time != last_time || always_print) + { + last_time = cur_time; + double delta_t = static_cast(cur_time - start_time); + double delta_val = std::abs(cur - first_val); + + // don't do anything if cur is equal to first_val + if (delta_val < std::numeric_limits::epsilon()) + return false; + + double seconds = delta_t/delta_val * std::abs(target_val - cur); + + std::ios::fmtflags oldflags = std::cout.flags(); + + std::cout.setf(std::ios::fixed,std::ios::floatfield); + std::streamsize ss; + + if (seconds < 60) + { + ss = std::cout.precision(0); + std::cout << "Time remaining: " << seconds << " seconds. \r" << std::flush; + } + else if (seconds < 60*60) + { + ss = std::cout.precision(2); + std::cout << "Time remaining: " << seconds/60 << " minutes. \r" << std::flush; + } + else + { + ss = std::cout.precision(2); + std::cout << "Time remaining: " << seconds/60/60 << " hours. \r" << std::flush; + } + + // restore previous output flags and precision settings + std::cout.flags(oldflags); + std::cout.precision(ss); + + return true; + } + + return false; + } + +// ---------------------------------------------------------------------------------------- + + double console_progress_indicator:: + target ( + ) const + { + return target_val; + } + +// ---------------------------------------------------------------------------------------- + + void console_progress_indicator:: + reset ( + double target_value + ) + { + *this = console_progress_indicator(target_value); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_CONSOLE_PROGRESS_INDiCATOR_Hh_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/cstring b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/cstring new file mode 100644 index 0000000..eb0e59e --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/cstring @@ -0,0 +1 @@ +#include "dlib_include_path_tutorial.txt" diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/dlib_basic_cpp_build_tutorial.txt b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/dlib_basic_cpp_build_tutorial.txt new file mode 100644 index 0000000..fa1a970 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/dlib_basic_cpp_build_tutorial.txt @@ -0,0 +1,13 @@ +#error "Don't write #include in your code." +/* + In C++, it is generally an error to #include .cpp files. This is because it + can lead to what are called multiply defined symbol errors. Therefore, you + should compile dlib/all/source.cpp into your application just like you would + compile any other .cpp file. + + If you are using Visual Studio you add .cpp files to your application using + the solution explorer window. Specifically, right click on Source Files, + then select Add -> Existing Item and select the .cpp files you want to add. + + For general information on compiling dlib see http://dlib.net/compile.html +*/ diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/dlib_include_path_tutorial.txt b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/dlib_include_path_tutorial.txt new file mode 100644 index 0000000..f279ce1 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/dlib_include_path_tutorial.txt @@ -0,0 +1,20 @@ +#error "Don't put the dlib folder in your include path" +/* + You are getting this error because you have added the dlib folder to your + compiler's include search path. + + You should *NOT* add the dlib folder itself to your compiler's include path. + Doing so will cause the build to fail because of name collisions (such as + dlib/string.h and string.h from the standard library). Instead you should + add the folder that contains the dlib folder to your include search path + and then use include statements of the form #include or + #include "dlib/queue.h". This will ensure that everything builds correctly. + + XCode: + The XCode IDE often puts all folders that it knows about into + the compiler search path. So if you are using XCode then either + don't drag the whole dlib folder into the project or alternatively + modify your XCode project settings to not auto-add all folders to + the include path. Instead just make sure that the dlib folder is + itself inside a folder in your include path. +*/ diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/enable_if.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/enable_if.h new file mode 100644 index 0000000..f081dea --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/enable_if.h @@ -0,0 +1,62 @@ +// Copyright 2003 (C) The Trustees of Indiana University. +// Use, modification, and distribution is 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) +// Authors: Jaakko Jarvi (jajarvi at osl.iu.edu) +// Jeremiah Willcock (jewillco at osl.iu.edu) +// Andrew Lumsdaine (lums at osl.iu.edu) +#ifndef DLIB_BOOST_UTILITY_ENABLE_IF_HPP +#define DLIB_BOOST_UTILITY_ENABLE_IF_HPP + +namespace dlib +{ + + template + struct enable_if_c { + typedef T type; + }; + + template + struct enable_if_c {}; + + template + struct enable_if : public enable_if_c {}; + + template + struct lazy_enable_if_c { + typedef typename T::type type; + }; + + template + struct lazy_enable_if_c {}; + + template + struct lazy_enable_if : public lazy_enable_if_c {}; + + + template + struct disable_if_c { + typedef T type; + }; + + template + struct disable_if_c {}; + + template + struct disable_if : public disable_if_c {}; + + template + struct lazy_disable_if_c { + typedef typename T::type type; + }; + + template + struct lazy_disable_if_c {}; + + template + struct lazy_disable_if : public lazy_disable_if_c {}; + +} // namespace dlib + +#endif // DLIB_BOOST_UTILITY_ENABLE_IF_HPP + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/error.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/error.h new file mode 100644 index 0000000..ce9b95b --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/error.h @@ -0,0 +1,449 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_ERROr_ +#define DLIB_ERROr_ + +#include +#include // for std::bad_alloc +#include +#include +#include +#include + +// ------------------------------- +// ------ exception classes ------ +// ------------------------------- + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + enum error_type + { + EPORT_IN_USE, + ETIMEOUT, + ECONNECTION, + ELISTENER, + ERESOLVE, + EMONITOR, + ECREATE_THREAD, + ECREATE_MUTEX, + ECREATE_SIGNALER, + EUNSPECIFIED, + EGENERAL_TYPE1, + EGENERAL_TYPE2, + EGENERAL_TYPE3, + EINVALID_OPTION, + ETOO_FEW_ARGS, + ETOO_MANY_ARGS, + ESOCKET, + ETHREAD, + EGUI, + EFATAL, + EBROKEN_ASSERT, + EIMAGE_LOAD, + EDIR_CREATE, + EINCOMPATIBLE_OPTIONS, + EMISSING_REQUIRED_OPTION, + EINVALID_OPTION_ARG, + EMULTIPLE_OCCURANCES, + ECONFIG_READER, + EIMAGE_SAVE, + ECAST_TO_STRING, + ESTRING_CAST, + EUTF8_TO_UTF32, + EOPTION_PARSE + }; + +// ---------------------------------------------------------------------------------------- + + // the base exception class + class error : public std::exception + { + /*! + WHAT THIS OBJECT REPRESENTS + This is the base exception class for the dlib library. i.e. all + exceptions in this library inherit from this class. + !*/ + + public: + error( + error_type t, + const std::string& a + ): info(a), type(t) {} + /*! + ensures + - #type == t + - #info == a + !*/ + + error( + error_type t + ): type(t) {} + /*! + ensures + - #type == t + - #info == "" + !*/ + + error( + const std::string& a + ): info(a), type(EUNSPECIFIED) {} + /*! + ensures + - #type == EUNSPECIFIED + - #info == a + !*/ + + error( + ): type(EUNSPECIFIED) {} + /*! + ensures + - #type == EUNSPECIFIED + - #info == "" + !*/ + + virtual ~error( + ) throw() {} + /*! + ensures + - does nothing + !*/ + + const char* what( + ) const throw() + /*! + ensures + - if (info.size() != 0) then + - returns info.c_str() + - else + - returns type_to_string(type) + !*/ + { + if (info.size() > 0) + return info.c_str(); + else + return type_to_string(); + } + + const char* type_to_string ( + ) const throw() + /*! + ensures + - returns a string that names the contents of the type member. + !*/ + { + if ( type == EPORT_IN_USE) return "EPORT_IN_USE"; + else if ( type == ETIMEOUT) return "ETIMEOUT"; + else if ( type == ECONNECTION) return "ECONNECTION"; + else if ( type == ELISTENER) return "ELISTENER"; + else if ( type == ERESOLVE) return "ERESOLVE"; + else if ( type == EMONITOR) return "EMONITOR"; + else if ( type == ECREATE_THREAD) return "ECREATE_THREAD"; + else if ( type == ECREATE_MUTEX) return "ECREATE_MUTEX"; + else if ( type == ECREATE_SIGNALER) return "ECREATE_SIGNALER"; + else if ( type == EUNSPECIFIED) return "EUNSPECIFIED"; + else if ( type == EGENERAL_TYPE1) return "EGENERAL_TYPE1"; + else if ( type == EGENERAL_TYPE2) return "EGENERAL_TYPE2"; + else if ( type == EGENERAL_TYPE3) return "EGENERAL_TYPE3"; + else if ( type == EINVALID_OPTION) return "EINVALID_OPTION"; + else if ( type == ETOO_FEW_ARGS) return "ETOO_FEW_ARGS"; + else if ( type == ETOO_MANY_ARGS) return "ETOO_MANY_ARGS"; + else if ( type == ESOCKET) return "ESOCKET"; + else if ( type == ETHREAD) return "ETHREAD"; + else if ( type == EGUI) return "EGUI"; + else if ( type == EFATAL) return "EFATAL"; + else if ( type == EBROKEN_ASSERT) return "EBROKEN_ASSERT"; + else if ( type == EIMAGE_LOAD) return "EIMAGE_LOAD"; + else if ( type == EDIR_CREATE) return "EDIR_CREATE"; + else if ( type == EINCOMPATIBLE_OPTIONS) return "EINCOMPATIBLE_OPTIONS"; + else if ( type == EMISSING_REQUIRED_OPTION) return "EMISSING_REQUIRED_OPTION"; + else if ( type == EINVALID_OPTION_ARG) return "EINVALID_OPTION_ARG"; + else if ( type == EMULTIPLE_OCCURANCES) return "EMULTIPLE_OCCURANCES"; + else if ( type == ECONFIG_READER) return "ECONFIG_READER"; + else if ( type == EIMAGE_SAVE) return "EIMAGE_SAVE"; + else if ( type == ECAST_TO_STRING) return "ECAST_TO_STRING"; + else if ( type == ESTRING_CAST) return "ESTRING_CAST"; + else if ( type == EUTF8_TO_UTF32) return "EUTF8_TO_UTF32"; + else if ( type == EOPTION_PARSE) return "EOPTION_PARSE"; + else return "undefined error type"; + } + + const std::string info; // info about the error + const error_type type; // the type of the error + + private: + const error& operator=(const error&); + }; + +// ---------------------------------------------------------------------------------------- + + class fatal_error : public error + { + /*! + WHAT THIS OBJECT REPRESENTS + As the name says, this object represents some kind of fatal error. + That is, it represents an unrecoverable error and any program that + throws this exception is, by definition, buggy and needs to be fixed. + + Note that a fatal_error exception can only be thrown once. The second + time an application attempts to construct a fatal_error it will be + immediately aborted and an error message will be printed to std::cerr. + The reason for this is because the first fatal_error was apparently ignored + so the second fatal_error is going to make itself impossible to ignore + by calling abort. The lesson here is that you should not try to ignore + fatal errors. + + This is also the exception thrown by the DLIB_ASSERT and DLIB_CASSERT macros. + !*/ + + public: + fatal_error( + error_type t, + const std::string& a + ): error(t,a) {check_for_previous_fatal_errors();} + /*! + ensures + - #type == t + - #info == a + !*/ + + fatal_error( + error_type t + ): error(t) {check_for_previous_fatal_errors();} + /*! + ensures + - #type == t + - #info == "" + !*/ + + fatal_error( + const std::string& a + ): error(EFATAL,a) {check_for_previous_fatal_errors();} + /*! + ensures + - #type == EFATAL + - #info == a + !*/ + + fatal_error( + ): error(EFATAL) {check_for_previous_fatal_errors();} + /*! + ensures + - #type == EFATAL + - #info == "" + !*/ + + private: + + static inline char* message () + { + static char buf[2000]; + buf[1999] = '\0'; // just to be extra safe + return buf; + } + + static inline void dlib_fatal_error_terminate ( + ) + { + std::cerr << "\n**************************** FATAL ERROR DETECTED ****************************"; + std::cerr << message() << std::endl; + std::cerr << "******************************************************************************\n" << std::endl; + } + + void check_for_previous_fatal_errors() + { + // If dlib is being use to create plugins for some other application, like + // MATLAB, then don't do these checks since it terminates the over arching + // system. Just let the errors go to the plugin handler and it will deal with + // them. +#if defined(MATLAB_MEX_FILE) || defined(DLIB_NO_ABORT_ON_2ND_FATAL_ERROR) + return; +#else + static bool is_first_fatal_error = true; + if (is_first_fatal_error == false) + { + std::cerr << "\n\n ************************** FATAL ERROR DETECTED ************************** " << std::endl; + std::cerr << " ************************** FATAL ERROR DETECTED ************************** " << std::endl; + std::cerr << " ************************** FATAL ERROR DETECTED ************************** \n" << std::endl; + std::cerr << "Two fatal errors have been detected, the first was inappropriately ignored. \n" + << "To prevent further fatal errors from being ignored this application will be \n" + << "terminated immediately and you should go fix this buggy program.\n\n" + << "The error message from this fatal error was:\n" << this->what() << "\n\n" << std::endl; + using namespace std; + assert(false); + abort(); + } + else + { + // copy the message into the fixed message buffer so that it can be recalled by dlib_fatal_error_terminate + // if needed. + char* msg = message(); + unsigned long i; + for (i = 0; i < 2000-1 && i < this->info.size(); ++i) + msg[i] = info[i]; + msg[i] = '\0'; + + // set this termination handler so that if the user doesn't catch this dlib::fatal_error that is being + // thrown then it will eventually be printed to standard error + std::set_terminate(&dlib_fatal_error_terminate); + } + is_first_fatal_error = false; +#endif + } + }; + +// ---------------------------------------------------------------------------------------- + + class gui_error : public error + { + public: + gui_error( + error_type t, + const std::string& a + ): error(t,a) {} + /*! + ensures + - #type == t + - #info == a + !*/ + + gui_error( + error_type t + ): error(t) {} + /*! + ensures + - #type == t + - #info == "" + !*/ + + gui_error( + const std::string& a + ): error(EGUI,a) {} + /*! + ensures + - #type == EGUI + - #info == a + !*/ + + gui_error( + ): error(EGUI) {} + /*! + ensures + - #type == EGUI + - #info == "" + !*/ + }; + +// ---------------------------------------------------------------------------------------- + + class socket_error : public error + { + public: + socket_error( + error_type t, + const std::string& a + ): error(t,a) {} + /*! + ensures + - #type == t + - #info == a + !*/ + + socket_error( + error_type t + ): error(t) {} + /*! + ensures + - #type == t + - #info == "" + !*/ + + socket_error( + const std::string& a + ): error(ESOCKET,a) {} + /*! + ensures + - #type == ESOCKET + - #info == a + !*/ + + socket_error( + ): error(ESOCKET) {} + /*! + ensures + - #type == ESOCKET + - #info == "" + !*/ + }; + +// ---------------------------------------------------------------------------------------- + + class thread_error : public error + { + public: + thread_error( + error_type t, + const std::string& a + ): error(t,a) {} + /*! + ensures + - #type == t + - #info == a + !*/ + + thread_error( + error_type t + ): error(t) {} + /*! + ensures + - #type == t + - #info == "" + !*/ + + thread_error( + const std::string& a + ): error(ETHREAD,a) {} + /*! + ensures + - #type == ETHREAD + - #info == a + !*/ + + thread_error( + ): error(ETHREAD) {} + /*! + ensures + - #type == ETHREAD + - #info == "" + !*/ + }; + +// ---------------------------------------------------------------------------------------- + + class impossible_labeling_error : public dlib::error + { + /*! + WHAT THIS OBJECT REPRESENTS + This is the exception thrown by code that trains object detectors (e.g. + structural_svm_object_detection_problem) when they detect that the set of + truth boxes given to the training algorithm contains some impossible to + obtain outputs. + + This kind of problem can happen when the set of image positions scanned by + the underlying object detection method doesn't include the truth rectangle + as a possible output. Another possibility is when two truth boxes are very + close together and hard coded non-max suppression logic would prevent two + boxes in such close proximity from being output. + !*/ + public: + impossible_labeling_error(const std::string& msg) : dlib::error(msg) {}; + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_ERROr_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/float_details.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/float_details.h new file mode 100644 index 0000000..3dc7eae --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/float_details.h @@ -0,0 +1,161 @@ +// Copyright (C) 2013 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_FLOAT_DEtAILS_Hh_ +#define DLIB_FLOAT_DEtAILS_Hh_ + +#include +#include "algs.h" +#include + +namespace dlib +{ + struct float_details + { + /*! + WHAT THIS OBJECT REPRESENTS + This object is a tool for converting floating point numbers into an + explicit integer representation and then also converting back. In + particular, a float_details object represents a floating point number with + a 64 bit mantissa and 16 bit exponent. These are stored in the public + fields of the same names. + + The main use of this object is to convert floating point values into a + known uniform representation so they can be serialized to an output stream. + This allows dlib serialization code to work on any system, regardless of + the floating point representation used by the hardware. It also means + that, for example, a double can be serialized and then deserialized into a + float and it will perform the appropriate conversion. + + + In more detail, this object represents a floating point value equal to + mantissa*pow(2,exponent), except when exponent takes on any of the + following special values: + - is_inf + - is_ninf + - is_nan + These values are used to indicate that the floating point value should be + either infinity, negative infinity, or not-a-number respectively. + !*/ + + float_details( + int64 man, + int16 exp + ) : mantissa(man), exponent(exp) {} + /*! + ensures + - #mantissa == man + - #exponent == exp + !*/ + + float_details() : + mantissa(0), exponent(0) + {} + /*! + ensures + - this object represents a floating point value of 0 + !*/ + + float_details ( const double& val) { *this = val; } + float_details ( const float& val) { *this = val; } + float_details ( const long double& val) { *this = val; } + /*! + ensures + - converts the given value into a float_details representation. This + means that converting #*this back into a floating point number should + recover the input val. + !*/ + + float_details& operator= ( const double& val) { convert_from_T(val); return *this; } + float_details& operator= ( const float& val) { convert_from_T(val); return *this; } + float_details& operator= ( const long double& val) { convert_from_T(val); return *this; } + /*! + ensures + - converts the given value into a float_details representation. This + means that converting #*this back into a floating point number should + recover the input val. + !*/ + + operator double () const { return convert_to_T(); } + operator float () const { return convert_to_T(); } + operator long double () const { return convert_to_T(); } + /*! + ensures + - converts the contents of this float_details object into a floating point number. + !*/ + + const static int16 is_inf = 32000; + const static int16 is_ninf = 32001; + const static int16 is_nan = 32002; + + int64 mantissa; + int16 exponent; + + + private: + + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// IMPLEMENTATION DETAILS +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template + void convert_from_T ( + const T& val + ) + { + mantissa = 0; + + const int digits = dlib::tmin::digits, 63>::value; + + if (val == std::numeric_limits::infinity()) + { + exponent = is_inf; + } + else if (val == -std::numeric_limits::infinity()) + { + exponent = is_ninf; + } + else if (val < std::numeric_limits::infinity()) + { + int exp; + mantissa = static_cast(std::frexp(val, &exp)*(((uint64)1)<>= 8; + exponent += 8; + } + } + else + { + exponent = is_nan; + } + } + + template + T convert_to_T ( + ) const + { + if (exponent < is_inf) + return std::ldexp((T)mantissa, exponent); + else if (exponent == is_inf) + return std::numeric_limits::infinity(); + else if (exponent == is_ninf) + return -std::numeric_limits::infinity(); + else + return std::numeric_limits::quiet_NaN(); + } + + }; + +} + +#endif // DLIB_FLOAT_DEtAILS_Hh_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/fstream b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/fstream new file mode 100644 index 0000000..eb0e59e --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/fstream @@ -0,0 +1 @@ +#include "dlib_include_path_tutorial.txt" diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/hash.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/hash.h new file mode 100644 index 0000000..5a018b4 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/hash.h @@ -0,0 +1,14 @@ +// Copyright (C) 2011 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_HASh_ +#define DLIB_HASh_ + + +#include "general_hash/hash.h" +#include "general_hash/random_hashing.h" +#include "general_hash/count_bits.h" + + +#endif // DLIB_HASh_ + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/interfaces/cmd_line_parser_option.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/interfaces/cmd_line_parser_option.h new file mode 100644 index 0000000..797dcd2 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/interfaces/cmd_line_parser_option.h @@ -0,0 +1,107 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_CMD_LINE_PARSER_OPTIOn_ +#define DLIB_CMD_LINE_PARSER_OPTIOn_ + +#include + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template < + typename charT + > + class cmd_line_parser_option + { + /*! + POINTERS AND REFERENCES TO INTERNAL DATA + None of the functions in cmd_line_parser_option will invalidate + pointers or references to internal data when called. + + WHAT THIS OBJECT REPRESENTS + This object represents a command line option. + !*/ + + public: + + typedef charT char_type; + typedef std::basic_string string_type; + + virtual ~cmd_line_parser_option ( + ) = 0; + + virtual const string_type& name ( + ) const = 0; + /*! + ensures + - returns the name of this option + !*/ + + virtual const string_type& group_name ( + ) const = 0; + /*! + ensures + - returns the name of the group this option is in. If no group was set for + this option then this function returns "". + !*/ + + virtual const string_type& description ( + ) const = 0; + /*! + ensures + - returns the description for this option + !*/ + + virtual unsigned long number_of_arguments( + ) const = 0; + /*! + ensures + - returns the number of arguments for this option + !*/ + + virtual unsigned long count( + ) const = 0; + /*! + ensures + - returns the number of times this option appears on the command line. + !*/ + + virtual const string_type& argument ( + unsigned long arg = 0, + unsigned long N = 0 + ) const = 0; + /*! + requires + - arg < number_of_arguments() + - N < count() + ensures + - returns the arg-th argument to the Nth occurrence of this + option on the command line. + !*/ + + inline operator bool ( + ) const { return count() > 0; } + /*! + ensures + - returns true if this option appears on the command line at all + !*/ + + protected: + + // restricted functions + cmd_line_parser_option& operator=(const cmd_line_parser_option&){return *this;} + + }; + + // destructor does nothing + template < typename charT > + cmd_line_parser_option::~cmd_line_parser_option() {} + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_CMD_LINE_PARSER_OPTIOn_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/interfaces/enumerable.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/interfaces/enumerable.h new file mode 100644 index 0000000..e8f5ae7 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/interfaces/enumerable.h @@ -0,0 +1,130 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_ENUMERABLe_INTERFACE_ +#define DLIB_ENUMERABLe_INTERFACE_ + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + class enumerable + { + /*! + POINTERS AND REFERENCES TO INTERNAL DATA + - if (at_start()) then + - all pointers and references to data returned via element() are + invalid. + - calling move_next() or reset() invalidates pointers and references to + data returned via element() and only data returned via element(). + - calling at_start(), current_element_valid(), size(), or element() + does NOT invalidate pointers or references to any internal data. + + INITIAL VALUE + current_element_valid() == false + at_start() == true + + WHAT THIS OBJECT REPRESENTS + This object represent an interface for iterating through the + elements in a container. It starts out one before the first element + in the container. + + + EXAMPLE: The following loops though all elements in the container + and prints them to cout. + + container.reset(); + while(container.move_next()) { + cout << container.element(); + } + !*/ + + public: + typedef T type; + + inline virtual ~enumerable( + ) = 0; + + virtual bool at_start ( + ) const = 0; + /*! + ensures + - returns true if *this represents one position before the first element + in the container (this would also make the current element invalid) + else returns false + !*/ + + virtual void reset ( + ) const = 0; + /*! + ensures + - #current_element_valid() == false + - #at_start() == true + !*/ + + virtual bool current_element_valid ( + ) const = 0; + /*! + ensures + - returns true if we are currently at a valid element else + returns false + !*/ + + virtual const T& element ( + ) const = 0; + /*! + requires + - current_element_valid() == true + ensures + - returns a const reference to the current element + !*/ + + virtual T& element ( + ) = 0; + /*! + requires + - current_element_valid() == true + ensures + - returns a non-const reference to the current element + !*/ + + virtual bool move_next ( + ) const = 0; + /*! + ensures + - moves to the next element. i.e. #element() will now + return the next element in the container + - the return value will be equal to #current_element_valid() + - #at_start() == false + + - returns true if there is another element + - returns false if there are no more elements in the container + !*/ + + virtual size_t size ( + ) const = 0; + /*! + ensures + - returns the number of elements in *this + !*/ + + protected: + + // restricted functions + enumerable& operator=(const enumerable&) {return *this;} // no assignment operator + + }; + + // destructor does nothing + template + enumerable::~enumerable() {} + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_ENUMERABLe_INTERFACE_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/interfaces/map_pair.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/interfaces/map_pair.h new file mode 100644 index 0000000..6431015 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/interfaces/map_pair.h @@ -0,0 +1,74 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MAP_PAIr_INTERFACE_ +#define DLIB_MAP_PAIr_INTERFACE_ + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template < + typename T1, + typename T2 + > + class map_pair + { + /*! + POINTERS AND REFERENCES TO INTERNAL DATA + None of the functions in map_pair will invalidate + pointers or references to internal data when called. + + WHAT THIS OBJECT REPRESENTS + this object is used to return the key/value pair used in the + map and hash_map containers when using the enumerable interface. + + note that the enumerable interface is defined in + interfaces/enumerable.h + !*/ + + public: + typedef T1 key_type; + typedef T2 value_type; + + virtual ~map_pair( + )=0; + + virtual const T1& key( + ) const =0; + /*! + ensures + - returns a const reference to the key + !*/ + + virtual const T2& value( + ) const =0; + /*! + ensures + - returns a const reference to the value associated with key + !*/ + + virtual T2& value( + )=0; + /*! + ensures + - returns a non-const reference to the value associated with key + !*/ + + protected: + + // restricted functions + map_pair& operator=(const map_pair&) {return *this;} // no assignment operator + + }; + + // destructor does nothing + template + map_pair::~map_pair () {} + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MAP_PAIr_INTERFACE_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/interfaces/remover.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/interfaces/remover.h new file mode 100644 index 0000000..f2098cb --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/interfaces/remover.h @@ -0,0 +1,220 @@ +// Copyright (C) 2005 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_REMOVER_KERNEl_INTERFACE_ +#define DLIB_REMOVER_KERNEl_INTERFACE_ + +#include + + +namespace dlib +{ + + template < + typename T + > + class remover + { + + /*! + REQUIREMENTS ON T + T is swappable by a global swap() and + T must have a default constructor + + POINTERS AND REFERENCES TO INTERNAL DATA + The size() function does not invalidate pointers or + references to internal data. All other functions have no such + guarantee. + + WHAT THIS OBJECT REPRESENTS + This object represents some generalized interface for removing + single items from container classes. + !*/ + + + public: + typedef T type; + + virtual ~remover( + ); + /*! + ensures + - all resources associated with *this have been released. + !*/ + + virtual void remove_any ( + T& item + ) = 0; + /*! + requires + - size() != 0 + ensures + - #size() == size() - 1 + - removes an element from *this and swaps it into item. + - if (*this implements the enumerable interface) then + - #at_start() == true + !*/ + + virtual size_t size ( + ) const = 0; + /*! + ensures + - returns the number of elements in *this + !*/ + + protected: + + // restricted functions + remover& operator=(const remover&) {return *this;} // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename compare + > + class asc_remover : public remover + { + /*! + REQUIREMENTS ON T + T is swappable by a global swap() and + T must have a default constructor and + T must be comparable by compare where compare is a functor compatible with std::less + + WHAT THIS OBJECT REPRESENTS + This object represents the same thing as remover except + that remove_any() will remove elements in ascending order + according to the compare functor. + !*/ + public: + typedef compare compare_type; + + protected: + // restricted functions + asc_remover& operator=(const asc_remover&) {return *this;} // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range + > + class pair_remover + { + + /*! + REQUIREMENTS ON domain + domain is swappable by a global swap() and + domain must have a default constructor + + REQUIREMENTS ON range + range is swappable by a global swap() and + range must have a default constructor + + POINTERS AND REFERENCES TO INTERNAL DATA + The size() function does not invalidate pointers or + references to internal data. All other functions have no such + guarantee. + + WHAT THIS OBJECT REPRESENTS + This object represents some generalized interface for removing + pairs from container classes which enforce some kind of pairing on + the elements that they contain. + !*/ + + public: + typedef domain domain_type; + typedef range range_type; + + virtual ~pair_remover( + ); + /*! + ensures + - all resources associated with *this have been released. + !*/ + + virtual void remove_any ( + domain& d, + range& r + ) = 0; + /*! + requires + - &d != &r (i.e. d and r cannot be the same variable) + - size() != 0 + ensures + - #size() == size() - 1 + - removes an element from the domain of *this and swaps it + into d. + - removes the element in *this's range that is associated + with #d and swaps it into r. + - if (*this implements the enumerable interface) then + - #at_start() == true + !*/ + + virtual size_t size ( + ) const = 0; + /*! + ensures + - returns the number of elements in *this + !*/ + + + protected: + + // restricted functions + pair_remover& operator=(const pair_remover&) {return *this;} // assignment operator + + + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename compare + > + class asc_pair_remover : public pair_remover + { + /*! + REQUIREMENTS ON domain + domain is swappable by a global swap() and + domain must have a default constructor and + domain must be comparable by compare where compare is a functor compatible with std::less + + REQUIREMENTS ON range + range is swappable by a global swap() and + range must have a default constructor + + WHAT THIS OBJECT REPRESENTS + This object represents the same thing as pair_remover except + that remove_any() will remove domain elements in ascending + order according to the compare functor. + !*/ + public: + typedef compare compare_type; + + protected: + // restricted functions + asc_pair_remover& operator=(const asc_pair_remover&) {return *this;} // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + + // destructor does nothing + template + remover::~remover() {} + + // destructor does nothing + template + pair_remover::~pair_remover() {} + + +// ---------------------------------------------------------------------------------------- + + +} + +#endif // DLIB_REMOVER_KERNEl_INTERFACE_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/iomanip b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/iomanip new file mode 100644 index 0000000..eb0e59e --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/iomanip @@ -0,0 +1 @@ +#include "dlib_include_path_tutorial.txt" diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/iosfwd b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/iosfwd new file mode 100644 index 0000000..eb0e59e --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/iosfwd @@ -0,0 +1 @@ +#include "dlib_include_path_tutorial.txt" diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/iostream b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/iostream new file mode 100644 index 0000000..eb0e59e --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/iostream @@ -0,0 +1 @@ +#include "dlib_include_path_tutorial.txt" diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/is_kind.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/is_kind.h new file mode 100644 index 0000000..e8dcb63 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/is_kind.h @@ -0,0 +1,162 @@ +// Copyright (C) 2007 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_IS_KINd_H_ +#define DLIB_IS_KINd_H_ + +#include + +namespace dlib +{ + /*! + This file contains a set of templates that enable you to determine if + a given type implements an abstract interface defined in one of the + dlib *_abstract.h files. + !*/ + +// ---------------------------------------------------------------------------------------- + + struct default_is_kind_value { static const bool value = false; }; + +// ---------------------------------------------------------------------------------------- + + template + struct is_graph : public default_is_kind_value + { + /*! + - if (T is an implementation of graph/graph_kernel_abstract.h) then + - is_graph::value == true + - else + - is_graph::value == false + !*/ + }; + +// ---------------------------------------------------------------------------------------- + + template + struct is_directed_graph : public default_is_kind_value + { + /*! + - if (T is an implementation of directed_graph/directed_graph_kernel_abstract.h) then + - is_directed_graph::value == true + - else + - is_directed_graph::value == false + !*/ + }; + +// ---------------------------------------------------------------------------------------- + + template + struct is_matrix : public default_is_kind_value + { + /*! + - if (T is some kind of matrix expression from the matrix/matrix_exp_abstract.h component) then + - is_matrix::value == true + - else + - is_matrix::value == false + !*/ + + // Don't set the helper to anything. Just let it be void. + ASSERT_ARE_SAME_TYPE(helper,void); + }; + +// ---------------------------------------------------------------------------------------- + + template + struct is_array2d : public default_is_kind_value + { + /*! + - if (T is an implementation of array2d/array2d_kernel_abstract.h) then + - is_array2d::value == true + - else + - is_array2d::value == false + !*/ + }; + +// ---------------------------------------------------------------------------------------- + + template + struct is_array : public default_is_kind_value + { + /*! + - if (T is an implementation of array/array_kernel_abstract.h) then + - is_array::value == true + - else + - is_array::value == false + !*/ + }; + +// ---------------------------------------------------------------------------------------- + + template + struct is_std_vector : public default_is_kind_value + { + /*! + - if (T is an implementation of the standard C++ std::vector object) then + - is_std_vector::value == true + - else + - is_std_vector::value == false + !*/ + }; + +// ---------------------------------------------------------------------------------------- + + template + struct is_pair : public default_is_kind_value + { + /*! + - if (T is a std::pair object) then + - is_std_vector::value == true + - else + - is_std_vector::value == false + !*/ + }; + +// ---------------------------------------------------------------------------------------- + + template + struct is_rand : public default_is_kind_value + { + /*! + - if (T is an implementation of rand/rand_kernel_abstract.h) then + - is_rand::value == true + - else + - is_rand::value == false + !*/ + }; + +// ---------------------------------------------------------------------------------------- + + template + struct is_config_reader : public default_is_kind_value + { + /*! + - if (T is an implementation of config_reader/config_reader_kernel_abstract.h) then + - is_config_reader::value == true + - else + - is_config_reader::value == false + !*/ + }; + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// Implementation details +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template + struct is_std_vector > { const static bool value = true; }; + template struct is_std_vector { const static bool value = is_std_vector::value; }; + template struct is_std_vector{ const static bool value = is_std_vector::value; }; + template struct is_std_vector { const static bool value = is_std_vector::value; }; + +// ---------------------------------------------------------------------------------------- + + template + struct is_pair > { const static bool value = true; }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_IS_KINd_H_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/istream b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/istream new file mode 100644 index 0000000..eb0e59e --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/istream @@ -0,0 +1 @@ +#include "dlib_include_path_tutorial.txt" diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/locale b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/locale new file mode 100644 index 0000000..eb0e59e --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/locale @@ -0,0 +1 @@ +#include "dlib_include_path_tutorial.txt" diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/logger.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/logger.h new file mode 100644 index 0000000..e49fad8 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/logger.h @@ -0,0 +1,11 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_LOGGEr_ +#define DLIB_LOGGEr_ + +#include "logger/logger_kernel_1.h" +#include "logger/extra_logger_headers.h" +#include "logger/logger_config_file.h" + +#endif // DLIB_LOGGEr_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/logger/extra_logger_headers.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/logger/extra_logger_headers.h new file mode 100644 index 0000000..6eb24d8 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/logger/extra_logger_headers.h @@ -0,0 +1,41 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_EXTRA_LOGGER_HEADERs_ +#define DLIB_EXTRA_LOGGER_HEADERs_ + +#include "logger_kernel_abstract.h" +#include "logger_kernel_1.h" +#include +#include +#include "../uintn.h" + +// ---------------------------------------------------------------------------------------- + +namespace dlib +{ + + void print_datetime_logger_header ( + std::ostream& out, + const std::string& logger_name, + const log_level& l, + const uint64 thread_id + ); + /*! + requires + - is not called more than once at a time (i.e. is not called from multiple + threads at the same time). + ensures + - let DATE be the current date and time (e.g. Thu Aug 31 16:41:52 2006). + - prints a string to out in the form: "l.name (DATE) [thread_id] logger_name:" + !*/ + +} + +// ---------------------------------------------------------------------------------------- + +#ifdef NO_MAKEFILE +#include "extra_logger_headers.cpp" +#endif + +#endif // DLIB_EXTRA_LOGGER_HEADERs_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/logger/logger_config_file.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/logger/logger_config_file.h new file mode 100644 index 0000000..b0a030f --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/logger/logger_config_file.h @@ -0,0 +1,135 @@ +// Copyright (C) 2007 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_LOGGER_CONFIg_FILE_ +#define DLIB_LOGGER_CONFIg_FILE_ + +#include "logger_kernel_abstract.h" +#include "logger_kernel_1.h" +#include +#include "../config_reader.h" + +// ---------------------------------------------------------------------------------------- + +namespace dlib +{ + class logger_config_file_error : public error + { + /*! + WHAT THIS OBJECT REPRESENTS + This is the exception class used by the configure_loggers_from_file() + function defined below. + !*/ + public: + logger_config_file_error(const std::string& s):error(s){} + }; + + void configure_loggers_from_file ( + const std::string& file_name + ); + /*! + ensures + - configures the loggers with the contents of the file_name file + throws + - dlib::logger_config_file_error + this exception is thrown if there is a problem reading the config file + !*/ + + void configure_loggers_from_file ( + const config_reader& cr + ); + /*! + ensures + - configures the loggers with the contents of cr. This function is just like + the above version that reads from a file except that it reads from an in-memory + config_reader instead. + throws + - dlib::logger_config_file_error + this exception is thrown if there is a problem reading the config file + !*/ + +// ---------------------------------------------------------------------------------------- + + /*! + # ----------------------------------------------- + # ------------- EXAMPLE CONFIG FILE ------------- + # ----------------------------------------------- + + # The overall format of the config file is the same as the one defined by + # the config_reader component of this library. + + # This line is a comment line + + # The config file always has a block named logger_config. This is where all the + # config data for the loggers reside. + logger_config + { + # This sets all loggers to the level LINFO since it is just inside the + # logger_config block + logging_level = info + + # Alternatively we could specify a user defined logging level by + # supplying a priority number. The following line would specify + # that only logging levels at or above 100 are printed. (note that + # you would have to comment out the logging_level statement above + # to avoid a conflict). + # logging_level = 100 + + parent_logger + { + # This sets all loggers named "parent_logger" or children of + # loggers with that name to not log at all (i.e. to logging level + # LNONE). + logging_level = none + } + + + parent_logger2 + { + # set loggers named "parent_logger2" and its children loggers + # to write their output to a file named out.txt + output = file out.txt + + child_logger + { + # Set loggers named "parent_logger2.child_logger" and children of loggers + # with this name to logging level LALL + logging_level = all + + # Note that this logger will also log to out.txt because that is what + # its parent does and we haven't overridden it here with something else. + # if we wanted this logger to write to cout instead we could uncomment + # the following line: + # output = cout + } + } + } + + # So in summary, all logger config stuff goes inside a block named logger_config. Then + # inside that block all blocks must be the names of loggers. There are only two keys, + # logging_level and output. + # + # The valid values of logging_level are: + # "LALL", "LNONE", "LTRACE", "LDEBUG", "LINFO", "LWARN", "LERROR", "LFATAL", + # "ALL", "NONE", "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL", + # "all", "none", "trace", "debug", "info", "warn", "error", "fatal", or + # any integral value + # + # The valid values of output are: + # "cout", "cerr", "clog", or a string of the form "file some_file_name" + # which causes the output to be logged to the specified file. + # + !*/ + + +} + +// ---------------------------------------------------------------------------------------- + +#ifdef NO_MAKEFILE +#include "logger_config_file.cpp" +#endif + +#endif // DLIB_LOGGER_CONFIg_FILE_ + + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/logger/logger_kernel_1.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/logger/logger_kernel_1.h new file mode 100644 index 0000000..528bd6f --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/logger/logger_kernel_1.h @@ -0,0 +1,687 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_LOGGER_KERNEl_1_ +#define DLIB_LOGGER_KERNEl_1_ + +#include +#include +#include +#include +#include + +#include "../threads.h" +#include "../misc_api.h" +#include "../set.h" +#include "logger_kernel_abstract.h" +#include "../algs.h" +#include "../assert.h" +#include "../uintn.h" +#include "../map.h" +#include "../member_function_pointer.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class log_level + { + public: + log_level( + int priority_, + const char* name_ + ) : + priority(priority_) + { + strncpy(name,name_,19); + name[19] = '\0'; + } + + bool operator< (const log_level& rhs) const { return priority < rhs.priority; } + bool operator<=(const log_level& rhs) const { return priority <= rhs.priority; } + bool operator> (const log_level& rhs) const { return priority > rhs.priority; } + bool operator>=(const log_level& rhs) const { return priority >= rhs.priority; } + + int priority; + char name[20]; + }; + + inline std::ostream& operator<< (std::ostream& out, const log_level& item) + { + out << item.name; + return out; + } + + const log_level LALL (std::numeric_limits::min(),"ALL"); + const log_level LNONE (std::numeric_limits::max(),"NONE"); + const log_level LTRACE(-100,"TRACE"); + const log_level LDEBUG(0 ,"DEBUG"); + const log_level LINFO (100,"INFO "); + const log_level LWARN (200,"WARN "); + const log_level LERROR(300,"ERROR"); + const log_level LFATAL(400,"FATAL"); + +// ---------------------------------------------------------------------------------------- + + void set_all_logging_output_streams ( + std::ostream& out + ); + + void set_all_logging_levels ( + const log_level& new_level + ); + + typedef void (*print_header_type)( + std::ostream& out, + const std::string& logger_name, + const log_level& l, + const uint64 thread_id + ); + + void set_all_logging_headers ( + const print_header_type& new_header + ); + +// ---------------------------------------------------------------------------------------- + + void print_default_logger_header ( + std::ostream& out, + const std::string& logger_name, + const log_level& l, + const uint64 thread_id + ); + + template < + typename T + > + void set_all_logging_output_hooks ( + T& object, + void (T::*hook_)(const std::string& logger_name, + const log_level& l, + const uint64 thread_id, + const char* message_to_log) + ); + + template < + typename T + > + void set_all_logging_output_hooks ( + T& object + ) + { + set_all_logging_output_hooks(object, &T::log); + } + +// ---------------------------------------------------------------------------------------- + + class logger + { + /*! + INITIAL VALUE + - print_header == print_default_logger_header + - out.rdbuf() == std::cout.rdbuf() + - cur_level == LERROR + - auto_flush_enabled == true + - hook.is_set() == false + + CONVENTION + - print_header == logger_header() + - if (hook.is_set() == false) then + - out.rdbuf() == output_streambuf() + - else + - out.rdbuf() == &gd.hookbuf + - output_streambuf() == 0 + + - cur_level == level() + - logger_name == name() + - auto_flush_enabled == auto_flush() + + - logger::gd::loggers == a set containing all currently existing loggers. + - logger::gd::m == the mutex used to lock everything in the logger + - logger::gd::thread_names == a map of thread ids to thread names. + - logger::gd::next_thread_name == the next thread name that will be given out + to a thread when we find that it isn't already in thread_names. + !*/ + + // ------------------------------------------------------------------------------------ + // ------------------------------------------------------------------------------------ + + class logger_stream + { + /*! + INITIAL VALUE + - been_used == false + + CONVENTION + - enabled == is_enabled() + - if (been_used) then + - logger::gd::m is locked + - someone has used the << operator to write something to the + output stream. + !*/ + public: + logger_stream ( + const log_level& l_, + logger& log_ + ) : + l(l_), + log(log_), + been_used(false), + enabled (l.priority >= log.cur_level.priority) + {} + + inline ~logger_stream( + ) + { + if (!been_used) + { + return; + } + else + { + print_end_of_line(); + } + } + + bool is_enabled ( + ) const { return enabled; } + + template + inline logger_stream& operator << ( + const T& item + ) + { + if (!enabled) + { + return *this; + } + else + { + print_header_and_stuff(); + log.out << item; + return *this; + } + } + + private: + + void print_header_and_stuff ( + ); + /*! + ensures + - if (!been_used) then + - prints the logger header + - locks log.gd.m + - #been_used == true + !*/ + + void print_end_of_line ( + ); + /*! + ensures + - prints a newline to log.out + - unlocks log.gd.m + !*/ + + const log_level& l; + logger& log; + bool been_used; + const bool enabled; + }; // end of class logger_stream + + // ------------------------------------------------------------------------------------ + // ------------------------------------------------------------------------------------ + + friend class logger_stream; + public: + + typedef member_function_pointer hook_mfp; + + logger ( + const std::string& name_ + ); + + virtual ~logger ( + ); + + const std::string& name ( + ) const { return logger_name; } + + logger_stream operator << ( + const log_level& l + ) const { return logger_stream(l,const_cast(*this)); } + + bool is_child_of ( + const logger& log + ) const + { + return (name().find(log.name() + ".") == 0) || (log.name() == name()); + } + + const log_level level ( + ) const + { + auto_mutex M(gd.m); + return log_level(cur_level); + }; + + void set_level ( + const log_level& new_level + ) + { + auto_mutex M(gd.m); + gd.loggers.reset(); + while (gd.loggers.move_next()) + { + if (gd.loggers.element()->is_child_of(*this)) + gd.loggers.element()->cur_level = new_level; + } + + gd.set_level(logger_name, new_level); + } + + bool auto_flush ( + ) const + { + auto_mutex M(gd.m); + return auto_flush_enabled; + }; + + void set_auto_flush ( + bool enabled + ) + { + auto_mutex M(gd.m); + gd.loggers.reset(); + while (gd.loggers.move_next()) + { + if (gd.loggers.element()->is_child_of(*this)) + gd.loggers.element()->auto_flush_enabled = enabled; + } + + gd.set_auto_flush(logger_name, enabled); + } + + std::streambuf* output_streambuf ( + ) + { + auto_mutex M(gd.m); + + // if there is an output hook set then we are supposed to return 0. + if (hook) + return 0; + else + return out.rdbuf(); + } + + template < + typename T + > + void set_output_hook ( + T& object, + void (T::*hook_)(const std::string& logger_name, + const log_level& l, + const uint64 thread_id, + const char* message_to_log) + ) + { + auto_mutex M(gd.m); + hook.set(object, hook_); + + gd.loggers.reset(); + while (gd.loggers.move_next()) + { + if (gd.loggers.element()->is_child_of(*this)) + { + gd.loggers.element()->out.rdbuf(&gd.hookbuf); + gd.loggers.element()->hook = hook; + } + } + + gd.set_output_hook(logger_name, hook); + gd.set_output_stream(logger_name, gd.hookbuf); + } + + void set_output_stream ( + std::ostream& out_ + ) + { + auto_mutex M(gd.m); + gd.loggers.reset(); + while (gd.loggers.move_next()) + { + if (gd.loggers.element()->is_child_of(*this)) + { + gd.loggers.element()->out.rdbuf(out_.rdbuf()); + gd.loggers.element()->hook.clear(); + } + } + + gd.set_output_stream(logger_name, out_); + + hook.clear(); + gd.set_output_hook(logger_name, hook); + } + + print_header_type logger_header ( + ) const { return print_header; } + + void set_logger_header ( + print_header_type ph + ) + { + auto_mutex M(gd.m); + gd.loggers.reset(); + while (gd.loggers.move_next()) + { + if (gd.loggers.element()->is_child_of(*this)) + gd.loggers.element()->print_header = ph; + } + + gd.set_logger_header(logger_name, ph); + } + + private: + + // ------------------------------------------------------------------------------------ + // ------------------------------------------------------------------------------------ + + struct global_data + { + rmutex m; + set::kernel_1b loggers; + map::kernel_1b thread_names; + uint64 next_thread_name; + + // Make a very simple streambuf that writes characters into a std::vector. We can + // use this as the output target for hooks. The reason we don't just use a std::ostringstream + // instead is that this way we can be guaranteed that logging doesn't perform memory allocations. + // This is because a std::vector never frees memory. I.e. its capacity() doesn't go down when + // you resize it back to 0. It just stays the same. + class hook_streambuf : public std::streambuf + { + public: + std::vector buffer; + int_type overflow ( int_type c) + { + if (c != EOF) buffer.push_back(static_cast(c)); + return c; + } + + std::streamsize xsputn ( const char* s, std::streamsize num) + { + buffer.insert(buffer.end(), s, s+num); + return num; + } + }; + + hook_streambuf hookbuf; + + global_data ( + ); + + ~global_data( + ); + + uint64 get_thread_name ( + ); + /*! + requires + - m is locked + ensures + - returns a unique id for the calling thread. also makes the number + small and nice unlike what you get from get_thread_id() + !*/ + + void thread_end_handler ( + ); + /*! + ensures + - removes the terminated thread from thread_names + !*/ + + struct level_container + { + level_container (); + + log_level val; + map >::kernel_1b_c table; + } level_table; + + const log_level level ( + const std::string& name + ) const; + /*! + ensures + - returns the level loggers with the given name are supposed + to have + !*/ + + void set_level ( + const std::string& name, + const log_level& new_level + ); + /*! + ensures + - for all children C of name: + - #level(C) == new_level + - if name == "" then + - for all loggers L: + - #level(L) == new_level + !*/ + + struct auto_flush_container + { + bool val; + map >::kernel_1b_c table; + } auto_flush_table; + + bool auto_flush ( + const std::string& name + ) const; + /*! + ensures + - returns the auto_flush value loggers with the given name are supposed + to have + !*/ + + void set_auto_flush ( + const std::string& name, + bool enabled + ); + /*! + ensures + - for all children C of name: + - #auto_flush_enabled(C) == enabled + - if name == "" then + - for all loggers L: + - #auto_flush_enabled(L) == enabled + !*/ + + struct output_streambuf_container + { + std::streambuf* val; + map >::kernel_1b_c table; + } streambuf_table; + + std::streambuf* output_streambuf ( + const std::string& name + ); + /*! + ensures + - returns the streambuf loggers with the given name are supposed + to have + !*/ + + void set_output_stream ( + const std::string& name, + std::ostream& out_ + ); + /*! + ensures + - for all children C of name: + - #output_streambuf(C) == out_.rdbuf() + - if name == "" then + - for all loggers L: + - #output_streambuf(L) == out_.rdbuf() + !*/ + + void set_output_stream ( + const std::string& name, + std::streambuf& buf + ); + /*! + ensures + - for all children C of name: + - #output_streambuf(C) == &buf + - if name == "" then + - for all loggers L: + - #output_streambuf(L) == &buf + !*/ + + struct output_hook_container + { + hook_mfp val; + map >::kernel_1b_c table; + } hook_table; + + hook_mfp output_hook ( + const std::string& name + ); + /*! + ensures + - returns the hook loggers with the given name are supposed + to have + !*/ + + void set_output_hook ( + const std::string& name, + const hook_mfp& hook + ); + /*! + ensures + - for all children C of name: + - #output_hook(C) == hook + - if name == "" then + - for all loggers L: + - #output_hook(L) == hook + !*/ + + struct logger_header_container + { + print_header_type val; + map >::kernel_1b_c table; + } header_table; + + print_header_type logger_header ( + const std::string& name + ); + /*! + ensures + - returns the header function loggers with the given name are supposed + to have + !*/ + + void set_logger_header ( + const std::string& name, + print_header_type ph + ); + /*! + ensures + - for all children C of name: + - #logger_header(C) == ph + - if name == "" then + - for all loggers L: + - #logger_header(L) == ph + !*/ + + }; // end of struct global_data + + static global_data& get_global_data(); + + // ------------------------------------------------------------------------------------ + // ------------------------------------------------------------------------------------ + + friend void set_all_logging_levels ( + const log_level& new_level + ); + + friend void set_all_logging_headers ( + const print_header_type& new_header + ); + + friend void set_all_logging_output_streams ( + std::ostream& out + ); + + template < + typename T + > + friend void set_all_logging_output_hooks ( + T& object, + void (T::*hook_)(const std::string& logger_name, + const log_level& l, + const uint64 thread_id, + const char* message_to_log) + ) + { + logger::hook_mfp hook; + + // There is a bug in one of the versions (but not all apparently) of + // Visual studio 2005 that causes it to error out if isn't in the + // following line of code. However, there is also a bug in gcc-3.3 + // that causes it to error out if is present. So this works around + // this problem. +#if defined(_MSC_VER) && _MSC_VER == 1400 + hook.set(object, hook_); +#else + hook.set(object, hook_); +#endif + + logger::global_data& gd = logger::get_global_data(); + auto_mutex M(gd.m); + gd.loggers.reset(); + while (gd.loggers.move_next()) + { + gd.loggers.element()->out.rdbuf(&gd.hookbuf); + gd.loggers.element()->hook = hook; + } + + gd.set_output_stream("",gd.hookbuf); + gd.set_output_hook("",hook); + } + + // ------------------------------------------------------------------------------------ + + global_data& gd; + + const std::string logger_name; + + print_header_type print_header; + bool auto_flush_enabled; + std::ostream out; + log_level cur_level; + + hook_mfp hook; + + + // restricted functions + logger(const logger&); // copy constructor + logger& operator=(const logger&); // assignment operator + + }; + +// ---------------------------------------------------------------------------------------- + + + + +} + +#ifdef NO_MAKEFILE +#include "logger_kernel_1.cpp" +#endif + +#endif // DLIB_LOGGER_KERNEl_1_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/logger/logger_kernel_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/logger/logger_kernel_abstract.h new file mode 100644 index 0000000..b6a4367 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/logger/logger_kernel_abstract.h @@ -0,0 +1,429 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_LOGGER_KERNEl_ABSTRACT_ +#ifdef DLIB_LOGGER_KERNEl_ABSTRACT_ + +#include "../threads.h" +#include +#include +#include +#include "../uintn.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + class log_level + { + /*! + WHAT THIS OBJECT REPRESENTS + This object is a simple named level to log at. It contains a numeric + priority and a name to use in the logging messages. + !*/ + public: + log_level( + int priority_, + const char* name_ + ); + /*! + ensures + - #priority = priority_ + - the first 19 characters of name_ are copied into name and name + is null terminated. + !*/ + + bool operator< (const log_level& rhs) const { return priority < rhs.priority; } + bool operator<=(const log_level& rhs) const { return priority <= rhs.priority; } + bool operator> (const log_level& rhs) const { return priority > rhs.priority; } + bool operator>=(const log_level& rhs) const { return priority >= rhs.priority; } + + int priority; + char name[20]; + }; + + inline std::ostream& operator<< (std::ostream& out, const log_level& item); + /*! + ensures + - performs out << item.name + - returns out + !*/ + +// ---------------------------------------------------------------------------------------- + + const log_level LALL (std::numeric_limits::min(),"ALL"); + const log_level LNONE (std::numeric_limits::max(),"NONE"); + const log_level LTRACE(-100,"TRACE"); + const log_level LDEBUG(0 ,"DEBUG"); + const log_level LINFO (100 ,"INFO "); + const log_level LWARN (200 ,"WARN "); + const log_level LERROR(300 ,"ERROR"); + const log_level LFATAL(400 ,"FATAL"); + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + void set_all_logging_output_streams ( + std::ostream& out + ); + /*! + ensures + - for all loggers L (even loggers not yet constructed): + - #L.output_streambuf() == out.rdbuf() + - Removes any previous output hook from L. So now the logger + L will write all its messages to the given output stream. + throws + - std::bad_alloc + !*/ + +// ---------------------------------------------------------------------------------------- + + typedef void (*print_header_type)( + std::ostream& out, + const std::string& logger_name, + const log_level& l, + const uint64 thread_id + ); + + void set_all_logging_headers ( + const print_header_type& new_header + ); + /*! + ensures + - for all loggers L (even loggers not yet constructed): + - #L.logger_header() == new_header + throws + - std::bad_alloc + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void set_all_logging_output_hooks ( + T& object, + void (T::*hook)(const std::string& logger_name, + const log_level& l, + const uint64 thread_id, + const char* message_to_log) + ); + /*! + ensures + - for all loggers L (even loggers not yet constructed): + - #L.output_streambuf() == 0 + - performs the equivalent to calling L.set_output_hook(object, hook); + (i.e. sets all loggers so that they will use the given hook function) + throws + - std::bad_alloc + !*/ + + template < + typename T + > + void set_all_logging_output_hooks ( + T& object + ); + /*! + ensures + - calls set_all_logging_output_hooks(object, &T::log); + !*/ + +// ---------------------------------------------------------------------------------------- + + void set_all_logging_levels ( + const log_level& new_level + ); + /*! + ensures + - for all loggers L (even loggers not yet constructed): + - #L.level() == new_level + throws + - std::bad_alloc + !*/ + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + void print_default_logger_header ( + std::ostream& out, + const std::string& logger_name, + const log_level& l, + const uint64 thread_id + ); + /*! + requires + - is not called more than once at a time (i.e. is not called from multiple + threads at the same time). + ensures + - let MS be the number of milliseconds since program start. + - prints a string to out in the form: "MS l.name [thread_id] logger_name:" + !*/ + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + class logger + { + /*! + INITIAL VALUE + - name() == a user supplied value given to the constructor + - The values of level(), output_streambuf(), logger_header(), and + auto_flush() are inherited from the parent of this logger. + + WHAT THIS OBJECT REPRESENTS + This object represents a logging output stream in the style of the log4j + logger available for Java. + + Additionally, the logger doesn't perform any memory allocations during + each logging action. It just writes directly into the user supplied output + stream. Alternatively, if you use a logging output hook no memory allocations + are performed either. Logging just goes straight into a memory buffer + which gets passed to the user supplied logging hook. + + DEFAULTS + If the user hasn't specified values for the four inherited values level(), + output_streambuf(), logger_header(), or auto_flush() then the default + values will be used. The defaults are as follows: + - level() == LERROR + - output_streambuf() == std::cout.rdbuf() (i.e. the default is to log + to standard output). + - logger_header() == print_default_logger_header + - auto_flush() == true + + THREAD SAFETY + All methods of this class are thread safe. Note that it is safe to + chain calls to operator << such as: + log << LINFO << "message " << variable << " more message"; + The logger ensures that the entire statement executes atomically so the + message won't be broken up by other loggers in other threads. + !*/ + + class logger_stream + { + public: + + bool is_enabled ( + ) const; + /*! + ensures + - returns true if this logger stream will print out items + given to it by the << operator. returns false otherwise. + !*/ + + template + logger_stream& operator << ( + const T& item + ); + /*! + ensures + - if (is_enabled()) then + - writes item to this output stream + - returns *this + !*/ + }; + + public: + + logger ( + const std::string& name_ + ); + /*! + requires + - name_ != "" + ensures + - #*this is properly initialized + - #name() == name_ + throws + - std::bad_alloc + - dlib::thread_error + !*/ + + virtual ~logger ( + ); + /*! + ensures + - any resources associated with *this have been released + !*/ + + const std::string& name ( + ) const; + /*! + ensures + - returns the name of this logger + !*/ + + logger_stream operator << ( + const log_level& l + ) const; + /*! + ensures + - if (l.priority >= level().priority) then + - returns a logger_stream with is_enabled() == true. I.e. this + returned stream will write its output to the I/O destination + used by this logger object. + - else + - returns a logger stream with is_enabled() == false + throws + - std::bad_alloc + !*/ + + bool is_child_of ( + const logger& log + ) const; + /*! + ensures + - if ( (name().find(log.name() + ".") == 0) || (log.name() == name()) ) then + - returns true + (i.e. if log.name() + "." is a prefix of name() or if both *this and log + have the same name then return true) + - else + - returns false + !*/ + + const log_level level ( + ) const; + /*! + ensures + - returns the current log level of this logger. + !*/ + + void set_level ( + const log_level& new_level + ); + /*! + ensures + - for all loggers L such that L.is_child_of(*this) == true: + - #L.level() == new_level + throws + - std::bad_alloc + !*/ + + bool auto_flush ( + ); + /*! + ensures + - returns true if the output stream is flushed after every logged message. + returns false otherwise. (Note that flushing only does anything if + the logger is set to use an output stream rather than a hook) + !*/ + + void set_auto_flush ( + bool enabled + ); + /*! + ensures + - for all loggers L such that L.is_child_of(*this) == true: + - #L.auto_flush() == enabled + throws + - std::bad_alloc + !*/ + + + template < + typename T + > + void set_output_hook ( + T& object, + void (T::*hook)(const std::string& logger_name, + const log_level& l, + const uint64 thread_id, + const char* message_to_log) + ); + /*! + requires + - hook is a valid pointer to a member function in T + ensures + - for all loggers L such that L.is_child_of(*this) == true: + - #L.output_streambuf() == 0 + - #L will not send its log messages to an ostream object anymore. Instead + it will call the given hook member function (i.e. (object.*hook)(name,l,id,msg) ) + for each message that needs to be logged. + - The arguments to the hook function have the following meanings: + - logger_name == The name of the logger that is printing the log message. + - l == The level of the logger that is printing the log message. + - thread_id == A number that uniquely identifies the thread trying to log + the message. Note that this number is unique among all threads, past and + present. Also note that this id is not the same one returned by + get_thread_id(). + - message_to_log == the actual text of the message the user is giving to + the logger object to log. + - All hook functions will also only be called one at a time. This means + that hook functions don't need to be thread safe. + !*/ + + std::streambuf* output_streambuf ( + ); + /*! + ensures + - if (an output hook isn't set) then + - returns the output stream buffer that this logger writes all + messages to. + - else + - returns 0 + !*/ + + void set_output_stream ( + std::ostream& out + ); + /*! + ensures + - for all loggers L such that L.is_child_of(*this) == true: + - #L.output_streambuf() == out.rdbuf() + - Removes any previous output hook from L. So now the logger + L will write all its messages to the given output stream. + throws + - std::bad_alloc + !*/ + + print_header_type logger_header ( + ) const; + /*! + ensures + - returns the function that is called to print the header information + onto each logged message. The arguments to the function have the following + meanings: + - out == The output stream this function writes the header to. + - logger_name == The name of the logger that is printing the log message. + - l == The level of the logger that is printing the log message. + - thread_id == A number that uniquely identifies the thread trying to log + the message. Note that this number is unique among all threads, past and + present. Also note that this id is not the same one returned by + get_thread_id(). + - This logger_header function will also only be called once at a time. This means + the logger_header function doesn't need to be thread safe. + - the logger_header function is only used when output_streambuf() != 0 + !*/ + + void set_logger_header ( + print_header_type print_header + ); + /*! + ensures + - for all loggers L such that L.is_child_of(*this) == true: + - #L.logger_header() == print_header + throws + - std::bad_alloc + !*/ + + private: + + // restricted functions + logger(const logger&); // copy constructor + logger& operator=(const logger&); // assignment operator + + }; + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_LOGGER_KERNEl_ABSTRACT_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/map.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/map.h new file mode 100644 index 0000000..1203638 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/map.h @@ -0,0 +1,59 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MAp_ +#define DLIB_MAp_ + +#include "map/map_kernel_1.h" +#include "map/map_kernel_c.h" + +#include "binary_search_tree.h" + + +#include "algs.h" +#include + + +namespace dlib +{ + + template < + typename domain, + typename range, + typename mem_manager = default_memory_manager, + typename compare = std::less + > + class map + { + map() {} + + + // a typedef for the binary search tree used by kernel_2 + typedef typename binary_search_tree::kernel_1a + binary_search_tree_1; + + // a typedef for the binary search tree used by kernel_2 + typedef typename binary_search_tree::kernel_2a + binary_search_tree_2; + + public: + + //----------- kernels --------------- + + // kernel_1a + typedef map_kernel_1 + kernel_1a; + typedef map_kernel_c + kernel_1a_c; + + // kernel_1b + typedef map_kernel_1 + kernel_1b; + typedef map_kernel_c + kernel_1b_c; + + + }; +} + +#endif // DLIB_MAp_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/map/map_kernel_1.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/map/map_kernel_1.h new file mode 100644 index 0000000..ea3ed6f --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/map/map_kernel_1.h @@ -0,0 +1,436 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MAP_KERNEl_1_ +#define DLIB_MAP_KERNEl_1_ + +#include "map_kernel_abstract.h" +#include "../algs.h" +#include "../interfaces/enumerable.h" +#include "../interfaces/map_pair.h" +#include "../interfaces/remover.h" +#include "../serialize.h" + +namespace dlib +{ + + template < + typename domain, + typename range, + typename bst_base, + typename mem_manager = default_memory_manager + > + class map_kernel_1 : public enumerable >, + public asc_pair_remover + { + + /*! + REQUIREMENTS ON BST_BASE + bst_base is instantiated with domain and range and + implements binary_search_tree/binary_search_tree_kernel_abstract.h + + INITIAL VALUE + bst has its initial value + + CONVENTION + bst.size() == the number of elements in the map and + the elements in map are stored in bst_base + !*/ + + public: + + typedef domain domain_type; + typedef range range_type; + typedef typename bst_base::compare_type compare_type; + typedef mem_manager mem_manager_type; + + map_kernel_1( + ) + {} + + virtual ~map_kernel_1( + ) + {} + + inline void clear( + ); + + inline void add ( + domain& d, + range& r + ); + + inline bool is_in_domain ( + const domain& d + ) const; + + inline void remove_any ( + domain& d, + range& r + ); + + inline void remove ( + const domain& d, + domain& d_copy, + range& r + ); + + inline void destroy ( + const domain& d + ); + + inline range& operator[] ( + const domain& d + ); + + inline const range& operator[] ( + const domain& d + ) const; + + inline void swap ( + map_kernel_1& item + ); + + // functions from the enumerable interface + inline size_t size ( + ) const; + + inline bool at_start ( + ) const; + + inline void reset ( + ) const; + + inline bool current_element_valid ( + ) const; + + inline const map_pair& element ( + ) const; + + inline map_pair& element ( + ); + + inline bool move_next ( + ) const; + + + private: + + bst_base bst; + + // restricted functions + map_kernel_1(map_kernel_1&); + map_kernel_1& operator= ( map_kernel_1&); + }; + + + template < + typename domain, + typename range, + typename bst_base, + typename mem_manager + > + inline void swap ( + map_kernel_1& a, + map_kernel_1& b + ) { a.swap(b); } + + + template < + typename domain, + typename range, + typename bst_base, + typename mem_manager + > + void deserialize ( + map_kernel_1& item, + std::istream& in + ) + { + try + { + item.clear(); + unsigned long size; + deserialize(size,in); + domain d; + range r; + for (unsigned long i = 0; i < size; ++i) + { + deserialize(d,in); + deserialize(r,in); + item.add(d,r); + } + } + catch (serialization_error& e) + { + item.clear(); + throw serialization_error(e.info + "\n while deserializing object of type map_kernel_1"); + } + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename bst_base, + typename mem_manager + > + void map_kernel_1:: + clear ( + ) + { + bst.clear(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename bst_base, + typename mem_manager + > + void map_kernel_1:: + add( + domain& d, + range& r + ) + { + // try to add pair to bst_base + bst.add(d,r); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename bst_base, + typename mem_manager + > + bool map_kernel_1:: + is_in_domain( + const domain& d + ) const + { + return (bst[d] != 0); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename bst_base, + typename mem_manager + > + void map_kernel_1:: + remove_any( + domain& d, + range& r + ) + { + bst.remove_any(d,r); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename bst_base, + typename mem_manager + > + void map_kernel_1:: + remove ( + const domain& d, + domain& d_copy, + range& r + ) + { + bst.remove(d,d_copy,r); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename bst_base, + typename mem_manager + > + void map_kernel_1:: + destroy ( + const domain& d + ) + { + bst.destroy(d); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename bst_base, + typename mem_manager + > + range& map_kernel_1:: + operator[]( + const domain& d + ) + { + return *bst[d]; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename bst_base, + typename mem_manager + > + const range& map_kernel_1:: + operator[]( + const domain& d + ) const + { + return *bst[d]; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename bst_base, + typename mem_manager + > + size_t map_kernel_1:: + size ( + ) const + { + return bst.size(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename bst_base, + typename mem_manager + > + void map_kernel_1:: + swap ( + map_kernel_1& item + ) + { + bst.swap(item.bst); + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // enumerable function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename bst_base, + typename mem_manager + > + bool map_kernel_1:: + at_start ( + ) const + { + return bst.at_start(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename bst_base, + typename mem_manager + > + void map_kernel_1:: + reset ( + ) const + { + bst.reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename bst_base, + typename mem_manager + > + bool map_kernel_1:: + current_element_valid ( + ) const + { + return bst.current_element_valid(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename bst_base, + typename mem_manager + > + const map_pair& map_kernel_1:: + element ( + ) const + { + return bst.element(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename bst_base, + typename mem_manager + > + map_pair& map_kernel_1:: + element ( + ) + { + return bst.element(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range, + typename bst_base, + typename mem_manager + > + bool map_kernel_1:: + move_next ( + ) const + { + return bst.move_next(); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MAP_KERNEl_1_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/map/map_kernel_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/map/map_kernel_abstract.h new file mode 100644 index 0000000..1e07e5e --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/map/map_kernel_abstract.h @@ -0,0 +1,235 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_MAP_KERNEl_ABSTRACT_ +#ifdef DLIB_MAP_KERNEl_ABSTRACT_ + +#include "../interfaces/map_pair.h" +#include "../interfaces/enumerable.h" +#include "../interfaces/remover.h" +#include "../serialize.h" +#include "../algs.h" +#include + +namespace dlib +{ + + template < + typename domain, + typename range, + typename mem_manager = default_memory_manager, + typename compare = std::less + > + class map : public enumerable >, + public asc_pair_remover + { + + /*! + REQUIREMENTS ON domain + domain must be comparable by compare where compare is a functor compatible with std::less and + domain is swappable by a global swap() and + domain must have a default constructor + + REQUIREMENTS ON range + range is swappable by a global swap() and + range must have a default constructor + + REQUIREMENTS ON mem_manager + must be an implementation of memory_manager/memory_manager_kernel_abstract.h or + must be an implementation of memory_manager_global/memory_manager_global_kernel_abstract.h or + must be an implementation of memory_manager_stateless/memory_manager_stateless_kernel_abstract.h + mem_manager::type can be set to anything. + + POINTERS AND REFERENCES TO INTERNAL DATA + swap(), is_in_domain(), and operator[] functions do not invalidate + pointers or references to internal data. + All other functions have no such guarantee. + + INITIAL VALUE + size() == 0 + + ENUMERATION ORDER + The enumerator will iterate over the domain (and each associated + range element) elements in ascending order according to the compare functor. + (i.e. the elements are enumerated in sorted order) + + WHAT THIS OBJECT REPRESENTS + map contains items of type domain and range + + This object is similar an array. It maps items of type domain on to + items of type range. + + Also note that unless specified otherwise, no member functions + of this object throw exceptions. + + definition of equivalent: + a is equivalent to b if + a < b == false and + b < a == false + !*/ + + public: + + typedef domain domain_type; + typedef range range_type; + typedef compare compare_type; + typedef mem_manager mem_manager_type; + + map( + ); + /*! + ensures + - #*this is properly initialized + throws + - std::bad_alloc or any exception thrown by domain's or range's + constructor. + !*/ + + virtual ~map( + ); + /*! + ensures + - all memory associated with *this has been released + !*/ + + void clear( + ); + /*! + ensures + - #*this has its initial value + throws + - std::bad_alloc or any exception thrown by domain's or range's + constructor. + if this exception is thrown then *this is unusable + until clear() is called and succeeds + !*/ + + void add ( + domain& d, + range& r + ); + /*! + requires + - &d != &r (i.e. d and r cannot be the same variable) + - is_in_domain(d) == false + ensures + - #is_in_domain(d) == true + - #operator[](d) == r + - #d and #r have initial values for their types + - #size() == size() + 1 + - #at_start() == true + throws + - std::bad_alloc or any exception thrown by domain's or range's + constructor. + if add() throws then it has no effect + !*/ + + bool is_in_domain ( + const domain& d + ) const; + /*! + ensures + - returns whether or not an element equivalent to d is in the + domain of *this + !*/ + + void remove ( + const domain& d, + domain& d_copy, + range& r + ); + /*! + requires + - &d != &r (i.e. d and r cannot be the same variable) + - &d != &d_copy (i.e. d and d_copy cannot be the same variable) + - &r != &d_copy (i.e. r and d_copy cannot be the same variable) + - is_in_domain(d) == true + ensures + - #is_in_domain(d) == false + - #d_copy is equivalent to d + - the element in the range of *this associated with #d_copy has been + swapped into #r + - #size() == size() - 1 + - #at_start() == true + !*/ + + void destroy ( + const domain& d + ); + /*! + requires + - is_in_domain(d) == true + ensures + - #is_in_domain(d) == false + - #size() == size() - 1 + - #at_start() == true + !*/ + + range& operator[] ( + const domain& d + ); + /*! + requires + - is_in_domain(d) == true + ensures + - returns a non-const reference to the element in the range of *this + associated with the element equivalent to d + !*/ + + const range& operator[] ( + const domain& d + ) const; + /*! + requires + - is_in_domain(d) == true + ensures + - returns a const reference to the element in the range of *this + associated with the element equivalent to d + !*/ + + void swap ( + map& item + ); + /*! + ensures + - swaps *this and item + !*/ + + + private: + + // restricted functions + map(map&); // copy constructor + map& operator=(map&); // assignment operator + }; + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + inline void swap ( + map& a, + map& b + ) { a.swap(b); } + /*! + provides a global swap function + !*/ + + template < + typename domain, + typename range, + typename mem_manager, + typename compare + > + void deserialize ( + map& item, + std::istream& in + ); + /*! + provides deserialization support + !*/ +} + +#endif // DLIB_MAP_KERNEl_ABSTRACT_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/map/map_kernel_c.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/map/map_kernel_c.h new file mode 100644 index 0000000..dfdbd46 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/map/map_kernel_c.h @@ -0,0 +1,248 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MAP_KERNEl_C_ +#define DLIB_MAP_KERNEl_C_ + +#include "map_kernel_abstract.h" +#include "../algs.h" +#include "../assert.h" +#include "../interfaces/map_pair.h" + +namespace dlib +{ + + template < + typename map_base + > + class map_kernel_c : public map_base + { + + typedef typename map_base::domain_type domain; + typedef typename map_base::range_type range; + + public: + void add ( + domain& d, + range& r + ); + + void remove_any ( + domain& d, + range& r + ); + + void remove ( + const domain& d, + domain& d_copy, + range& r + ); + + void destroy ( + const domain& d + ); + + range& operator[] ( + const domain& d + ); + + const range& operator[] ( + const domain& d + ) const; + + const map_pair& element ( + ) const + { + // make sure requires clause is not broken + DLIB_CASSERT(this->current_element_valid() == true, + "\tconst map_pair& map::element" + << "\n\tyou can't access the current element if it doesn't exist" + << "\n\tthis: " << this + ); + + // call the real function + return map_base::element(); + } + + map_pair& element ( + ) + { + // make sure requires clause is not broken + DLIB_CASSERT(this->current_element_valid() == true, + "\tmap_pair& map::element" + << "\n\tyou can't access the current element if it doesn't exist" + << "\n\tthis: " << this + ); + + // call the real function + return map_base::element(); + } + + }; + + template < + typename map_base + > + inline void swap ( + map_kernel_c& a, + map_kernel_c& b + ) { a.swap(b); } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename map_base + > + void map_kernel_c:: + add ( + domain& d, + range& r + ) + { + // make sure requires clause is not broken + DLIB_CASSERT( (!this->is_in_domain(d)) && + (static_cast(&d) != static_cast(&r)), + "\tvoid map::add" + << "\n\tdomain element being added must not already be in the map" + << "\n\tand d and r must not be the same variable" + << "\n\tis_in_domain(d): " << (this->is_in_domain(d) ? "true" : "false") + << "\n\tthis: " << this + << "\n\t&d: " << static_cast(&d) + << "\n\t&r: " << static_cast(&r) + ); + + // call the real function + map_base::add(d,r); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename map_base + > + void map_kernel_c:: + remove_any ( + domain& d, + range& r + ) + { + // make sure requires clause is not broken + DLIB_CASSERT( (this->size() > 0) && + (static_cast(&d) != static_cast(&r)), + "\tvoid map::remove_any" + << "\n\tsize() must be greater than zero if something is going to be removed" + << "\n\tand d and r must not be the same variable." + << "\n\tsize(): " << this->size() + << "\n\tthis: " << this + << "\n\t&d: " << static_cast(&d) + << "\n\t&r: " << static_cast(&r) + ); + + // call the real function + map_base::remove_any(d,r); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename map_base + > + void map_kernel_c:: + remove ( + const domain& d, + domain& d_copy, + range& r + ) + { + // make sure requires clause is not broken + DLIB_CASSERT( (this->is_in_domain(d)) && + (static_cast(&d) != static_cast(&r)) && + (static_cast(&r) != static_cast(&d_copy)) && + (static_cast(&d) != static_cast(&d_copy)), + "\tvoid map::remove" + << "\n\tcan't remove something that isn't in the map or if the paremeters actually" + << "\n\tare the same variable. Either way can't remove." + << "\n\tis_in_domain(d): " << (this->is_in_domain(d) ? "true" : "false") + << "\n\tthis: " << this + << "\n\t&d: " << static_cast(&d) + << "\n\t&r: " << static_cast(&r) + << "\n\t&d_copy: " << static_cast(&d_copy) + ); + + // call the real function + map_base::remove(d,d_copy,r); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename map_base + > + void map_kernel_c:: + destroy ( + const domain& d + ) + { + // make sure requires clause is not broken + DLIB_CASSERT(this->is_in_domain(d), + "\tvoid map::destroy" + << "\n\tcan't remove something that isn't in the map" + << "\n\tthis: " << this + << "\n\t&d: " << static_cast(&d) + ); + + // call the real function + map_base::destroy(d); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename map_base + > + typename map_base::range_type& map_kernel_c:: + operator[] ( + const domain& d + ) + { + // make sure requires clause is not broken + DLIB_CASSERT( this->is_in_domain(d), + "\trange& map::operator[]" + << "\n\td must be in the domain of the map" + << "\n\tthis: " << this + ); + + // call the real function + return map_base::operator[](d); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename map_base + > + const typename map_base::range_type& map_kernel_c:: + operator[] ( + const domain& d + ) const + { + // make sure requires clause is not broken + DLIB_CASSERT( this->is_in_domain(d), + "\tconst range& map::operator[]" + << "\n\td must be in the domain of the map" + << "\n\tthis: " << this + ); + + // call the real function + return map_base::operator[](d); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MAP_KERNEl_C_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/member_function_pointer.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/member_function_pointer.h new file mode 100644 index 0000000..3dd72f5 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/member_function_pointer.h @@ -0,0 +1,10 @@ +// Copyright (C) 2005 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MEMBER_FUNCTION_POINTEr_ +#define DLIB_MEMBER_FUNCTION_POINTEr_ + +#include "member_function_pointer/member_function_pointer_kernel_1.h" +#include "member_function_pointer/make_mfp.h" + +#endif // DLIB_MEMBER_FUNCTION_POINTEr_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/member_function_pointer/make_mfp.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/member_function_pointer/make_mfp.h new file mode 100644 index 0000000..fff9b27 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/member_function_pointer/make_mfp.h @@ -0,0 +1,179 @@ +// Copyright (C) 2011 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MAKE_MFp_H_ +#define DLIB_MAKE_MFp_H_ + +#include "member_function_pointer_kernel_1.h" +#include "make_mfp_abstract.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + member_function_pointer<> make_mfp ( + T& object, + void (T::*cb)() + ) + { + member_function_pointer<> temp; + temp.set(object, cb); + return temp; + } + + template < + typename T + > + member_function_pointer<> make_mfp ( + const T& object, + void (T::*cb)()const + ) + { + member_function_pointer<> temp; + temp.set(object, cb); + return temp; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename A1 + > + member_function_pointer make_mfp ( + T& object, + void (T::*cb)(A1) + ) + { + member_function_pointer temp; + temp.set(object, cb); + return temp; + } + + template < + typename T, + typename A1 + > + member_function_pointer make_mfp ( + const T& object, + void (T::*cb)(A1)const + ) + { + member_function_pointer temp; + temp.set(object, cb); + return temp; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename A1, + typename A2 + > + member_function_pointer make_mfp ( + T& object, + void (T::*cb)(A1,A2) + ) + { + member_function_pointer temp; + temp.set(object, cb); + return temp; + } + + template < + typename T, + typename A1, + typename A2 + > + member_function_pointer make_mfp ( + const T& object, + void (T::*cb)(A1,A2)const + ) + { + member_function_pointer temp; + temp.set(object, cb); + return temp; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename A1, + typename A2, + typename A3 + > + member_function_pointer make_mfp ( + T& object, + void (T::*cb)(A1,A2,A3) + ) + { + member_function_pointer temp; + temp.set(object, cb); + return temp; + } + + template < + typename T, + typename A1, + typename A2, + typename A3 + > + member_function_pointer make_mfp ( + const T& object, + void (T::*cb)(A1,A2,A3)const + ) + { + member_function_pointer temp; + temp.set(object, cb); + return temp; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename A1, + typename A2, + typename A3, + typename A4 + > + member_function_pointer make_mfp ( + T& object, + void (T::*cb)(A1,A2,A3,A4) + ) + { + member_function_pointer temp; + temp.set(object, cb); + return temp; + } + + template < + typename T, + typename A1, + typename A2, + typename A3, + typename A4 + > + member_function_pointer make_mfp ( + const T& object, + void (T::*cb)(A1,A2,A3,A4)const + ) + { + member_function_pointer temp; + temp.set(object, cb); + return temp; + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MAKE_MFp_H_ + + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/member_function_pointer/make_mfp_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/member_function_pointer/make_mfp_abstract.h new file mode 100644 index 0000000..5074ca9 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/member_function_pointer/make_mfp_abstract.h @@ -0,0 +1,207 @@ +// Copyright (C) 2011 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_MAKE_MFp_ABSTRACT_ +#ifdef DLIB_MAKE_MFp_ABSTRACT_ + +#include "member_function_pointer_kernel_abstract.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + member_function_pointer<> make_mfp ( + T& object, + void (T::*cb)() + ); + /*! + requires + - cb == a valid member function pointer for class T + ensures + - returns a member function pointer object MFP such that: + - MFP.is_set() == true + - calls to MFP() will call (object.*cb)() + !*/ + + template < + typename T + > + member_function_pointer<> make_mfp ( + const T& object, + void (T::*cb)()const + ); + /*! + requires + - cb == a valid member function pointer for class T + ensures + - returns a member function pointer object MFP such that: + - MFP.is_set() == true + - calls to MFP() will call (object.*cb)() + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename A1 + > + member_function_pointer make_mfp ( + T& object, + void (T::*cb)(A1 a1) + ); + /*! + requires + - cb == a valid member function pointer for class T + ensures + - returns a member function pointer object MFP such that: + - MFP.is_set() == true + - calls to MFP(a1) will call (object.*cb)(a1) + !*/ + + template < + typename T, + typename A1 + > + member_function_pointer make_mfp ( + const T& object, + void (T::*cb)(A1 a1)const + ); + /*! + requires + - cb == a valid member function pointer for class T + ensures + - returns a member function pointer object MFP such that: + - MFP.is_set() == true + - calls to MFP(a1) will call (object.*cb)(a1) + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename A1, + typename A2 + > + member_function_pointer make_mfp ( + T& object, + void (T::*cb)(A1 a1, A2 a2) + ); + /*! + requires + - cb == a valid member function pointer for class T + ensures + - returns a member function pointer object MFP such that: + - MFP.is_set() == true + - calls to MFP(a1,a2) will call (object.*cb)(a1,a2) + !*/ + + template < + typename T, + typename A1, + typename A2 + > + member_function_pointer make_mfp ( + const T& object, + void (T::*cb)(A1 a1, A2 a2)const + ); + /*! + requires + - cb == a valid member function pointer for class T + ensures + - returns a member function pointer object MFP such that: + - MFP.is_set() == true + - calls to MFP(a1,a2) will call (object.*cb)(a1,a2) + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename A1, + typename A2, + typename A3 + > + member_function_pointer make_mfp ( + T& object, + void (T::*cb)(A1 a1, A2 a2, A3 a3) + ); + /*! + requires + - cb == a valid member function pointer for class T + ensures + - returns a member function pointer object MFP such that: + - MFP.is_set() == true + - calls to MFP(a1,a2,a3) will call (object.*cb)(a1,a2,a3) + !*/ + + template < + typename T, + typename A1, + typename A2, + typename A3 + > + member_function_pointer make_mfp ( + const T& object, + void (T::*cb)(A1 a1, A2 a2, A3 a3)const + ); + /*! + requires + - cb == a valid member function pointer for class T + ensures + - returns a member function pointer object MFP such that: + - MFP.is_set() == true + - calls to MFP(a1,a2,a3) will call (object.*cb)(a1,a2,a3) + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename A1, + typename A2, + typename A3, + typename A4 + > + member_function_pointer make_mfp ( + T& object, + void (T::*cb)(A1 a1, A2 a2, A3 a3, A4 a4) + ); + /*! + requires + - cb == a valid member function pointer for class T + ensures + - returns a member function pointer object MFP such that: + - MFP.is_set() == true + - calls to MFP(a1,a2,a3,a4) will call (object.*cb)(a1,a2,a3,a4) + !*/ + + template < + typename T, + typename A1, + typename A2, + typename A3, + typename A4 + > + member_function_pointer make_mfp ( + const T& object, + void (T::*cb)(A1 a1, A2 a2, A3 a3, A4 a4)const + ); + /*! + requires + - cb == a valid member function pointer for class T + ensures + - returns a member function pointer object MFP such that: + - MFP.is_set() == true + - calls to MFP(a1,a2,a3,a4) will call (object.*cb)(a1,a2,a3,a4) + !*/ + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MAKE_MFp_ABSTRACT_ + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/member_function_pointer/member_function_pointer_kernel_1.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/member_function_pointer/member_function_pointer_kernel_1.h new file mode 100644 index 0000000..04ac631 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/member_function_pointer/member_function_pointer_kernel_1.h @@ -0,0 +1,509 @@ +// Copyright (C) 2005 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MEMBER_FUNCTION_POINTER_KERNEl_1_ +#define DLIB_MEMBER_FUNCTION_POINTER_KERNEl_1_ + +#include "../algs.h" +#include "member_function_pointer_kernel_abstract.h" +#include "../enable_if.h" +#include + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template < + typename PARAM1 = void, + typename PARAM2 = void, + typename PARAM3 = void, + typename PARAM4 = void + > + class member_function_pointer; + +// ---------------------------------------------------------------------------------------- + +#define DLIB_MFP_SC DLIB_ASSERT(cb != 0, \ + "\tvoid member_function_pointer::set" \ + << "\n\tthe member function pointer can't be null" \ + << "\n\tthis: " << this ); + + +#define DLIB_MFP_OC DLIB_ASSERT(this->is_set() == true , \ + "\tvoid member_function_pointer::operator()" \ + << "\n\tYou must call set() before you can use this function" \ + << "\n\tthis: " << this); + +// ---------------------------------------------------------------------------------------- + + template + class mfp_kernel_1_base_class + { + /* + All member function pointer classes inherit from this class. This + is where most of the things in a member function pointer are defined. + + The reason for the num_args template argument to this class is to prevent + any sort of implicit casting between derived member function pointer classes + that take different numbers of arguments. + */ + protected: + enum mfp_type { mfp_nonconst, mfp_const, mfp_null}; + + class mp_base_base + { + public: + mp_base_base(void* ptr, mfp_type type_) : o(ptr),type(type_) {} + virtual ~mp_base_base(){} + virtual void clone(void* ptr) const = 0; + virtual bool is_same (const mp_base_base* item) const = 0; + bool is_set () const { return o!=0; } + + void* const o; + const mfp_type type; + }; + + template + class mp_null : public mp_base_base + { + public: + typedef void (T::*mfp_pointer_type)() ; + + mp_null (void* , mfp_pointer_type ) : mp_base_base(0,mfp_null), callback(0) {} + mp_null () : mp_base_base(0,mfp_null), callback(0) {} + + const mfp_pointer_type callback; + }; + + template + class mp_impl_T : public mp_impl + { + /* + This class supplies the implementations clone() and is_same() for any + classes that inherit from mp_base_base. It does this in a very + roundabout way... + */ + + public: + typedef typename mp_impl::mfp_pointer_type mfp_pointer_type; + + mp_impl_T() : mp_impl(0,0) {} + mp_impl_T(void* ptr, mfp_pointer_type cb) : mp_impl(ptr,cb) {} + + template + void safe_clone(stack_based_memory_block& buf) + { + // This is here just to validate the assumption that our block of memory we have made + // in mp_memory is the right size to store the data for this object. If you + // get a compiler error on this line then email me :) + COMPILE_TIME_ASSERT(sizeof(mp_impl_T) <= mem_size); + clone(buf.get()); + } + + void clone (void* ptr) const { new(ptr) mp_impl_T(this->o,this->callback); } + bool is_same (const mp_base_base* item) const + { + if (item->o == 0 && this->o == 0) + { + return true; + } + else if (item->o == this->o && this->type == item->type) + { + const mp_impl* i = reinterpret_cast(item); + return (i->callback == this->callback); + } + return false; + } + }; + + // MSVC with the /vms option, we get C2287 since the dummy class requires virtual + // inheritance. Adding the __virtual_inheritance specifier explicitly fixes the issue, + // but then Clang-CL no longer accepts it. + #if defined(_MSC_VER) && !defined(__clang__) + #define DLIB_MSVC_INHERITANCE_VIRTUAL __virtual_inheritance + #else + #define DLIB_MSVC_INHERITANCE_VIRTUAL + #endif + + struct dummy_base { virtual void nonnull() {}; virtual ~dummy_base(){}; int a; }; + struct DLIB_MSVC_INHERITANCE_VIRTUAL dummy : virtual public dummy_base{ void nonnull() {}; }; + + #undef DLIB_MSVC_INHERITANCE_VIRTUAL + + typedef mp_impl_T > mp_null_impl; + public: + + mfp_kernel_1_base_class ( + const mfp_kernel_1_base_class& item + ) { item.mp()->clone(mp_memory.get()); } + + mfp_kernel_1_base_class ( + ) { mp_null_impl().safe_clone(mp_memory); } + + bool operator == ( + const mfp_kernel_1_base_class& item + ) const { return mp()->is_same(item.mp()); } + + bool operator != ( + const mfp_kernel_1_base_class& item + ) const { return !(*this == item); } + + mfp_kernel_1_base_class& operator= ( + const mfp_kernel_1_base_class& item + ) { mfp_kernel_1_base_class(item).swap(*this); return *this; } + + ~mfp_kernel_1_base_class ( + ) { destroy_mp_memory(); } + + void clear( + ) { mfp_kernel_1_base_class().swap(*this); } + + bool is_set ( + ) const { return mp()->is_set(); } + + private: + typedef void (dummy::*safe_bool)(); + + public: + operator safe_bool () const { return is_set() ? &dummy::nonnull : 0; } + bool operator!() const { return !is_set(); } + + void swap ( + mfp_kernel_1_base_class& item + ) + { + // make a temp copy of item + mfp_kernel_1_base_class temp(item); + + // destory the stuff in item + item.destroy_mp_memory(); + // copy *this into item + mp()->clone(item.mp_memory.get()); + + // destory the stuff in this + destroy_mp_memory(); + // copy temp into *this + temp.mp()->clone(mp_memory.get()); + } + + protected: + + // The reason for adding 1 here is because visual studio 2003 will sometimes + // try to compile this code with sizeof(mp_null_impl) == 0 (which is a bug in visual studio). + // Fortunately, no actual real instances of this template seem to end up with that screwed up + // value so everything works fine if we just add 1 so that this degenerate case doesn't cause + // trouble. Note that we know it all works fine because safe_clone() checks the size of this + // memory block whenever the member function pointer is used. + stack_based_memory_block mp_memory; + + void destroy_mp_memory ( + ) + { + // Honestly this probably doesn't even do anything but I'm putting + // it here just for good measure. + mp()->~mp_base_base(); + } + + mp_base_base* mp () { return static_cast(mp_memory.get()); } + const mp_base_base* mp () const { return static_cast(mp_memory.get()); } + + }; + +// ---------------------------------------------------------------------------------------- + + template <> + class member_function_pointer : public mfp_kernel_1_base_class<0> + { + class mp_base : public mp_base_base { + public: + mp_base(void* ptr, mfp_type type_) : mp_base_base(ptr,type_) {} + virtual void call() const = 0; + }; + + template + class mp_impl : public mp_base { + public: + typedef void (T::*mfp_pointer_type)() ; + void call () const { (static_cast(this->o)->*callback)(); } + + mp_impl ( void* object, mfp_pointer_type cb) : mp_base(object, mfp_nonconst), callback(cb) {} + const mfp_pointer_type callback; + }; + + template + class mp_impl_const : public mp_base { + public: + typedef void ((T::*mfp_pointer_type)()const); + void call () const { (static_cast(this->o)->*callback)(); } + + mp_impl_const ( void* object, mfp_pointer_type cb) : mp_base(object,mfp_const), callback(cb) {} + const mfp_pointer_type callback; + }; + + public: + typedef void param1_type; + typedef void param2_type; + typedef void param3_type; + typedef void param4_type; + + // These two typedefs are here for backwards compatibility with previous versions + // of dlib. + typedef member_function_pointer kernel_1a; + typedef member_function_pointer kernel_1a_c; + + + void operator() () const { DLIB_MFP_OC; static_cast(mp_memory.get())->call(); } + + // the reason for putting disable_if on this function is that it avoids an overload + // resolution bug in visual studio. + template typename disable_if,void>::type + set(T& object, typename mp_impl::mfp_pointer_type cb) + { DLIB_MFP_SC; destroy_mp_memory(); mp_impl_T >(&object,cb).safe_clone(mp_memory); } + + template void set(const T& object, typename mp_impl_const::mfp_pointer_type cb) + { DLIB_MFP_SC; destroy_mp_memory(); mp_impl_T >((void*)&object,cb).safe_clone(mp_memory); } + + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename PARAM1 + > + class member_function_pointer : public mfp_kernel_1_base_class<1> + { + class mp_base : public mp_base_base { + public: + mp_base(void* ptr, mfp_type type_) : mp_base_base(ptr,type_) {} + virtual void call(PARAM1) const = 0; + }; + + template + class mp_impl : public mp_base { + public: + typedef void (T::*mfp_pointer_type)(PARAM1) ; + void call (PARAM1 p1) const { (static_cast(this->o)->*callback)(p1); } + + mp_impl ( void* object, mfp_pointer_type cb) : mp_base(object, mfp_nonconst), callback(cb) {} + const mfp_pointer_type callback; + }; + + template + class mp_impl_const : public mp_base { + public: + typedef void ((T::*mfp_pointer_type)(PARAM1)const); + void call (PARAM1 p1) const { (static_cast(this->o)->*callback)(p1); } + + mp_impl_const ( void* object, mfp_pointer_type cb) : mp_base(object,mfp_const), callback(cb) {} + const mfp_pointer_type callback; + }; + + public: + typedef PARAM1 param1_type; + typedef void param2_type; + typedef void param3_type; + typedef void param4_type; + + // These two typedefs are here for backwards compatibility with previous versions + // of dlib. + typedef member_function_pointer kernel_1a; + typedef member_function_pointer kernel_1a_c; + + + void operator() (PARAM1 p1) const { DLIB_MFP_OC; static_cast(mp_memory.get())->call(p1); } + + // the reason for putting disable_if on this function is that it avoids an overload + // resolution bug in visual studio. + template typename disable_if,void>::type + set(T& object, typename mp_impl::mfp_pointer_type cb) + { DLIB_MFP_SC; destroy_mp_memory(); mp_impl_T >(&object,cb).safe_clone(mp_memory); } + + template void set(const T& object, typename mp_impl_const::mfp_pointer_type cb) + { DLIB_MFP_SC; destroy_mp_memory(); mp_impl_T >((void*)&object,cb).safe_clone(mp_memory); } + + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename PARAM1, + typename PARAM2 + > + class member_function_pointer : public mfp_kernel_1_base_class<2> + { + class mp_base : public mp_base_base { + public: + mp_base(void* ptr, mfp_type type_) : mp_base_base(ptr,type_) {} + virtual void call(PARAM1,PARAM2) const = 0; + }; + + template + class mp_impl : public mp_base { + public: + typedef void (T::*mfp_pointer_type)(PARAM1,PARAM2) ; + void call (PARAM1 p1, PARAM2 p2) const { (static_cast(this->o)->*callback)(p1,p2); } + + mp_impl ( void* object, mfp_pointer_type cb) : mp_base(object, mfp_nonconst), callback(cb) {} + const mfp_pointer_type callback; + }; + + template + class mp_impl_const : public mp_base { + public: + typedef void ((T::*mfp_pointer_type)(PARAM1,PARAM2)const); + void call (PARAM1 p1, PARAM2 p2) const { (static_cast(this->o)->*callback)(p1,p2); } + + mp_impl_const ( void* object, mfp_pointer_type cb) : mp_base(object,mfp_const), callback(cb) {} + const mfp_pointer_type callback; + }; + + public: + typedef PARAM1 param1_type; + typedef PARAM2 param2_type; + typedef void param3_type; + typedef void param4_type; + + // These two typedefs are here for backwards compatibility with previous versions + // of dlib. + typedef member_function_pointer kernel_1a; + typedef member_function_pointer kernel_1a_c; + + void operator() (PARAM1 p1, PARAM2 p2) const { DLIB_MFP_OC; static_cast(mp_memory.get())->call(p1,p2); } + + // the reason for putting disable_if on this function is that it avoids an overload + // resolution bug in visual studio. + template typename disable_if,void>::type + set(T& object, typename mp_impl::mfp_pointer_type cb) + { DLIB_MFP_SC; destroy_mp_memory(); mp_impl_T >(&object,cb).safe_clone(mp_memory); } + + template void set(const T& object, typename mp_impl_const::mfp_pointer_type cb) + { DLIB_MFP_SC; destroy_mp_memory(); mp_impl_T >((void*)&object,cb).safe_clone(mp_memory); } + + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename PARAM1, + typename PARAM2, + typename PARAM3 + > + class member_function_pointer : public mfp_kernel_1_base_class<3> + { + class mp_base : public mp_base_base { + public: + mp_base(void* ptr, mfp_type type_) : mp_base_base(ptr,type_) {} + virtual void call(PARAM1,PARAM2,PARAM3) const = 0; + }; + + template + class mp_impl : public mp_base { + public: + typedef void (T::*mfp_pointer_type)(PARAM1,PARAM2,PARAM3) ; + void call (PARAM1 p1, PARAM2 p2, PARAM3 p3) const { (static_cast(this->o)->*callback)(p1,p2,p3); } + + mp_impl ( void* object, mfp_pointer_type cb) : mp_base(object, mfp_nonconst), callback(cb) {} + const mfp_pointer_type callback; + }; + + template + class mp_impl_const : public mp_base { + public: + typedef void ((T::*mfp_pointer_type)(PARAM1,PARAM2,PARAM3)const); + void call (PARAM1 p1, PARAM2 p2, PARAM3 p3) const { (static_cast(this->o)->*callback)(p1,p2,p3); } + + mp_impl_const ( void* object, mfp_pointer_type cb) : mp_base(object,mfp_const), callback(cb) {} + const mfp_pointer_type callback; + }; + + public: + typedef PARAM1 param1_type; + typedef PARAM2 param2_type; + typedef PARAM3 param3_type; + typedef void param4_type; + + // These two typedefs are here for backwards compatibility with previous versions + // of dlib. + typedef member_function_pointer kernel_1a; + typedef member_function_pointer kernel_1a_c; + + void operator() (PARAM1 p1, PARAM2 p2, PARAM3 p3) const { DLIB_MFP_OC; static_cast(mp_memory.get())->call(p1,p2,p3); } + + // the reason for putting disable_if on this function is that it avoids an overload + // resolution bug in visual studio. + template typename disable_if,void>::type + set(T& object, typename mp_impl::mfp_pointer_type cb) + { DLIB_MFP_SC; destroy_mp_memory(); mp_impl_T >(&object,cb).safe_clone(mp_memory); } + + template void set(const T& object, typename mp_impl_const::mfp_pointer_type cb) + { DLIB_MFP_SC; destroy_mp_memory(); mp_impl_T >((void*)&object,cb).safe_clone(mp_memory); } + + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename PARAM1, + typename PARAM2, + typename PARAM3, + typename PARAM4 + > + class member_function_pointer : public mfp_kernel_1_base_class<4> + { + class mp_base : public mp_base_base { + public: + mp_base(void* ptr, mfp_type type_) : mp_base_base(ptr,type_) {} + virtual void call(PARAM1,PARAM2,PARAM3,PARAM4) const = 0; + }; + + template + class mp_impl : public mp_base { + public: + typedef void (T::*mfp_pointer_type)(PARAM1,PARAM2,PARAM3, PARAM4) ; + void call (PARAM1 p1, PARAM2 p2, PARAM3 p3, PARAM4 p4) const { (static_cast(this->o)->*callback)(p1,p2,p3,p4); } + + mp_impl ( void* object, mfp_pointer_type cb) : mp_base(object, mfp_nonconst), callback(cb) {} + const mfp_pointer_type callback; + }; + + template + class mp_impl_const : public mp_base { + public: + typedef void ((T::*mfp_pointer_type)(PARAM1,PARAM2,PARAM3,PARAM4)const); + void call (PARAM1 p1, PARAM2 p2, PARAM3 p3, PARAM4 p4) const { (static_cast(this->o)->*callback)(p1,p2,p3,p4); } + + mp_impl_const ( void* object, mfp_pointer_type cb) : mp_base(object,mfp_const), callback(cb) {} + const mfp_pointer_type callback; + }; + + public: + typedef PARAM1 param1_type; + typedef PARAM2 param2_type; + typedef PARAM3 param3_type; + typedef PARAM4 param4_type; + + // These two typedefs are here for backwards compatibility with previous versions + // of dlib. + typedef member_function_pointer kernel_1a; + typedef member_function_pointer kernel_1a_c; + + void operator() (PARAM1 p1, PARAM2 p2, PARAM3 p3, PARAM4 p4) const + { DLIB_MFP_OC; static_cast(mp_memory.get())->call(p1,p2,p3,p4); } + + // the reason for putting disable_if on this function is that it avoids an overload + // resolution bug in visual studio. + template typename disable_if,void>::type + set(T& object, typename mp_impl::mfp_pointer_type cb) + { DLIB_MFP_SC; destroy_mp_memory(); mp_impl_T >(&object,cb).safe_clone(mp_memory); } + + template void set(const T& object, typename mp_impl_const::mfp_pointer_type cb) + { DLIB_MFP_SC; destroy_mp_memory(); mp_impl_T >((void*)&object,cb).safe_clone(mp_memory); } + + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MEMBER_FUNCTION_POINTER_KERNEl_1_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/member_function_pointer/member_function_pointer_kernel_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/member_function_pointer/member_function_pointer_kernel_abstract.h new file mode 100644 index 0000000..e152972 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/member_function_pointer/member_function_pointer_kernel_abstract.h @@ -0,0 +1,483 @@ +// Copyright (C) 2005 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_MEMBER_FUNCTION_POINTER_KERNEl_ABSTRACT_ +#ifdef DLIB_MEMBER_FUNCTION_POINTER_KERNEl_ABSTRACT_ + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template < + typename PARAM1 = void, + typename PARAM2 = void, + typename PARAM3 = void, + typename PARAM4 = void + > + class member_function_pointer; + +// ---------------------------------------------------------------------------------------- + + template <> + class member_function_pointer + { + /*! + INITIAL VALUE + is_set() == false + + WHAT THIS OBJECT REPRESENTS + This object represents a member function pointer. It is useful because + instances of this object can be created without needing to know the type + of object whose member function we will be calling. + + There are five template specializations of this object. The first + represents a pointer to a member function taking no parameters, the + second represents a pointer to a member function taking one parameter, + the third to one taking two parameters, and so on. + + You specify the parameters to your member function pointer by filling in + the PARAM template parameters. For example: + + To use a pointer to a function with no parameters you would say: + member_function_pointer<> my_pointer; + To use a pointer to a function that takes a single int you would say: + member_function_pointer my_pointer; + To use a pointer to a function that takes an int and then a reference + to a string you would say: + member_function_pointer my_pointer; + + Also note that the formal comments are only present for the first + template specialization. They are all exactly the same except for the + number of parameters each takes in its member function pointer. + !*/ + + public: + typedef void param1_type; + typedef void param2_type; + typedef void param3_type; + typedef void param4_type; + + member_function_pointer ( + ); + /*! + ensures + - #*this is properly initialized + !*/ + + member_function_pointer( + const member_function_pointer& item + ); + /*! + ensures + - *this == item + !*/ + + ~member_function_pointer ( + ); + /*! + ensures + - any resources associated with *this have been released + !*/ + + member_function_pointer& operator=( + const member_function_pointer& item + ); + /*! + ensures + - *this == item + !*/ + + bool operator == ( + const member_function_pointer& item + ) const; + /*! + ensures + - if (is_set() == false && item.is_set() == false) then + - returns true + - else if (both *this and item point to the same member function + in the same object instance) then + - returns true + - else + - returns false + !*/ + + bool operator != ( + const member_function_pointer& item + ) const; + /*! + ensures + - returns !(*this == item) + !*/ + + void clear( + ); + /*! + ensures + - #*this has its initial value + !*/ + + bool is_set ( + ) const; + /*! + ensures + - if (this->set() has been called) then + - returns true + - else + - returns false + !*/ + + template < + typename T + > + void set ( + T& object, + void (T::*cb)() + ); + /*! + requires + - cb == a valid member function pointer for class T + ensures + - #is_set() == true + - calls to this->operator() will call (object.*cb)() + !*/ + + template < + typename T + > + void set ( + const T& object, + void (T::*cb)()const + ); + /*! + requires + - cb == a valid member function pointer for class T + ensures + - #is_set() == true + - calls to this->operator() will call (object.*cb)() + !*/ + + operator some_undefined_pointer_type ( + ) const; + /*! + ensures + - if (is_set()) then + - returns a non 0 value + - else + - returns a 0 value + !*/ + + bool operator! ( + ) const; + /*! + ensures + - returns !is_set() + !*/ + + void operator () ( + ) const; + /*! + requires + - is_set() == true + ensures + - calls the member function on the object specified by the last + call to this->set() + throws + - any exception thrown by the member function specified by + the previous call to this->set(). + If any of these exceptions are thrown then the call to this + function will have no effect on *this. + !*/ + + void swap ( + member_function_pointer& item + ); + /*! + ensures + - swaps *this and item + !*/ + + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename PARAM1 + > + class member_function_pointer + { + public: + typedef PARAM1 param1_type; + typedef void param2_type; + typedef void param3_type; + typedef void param4_type; + + member_function_pointer (); + + member_function_pointer( + const member_function_pointer& item + ); + + ~member_function_pointer ( + ); + + member_function_pointer& operator=( + const member_function_pointer& item + ); + + bool operator == ( + const member_function_pointer& item + ) const; + + bool operator != ( + const member_function_pointer& item + ) const; + + void clear(); + + bool is_set () const; + + template + void set ( + T& object, + void (T::*cb)(PARAM1) + ); + + template + void set ( + const T& object, + void (T::*cb)(PARAM1)const + ); + + operator some_undefined_pointer_type ( + ) const; + + bool operator! ( + ) const; + + void operator () ( + PARAM1 param1 + ) const; + + void swap ( + member_function_pointer& item + ); + + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename PARAM1, + typename PARAM2 + > + class member_function_pointer + { + public: + typedef PARAM1 param1_type; + typedef PARAM2 param2_type; + typedef void param3_type; + typedef void param4_type; + + member_function_pointer (); + + member_function_pointer( + const member_function_pointer& item + ); + + ~member_function_pointer ( + ); + + member_function_pointer& operator=( + const member_function_pointer& item + ); + + bool operator == ( + const member_function_pointer& item + ) const; + + bool operator != ( + const member_function_pointer& item + ) const; + + void clear(); + + bool is_set () const; + + template + void set ( + T& object, + void (T::*cb)(PARAM1,PARAM2) + ); + + template + void set ( + const T& object, + void (T::*cb)(PARAM1,PARAM2)const + ); + + operator some_undefined_pointer_type ( + ) const; + + bool operator! ( + ) const; + + void operator () ( + PARAM1 param1, + PARAM2 param2 + ) const; + + void swap ( + member_function_pointer& item + ); + + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename PARAM1, + typename PARAM2, + typename PARAM3 + > + class member_function_pointer + { + public: + typedef PARAM1 param1_type; + typedef PARAM2 param2_type; + typedef PARAM3 param3_type; + typedef void param4_type; + + member_function_pointer (); + + member_function_pointer( + const member_function_pointer& item + ); + + ~member_function_pointer ( + ); + + member_function_pointer& operator=( + const member_function_pointer& item + ); + + bool operator == ( + const member_function_pointer& item + ) const; + + bool operator != ( + const member_function_pointer& item + ) const; + + void clear(); + + bool is_set () const; + + template + void set ( + T& object, + void (T::*cb)(PARAM1,PARAM2,PARAM3) + ); + + template + void set ( + const T& object, + void (T::*cb)(PARAM1,PARAM2,PARAM3)const + ); + + operator some_undefined_pointer_type ( + ) const; + + bool operator! ( + ) const; + + void operator () ( + PARAM1 param1, + PARAM2 param2, + PARAM2 param3 + ) const; + + void swap ( + member_function_pointer& item + ); + + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename PARAM1, + typename PARAM2, + typename PARAM3, + typename PARAM4 + > + class member_function_pointer + { + public: + typedef PARAM1 param1_type; + typedef PARAM2 param2_type; + typedef PARAM3 param3_type; + typedef PARAM4 param4_type; + + member_function_pointer (); + + member_function_pointer( + const member_function_pointer& item + ); + + ~member_function_pointer ( + ); + + member_function_pointer& operator=( + const member_function_pointer& item + ); + + bool operator == ( + const member_function_pointer& item + ) const; + + bool operator != ( + const member_function_pointer& item + ) const; + + void clear(); + + bool is_set () const; + + template + void set ( + T& object, + void (T::*cb)(PARAM1,PARAM2,PARAM3,PARAM4) + ); + + template + void set ( + const T& object, + void (T::*cb)(PARAM1,PARAM2,PARAM3,PARAM4)const + ); + + operator some_undefined_pointer_type ( + ) const; + + bool operator! ( + ) const; + + void operator () ( + PARAM1 param1, + PARAM2 param2, + PARAM2 param3, + PARAM2 param4 + ) const; + + void swap ( + member_function_pointer& item + ); + + }; + +// ---------------------------------------------------------------------------------------- + + +} + +#endif // DLIB_MEMBER_FUNCTION_POINTER_KERNEl_ABSTRACT_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager.h new file mode 100644 index 0000000..5b52832 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager.h @@ -0,0 +1,73 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MEMORY_MANAGEr_ +#define DLIB_MEMORY_MANAGEr_ + +#include "memory_manager/memory_manager_kernel_1.h" +#include "memory_manager/memory_manager_kernel_2.h" +#include "memory_manager/memory_manager_kernel_3.h" + + + +namespace dlib +{ + + template < + typename T + > + class memory_manager + { + memory_manager() {} + + + public: + + //----------- kernels --------------- + + // kernel_1 + typedef memory_manager_kernel_1 + kernel_1a; + typedef memory_manager_kernel_1 + kernel_1b; + typedef memory_manager_kernel_1 + kernel_1c; + typedef memory_manager_kernel_1 + kernel_1d; + typedef memory_manager_kernel_1 + kernel_1e; + typedef memory_manager_kernel_1 + kernel_1f; + + // kernel_2 + typedef memory_manager_kernel_2 + kernel_2a; + typedef memory_manager_kernel_2 + kernel_2b; + typedef memory_manager_kernel_2 + kernel_2c; + typedef memory_manager_kernel_2 + kernel_2d; + typedef memory_manager_kernel_2 + kernel_2e; + + + // kernel_3 + typedef memory_manager_kernel_3 + kernel_3a; + typedef memory_manager_kernel_3 + kernel_3b; + typedef memory_manager_kernel_3 + kernel_3c; + typedef memory_manager_kernel_3 + kernel_3d; + typedef memory_manager_kernel_3 + kernel_3e; + + + + + }; +} + +#endif // DLIB_MEMORY_MANAGEr_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager/memory_manager_kernel_1.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager/memory_manager_kernel_1.h new file mode 100644 index 0000000..8333aca --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager/memory_manager_kernel_1.h @@ -0,0 +1,305 @@ +// Copyright (C) 2004 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MEMORY_MANAGER_KERNEl_1_ +#define DLIB_MEMORY_MANAGER_KERNEl_1_ + +#include "../algs.h" +#include "memory_manager_kernel_abstract.h" +#include "../assert.h" +#include + + +namespace dlib +{ + + template < + typename T, + size_t max_pool_size + > + class memory_manager_kernel_1 + { + /*! + INITIAL VALUE + allocations == 0 + next == 0 + pool_size == 0 + + REQUIREMENTS ON max_pool_size + max_pool_size is the maximum number of nodes we will keep in our linked list at once. + So you can put any value in for this argument. + + CONVENTION + This memory manager implementation allocates T objects one at a time when there are + allocation requests. Then when there is a deallocate request the returning T object + is place into a list of free blocks if that list has less than max_pool_size + blocks in it. subsequent allocation requests will be serviced by drawing from the + free list whenever it isn't empty. + + + allocations == get_number_of_allocations() + + - if (next != 0) then + - next == the next pointer to return from allocate() + and next == pointer to the first node in a linked list. each node + is one item in the memory pool. + - the last node in the linked list has next set to 0 + - pool_size == the number of nodes in the linked list + - pool_size <= max_pool_size + - else + - we need to call new to get the next pointer to return from allocate() + + !*/ + + union node + { + node* next; + char item[sizeof(T)]; + }; + + public: + + typedef T type; + + template + struct rebind { + typedef memory_manager_kernel_1 other; + }; + + + memory_manager_kernel_1( + ) : + allocations(0), + next(0), + pool_size(0) + { + } + + virtual ~memory_manager_kernel_1( + ) + { + + while (next != 0) + { + node* temp = next; + next = next->next; + ::operator delete ( static_cast(temp)); + } + } + + size_t get_number_of_allocations ( + ) const { return allocations; } + + T* allocate_array ( + size_t size + ) + { + T* temp = new T[size]; + ++allocations; + return temp; + } + + void deallocate_array ( + T* item + ) + { + --allocations; + delete [] item; + } + + T* allocate ( + ) + { + T* temp; + if (next != 0) + { + temp = reinterpret_cast(next); + + node* n = next->next; + + try + { + // construct this new T object with placement new. + new (static_cast(temp))T(); + } + catch (...) + { + next->next = n; + throw; + } + + next = n; + + --pool_size; + } + else + { + temp = static_cast(::operator new(sizeof(node))); + try + { + // construct this new T object with placement new. + new (static_cast(temp))T(); + } + catch (...) + { + // construction of the new object threw so delete the block of memory + ::operator delete ( static_cast(temp)); + throw; + } + } + + ++allocations; + return temp; + } + + void deallocate ( + T* item + ) + { + --allocations; + item->~T(); + + if (pool_size >= max_pool_size) + { + ::operator delete ( static_cast(item)); + return; + } + + // add this memory chunk into our linked list. + node* temp = reinterpret_cast(item); + temp->next = next; + next = temp; + ++pool_size; + } + + void swap ( + memory_manager_kernel_1& item + ) + { + exchange(allocations,item.allocations); + exchange(next,item.next); + exchange(pool_size,item.pool_size); + } + + private: + + // data members + size_t allocations; + node* next; + size_t pool_size; + + // restricted functions + memory_manager_kernel_1(memory_manager_kernel_1&); // copy constructor + memory_manager_kernel_1& operator=(memory_manager_kernel_1&); // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + class memory_manager_kernel_1 + { + /*! + INITIAL VALUE + allocations == 0 + + CONVENTION + This memory manager just calls new and delete directly so it doesn't + really do anything. + + allocations == get_number_of_allocations() + !*/ + + public: + + typedef T type; + + template + struct rebind { + typedef memory_manager_kernel_1 other; + }; + + + memory_manager_kernel_1( + ) : + allocations(0) + { + } + + virtual ~memory_manager_kernel_1( + ) + { + } + + size_t get_number_of_allocations ( + ) const { return allocations; } + + T* allocate_array ( + size_t size + ) + { + T* temp = new T[size]; + ++allocations; + return temp; + } + + void deallocate_array ( + T* item + ) + { + --allocations; + delete [] item; + } + + T* allocate ( + ) + { + T* temp = new T; + ++allocations; + return temp; + } + + void deallocate ( + T* item + ) + { + delete item; + --allocations; + } + + void swap ( + memory_manager_kernel_1& item + ) + { + exchange(allocations,item.allocations); + } + + private: + + // data members + size_t allocations; + + // restricted functions + memory_manager_kernel_1(memory_manager_kernel_1&); // copy constructor + memory_manager_kernel_1& operator=(memory_manager_kernel_1&); // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + size_t max_pool_size + > + inline void swap ( + memory_manager_kernel_1& a, + memory_manager_kernel_1& b + ) { a.swap(b); } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MEMORY_MANAGER_KERNEl_1_ + + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager/memory_manager_kernel_2.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager/memory_manager_kernel_2.h new file mode 100644 index 0000000..5134afa --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager/memory_manager_kernel_2.h @@ -0,0 +1,253 @@ +// Copyright (C) 2004 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MEMORY_MANAGER_KERNEl_2_ +#define DLIB_MEMORY_MANAGER_KERNEl_2_ + +#include "../algs.h" +#include "memory_manager_kernel_abstract.h" +#include "../assert.h" +#include + +namespace dlib +{ + + template < + typename T, + size_t chunk_size + > + class memory_manager_kernel_2 + { + /*! + INITIAL VALUE + allocations == 0 + next == 0 + first_chunk == 0 + + REQUIREMENTS ON chunk_size + chunk_size is the number of items of type T we will allocate at a time. so + it must be > 0. + + CONVENTION + This memory manager implementation allocates memory in blocks of chunk_size*sizeof(T) + bytes. All the sizeof(T) subblocks are kept in a linked list of free memory blocks + and are given out whenever an allocation request occurs. Also, memory is not freed + until this object is destructed. + + Note that array allocations are not memory managed. + + + + allocations == get_number_of_allocations() + + - if (next != 0) then + - next == the next pointer to return from allocate() + and next == pointer to the first node in a linked list. each node + is one item in the memory pool. + - the last node in the linked list has next set to 0 + - else + - we need to call new to get the next pointer to return from allocate() + + + - if (first_chunk != 0) then + - first_chunk == the first node in a linked list that contains pointers + to all the chunks we have ever allocated. The last link in the list + has its next pointer set to 0. + !*/ + + union node + { + node* next; + char item[sizeof(T)]; + }; + + struct chunk_node + { + node* chunk; + chunk_node* next; + }; + + public: + + typedef T type; + + template + struct rebind { + typedef memory_manager_kernel_2 other; + }; + + + memory_manager_kernel_2( + ) : + allocations(0), + next(0), + first_chunk(0) + { + // You FOOL! You can't have a zero chunk_size. + COMPILE_TIME_ASSERT(chunk_size > 0); + } + + virtual ~memory_manager_kernel_2( + ) + { + if (allocations == 0) + { + while (first_chunk != 0) + { + chunk_node* temp = first_chunk; + first_chunk = first_chunk->next; + // delete the memory chunk + ::operator delete ( static_cast(temp->chunk)); + // delete the chunk_node + delete temp; + } + } + } + + size_t get_number_of_allocations ( + ) const { return allocations; } + + T* allocate_array ( + size_t size + ) + { + T* temp = new T[size]; + ++allocations; + return temp; + } + + void deallocate_array ( + T* item + ) + { + --allocations; + delete [] item; + } + + T* allocate ( + ) + { + T* temp = 0; + if (next != 0) + { + temp = reinterpret_cast(next); + node* n = next->next; + + try + { + // construct this new T object with placement new. + new (static_cast(temp))T(); + } + catch (...) + { + next->next = n; + throw; + } + + next = n; + } + else + { + // the linked list is empty so we need to allocate some more memory + node* block = 0; + block = static_cast(::operator new (sizeof(node)*chunk_size)); + + // the first part of this block can be our new object + temp = reinterpret_cast(block); + + try + { + // construct this new T object with placement new. + new (static_cast(temp))T(); + } + catch (...) + { + // construction of the new object threw so delete the block of memory + ::operator delete ( static_cast(block)); + throw; + } + + // allocate a new chunk_node + chunk_node* chunk; + try {chunk = new chunk_node; } + catch (...) + { + temp->~T(); + ::operator delete ( static_cast(block)); + throw; + } + + // add this block into the chunk list + chunk->chunk = block; + chunk->next = first_chunk; + first_chunk = chunk; + + + ++block; + // now add the rest of the block into the linked list of free nodes. + for (size_t i = 0; i < chunk_size-1; ++i) + { + block->next = next; + next = block; + ++block; + } + + } + + + ++allocations; + return temp; + } + + void deallocate ( + T* item + ) + { + --allocations; + item->~T(); + + // add this memory into our linked list. + node* temp = reinterpret_cast(item); + temp->next = next; + next = temp; + } + + void swap ( + memory_manager_kernel_2& item + ) + { + exchange(allocations,item.allocations); + exchange(next,item.next); + exchange(first_chunk,item.first_chunk); + } + + private: + + // data members + size_t allocations; + node* next; + + chunk_node* first_chunk; + + + + + // restricted functions + memory_manager_kernel_2(memory_manager_kernel_2&); // copy constructor + memory_manager_kernel_2& operator=(memory_manager_kernel_2&); // assignment operator + }; + + template < + typename T, + size_t chunk_size + > + inline void swap ( + memory_manager_kernel_2& a, + memory_manager_kernel_2& b + ) { a.swap(b); } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MEMORY_MANAGER_KERNEl_2_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager/memory_manager_kernel_3.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager/memory_manager_kernel_3.h new file mode 100644 index 0000000..4b85990 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager/memory_manager_kernel_3.h @@ -0,0 +1,385 @@ +// Copyright (C) 2004 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MEMORY_MANAGER_KERNEl_3_ +#define DLIB_MEMORY_MANAGER_KERNEl_3_ + +#include "../algs.h" +#include "memory_manager_kernel_abstract.h" +#include "../assert.h" +#include +#include "memory_manager_kernel_2.h" +#include "../binary_search_tree/binary_search_tree_kernel_2.h" + + +namespace dlib +{ + + template < + typename T, + size_t chunk_size + > + class memory_manager_kernel_3 + { + /*! + INITIAL VALUE + allocations == 0 + next == 0 + first_chunk == 0 + bst_of_arrays == 0 + + REQUIREMENTS ON chunk_size + chunk_size is the number of items of type T we will allocate at a time. so + it must be > 0. + + CONVENTION + This memory manager implementation allocates memory in blocks of chunk_size*sizeof(T) + bytes. All the sizeof(T) subblocks are kept in a linked list of free memory blocks + and are given out whenever an allocation request occurs. Also, memory is not freed + until this object is destructed. + + + + allocations == get_number_of_allocations() + + - if (next != 0) then + - next == the next pointer to return from allocate() + and next == pointer to the first node in a linked list. each node + is one item in the memory pool. + - the last node in the linked list has next set to 0 + - else + - we need to call new to get the next pointer to return from allocate() + + - if (arrays != 0) then + - someone has called allocate_array() + - (*arrays)[size] == an array of size bytes of memory + + - if (first_chunk != 0) then + - first_chunk == the first node in a linked list that contains pointers + to all the chunks we have ever allocated. The last link in the list + has its next pointer set to 0. + !*/ + + union node + { + node* next; + char item[sizeof(T)]; + }; + + struct chunk_node + { + node* chunk; + chunk_node* next; + }; + + + typedef binary_search_tree_kernel_2< + size_t, + char*, + memory_manager_kernel_2 + > bst_of_arrays; + + public: + + typedef T type; + + template + struct rebind { + typedef memory_manager_kernel_3 other; + }; + + + memory_manager_kernel_3( + ) : + allocations(0), + next(0), + first_chunk(0), + arrays(0) + { + // You FOOL! You can't have a zero chunk_size. + COMPILE_TIME_ASSERT(chunk_size > 0); + } + + virtual ~memory_manager_kernel_3( + ) + { + if (allocations == 0) + { + while (first_chunk != 0) + { + chunk_node* temp = first_chunk; + first_chunk = first_chunk->next; + // delete the memory chunk + ::operator delete ( static_cast(temp->chunk)); + // delete the chunk_node + delete temp; + } + } + + if (arrays) + { + arrays->reset(); + while (arrays->move_next()) + { + ::operator delete (arrays->element().value()); + } + delete arrays; + } + } + + size_t get_number_of_allocations ( + ) const { return allocations; } + + T* allocate_array ( + size_t size + ) + { + size_t block_size = sizeof(T)*size + sizeof(size_t)*2; + + // make sure we have initialized the arrays object. + if (arrays == 0) + { + arrays = new bst_of_arrays; + } + + char* temp; + + // see if we have a suitable block of memory already. + arrays->position_enumerator(block_size); + if (arrays->current_element_valid()) + { + // we have a suitable block of memory already so use that one. + arrays->remove_current_element(block_size,temp); + } + else + { + temp = static_cast(::operator new(block_size)); + } + + reinterpret_cast(temp)[0] = block_size; + reinterpret_cast(temp)[1] = size; + temp += sizeof(size_t)*2; + + try + { + initialize_array(reinterpret_cast(temp),size); + } + catch (...) + { + // something was thrown while we were initializing the array so + // stick our memory block into arrays and rethrow the exception + temp -= sizeof(size_t)*2; + arrays->add(block_size,temp); + throw; + } + + ++allocations; + return reinterpret_cast(temp); + } + + void deallocate_array ( + T* item + ) + { + char* temp = reinterpret_cast(item); + temp -= sizeof(size_t)*2; + size_t block_size = reinterpret_cast(temp)[0]; + size_t size = reinterpret_cast(temp)[1]; + + deinitialize_array(item,size); + + arrays->add(block_size,temp); + + --allocations; + } + + T* allocate ( + ) + { + T* temp; + if (next != 0) + { + temp = reinterpret_cast(next); + node* n = next->next; + + try + { + // construct this new T object with placement new. + new (static_cast(temp))T(); + } + catch (...) + { + next->next = n; + throw; + } + + next = n; + } + else + { + // the linked list is empty so we need to allocate some more memory + node* block = static_cast(::operator new (sizeof(node)*chunk_size)); + + // the first part of this block can be our new object + temp = reinterpret_cast(block); + + try + { + // construct this new T object with placement new. + new (static_cast(temp))T(); + } + catch (...) + { + // construction of the new object threw so delete the block of memory + ::operator delete ( static_cast(block)); + throw; + } + + // allocate a new chunk_node + chunk_node* chunk; + try {chunk = new chunk_node; } + catch (...) + { + temp->~T(); + ::operator delete ( static_cast(block)); + throw; + } + + // add this block into the chunk list + chunk->chunk = block; + chunk->next = first_chunk; + first_chunk = chunk; + + + ++block; + // now add the rest of the block into the linked list of free nodes. + for (size_t i = 0; i < chunk_size-1; ++i) + { + block->next = next; + next = block; + ++block; + } + + } + + + ++allocations; + return temp; + } + + void deallocate ( + T* item + ) + { + --allocations; + item->~T(); + + // add this memory into our linked list. + node* temp = reinterpret_cast(item); + temp->next = next; + next = temp; + } + + void swap ( + memory_manager_kernel_3& item + ) + { + exchange(allocations,item.allocations); + exchange(next,item.next); + exchange(first_chunk,item.first_chunk); + exchange(arrays,item.arrays); + } + + private: + + // data members + size_t allocations; + node* next; + + chunk_node* first_chunk; + bst_of_arrays* arrays; + + + void initialize_array ( + T* array, + size_t size + ) const + { + size_t i; + try + { + for (i = 0; i < size; ++i) + { + // construct this new T object with placement new. + new (static_cast(array+i))T(); + } + } + catch (...) + { + // Catch any exceptions thrown during the construction process + // and then destruct any T objects that actually were successfully + // constructed. + for (size_t j = 0; j < i; ++j) + { + array[i].~T(); + } + throw; + } + } + + void deinitialize_array ( + T* array, + size_t size + ) const + { + for (size_t i = 0; i < size; ++i) + { + array[i].~T(); + } + } + + // don't do any initialization for the built in types + void initialize_array(unsigned char*, size_t) {} + void deinitialize_array(unsigned char*, size_t) {} + void initialize_array(signed char*, size_t) {} + void deinitialize_array(signed char*, size_t) {} + void initialize_array(char*, size_t) {} + void deinitialize_array(char*, size_t) {} + void initialize_array(int*, size_t) {} + void deinitialize_array(int*, size_t) {} + void initialize_array(unsigned int*, size_t) {} + void deinitialize_array(unsigned int*, size_t) {} + void initialize_array(unsigned long*, size_t) {} + void deinitialize_array(unsigned long*, size_t) {} + void initialize_array(long*, size_t) {} + void deinitialize_array(long*, size_t) {} + void initialize_array(float*, size_t) {} + void deinitialize_array(float*, size_t) {} + void initialize_array(double*, size_t) {} + void deinitialize_array(double*, size_t) {} + void initialize_array(short*, size_t) {} + void deinitialize_array(short*, size_t) {} + void initialize_array(unsigned short*, size_t) {} + void deinitialize_array(unsigned short*, size_t) {} + + + + // restricted functions + memory_manager_kernel_3(memory_manager_kernel_3&); // copy constructor + memory_manager_kernel_3& operator=(memory_manager_kernel_3&); // assignment operator + }; + + template < + typename T, + size_t chunk_size + > + inline void swap ( + memory_manager_kernel_3& a, + memory_manager_kernel_3& b + ) { a.swap(b); } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MEMORY_MANAGER_KERNEl_3_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager/memory_manager_kernel_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager/memory_manager_kernel_abstract.h new file mode 100644 index 0000000..5269db3 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager/memory_manager_kernel_abstract.h @@ -0,0 +1,146 @@ +// Copyright (C) 2004 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_MEMORY_MANAGER_KERNEl_ABSTRACT_ +#ifdef DLIB_MEMORY_MANAGER_KERNEl_ABSTRACT_ + +#include "../algs.h" + +namespace dlib +{ + template < + typename T + > + class memory_manager + { + /*! + REQUIREMENTS ON T + T must have a default constructor. + + INITIAL VALUE + get_number_of_allocations() == 0 + + WHAT THIS OBJECT REPRESENTS + This object represents some kind of memory manager or memory pool. + !*/ + + public: + + typedef T type; + + template + struct rebind { + typedef memory_manager other; + }; + + memory_manager( + ); + /*! + ensures + - #*this is properly initialized + throws + - std::bad_alloc + !*/ + + virtual ~memory_manager( + ); + /*! + ensures + - if (get_number_of_allocations() == 0) then + - all resources associated with *this have been released. + - else + - The memory still allocated will not be deleted and this + causes a memory leak. + !*/ + + size_t get_number_of_allocations ( + ) const; + /*! + ensures + - returns the current number of outstanding allocations + !*/ + + T* allocate ( + ); + /*! + ensures + - allocates a new object of type T and returns a pointer to it. + - #get_number_of_allocations() == get_number_of_allocations() + 1 + throws + - std::bad_alloc or any exception thrown by T's constructor. + If this exception is thrown then the call to allocate() + has no effect on #*this. + !*/ + + void deallocate ( + T* item + ); + /*! + requires + - item == is a pointer to memory that was obtained from a call to + this->allocate(). (i.e. you can't deallocate a pointer you + got from a different memory_manager instance.) + - the memory pointed to by item hasn't already been deallocated. + ensures + - deallocates the object pointed to by item + - #get_number_of_allocations() == get_number_of_allocations() - 1 + !*/ + + T* allocate_array ( + size_t size + ); + /*! + ensures + - allocates a new array of size objects of type T and returns a + pointer to it. + - #get_number_of_allocations() == get_number_of_allocations() + 1 + throws + - std::bad_alloc or any exception thrown by T's constructor. + If this exception is thrown then the call to allocate() + has no effect on #*this. + !*/ + + void deallocate_array ( + T* item + ); + /*! + requires + - item == is a pointer to memory that was obtained from a call to + this->allocate_array(). (i.e. you can't deallocate a pointer you + got from a different memory_manager instance and it must be an + array.) + - the memory pointed to by item hasn't already been deallocated. + ensures + - deallocates the array pointed to by item + - #get_number_of_allocations() == get_number_of_allocations() - 1 + !*/ + + void swap ( + memory_manager& item + ); + /*! + ensures + - swaps *this and item + !*/ + + private: + + // restricted functions + memory_manager(memory_manager&); // copy constructor + memory_manager& operator=(memory_manager&); // assignment operator + }; + + template < + typename T + > + inline void swap ( + memory_manager& a, + memory_manager& b + ) { a.swap(b); } + /*! + provides a global swap function + !*/ + +} + +#endif // DLIB_MEMORY_MANAGER_KERNEl_ABSTRACT_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager_global.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager_global.h new file mode 100644 index 0000000..05f439f --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager_global.h @@ -0,0 +1,38 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MEMORY_MANAGER_GLOBAl_ +#define DLIB_MEMORY_MANAGER_GLOBAl_ + +#include "memory_manager_global/memory_manager_global_kernel_1.h" +#include "memory_manager.h" + + + +namespace dlib +{ + + template < + typename T, + typename factory + > + class memory_manager_global + { + memory_manager_global() {} + + + public: + + //----------- kernels --------------- + + // kernel_1 + typedef memory_manager_global_kernel_1 + kernel_1a; + + + + + }; +} + +#endif // DLIB_MEMORY_MANAGER_GLOBAl_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager_global/memory_manager_global_kernel_1.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager_global/memory_manager_global_kernel_1.h new file mode 100644 index 0000000..7c43048 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager_global/memory_manager_global_kernel_1.h @@ -0,0 +1,113 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MEMORY_MANAGER_GLOBAl_1_ +#define DLIB_MEMORY_MANAGER_GLOBAl_1_ + +#include "../algs.h" +#include "../memory_manager/memory_manager_kernel_abstract.h" +#include "memory_manager_global_kernel_abstract.h" + +namespace dlib +{ + template < + typename T, + typename factory + > + class memory_manager_global_kernel_1 + { + /*! + INITIAL VALUE + - *global_mm == get_global_memory_manager() + + CONVENTION + - global_mm->get_number_of_allocations() == get_number_of_allocations() + - *global_mm == get_global_memory_manager() + !*/ + + public: + + typedef typename factory::template return_type::type mm_global_type; + + typedef T type; + + template + struct rebind { + typedef memory_manager_global_kernel_1 other; + }; + + memory_manager_global_kernel_1( + ) : + global_mm(factory::template get_instance()) + {} + + virtual ~memory_manager_global_kernel_1( + ) {} + + size_t get_number_of_allocations ( + ) const { return global_mm->get_number_of_allocations(); } + + mm_global_type& get_global_memory_manager ( + ) { return *global_mm; } + + T* allocate ( + ) + { + return global_mm->allocate(); + } + + void deallocate ( + T* item + ) + { + global_mm->deallocate(item); + } + + T* allocate_array ( + size_t size + ) + { + return global_mm->allocate_array(size); + } + + void deallocate_array ( + T* item + ) + { + global_mm->deallocate_array(item); + } + + void swap ( + memory_manager_global_kernel_1& item + ) + { + exchange(item.global_mm, global_mm); + } + + private: + + mm_global_type* global_mm; + + + // restricted functions + memory_manager_global_kernel_1(memory_manager_global_kernel_1&); // copy constructor + memory_manager_global_kernel_1& operator=(memory_manager_global_kernel_1&); // assignment operator + }; + + template < + typename T, + typename factory + > + inline void swap ( + memory_manager_global_kernel_1& a, + memory_manager_global_kernel_1& b + ) { a.swap(b); } + /*! + provides a global swap function + !*/ + +} + +#endif // DLIB_MEMORY_MANAGER_GLOBAl_1_ + + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager_global/memory_manager_global_kernel_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager_global/memory_manager_global_kernel_abstract.h new file mode 100644 index 0000000..20b1c6f --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager_global/memory_manager_global_kernel_abstract.h @@ -0,0 +1,181 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_MEMORY_MANAGER_GLOBAl_ABSTRACT_ +#ifdef DLIB_MEMORY_MANAGER_GLOBAl_ABSTRACT_ + +#include "../algs.h" +#include "../memory_manager/memory_manager_kernel_abstract.h" + +namespace dlib +{ + template < + typename T, + typename factory + > + class memory_manager_global + { + /*! + REQUIREMENTS ON T + T must have a default constructor. + + REQUIREMENTS ON factory + factory must be defined as follows: + struct factory + { + template + struct return_type { + typedef typename memory_manager_type type; + }; + + template + static typename return_type::type* get_instance ( + ); + / *! + ensures + - returns a pointer to an instance of a memory_manager object + where memory_manager_type implements the interface defined + by dlib/memory_manager/memory_manager_kernel_abstract.h + !* / + }; + + WHAT THIS OBJECT REPRESENTS + This object represents some kind of global memory manager or memory pool. + It is identical to the memory_manager object except that it gets all of + its allocations from a global instance of a memory_manager object which + is provided by the factory object's static member get_instance(). + + THREAD SAFETY + This object is, by itself, threadsafe. However, if you want to use this + object in multiple threads then you must ensure that your factory is + threadsafe. This means its factory::get_instance() method should be + threadsafe and the memory_manager object it returns must also be threadsafe. + !*/ + + public: + + typedef typename factory::template return_type::type mm_global_type; + + typedef T type; + + template + struct rebind { + typedef memory_manager_global other; + }; + + memory_manager_global( + ); + /*! + ensures + - #*this is properly initialized + - #get_global_memory_manager() == the memory manager that was + returned by a call to factory::get_instance() + throws + - std::bad_alloc + !*/ + + virtual ~memory_manager_global( + ); + /*! + ensures + - This destructor has no effect on the global memory_manager + get_global_memory_manager(). + !*/ + + size_t get_number_of_allocations ( + ) const; + /*! + ensures + - returns get_global_memory_manager().get_number_of_allocations() + !*/ + + mm_global_type& get_global_memory_manager ( + ); + /*! + ensures + - returns a reference to the global memory manager instance being + used by *this. + !*/ + + T* allocate ( + ); + /*! + ensures + - #get_number_of_allocations() == get_number_of_allocations() + 1 + - returns get_global_memory_manager().allocate() + throws + - std::bad_alloc or any exception thrown by T's constructor. + If this exception is thrown then the call to allocate() + has no effect on #*this. + !*/ + + void deallocate ( + T* item + ); + /*! + requires + - item == is a pointer to memory that was obtained from a call to + the get_global_memory_manager() object's allocate() method. + - the memory pointed to by item hasn't already been deallocated. + ensures + - calls get_global_memory_manager().deallocate(item) + - #get_number_of_allocations() == get_number_of_allocations() - 1 + !*/ + + T* allocate_array ( + size_t size + ); + /*! + ensures + - #get_number_of_allocations() == get_number_of_allocations() + 1 + - returns get_global_memory_manager().allocate_array() + throws + - std::bad_alloc or any exception thrown by T's constructor. + If this exception is thrown then the call to allocate_array() + has no effect on #*this. + !*/ + + void deallocate_array ( + T* item + ); + /*! + requires + - item == is a pointer to memory that was obtained from a call to + the get_global_memory_manager() object's allocate_array() method. + - the memory pointed to by item hasn't already been deallocated. + ensures + - calls get_global_memory_manager().deallocate_array(item) + - #get_number_of_allocations() == get_number_of_allocations() - 1 + !*/ + + void swap ( + memory_manager_global& item + ); + /*! + ensures + - swaps *this and item + !*/ + + private: + + // restricted functions + memory_manager_global(memory_manager_global&); // copy constructor + memory_manager_global& operator=(memory_manager_global&); // assignment operator + }; + + template < + typename T, + typename factory + > + inline void swap ( + memory_manager_global& a, + memory_manager_global& b + ) { a.swap(b); } + /*! + provides a global swap function + !*/ + +} + +#endif // DLIB_MEMORY_MANAGER_GLOBAl_ABSTRACT_ + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager_stateless.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager_stateless.h new file mode 100644 index 0000000..32bc7e9 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager_stateless.h @@ -0,0 +1,72 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MEMORY_MANAGER_STATELESs_ +#define DLIB_MEMORY_MANAGER_STATELESs_ + +#include "memory_manager_stateless/memory_manager_stateless_kernel_1.h" +#include "memory_manager_stateless/memory_manager_stateless_kernel_2.h" +#include "memory_manager.h" + + + +namespace dlib +{ + + template < + typename T + > + class memory_manager_stateless + { + memory_manager_stateless() {} + + + public: + + //----------- kernels --------------- + + // kernel_1 + typedef memory_manager_stateless_kernel_1 + kernel_1a; + + // kernel_2 + typedef memory_manager_stateless_kernel_2::kernel_1a> + kernel_2_1a; + typedef memory_manager_stateless_kernel_2::kernel_1b> + kernel_2_1b; + typedef memory_manager_stateless_kernel_2::kernel_1c> + kernel_2_1c; + typedef memory_manager_stateless_kernel_2::kernel_1d> + kernel_2_1d; + typedef memory_manager_stateless_kernel_2::kernel_1e> + kernel_2_1e; + typedef memory_manager_stateless_kernel_2::kernel_1f> + kernel_2_1f; + + typedef memory_manager_stateless_kernel_2::kernel_2a> + kernel_2_2a; + typedef memory_manager_stateless_kernel_2::kernel_2b> + kernel_2_2b; + typedef memory_manager_stateless_kernel_2::kernel_2c> + kernel_2_2c; + typedef memory_manager_stateless_kernel_2::kernel_2d> + kernel_2_2d; + typedef memory_manager_stateless_kernel_2::kernel_2e> + kernel_2_2e; + + typedef memory_manager_stateless_kernel_2::kernel_3a> + kernel_2_3a; + typedef memory_manager_stateless_kernel_2::kernel_3b> + kernel_2_3b; + typedef memory_manager_stateless_kernel_2::kernel_3c> + kernel_2_3c; + typedef memory_manager_stateless_kernel_2::kernel_3d> + kernel_2_3d; + typedef memory_manager_stateless_kernel_2::kernel_3e> + kernel_2_3e; + + + }; +} + +#endif // DLIB_MEMORY_MANAGER_STATELESs_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager_stateless/memory_manager_stateless_kernel_1.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager_stateless/memory_manager_stateless_kernel_1.h new file mode 100644 index 0000000..a99b7f0 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager_stateless/memory_manager_stateless_kernel_1.h @@ -0,0 +1,101 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MEMORY_MANAGER_STATELESs_1_ +#define DLIB_MEMORY_MANAGER_STATELESs_1_ + +#include "memory_manager_stateless_kernel_abstract.h" +#include + +namespace dlib +{ + template < + typename T + > + class memory_manager_stateless_kernel_1 + { + /*! + this implementation just calls new and delete directly + !*/ + + public: + + typedef T type; + const static bool is_stateless = true; + + template + struct rebind { + typedef memory_manager_stateless_kernel_1 other; + }; + + memory_manager_stateless_kernel_1( + ) + {} + + virtual ~memory_manager_stateless_kernel_1( + ) {} + + T* allocate ( + ) + { + return new T; + } + + void deallocate ( + T* item + ) + { + delete item; + } + + T* allocate_array ( + size_t size + ) + { + return new T[size]; + } + + void deallocate_array ( + T* item + ) + { + delete [] item; + } + + void swap (memory_manager_stateless_kernel_1&) + {} + + std::unique_ptr extract( + T* item + ) + { + return std::unique_ptr(item); + } + + std::unique_ptr extract_array( + T* item + ) + { + return std::unique_ptr(item); + } + + private: + + // restricted functions + memory_manager_stateless_kernel_1(memory_manager_stateless_kernel_1&); // copy constructor + memory_manager_stateless_kernel_1& operator=(memory_manager_stateless_kernel_1&); // assignment operator + }; + + template < + typename T + > + inline void swap ( + memory_manager_stateless_kernel_1& a, + memory_manager_stateless_kernel_1& b + ) { a.swap(b); } + +} + +#endif // DLIB_MEMORY_MANAGER_STATELESs_1_ + + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager_stateless/memory_manager_stateless_kernel_2.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager_stateless/memory_manager_stateless_kernel_2.h new file mode 100644 index 0000000..7d76f89 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager_stateless/memory_manager_stateless_kernel_2.h @@ -0,0 +1,119 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MEMORY_MANAGER_STATELESs_2_ +#define DLIB_MEMORY_MANAGER_STATELESs_2_ + +#include "../algs.h" +#include "memory_manager_stateless_kernel_abstract.h" +#include "../threads.h" + +namespace dlib +{ + template < + typename T, + typename mem_manager + > + class memory_manager_stateless_kernel_2 + { + /*! + REQUIREMENTS ON mem_manager + mem_manager must be an implementation of memory_manager/memory_manager_kernel_abstract.h + + CONVENTION + this object has a single global instance of mem_manager + !*/ + + public: + + typedef T type; + const static bool is_stateless = true; + + template + struct rebind { + typedef memory_manager_stateless_kernel_2 other; + }; + + memory_manager_stateless_kernel_2( + ) + { + // call this just to make sure the mutex is is initialized before + // multiple threads start calling the member functions. + global_mutex(); + } + + virtual ~memory_manager_stateless_kernel_2( + ) {} + + T* allocate ( + ) + { + auto_mutex M(global_mutex()); + return global_mm().allocate(); + } + + void deallocate ( + T* item + ) + { + auto_mutex M(global_mutex()); + return global_mm().deallocate(item); + } + + T* allocate_array ( + size_t size + ) + { + auto_mutex M(global_mutex()); + return global_mm().allocate_array(size); + } + + void deallocate_array ( + T* item + ) + { + auto_mutex M(global_mutex()); + return global_mm().deallocate_array(item); + } + + void swap (memory_manager_stateless_kernel_2&) + {} + + private: + + static mutex& global_mutex ( + ) + { + static mutex lock; + return lock; + } + + typedef typename mem_manager::template rebind::other rebound_mm_type; + + static rebound_mm_type& global_mm ( + ) + { + static rebound_mm_type mm; + return mm; + } + + // restricted functions + memory_manager_stateless_kernel_2(memory_manager_stateless_kernel_2&); // copy constructor + memory_manager_stateless_kernel_2& operator=(memory_manager_stateless_kernel_2&); // assignment operator + }; + + template < + typename T, + typename mem_manager + > + inline void swap ( + memory_manager_stateless_kernel_2& a, + memory_manager_stateless_kernel_2& b + ) { a.swap(b); } + +} + +#endif // DLIB_MEMORY_MANAGER_STATELESs_2_ + + + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager_stateless/memory_manager_stateless_kernel_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager_stateless/memory_manager_stateless_kernel_abstract.h new file mode 100644 index 0000000..ffca186 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/memory_manager_stateless/memory_manager_stateless_kernel_abstract.h @@ -0,0 +1,173 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_MEMORY_MANAGER_STATELESs_ABSTRACT_ +#ifdef DLIB_MEMORY_MANAGER_STATELESs_ABSTRACT_ + +#include "../algs.h" +#include + +namespace dlib +{ + template < + typename T + > + class memory_manager_stateless + { + /*! + REQUIREMENTS ON T + T must have a default constructor. + + WHAT THIS OBJECT REPRESENTS + This object represents some kind of stateless memory manager or memory pool. + Stateless means that all instances (instances of the same kernel implementation that is) + of this object are identical and can be used interchangeably. Note that + implementations are allowed to have some shared global state such as a + global memory pool. + + THREAD SAFETY + This object is thread safe. You may access it from any thread at any time + without synchronizing access. + !*/ + + public: + + typedef T type; + const static bool is_stateless = true; + + template + struct rebind { + typedef memory_manager_stateless other; + }; + + memory_manager_stateless( + ); + /*! + ensures + - #*this is properly initialized + throws + - std::bad_alloc + !*/ + + virtual ~memory_manager_stateless( + ); + /*! + ensures + - frees any resources used by *this but has no effect on any shared global + resources used by the implementation. + !*/ + + T* allocate ( + ); + /*! + ensures + - allocates a new object of type T and returns a pointer to it. + throws + - std::bad_alloc or any exception thrown by T's constructor. + If this exception is thrown then the call to allocate() + has no effect on #*this. + !*/ + + void deallocate ( + T* item + ); + /*! + requires + - item == is a pointer to memory that was obtained from a call to + allocate(). (i.e. The pointer you are deallocating must have + come from the same implementation of memory_manager_stateless + that is trying to deallocate it.) + - the memory pointed to by item hasn't already been deallocated. + ensures + - deallocates the object pointed to by item + !*/ + + T* allocate_array ( + size_t size + ); + /*! + ensures + - allocates a new array of size objects of type T and returns a + pointer to it. + throws + - std::bad_alloc or any exception thrown by T's constructor. + If this exception is thrown then the call to allocate() + has no effect on #*this. + !*/ + + void deallocate_array ( + T* item + ); + /*! + requires + - item == is a pointer to memory that was obtained from a call to + allocate_array(). (i.e. The pointer you are deallocating must have + come from the same implementation of memory_manager_stateless + that is trying to deallocate it.) + - the memory pointed to by item hasn't already been deallocated. + ensures + - deallocates the array pointed to by item + !*/ + + void swap ( + memory_manager_stateless& item + ); + /*! + ensures + - this function has no effect on *this or item. It is just provided + to make this object's interface more compatible with the other + memory managers. + !*/ + + std::unique_ptr extract( + T* item + ); + /*! + requires + - item == is a pointer to memory that was obtained from a call to + allocate(). + ensures + - returns a unique_ptr that owns item. That is, if the returned ptr is + PTR then PTR.get() == item. Therefore, this function extracts item + from the memory manager's internal pool. Therefore, you shouldn't + call deallocate(item) after this. + - Note that not all memory managers implement extract(). + !*/ + + std::unique_ptr extract_array( + T* item + ); + /*! + requires + - item == is a pointer to memory that was obtained from a call to + allocate_array(). + ensures + - returns a unique_ptr that owns item. That is, if the returned ptr is + PTR then PTR.get() == item. Therefore, this function extracts item + from the memory manager's internal pool. Therefore, you shouldn't + call deallocate_array(item) after this. + - Note that not all memory managers implement extract(). + !*/ + + private: + + // restricted functions + memory_manager_stateless(memory_manager_stateless&); // copy constructor + memory_manager_stateless& operator=(memory_manager_stateless&); // assignment operator + }; + + template < + typename T + > + inline void swap ( + memory_manager_stateless& a, + memory_manager_stateless& b + ) { a.swap(b); } + /*! + provides a global swap function + !*/ + +} + +#endif // DLIB_MEMORY_MANAGER_STATELESs_ABSTRACT_ + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/metaprogramming.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/metaprogramming.h new file mode 100644 index 0000000..b9ad070 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/metaprogramming.h @@ -0,0 +1,111 @@ +// Copyright (C) 2017 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_METApROGRAMMING_Hh_ +#define DLIB_METApROGRAMMING_Hh_ + +#include "algs.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template + struct compile_time_integer_list + { + /*! + WHAT THIS OBJECT REPRESENTS + The point of this type is to, as the name suggests, hold a compile time list of integers. + As an example, here is something simple you could do with it: + + template + void print_compile_time_ints ( + compile_time_integer_list + ) + { + print(ints...); + } + + int main() + { + print_compile_time_ints(compile_time_integer_list<0,4,9>()); + } + + Which just calls: print(0,4,9); + + This is a simple example, but this kind of thing is useful in larger and + more complex template metaprogramming constructs. + !*/ + + template + struct push_back + { + typedef compile_time_integer_list type; + }; + }; + +// ---------------------------------------------------------------------------------------- + + template + struct make_compile_time_integer_range + { + /*! + WHAT THIS OBJECT REPRESENTS + This object makes a compile_time_integer_list containing the integers in the range [1,max] inclusive. + For example: + make_compile_time_integer_range<4>::type + evaluates to: + compile_time_integer_list<1,2,3,4> + !*/ + + typedef typename make_compile_time_integer_range::type::template push_back::type type; + }; + // base case + template <> struct make_compile_time_integer_range<0> { typedef compile_time_integer_list<> type; }; + +// ---------------------------------------------------------------------------------------- + + namespace impl + { + template < + typename Funct, + typename... Args, + typename int_()(std::declval()...))>::type = 0 + > + bool call_if_valid ( + special_, + Funct&& f, Args&&... args + ) + { + f(std::forward(args)...); + return true; + } + + template < + typename Funct, + typename... Args + > + bool call_if_valid ( + general_, + Funct&& /*f*/, Args&&... /*args*/ + ) { return false; } + } + + template + bool call_if_valid(Funct&& f, Args&&... args) + /*! + ensures + - if f(std::forward(args)...) is a valid expression then we evaluate it and return + true. Otherwise we do nothing and return false. + !*/ + { + return impl::call_if_valid(special_(), f, std::forward(args)...); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_METApROGRAMMING_Hh_ + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/misc_api.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/misc_api.h new file mode 100644 index 0000000..acf87be --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/misc_api.h @@ -0,0 +1,20 @@ +// Copyright (C) 2004 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. + +#ifndef DLIB_MISC_APi_ +#define DLIB_MISC_APi_ + +#include "platform.h" + +#ifdef WIN32 +#include "misc_api/windows.h" +#endif + +#ifndef WIN32 +#include "misc_api/posix.h" +#endif + +#include "misc_api/misc_api_shared.h" + +#endif // DLIB_MISC_APi_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/misc_api/misc_api_kernel_1.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/misc_api/misc_api_kernel_1.h new file mode 100644 index 0000000..a500e99 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/misc_api/misc_api_kernel_1.h @@ -0,0 +1,110 @@ +// Copyright (C) 2004 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MISC_API_KERNEl_1_ +#define DLIB_MISC_API_KERNEl_1_ + +#ifdef DLIB_ISO_CPP_ONLY +#error "DLIB_ISO_CPP_ONLY is defined so you can't use this OS dependent code. Turn DLIB_ISO_CPP_ONLY off if you want to use it." +#endif + + +#include "misc_api_kernel_abstract.h" +#include "../algs.h" +#include +#include "../uintn.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + void sleep ( + unsigned long milliseconds + ); + +// ---------------------------------------------------------------------------------------- + + std::string get_current_dir ( + ); + +// ---------------------------------------------------------------------------------------- + + class set_current_dir_error : public error + { + public: + set_current_dir_error( + const std::string& a + ): error(a) {} + }; + + void set_current_dir ( + const std::string& new_dir + ); + +// ---------------------------------------------------------------------------------------- + + class timestamper + { + /*! + INITIAL VALUE + - last_time == 0 + - offset == 0 + - dword_max == 2^32 + + CONVENTION + - last_time == the time returned by GetTickCount() the last time we + called it. + - offset == the number of microseconds we should add to the result of + GetTickCount() so that it is correct. + - dword_max == 2^32. + This is the number of values representable by a DWORD. + !*/ + + mutable unsigned long last_time; + mutable uint64 offset; + mutable uint64 dword_max; + + public: + timestamper( + ) : + last_time(0), + offset(0) + { + dword_max = 0xFFFFFFFF; + ++dword_max; + } + + uint64 get_timestamp ( + ) const; + }; + +// ---------------------------------------------------------------------------------------- + + class dir_create_error : public error + { + public: + dir_create_error( + const std::string& dir_name + ) : + error(EDIR_CREATE,"Error creating directory '" + dir_name + "'."), + name(dir_name) + {} + + ~dir_create_error() throw() {} + const std::string name; + }; + + void create_directory ( + const std::string& dir + ); + +// ---------------------------------------------------------------------------------------- + +} + +#ifdef NO_MAKEFILE +#include "misc_api_kernel_1.cpp" +#endif + +#endif // DLIB_MISC_API_KERNEl_1_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/misc_api/misc_api_kernel_2.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/misc_api/misc_api_kernel_2.h new file mode 100644 index 0000000..86e8a7f --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/misc_api/misc_api_kernel_2.h @@ -0,0 +1,81 @@ +// Copyright (C) 2004 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MISC_API_KERNEl_2_ +#define DLIB_MISC_API_KERNEl_2_ + +#ifdef DLIB_ISO_CPP_ONLY +#error "DLIB_ISO_CPP_ONLY is defined so you can't use this OS dependent code. Turn DLIB_ISO_CPP_ONLY off if you want to use it." +#endif + + +#include "misc_api_kernel_abstract.h" +#include "../algs.h" +#include +#include "../uintn.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + void sleep ( + unsigned long milliseconds + ); + +// ---------------------------------------------------------------------------------------- + + std::string get_current_dir ( + ); + +// ---------------------------------------------------------------------------------------- + + class set_current_dir_error : public error + { + public: + set_current_dir_error( + const std::string& a + ): error(a) {} + }; + + void set_current_dir ( + const std::string& new_dir + ); + +// ---------------------------------------------------------------------------------------- + + class timestamper + { + public: + uint64 get_timestamp ( + ) const; + }; + +// ---------------------------------------------------------------------------------------- + + class dir_create_error : public error + { + public: + dir_create_error( + const std::string& dir_name + ) : + error(EDIR_CREATE,"Error creating directory '" + dir_name + "'."), + name(dir_name) + {} + const std::string& name; + }; + + + void create_directory ( + const std::string& dir + ); + +// ---------------------------------------------------------------------------------------- + +} + +#ifdef NO_MAKEFILE +#include "misc_api_kernel_2.cpp" +#endif + +#endif // DLIB_MISC_API_KERNEl_2_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/misc_api/misc_api_kernel_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/misc_api/misc_api_kernel_abstract.h new file mode 100644 index 0000000..47749b9 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/misc_api/misc_api_kernel_abstract.h @@ -0,0 +1,159 @@ +// Copyright (C) 2004 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_MISC_API_KERNEl_ABSTRACT_ +#ifdef DLIB_MISC_API_KERNEl_ABSTRACT_ + +#include +#include "../uintn.h" +#include "../algs.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + /*! + GENERAL COMMENTS + This file just contains miscellaneous api functions + !*/ + +// ---------------------------------------------------------------------------------------- + + void sleep ( + unsigned long milliseconds + ); + /*! + ensures + - causes the calling thread to sleep for the given number of + milliseconds. + !*/ + +// ---------------------------------------------------------------------------------------- + + std::string get_current_dir ( + ); + /*! + ensures + - if (no errors occur) then + - returns the path to the current working directory + - else + - returns "" + throws + - std::bad_alloc + !*/ + +// ---------------------------------------------------------------------------------------- + + class set_current_dir_error : public error; + + void set_current_dir ( + const std::string& new_dir + ); + /*! + ensures + - sets the current working directory to new_dir + throws + - std::bad_alloc + - set_current_dir_error + This exception is thrown if there is an error when attempting + to change the current working directory. + !*/ + +// ---------------------------------------------------------------------------------------- + + class locally_change_current_dir : noncopyable + { + /*! + WHAT THIS OBJECT REPRESENTS + This object is a RAII tool for safely switching the current directory + to a new directory and then automatically switching back to the original + directory upon this object's destruction. + !*/ + public: + explicit locally_change_current_dir ( + const std::string& new_dir + ); + /*! + ensures + - calls set_current_dir(new_dir) + - #old_dir() == The value of get_current_dir() prior to switching to new_dir. + !*/ + + const std::string& old_dir ( + ) const; + /*! + ensures + - returns the directory we switch back to once this object is destructed. + !*/ + + ~locally_change_current_dir( + ); + /*! + ensures + - if (revert() hasn't already been called) then + - calls set_current_dir(old_dir()) + !*/ + + void revert ( + ); + /*! + ensures + - if (revert() hasn't already been called) then + - calls set_current_dir(old_dir()) + !*/ + }; + +// ---------------------------------------------------------------------------------------- + + class dir_create_error : public error { + public: + const std::string name + }; + + void create_directory ( + const std::string& dir + ); + /*! + ensures + - if (dir does not already exist) then + - creates the given directory. + - else + - the call to create_directory() has no effect. + throws + - dir_create_error + This exception is thrown if we were unable to create the requested + directory and it didn't already exist. The type member of the exception + will bet set to EDIR_CREATE and the name member will be set to dir. + !*/ + +// ---------------------------------------------------------------------------------------- + + class timestamper + { + /*! + WHAT THIS OBJECT REPRESENTS + This object represents a timer that is capable of returning + timestamps. + + Note that the time is measured in microseconds but you are not + guaranteed to have that level of resolution. The actual resolution + is implementation dependent. + !*/ + + public: + uint64 get_timestamp ( + ) const; + /*! + ensures + - returns a timestamp that measures the time in microseconds since an + arbitrary point in the past. Note that this arbitrary point remains + the same between all calls to get_timestamp(). + !*/ + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MISC_API_KERNEl_ABSTRACT_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/misc_api/misc_api_shared.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/misc_api/misc_api_shared.h new file mode 100644 index 0000000..6b84dd6 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/misc_api/misc_api_shared.h @@ -0,0 +1,57 @@ +// Copyright (C) 2014 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MISC_API_ShARED_Hh_ +#define DLIB_MISC_API_ShARED_Hh_ + +#include +#include "../noncopyable.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class locally_change_current_dir : noncopyable + { + public: + explicit locally_change_current_dir ( + const std::string& new_dir + ) + { + reverted = false; + _old_dir = get_current_dir(); + set_current_dir(new_dir); + } + + ~locally_change_current_dir() + { + revert(); + } + + const std::string& old_dir ( + ) const + { + return _old_dir; + } + + void revert ( + ) + { + if (!reverted) + { + set_current_dir(_old_dir); + reverted = true; + } + } + + private: + bool reverted; + std::string _old_dir; + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MISC_API_ShARED_Hh_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/misc_api/posix.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/misc_api/posix.h new file mode 100644 index 0000000..1dbb380 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/misc_api/posix.h @@ -0,0 +1,6 @@ +// Copyright (C) 2004 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MISC_API_KERNEl_1_ +#include "misc_api_kernel_2.h" +#endif + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/misc_api/windows.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/misc_api/windows.h new file mode 100644 index 0000000..0817c2a --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/misc_api/windows.h @@ -0,0 +1,6 @@ +// Copyright (C) 2004 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MISC_API_KERNEl_2_ +#include "misc_api_kernel_1.h" +#endif + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/noncopyable.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/noncopyable.h new file mode 100644 index 0000000..20b9866 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/noncopyable.h @@ -0,0 +1,32 @@ +// (C) Copyright Beman Dawes 1999-2003. 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) +// Contributed by Dave Abrahams +// See http://www.boost.org/libs/utility for documentation. + +#ifndef DLIB_BOOST_NONCOPYABLE_HPP_INCLUDED +#define DLIB_BOOST_NONCOPYABLE_HPP_INCLUDED + + +namespace dlib +{ + class noncopyable + { + /*! + This class makes it easier to declare a class as non-copyable. + If you want to make an object that can't be copied just inherit + from this object. + !*/ + + protected: + noncopyable() = default; + ~noncopyable() = default; + private: // emphasize the following members are private + noncopyable(const noncopyable&); + const noncopyable& operator=(const noncopyable&); + + }; +} + +#endif // DLIB_BOOST_NONCOPYABLE_HPP_INCLUDED + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/numeric_constants.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/numeric_constants.h new file mode 100644 index 0000000..05f2631 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/numeric_constants.h @@ -0,0 +1,53 @@ +//Copyright (C) 2013 Steve Taylor (steve98654@gmail.com), Davis E. King +//License: Boost Software License. See LICENSE.txt for full license. +#ifndef DLIB_NUMERIC_CONSTANTs_H_ +#define DLIB_NUMERIC_CONSTANTs_H_ + +namespace dlib +{ + + // pi -- Pi + const double pi = 3.1415926535897932385; + + // e -- Euler's Constant + const double e = 2.7182818284590452354; + + // sqrt_2 -- The square root of 2 + const double sqrt_2 = 1.4142135623730950488; + + // sqrt_3 -- The square root of 3 + const double sqrt_3 = 1.7320508075688772935; + + // log10_2 -- The logarithm base 10 of two + const double log10_2 = 0.30102999566398119521; + + // light_spd -- The speed of light in vacuum in meters per second + const double light_spd = 2.99792458e8; + + // newton_G -- Newton's gravitational constant (in metric units of m^3/(kg*s^2)) + const double newton_G = 6.67384e-11; + + // planck_cst -- Planck's constant (in units of Joules * seconds) + const double planck_cst = 6.62606957e-34; + + // golden_ratio -- The Golden Ratio + const double golden_ratio = 1.6180339887498948482; + + // euler_gamma -- The Euler Mascheroni Constant + const double euler_gamma = 0.5772156649015328606065; + + // catalan -- Catalan's Constant + const double catalan = 0.91596559417721901505; + + // glaisher -- Glaisher Kinkelin constant + const double glaisher = 1.2824271291006226369; + + // khinchin -- Khinchin's constant + const double khinchin = 2.6854520010653064453; + + // apery -- Apery's constant + const double apery = 1.2020569031595942854; +} + +#endif //DLIB_NUMERIC_CONSTANTs_H_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/numerical_integration.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/numerical_integration.h new file mode 100644 index 0000000..6676c98 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/numerical_integration.h @@ -0,0 +1,8 @@ +// Copyright (C) 2013 Steve Taylor (steve98654@gmail.com) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_INTEGRATE_FUNCTION_ADAPT_SIMPSON_HEADER +#define DLIB_INTEGRATE_FUNCTION_ADAPT_SIMPSON_HEADER + +#include "numerical_integration/integrate_function_adapt_simpson.h" + +#endif // DLIB_INTEGRATE_FUNCTION_ADAPT_SIMPSON_HEADER diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/numerical_integration/integrate_function_adapt_simpson.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/numerical_integration/integrate_function_adapt_simpson.h new file mode 100644 index 0000000..c30e21c --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/numerical_integration/integrate_function_adapt_simpson.h @@ -0,0 +1,93 @@ +// Copyright (C) 2013 Steve Taylor (steve98654@gmail.com) +// License: Boost Software License See LICENSE.txt for full license +#ifndef DLIB_INTEGRATE_FUNCTION_ADAPT_SIMPSONh_ +#define DLIB_INTEGRATE_FUNCTION_ADAPT_SIMPSONh_ + +#include "integrate_function_adapt_simpson_abstract.h" +#include "../assert.h" + +// ---------------------------------------------------------------------------------------- + +namespace dlib +{ + template + T impl_adapt_simp_stop(const funct& f, T a, T b, T fa, T fm, T fb, T is, int cnt) + { + const int maxint = 500; + + T m = (a + b)/2.0; + T h = (b - a)/4.0; + T fml = f(a + h); + T fmr = f(b - h); + T i1 = h/1.5*(fa+4.0*fm+fb); + T i2 = h/3.0*(fa+4.0*(fml+fmr)+2.0*fm+fb); + i1 = (16.0*i2 - i1)/15.0; + T Q = 0; + + if ((std::abs(i1-i2) <= std::abs(is)) || (m <= a) || (b <= m)) + { + Q = i1; + } + else + { + if(cnt < maxint) + { + cnt = cnt + 1; + + Q = impl_adapt_simp_stop(f,a,m,fa,fml,fm,is,cnt) + + impl_adapt_simp_stop(f,m,b,fm,fmr,fb,is,cnt); + } + } + + return Q; + } + +// ---------------------------------------------------------------------------------------- + + template + T integrate_function_adapt_simp( + const funct& f, + T a, + T b, + T tol = 1e-10 + ) + { + // make sure requires clause is not broken + DLIB_ASSERT(b > a && tol > 0, + "\t T integrate_function_adapt_simp()" + << "\n\t Invalid arguments were given to this function." + << "\n\t a: " << a + << "\n\t b: " << b + << "\n\t tol: " << tol + ); + + T eps = std::numeric_limits::epsilon(); + if(tol < eps) + { + tol = eps; + } + + const T ba = b-a; + const T fa = f(a); + const T fb = f(b); + const T fm = f((a+b)/2); + + T is = ba/8*(fa+fb+fm+ f(a + 0.9501*ba) + f(a + 0.2311*ba) + f(a + 0.6068*ba) + + f(a + 0.4860*ba) + f(a + 0.8913*ba)); + + if(is == 0) + { + is = b-a; + } + + is = is*tol; + + int cnt = 0; + + return impl_adapt_simp_stop(f, a, b, fa, fm, fb, is, cnt); + } +} + +// ---------------------------------------------------------------------------------------- + +#endif // DLIB_INTEGRATE_FUNCTION_ADAPT_SIMPSONh_ diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/numerical_integration/integrate_function_adapt_simpson_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/numerical_integration/integrate_function_adapt_simpson_abstract.h new file mode 100644 index 0000000..90badcf --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/numerical_integration/integrate_function_adapt_simpson_abstract.h @@ -0,0 +1,34 @@ +// Copyright (C) 2013 Steve Taylor (steve98654@gmail.com) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_INTEGRATE_FUNCTION_ADAPT_SIMPSON_ABSTRACTh_ +#ifdef DLIB_INTEGRATE_FUNCTION_ADAPT_SIMPSON_ABSTRACTh_ + +namespace dlib +{ + + template + T integrate_function_adapt_simp( + const funct& f, + T a, + T b, + T tol = 1e-10 + ); + /*! + requires + - b > a + - tol > 0 + - T should be either float, double, or long double + - The expression f(a) should be a valid expression that evaluates to a T. + I.e. f() should be a real valued function of a single variable. + ensures + - returns an approximation of the integral of f over the domain [a,b] using the + adaptive Simpson method outlined in Gander, W. and W. Gautshi, "Adaptive + Quadrature -- Revisited" BIT, Vol. 40, (2000), pp.84-101 + - tol is a tolerance parameter that determines the overall accuracy of + approximated integral. We suggest a default value of 1e-10 for tol. + !*/ + +} + +#endif // DLIB_INTEGRATE_FUNCTION_ADAPT_SIMPSON_ABSTRACTh_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/ostream b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/ostream new file mode 100644 index 0000000..eb0e59e --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/ostream @@ -0,0 +1 @@ +#include "dlib_include_path_tutorial.txt" diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/pipe.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/pipe.h new file mode 100644 index 0000000..023b985 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/pipe.h @@ -0,0 +1,10 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_PIPe_ +#define DLIB_PIPe_ + +#include "pipe/pipe_kernel_1.h" + + +#endif // DLIB_PIPe_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/pipe/pipe_kernel_1.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/pipe/pipe_kernel_1.h new file mode 100644 index 0000000..5437541 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/pipe/pipe_kernel_1.h @@ -0,0 +1,756 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_PIPE_KERNEl_1_ +#define DLIB_PIPE_KERNEl_1_ + +#include "../algs.h" +#include "../threads.h" +#include "pipe_kernel_abstract.h" + +namespace dlib +{ + + template < + typename T + > + class pipe + { + /*! + INITIAL VALUE + - pipe_size == 0 + - pipe_max_size == defined by constructor + - enabled == true + - data == a pointer to an array of ((pipe_max_size>0)?pipe_max_size:1) T objects. + - dequeue_waiters == 0 + - enqueue_waiters == 0 + - first == 1 + - last == 1 + - unblock_sig_waiters == 0 + + CONVENTION + - size() == pipe_size + - max_size() == pipe_max_size + - is_enabled() == enabled + + - m == the mutex used to lock access to all the members of this class + + - dequeue_waiters == the number of threads blocked on calls to dequeue() + - enqueue_waiters == the number of threads blocked on calls to enqueue() and + wait_until_empty() + - unblock_sig_waiters == the number of threads blocked on calls to + wait_for_num_blocked_dequeues() and the destructor. (i.e. the number of + blocking calls to unblock_sig.wait()) + + - dequeue_sig == the signaler that threads blocked on calls to dequeue() wait on + - enqueue_sig == the signaler that threads blocked on calls to enqueue() + or wait_until_empty() wait on. + - unblock_sig == the signaler that is signaled when a thread stops blocking on a call + to enqueue() or dequeue(). It is also signaled when a dequeue that will probably + block is called. The destructor and wait_for_num_blocked_dequeues are the only + things that will wait on this signaler. + + - if (pipe_size > 0) then + - data[first] == the next item to dequeue + - data[last] == the item most recently added via enqueue, so the last to dequeue. + - else if (pipe_max_size == 0) + - if (first == 0 && last == 0) then + - data[0] == the next item to dequeue + - else if (first == 0 && last == 1) then + - data[0] has been taken out already by a dequeue + !*/ + + public: + // this is here for backwards compatibility with older versions of dlib. + typedef pipe kernel_1a; + + typedef T type; + + explicit pipe ( + size_t maximum_size + ); + + virtual ~pipe ( + ); + + void empty ( + ); + + void wait_until_empty ( + ) const; + + void wait_for_num_blocked_dequeues ( + unsigned long num + )const; + + void enable ( + ); + + void disable ( + ); + + bool is_enqueue_enabled ( + ) const; + + void disable_enqueue ( + ); + + void enable_enqueue ( + ); + + bool is_dequeue_enabled ( + ) const; + + void disable_dequeue ( + ); + + void enable_dequeue ( + ); + + bool is_enabled ( + ) const; + + size_t max_size ( + ) const; + + size_t size ( + ) const; + + bool enqueue ( + T& item + ); + + bool enqueue ( + T&& item + ) { return enqueue(item); } + + bool dequeue ( + T& item + ); + + bool enqueue_or_timeout ( + T& item, + unsigned long timeout + ); + + bool enqueue_or_timeout ( + T&& item, + unsigned long timeout + ) { return enqueue_or_timeout(item,timeout); } + + bool dequeue_or_timeout ( + T& item, + unsigned long timeout + ); + + private: + + size_t pipe_size; + const size_t pipe_max_size; + bool enabled; + + T* const data; + + size_t first; + size_t last; + + mutex m; + signaler dequeue_sig; + signaler enqueue_sig; + signaler unblock_sig; + + unsigned long dequeue_waiters; + mutable unsigned long enqueue_waiters; + mutable unsigned long unblock_sig_waiters; + bool enqueue_enabled; + bool dequeue_enabled; + + // restricted functions + pipe(const pipe&); // copy constructor + pipe& operator=(const pipe&); // assignment operator + + }; + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + pipe:: + pipe ( + size_t maximum_size + ) : + pipe_size(0), + pipe_max_size(maximum_size), + enabled(true), + data(new T[(maximum_size>0) ? maximum_size : 1]), + first(1), + last(1), + dequeue_sig(m), + enqueue_sig(m), + unblock_sig(m), + dequeue_waiters(0), + enqueue_waiters(0), + unblock_sig_waiters(0), + enqueue_enabled(true), + dequeue_enabled(true) + { + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + pipe:: + ~pipe ( + ) + { + auto_mutex M(m); + ++unblock_sig_waiters; + + // first make sure no one is blocked on any calls to enqueue() or dequeue() + enabled = false; + dequeue_sig.broadcast(); + enqueue_sig.broadcast(); + unblock_sig.broadcast(); + + // wait for all threads to unblock + while (dequeue_waiters > 0 || enqueue_waiters > 0 || unblock_sig_waiters > 1) + unblock_sig.wait(); + + delete [] data; + --unblock_sig_waiters; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void pipe:: + empty ( + ) + { + auto_mutex M(m); + pipe_size = 0; + + // let any calls to enqueue() know that the pipe is now empty + if (enqueue_waiters > 0) + enqueue_sig.broadcast(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void pipe:: + wait_until_empty ( + ) const + { + auto_mutex M(m); + // this function is sort of like a call to enqueue so treat it like that + ++enqueue_waiters; + + while (pipe_size > 0 && enabled && dequeue_enabled ) + enqueue_sig.wait(); + + // let the destructor know we are ending if it is blocked waiting + if (enabled == false) + unblock_sig.broadcast(); + + --enqueue_waiters; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void pipe:: + enable ( + ) + { + auto_mutex M(m); + enabled = true; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void pipe:: + disable ( + ) + { + auto_mutex M(m); + enabled = false; + dequeue_sig.broadcast(); + enqueue_sig.broadcast(); + unblock_sig.broadcast(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + bool pipe:: + is_enabled ( + ) const + { + auto_mutex M(m); + return enabled; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + size_t pipe:: + max_size ( + ) const + { + auto_mutex M(m); + return pipe_max_size; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + size_t pipe:: + size ( + ) const + { + auto_mutex M(m); + return pipe_size; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + bool pipe:: + enqueue ( + T& item + ) + { + auto_mutex M(m); + ++enqueue_waiters; + + // wait until there is room or we are disabled + while (pipe_size == pipe_max_size && enabled && enqueue_enabled && + !(pipe_max_size == 0 && first == 1) ) + enqueue_sig.wait(); + + if (enabled == false || enqueue_enabled == false) + { + --enqueue_waiters; + // let the destructor know we are unblocking + unblock_sig.broadcast(); + return false; + } + + // set the appropriate values for first and last + if (pipe_size == 0) + { + first = 0; + last = 0; + } + else + { + last = (last+1)%pipe_max_size; + } + + + exchange(item,data[last]); + + // wake up a call to dequeue() if there are any currently blocked + if (dequeue_waiters > 0) + dequeue_sig.signal(); + + if (pipe_max_size > 0) + { + ++pipe_size; + } + else + { + // wait for a dequeue to take the item out + while (last == 0 && enabled && enqueue_enabled) + enqueue_sig.wait(); + + if (last == 0 && (enabled == false || enqueue_enabled == false)) + { + last = 1; + first = 1; + + // no one dequeued this object to put it back into item + exchange(item,data[0]); + + --enqueue_waiters; + // let the destructor know we are unblocking + if (unblock_sig_waiters > 0) + unblock_sig.broadcast(); + return false; + } + + last = 1; + first = 1; + + // tell any waiting calls to enqueue() that one of them can proceed + if (enqueue_waiters > 1) + enqueue_sig.broadcast(); + + // let the destructor know we are unblocking + if (enabled == false && unblock_sig_waiters > 0) + unblock_sig.broadcast(); + } + + --enqueue_waiters; + return true; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + bool pipe:: + dequeue ( + T& item + ) + { + auto_mutex M(m); + ++dequeue_waiters; + + if (pipe_size == 0) + { + // notify wait_for_num_blocked_dequeues() + if (unblock_sig_waiters > 0) + unblock_sig.broadcast(); + + // notify any blocked enqueue_or_timeout() calls + if (enqueue_waiters > 0) + enqueue_sig.broadcast(); + } + + // wait until there is something in the pipe or we are disabled + while (pipe_size == 0 && enabled && dequeue_enabled && + !(pipe_max_size == 0 && first == 0 && last == 0) ) + dequeue_sig.wait(); + + if (enabled == false || dequeue_enabled == false) + { + --dequeue_waiters; + // let the destructor know we are unblocking + unblock_sig.broadcast(); + return false; + } + + exchange(item,data[first]); + + if (pipe_max_size > 0) + { + // set the appropriate values for first + first = (first+1)%pipe_max_size; + + --pipe_size; + } + else + { + // let the enqueue waiting on us know that we took the + // item out already. + last = 1; + } + + // wake up a call to enqueue() if there are any currently blocked + if (enqueue_waiters > 0) + enqueue_sig.broadcast(); + + --dequeue_waiters; + return true; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + bool pipe:: + enqueue_or_timeout ( + T& item, + unsigned long timeout + ) + { + auto_mutex M(m); + ++enqueue_waiters; + + // wait until there is room or we are disabled or + // we run out of time. + bool timed_out = false; + while (pipe_size == pipe_max_size && enabled && enqueue_enabled && + !(pipe_max_size == 0 && dequeue_waiters > 0 && first == 1) ) + { + if (timeout == 0 || enqueue_sig.wait_or_timeout(timeout) == false) + { + timed_out = true; + break; + } + } + + if (enabled == false || timed_out || enqueue_enabled == false) + { + --enqueue_waiters; + // let the destructor know we are unblocking + unblock_sig.broadcast(); + return false; + } + + // set the appropriate values for first and last + if (pipe_size == 0) + { + first = 0; + last = 0; + } + else + { + last = (last+1)%pipe_max_size; + } + + + exchange(item,data[last]); + + // wake up a call to dequeue() if there are any currently blocked + if (dequeue_waiters > 0) + dequeue_sig.signal(); + + if (pipe_max_size > 0) + { + ++pipe_size; + } + else + { + // wait for a dequeue to take the item out + while (last == 0 && enabled && enqueue_enabled) + enqueue_sig.wait(); + + if (last == 0 && (enabled == false || enqueue_enabled == false)) + { + last = 1; + first = 1; + + // no one dequeued this object to put it back into item + exchange(item,data[0]); + + --enqueue_waiters; + // let the destructor know we are unblocking + if (unblock_sig_waiters > 0) + unblock_sig.broadcast(); + return false; + } + + last = 1; + first = 1; + + // tell any waiting calls to enqueue() that one of them can proceed + if (enqueue_waiters > 1) + enqueue_sig.broadcast(); + + // let the destructor know we are unblocking + if (enabled == false && unblock_sig_waiters > 0) + unblock_sig.broadcast(); + } + + --enqueue_waiters; + return true; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + bool pipe:: + dequeue_or_timeout ( + T& item, + unsigned long timeout + ) + { + auto_mutex M(m); + ++dequeue_waiters; + + if (pipe_size == 0) + { + // notify wait_for_num_blocked_dequeues() + if (unblock_sig_waiters > 0) + unblock_sig.broadcast(); + + // notify any blocked enqueue_or_timeout() calls + if (enqueue_waiters > 0) + enqueue_sig.broadcast(); + } + + bool timed_out = false; + // wait until there is something in the pipe or we are disabled or we timeout. + while (pipe_size == 0 && enabled && dequeue_enabled && + !(pipe_max_size == 0 && first == 0 && last == 0) ) + { + if (timeout == 0 || dequeue_sig.wait_or_timeout(timeout) == false) + { + timed_out = true; + break; + } + } + + if (enabled == false || timed_out || dequeue_enabled == false) + { + --dequeue_waiters; + // let the destructor know we are unblocking + unblock_sig.broadcast(); + return false; + } + + exchange(item,data[first]); + + if (pipe_max_size > 0) + { + // set the appropriate values for first + first = (first+1)%pipe_max_size; + + --pipe_size; + } + else + { + // let the enqueue waiting on us know that we took the + // item out already. + last = 1; + } + + // wake up a call to enqueue() if there are any currently blocked + if (enqueue_waiters > 0) + enqueue_sig.broadcast(); + + --dequeue_waiters; + return true; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void pipe:: + wait_for_num_blocked_dequeues ( + unsigned long num + )const + { + auto_mutex M(m); + ++unblock_sig_waiters; + + while ( (dequeue_waiters < num || pipe_size != 0) && enabled && dequeue_enabled) + unblock_sig.wait(); + + // let the destructor know we are ending if it is blocked waiting + if (enabled == false) + unblock_sig.broadcast(); + + --unblock_sig_waiters; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + bool pipe:: + is_enqueue_enabled ( + ) const + { + auto_mutex M(m); + return enqueue_enabled; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void pipe:: + disable_enqueue ( + ) + { + auto_mutex M(m); + enqueue_enabled = false; + enqueue_sig.broadcast(); + } + + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void pipe:: + enable_enqueue ( + ) + { + auto_mutex M(m); + enqueue_enabled = true; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + bool pipe:: + is_dequeue_enabled ( + ) const + { + auto_mutex M(m); + return dequeue_enabled; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void pipe:: + disable_dequeue ( + ) + { + auto_mutex M(m); + dequeue_enabled = false; + dequeue_sig.broadcast(); + } + + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void pipe:: + enable_dequeue ( + ) + { + auto_mutex M(m); + dequeue_enabled = true; + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_PIPE_KERNEl_1_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/pipe/pipe_kernel_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/pipe/pipe_kernel_abstract.h new file mode 100644 index 0000000..91b2205 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/pipe/pipe_kernel_abstract.h @@ -0,0 +1,323 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_PIPE_KERNEl_ABSTRACT_ +#ifdef DLIB_PIPE_KERNEl_ABSTRACT_ + +#include "../threads.h" + +namespace dlib +{ + + template < + typename T + > + class pipe + { + /*! + REQUIREMENTS ON T + T must be swappable by a global swap() + T must have a default constructor + + INITIAL VALUE + size() == 0 + is_enabled() == true + is_enqueue_enabled() == true + is_dequeue_enabled() == true + + WHAT THIS OBJECT REPRESENTS + This is a first in first out queue with a fixed maximum size containing + items of type T. It is suitable for passing objects between threads. + + THREAD SAFETY + All methods of this class are thread safe. You may call them from any + thread and any number of threads my call them at once. + !*/ + + public: + + typedef T type; + + explicit pipe ( + size_t maximum_size + ); + /*! + ensures + - #*this is properly initialized + - #max_size() == maximum_size + throws + - std::bad_alloc + - dlib::thread_error + !*/ + + virtual ~pipe ( + ); + /*! + ensures + - any resources associated with *this have been released + - disables (i.e. sets is_enabled() == false) this object so that + all calls currently blocking on it will return immediately. + !*/ + + void enable ( + ); + /*! + ensures + - #is_enabled() == true + !*/ + + void disable ( + ); + /*! + ensures + - #is_enabled() == false + - causes all current and future calls to enqueue(), dequeue(), + enqueue_or_timeout() and dequeue_or_timeout() to not block but + to return false immediately until enable() is called. + - causes all current and future calls to wait_until_empty() and + wait_for_num_blocked_dequeues() to not block but return + immediately until enable() is called. + !*/ + + bool is_enabled ( + ) const; + /*! + ensures + - returns true if this pipe is currently enabled, false otherwise. + !*/ + + void empty ( + ); + /*! + ensures + - #size() == 0 + !*/ + + void wait_until_empty ( + ) const; + /*! + ensures + - blocks until one of the following is the case: + - size() == 0 + - is_enabled() == false + - is_dequeue_enabled() == false + !*/ + + void wait_for_num_blocked_dequeues ( + unsigned long num + ) const; + /*! + ensures + - blocks until one of the following is the case: + - size() == 0 and the number of threads blocked on calls + to dequeue() and dequeue_or_timeout() is greater than + or equal to num. + - is_enabled() == false + - is_dequeue_enabled() == false + !*/ + + bool is_enqueue_enabled ( + ) const; + /*! + ensures + - returns true if the enqueue() and enqueue_or_timeout() functions are + currently enabled, returns false otherwise. (note that the higher + level is_enabled() function can overrule this one. So if + is_enabled() == false then enqueue functions are still disabled even + if is_enqueue_enabled() returns true. But if is_enqueue_enabled() == false + then enqueue functions are always disabled no matter the state of + is_enabled()) + !*/ + + void disable_enqueue ( + ); + /*! + ensures + - #is_enqueue_enabled() == false + - causes all current and future calls to enqueue() and + enqueue_or_timeout() to not block but to return false + immediately until enable_enqueue() is called. + !*/ + + void enable_enqueue ( + ); + /*! + ensures + - #is_enqueue_enabled() == true + !*/ + + bool is_dequeue_enabled ( + ) const; + /*! + ensures + - returns true if the dequeue() and dequeue_or_timeout() functions are + currently enabled, returns false otherwise. (note that the higher + level is_enabled() function can overrule this one. So if + is_enabled() == false then dequeue functions are still disabled even + if is_dequeue_enabled() returns true. But if is_dequeue_enabled() == false + then dequeue functions are always disabled no matter the state of + is_enabled()) + !*/ + + void disable_dequeue ( + ); + /*! + ensures + - #is_dequeue_enabled() == false + - causes all current and future calls to dequeue() and + dequeue_or_timeout() to not block but to return false + immediately until enable_dequeue() is called. + !*/ + + void enable_dequeue ( + ); + /*! + ensures + - #is_dequeue_enabled() == true + !*/ + + size_t max_size ( + ) const; + /*! + ensures + - returns the maximum number of objects of type T that this + pipe can contain. + !*/ + + size_t size ( + ) const; + /*! + ensures + - returns the number of objects of type T that this + object currently contains. + !*/ + + bool enqueue ( + T& item + ); + /*! + ensures + - if (size() == max_size()) then + - this call to enqueue() blocks until one of the following is the case: + - there is room in the pipe for another item + - max_size() == 0 and another thread is trying to dequeue from this + pipe and we can pass our item object directly to that thread. + - someone calls disable() + - someone calls disable_enqueue() + - else + - this call does not block. + - if (this call to enqueue() returns true) then + - #is_enabled() == true + - #is_enqueue_enabled() == true + - if (max_size() == 0) then + - using global swap, item was passed directly to a + thread attempting to dequeue from this pipe + - else + - using global swap, item was added into this pipe. + - #item is in an undefined but valid state for its type + - else + - item was NOT added into the pipe + - #item == item (i.e. the value of item is unchanged) + !*/ + + bool enqueue (T&& item) { return enqueue(item); } + /*! + enable enqueueing from rvalues + !*/ + + bool enqueue_or_timeout ( + T& item, + unsigned long timeout + ); + /*! + ensures + - if (size() == max_size() && timeout > 0) then + - this call to enqueue_or_timeout() blocks until one of the following is the case: + - there is room in the pipe to add another item + - max_size() == 0 and another thread is trying to dequeue from this pipe + and we can pass our item object directly to that thread. + - someone calls disable() + - someone calls disable_enqueue() + - timeout milliseconds passes + - else + - this call does not block. + - if (this call to enqueue() returns true) then + - #is_enabled() == true + - #is_enqueue_enabled() == true + - if (max_size() == 0) then + - using global swap, item was passed directly to a + thread attempting to dequeue from this pipe + - else + - using global swap, item was added into this pipe. + - #item is in an undefined but valid state for its type + - else + - item was NOT added into the pipe + - #item == item (i.e. the value of item is unchanged) + !*/ + + bool enqueue_or_timeout (T&& item, unsigned long timeout) { return enqueue_or_timeout(item,timeout); } + /*! + enable enqueueing from rvalues + !*/ + + bool dequeue ( + T& item + ); + /*! + ensures + - if (size() == 0) then + - this call to dequeue() blocks until one of the following is the case: + - there is something in the pipe we can dequeue + - max_size() == 0 and another thread is trying to enqueue an item + onto this pipe and we can receive our item directly from that thread. + - someone calls disable() + - someone calls disable_dequeue() + - else + - this call does not block. + - if (this call to dequeue() returns true) then + - #is_enabled() == true + - #is_dequeue_enabled() == true + - the oldest item that was enqueued into this pipe has been + swapped into #item. + - else + - nothing was dequeued from this pipe. + - #item == item (i.e. the value of item is unchanged) + !*/ + + bool dequeue_or_timeout ( + T& item, + unsigned long timeout + ); + /*! + ensures + - if (size() == 0 && timeout > 0) then + - this call to dequeue_or_timeout() blocks until one of the following is the case: + - there is something in the pipe we can dequeue + - max_size() == 0 and another thread is trying to enqueue an item onto this + pipe and we can receive our item directly from that thread. + - someone calls disable() + - someone calls disable_dequeue() + - timeout milliseconds passes + - else + - this call does not block. + - if (this call to dequeue_or_timeout() returns true) then + - #is_enabled() == true + - #is_dequeue_enabled() == true + - the oldest item that was enqueued into this pipe has been + swapped into #item. + - else + - nothing was dequeued from this pipe. + - #item == item (i.e. the value of item is unchanged) + !*/ + + private: + + // restricted functions + pipe(const pipe&); // copy constructor + pipe& operator=(const pipe&); // assignment operator + + }; + +} + +#endif // DLIB_PIPE_KERNEl_ABSTRACT_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/platform.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/platform.h new file mode 100644 index 0000000..3499545 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/platform.h @@ -0,0 +1,65 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. + +#ifdef DLIB_ALL_SOURCE_END +#include "dlib_basic_cpp_build_tutorial.txt" +#endif + +#ifndef DLIB_PLATFORm_ +#define DLIB_PLATFORm_ + + +/*! + This file ensures that: + - if (we are compiling under a posix platform) then + - DLIB_POSIX will be defined + - if (this is also Mac OS X) then + - MACOSX will be defined + - if (this is also HP-UX) then + - HPUX will be defined + - if (we are compiling under an MS Windows platform) then + - WIN32 will be defined +!*/ + + +/* + A good reference for this sort of information is + http://predef.sourceforge.net/ +*/ + +// Define WIN32 if this is MS Windows +#ifndef WIN32 + #if defined( _MSC_VER) || defined(__BORLANDC__) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) + #define WIN32 + #endif +#endif + +#ifndef WIN32 + // since this is the only other platform the library currently supports + // just assume it is DLIB_POSIX if it isn't WIN32 + #ifndef DLIB_POSIX + #define DLIB_POSIX + #endif + + #ifndef HPUX + #if defined(__hpux ) || defined(hpux) || defined (_hpux) + #define HPUX + #endif + #endif + + #ifndef MACOSX + #ifdef __MACOSX__ + #define MACOSX + #endif + #ifdef __APPLE__ + #define MACOSX + #endif + #endif + +#endif + + + + +#endif // DLIB_PLATFORm_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/queue.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/queue.h new file mode 100644 index 0000000..b0f331d --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/queue.h @@ -0,0 +1,84 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_QUEUe_ +#define DLIB_QUEUe_ + +#include "queue/queue_kernel_1.h" +#include "queue/queue_kernel_2.h" +#include "queue/queue_kernel_c.h" + +#include "queue/queue_sort_1.h" + + +#include "algs.h" + +namespace dlib +{ + + template < + typename T, + typename mem_manager = default_memory_manager + > + class queue + { + queue() {} + public: + + + //----------- kernels --------------- + + // kernel_1a + typedef queue_kernel_1 + kernel_1a; + typedef queue_kernel_c + kernel_1a_c; + + + // kernel_2a + typedef queue_kernel_2 + kernel_2a; + typedef queue_kernel_c + kernel_2a_c; + + + // kernel_2b + typedef queue_kernel_2 + kernel_2b; + typedef queue_kernel_c + kernel_2b_c; + + + + + //---------- extensions ------------ + + // sort_1 extend kernel_1a + typedef queue_sort_1 + sort_1a; + typedef queue_sort_1 + sort_1a_c; + + + // sort_1 extend kernel_2a + typedef queue_sort_1 + sort_1b; + typedef queue_sort_1 + sort_1b_c; + + + + // sort_1 extend kernel_2b + typedef queue_sort_1 + sort_1c; + typedef queue_sort_1 + sort_1c_c; + + + + + + }; +} + +#endif // DLIB_QUEUe_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/queue/queue_kernel_1.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/queue/queue_kernel_1.h new file mode 100644 index 0000000..2dfb777 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/queue/queue_kernel_1.h @@ -0,0 +1,554 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_QUEUE_KERNEl_1_ +#define DLIB_QUEUE_KERNEl_1_ + +#include "queue_kernel_abstract.h" +#include "../algs.h" +#include "../interfaces/enumerable.h" +#include "../interfaces/remover.h" +#include "../serialize.h" + +namespace dlib +{ + + template < + typename T, + typename mem_manager = default_memory_manager + > + class queue_kernel_1 : public enumerable, + public remover + { + + /*! + INITIAL VALUE + queue_size == 0 + current_element == 0 + at_start_ == true + + CONVENTION + queue_size == the number of elements in the queue + at_start() == at_start_ + current_element_valid() == (current_element != 0) + element() == current_element->item + + if (queue_size > 0) + { + in points to the last element to be inserted into the queue + out points to the next element to be dequeued + + each node points to the node inserted after it except for the most + recently inserted node + + current_element == 0 + } + + !*/ + + + struct node + { + node* last; + + T item; + }; + + + public: + + typedef T type; + typedef mem_manager mem_manager_type; + + queue_kernel_1 ( + ) : + in(0), + out(0), + queue_size(0), + current_element(0), + at_start_(true) + { + } + + virtual ~queue_kernel_1 ( + ); + + inline void clear( + ); + + void enqueue ( + T& item + ); + + void dequeue ( + T& item + ); + + void cat ( + queue_kernel_1& item + ); + + T& current ( + ); + + const T& current ( + ) const; + + void swap ( + queue_kernel_1& item + ); + + // functions from the remover interface + inline void remove_any ( + T& item + ); + + // functions from the enumerable interface + inline size_t size ( + ) const; + + inline bool at_start ( + ) const; + + inline void reset ( + ) const; + + bool current_element_valid ( + ) const; + + inline const T& element ( + ) const; + + inline T& element ( + ); + + bool move_next ( + ) const; + + private: + + void delete_nodes ( + node* start, + unsigned long length + ); + /*! + requires + - start points to a node in a singly linked list + - start->last points to the next node in the list + - there are at least length nodes in the list beginning with start + ensures + - length nodes have been deleted starting with the node pointed + to by start + !*/ + + // data members + + node* in; + node* out; + unsigned long queue_size; + mutable node* current_element; + mutable bool at_start_; + + // restricted functions + queue_kernel_1(queue_kernel_1&); // copy constructor + queue_kernel_1& operator=(queue_kernel_1&); // assignment operator + + }; + + template < + typename T, + typename mem_manager + > + inline void swap ( + queue_kernel_1& a, + queue_kernel_1& b + ) { a.swap(b); } + + template < + typename T, + typename mem_manager + > + void deserialize ( + queue_kernel_1& item, + std::istream& in + ) + { + try + { + item.clear(); + unsigned long size; + deserialize(size,in); + T temp; + for (unsigned long i = 0; i < size; ++i) + { + deserialize(temp,in); + item.enqueue(temp); + } + } + catch (serialization_error& e) + { + item.clear(); + throw serialization_error(e.info + "\n while deserializing object of type queue_kernel_1"); + } + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + queue_kernel_1:: + ~queue_kernel_1 ( + ) + { + delete_nodes(out,queue_size); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + void queue_kernel_1:: + clear ( + ) + { + delete_nodes(out,queue_size); + queue_size = 0; + + // put the enumerator at the start + reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + void queue_kernel_1:: + enqueue ( + T& item + ) + { + // make new node + node* temp = new node; + + // swap item into new node + exchange(item,temp->item); + + if (queue_size == 0) + out = temp; + else + in->last = temp; + + // make in point to the new node + in = temp; + + ++queue_size; + + // put the enumerator at the start + reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + void queue_kernel_1:: + dequeue ( + T& item + ) + { + // swap out into item + exchange(item,out->item); + + --queue_size; + + if (queue_size == 0) + { + delete out; + } + else + { + node* temp = out; + + // move out pointer to the next element in the queue + out = out->last; + + // delete old node + delete temp; + } + + // put the enumerator at the start + reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + void queue_kernel_1:: + cat ( + queue_kernel_1& item + ) + { + if (item.queue_size > 0) + { + if (queue_size > 0) + { + in->last = item.out; + } + else + { + out = item.out; + } + + + in = item.in; + queue_size += item.queue_size; + item.queue_size = 0; + } + + // put the enumerator at the start + reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + T& queue_kernel_1:: + current ( + ) + { + return out->item; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + const T& queue_kernel_1:: + current ( + ) const + { + return out->item; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + void queue_kernel_1:: + swap ( + queue_kernel_1& item + ) + { + node* in_temp = in; + node* out_temp = out; + unsigned long queue_size_temp = queue_size; + node* current_element_temp = current_element; + bool at_start_temp = at_start_; + + in = item.in; + out = item.out; + queue_size = item.queue_size; + current_element = item.current_element; + at_start_ = item.at_start_; + + item.in = in_temp; + item.out = out_temp; + item.queue_size = queue_size_temp; + item.current_element = current_element_temp; + item.at_start_ = at_start_temp; + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // enumerable function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + bool queue_kernel_1:: + at_start ( + ) const + { + return at_start_; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + size_t queue_kernel_1:: + size ( + ) const + { + return queue_size; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + void queue_kernel_1:: + reset ( + ) const + { + at_start_ = true; + current_element = 0; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + bool queue_kernel_1:: + current_element_valid ( + ) const + { + return (current_element != 0); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + const T& queue_kernel_1:: + element ( + ) const + { + return current_element->item; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + T& queue_kernel_1:: + element ( + ) + { + return current_element->item; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + bool queue_kernel_1:: + move_next ( + ) const + { + if (at_start_) + { + at_start_ = false; + // if the queue is empty then there is nothing to do + if (queue_size == 0) + { + return false; + } + else + { + current_element = out; + return true; + } + } + else + { + // if we are at the last element then the enumeration has finished + if (current_element == in || current_element == 0) + { + current_element = 0; + return false; + } + else + { + current_element = current_element->last; + return true; + } + } + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // remover function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + void queue_kernel_1:: + remove_any ( + T& item + ) + { + dequeue(item); + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // private member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + void queue_kernel_1:: + delete_nodes ( + node* start, + unsigned long length + ) + { + node* temp; + while (length) + { + temp = start->last; + delete start; + start = temp; + --length; + } + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_QUEUE_KERNEl_1_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/queue/queue_kernel_2.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/queue/queue_kernel_2.h new file mode 100644 index 0000000..4cfb3a8 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/queue/queue_kernel_2.h @@ -0,0 +1,600 @@ +// Copyright (C) 2004 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_QUEUE_KERNEl_2_ +#define DLIB_QUEUE_KERNEl_2_ + +#include "queue_kernel_abstract.h" +#include "../algs.h" +#include "../assert.h" +#include "../interfaces/enumerable.h" +#include "../interfaces/remover.h" +#include "../serialize.h" + +namespace dlib +{ + + template < + typename T, + unsigned long block_size, + typename mem_manager = default_memory_manager + > + class queue_kernel_2 : public enumerable, + public remover + { + + /*! + REQUIREMENTS ON block_size + 0 < block_size < 2000000000 + + INITIAL VALUE + queue_size == 0 + current_element == 0 + at_start_ == true + + CONVENTION + queue_size == the number of elements in the queue + at_start() == at_start_ + current_element_valid() == (current_element != 0) + if (current_element_valid()) then + element() == current_element->item[current_element_pos] + + if (queue_size > 0) + { + in->item[in_pos] == the spot where we will put the next item added + into the queue + out->item[out_pos] == current() + + when enqueuing elements inside each node item[0] is filled first, then + item[1], then item[2], etc. + + + each node points to the node inserted after it except for the most + recently inserted node. + } + + !*/ + + + struct node + { + node* next; + + T item[block_size]; + }; + + + public: + + typedef T type; + typedef mem_manager mem_manager_type; + + queue_kernel_2 ( + ) : + in(0), + out(0), + queue_size(0), + current_element(0), + at_start_(true) + { + } + + virtual ~queue_kernel_2 ( + ); + + inline void clear( + ); + + void enqueue ( + T& item + ); + + void dequeue ( + T& item + ); + + void cat ( + queue_kernel_2& item + ); + + T& current ( + ); + + const T& current ( + ) const; + + void swap ( + queue_kernel_2& item + ); + + // functions from the remover interface + inline void remove_any ( + T& item + ); + + // functions from the enumerable interface + inline size_t size ( + ) const; + + inline bool at_start ( + ) const; + + inline void reset ( + ) const; + + bool current_element_valid ( + ) const; + + inline const T& element ( + ) const; + + inline T& element ( + ); + + bool move_next ( + ) const; + + private: + + void delete_nodes ( + node* start, + node* end + ); + /*! + requires + - start points to a node in a singly linked list + - start->next points to the next node in the list + - by following the next pointers you eventually hit the node pointed + to by end + ensures + - calls delete on the start node, the end node, and all nodes in between + !*/ + + // data members + + typename mem_manager::template rebind::other pool; + + node* in; + node* out; + size_t queue_size; + size_t in_pos; + size_t out_pos; + + + mutable node* current_element; + mutable size_t current_element_pos; + mutable bool at_start_; + + // restricted functions + queue_kernel_2(queue_kernel_2&); // copy constructor + queue_kernel_2& operator=(queue_kernel_2&); // assignment operator + + }; + + template < + typename T, + unsigned long block_size, + typename mem_manager + > + inline void swap ( + queue_kernel_2& a, + queue_kernel_2& b + ) { a.swap(b); } + + template < + typename T, + unsigned long block_size, + typename mem_manager + > + void deserialize ( + queue_kernel_2& item, + std::istream& in + ) + { + try + { + item.clear(); + unsigned long size; + deserialize(size,in); + T temp; + for (unsigned long i = 0; i < size; ++i) + { + deserialize(temp,in); + item.enqueue(temp); + } + } + catch (serialization_error& e) + { + item.clear(); + throw serialization_error(e.info + "\n while deserializing object of type queue_kernel_2"); + } + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename T, + unsigned long block_size, + typename mem_manager + > + queue_kernel_2:: + ~queue_kernel_2 ( + ) + { + COMPILE_TIME_ASSERT(0 < block_size && block_size < (unsigned long)(2000000000)); + + if (queue_size > 0) + delete_nodes(out,in); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + unsigned long block_size, + typename mem_manager + > + void queue_kernel_2:: + clear ( + ) + { + if (queue_size > 0) + { + delete_nodes(out,in); + queue_size = 0; + } + + // put the enumerator at the start + reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + unsigned long block_size, + typename mem_manager + > + void queue_kernel_2:: + enqueue ( + T& item + ) + { + if (queue_size == 0) + { + out = in = pool.allocate(); + in_pos = 0; + out_pos = 0; + } + else if (in_pos >= block_size) + { + in->next = pool.allocate(); + in_pos = 0; + in = in->next; + } + + exchange(item,in->item[in_pos]); + ++in_pos; + + ++queue_size; + + // put the enumerator at the start + reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + unsigned long block_size, + typename mem_manager + > + void queue_kernel_2:: + dequeue ( + T& item + ) + { + // swap out into item + exchange(item,out->item[out_pos]); + + ++out_pos; + --queue_size; + + // if this was the last element in this node then remove this node + if (out_pos == block_size) + { + out_pos = 0; + node* temp = out; + out = out->next; + pool.deallocate(temp); + } + else if (queue_size == 0) + { + pool.deallocate(out); + } + + // put the enumerator at the start + reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + unsigned long block_size, + typename mem_manager + > + void queue_kernel_2:: + cat ( + queue_kernel_2& item + ) + { + if (queue_size > 0) + { + T temp; + assign_zero_if_built_in_scalar_type(temp); + while (item.size() > 0) + { + item.dequeue(temp); + enqueue(temp); + } + } + else + { + in = item.in; + out = item.out; + out_pos = item.out_pos; + in_pos = item.in_pos; + + queue_size = item.queue_size; + item.queue_size = 0; + + // put the enumerator at the start + reset(); + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + unsigned long block_size, + typename mem_manager + > + T& queue_kernel_2:: + current ( + ) + { + return out->item[out_pos]; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + unsigned long block_size, + typename mem_manager + > + const T& queue_kernel_2:: + current ( + ) const + { + return out->item[out_pos]; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + unsigned long block_size, + typename mem_manager + > + void queue_kernel_2:: + swap ( + queue_kernel_2& item + ) + { + exchange(in,item.in); + exchange(out,item.out); + exchange(queue_size,item.queue_size); + exchange(in_pos,item.in_pos); + exchange(out_pos,item.out_pos); + exchange(current_element,item.current_element); + exchange(current_element_pos,item.current_element_pos); + exchange(at_start_,item.at_start_); + pool.swap(item.pool); + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // enumerable function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename T, + unsigned long block_size, + typename mem_manager + > + size_t queue_kernel_2:: + size ( + ) const + { + return queue_size; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + unsigned long block_size, + typename mem_manager + > + bool queue_kernel_2:: + at_start ( + ) const + { + return at_start_; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + unsigned long block_size, + typename mem_manager + > + void queue_kernel_2:: + reset ( + ) const + { + at_start_ = true; + current_element = 0; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + unsigned long block_size, + typename mem_manager + > + bool queue_kernel_2:: + current_element_valid ( + ) const + { + return (current_element != 0); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + unsigned long block_size, + typename mem_manager + > + const T& queue_kernel_2:: + element ( + ) const + { + return current_element->item[current_element_pos]; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + unsigned long block_size, + typename mem_manager + > + T& queue_kernel_2:: + element ( + ) + { + return current_element->item[current_element_pos]; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + unsigned long block_size, + typename mem_manager + > + bool queue_kernel_2:: + move_next ( + ) const + { + if (at_start_) + { + at_start_ = false; + // if the queue is empty then there is nothing to do + if (queue_size == 0) + { + return false; + } + else + { + current_element = out; + current_element_pos = out_pos; + return true; + } + } + else if (current_element == 0) + { + return false; + } + else + { + ++current_element_pos; + // if we are at the last element then the enumeration has finished + if (current_element == in && current_element_pos == in_pos ) + { + current_element = 0; + return false; + } + else if (current_element_pos == block_size) + { + current_element_pos = 0; + current_element = current_element->next; + } + + return true; + } + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // remover function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename T, + unsigned long block_size, + typename mem_manager + > + void queue_kernel_2:: + remove_any ( + T& item + ) + { + dequeue(item); + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // private member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename T, + unsigned long block_size, + typename mem_manager + > + void queue_kernel_2:: + delete_nodes ( + node* start, + node* end + ) + { + node* temp; + while (start != end) + { + temp = start; + start = start->next; + pool.deallocate(temp); + } + pool.deallocate(start); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_QUEUE_KERNEl_2_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/queue/queue_kernel_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/queue/queue_kernel_abstract.h new file mode 100644 index 0000000..4fd4c7d --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/queue/queue_kernel_abstract.h @@ -0,0 +1,196 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_QUEUE_KERNEl_ABSTRACT_ +#ifdef DLIB_QUEUE_KERNEl_ABSTRACT_ + +#include "../interfaces/enumerable.h" +#include "../interfaces/remover.h" +#include "../serialize.h" +#include "../algs.h" + +namespace dlib +{ + + template < + typename T, + typename mem_manager = default_memory_manager + > + class queue : public enumerable, + public remover + { + + /*! + REQUIREMENTS ON T + T must be swappable by a global swap() + T must have a default constructor + + REQUIREMENTS ON mem_manager + must be an implementation of memory_manager/memory_manager_kernel_abstract.h or + must be an implementation of memory_manager_global/memory_manager_global_kernel_abstract.h or + must be an implementation of memory_manager_stateless/memory_manager_stateless_kernel_abstract.h + mem_manager::type can be set to anything. + + POINTERS AND REFERENCES TO INTERNAL DATA + swap() and current() functions do not invalidate pointers or + references to internal data. + All other functions have no such guarantee. + + INITIAL VALUE + size() == 0 + + ENUMERATION ORDER + The enumerator will iterate over the elements in the queue in the + same order they would be removed by repeated calls to dequeue(). + (e.g. current() would be the first element enumerated) + + WHAT THIS OBJECT REPRESENTS + This is a first in first out queue containing items of type T + + e.g. if the queue is {b,c,d,e} and then 'a' is enqueued + the queue becomes {a,b,c,d,e} and then calling dequeue takes e out + making the queue {a,b,c,d} + + Also note that unless specified otherwise, no member functions + of this object throw exceptions. + !*/ + + public: + + typedef T type; + typedef mem_manager mem_manager_type; + + queue ( + ); + /*! + ensures + - #*this is properly initialized + throws + - std::bad_alloc or any exception thrown by T's constructor + !*/ + + virtual ~queue ( + ); + /*! + ensures + - all memory associated with *this has been released + !*/ + + void clear( + ); + /*! + ensures + - #*this has its initial value + throws + - std::bad_alloc or any exception thrown by T's constructor + if this exception is thrown then *this is unusable + until clear() is called and succeeds + !*/ + + void enqueue ( + T& item + ); + /*! + ensures + - item is now at the left end of #*this + - #item has an initial value for its type + - #size() == size() + 1 + - #at_start() == true + throws + - std::bad_alloc or any exception thrown by T's constructor + if enqueue() throws then it has no effect + !*/ + + void dequeue ( + T& item + ); + /*! + requires + - size() != 0 + ensures + - #size() == size() - 1 + - the far right element of *this has been removed and swapped + into #item + - #at_start() == true + !*/ + + void cat ( + queue& item + ); + /*! + ensures + - item has been concatenated onto the left end of *this. + i.e. item.current() is attached onto the left end of *this and + the left most element in item will also be the left most item + in #*this + - #size() == size() + item.size() + - #item has its initial value + - #at_start() == true + throws + - std::bad_alloc or any exception thrown by T's constructor + if cat() throws then the state of #item and *this is undefined + until clear() is successfully called on them. + !*/ + + T& current ( + ); + /*! + requires + - size() != 0 + ensures + - returns a const reference to the next element to be dequeued. + i.e. the right most element. + !*/ + + const T& current ( + ) const; + /*! + requires + - size() != 0 + ensures + - returns a non-const reference to the next element to be dequeued. + i.e. the right most element. + !*/ + + void swap ( + queue& item + ); + /*! + ensures + - swaps *this and item + !*/ + + private: + + // restricted functions + queue(queue&); // copy constructor + queue& operator=(queue&); // assignment operator + + }; + + template < + typename T, + typename mem_manager + > + inline void swap ( + queue& a, + queue& b + ) { a.swap(b); } + /*! + provides a global swap function + !*/ + + template < + typename T, + typename mem_manager + > + void deserialize ( + queue& item, + std::istream& in + ); + /*! + provides deserialization support + !*/ +} + +#endif // DLIB_QUEUE_KERNEl_ABSTRACT_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/queue/queue_kernel_c.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/queue/queue_kernel_c.h new file mode 100644 index 0000000..554c9ae --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/queue/queue_kernel_c.h @@ -0,0 +1,187 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_QUEUE_KERNEl_C_ +#define DLIB_QUEUE_KERNEl_C_ + +#include "queue_kernel_abstract.h" +#include "../algs.h" +#include "../assert.h" + +namespace dlib +{ + + + template < + typename queue_base // is an implementation of queue_kernel_abstract.h + > + class queue_kernel_c : public queue_base + { + typedef typename queue_base::type T; + + public: + + void dequeue ( + T& item + ); + + T& current ( + ); + + const T& current ( + ) const; + + const T& element ( + ) const; + + T& element ( + ); + + void remove_any ( + T& item + ); + + }; + + template < + typename queue_base + > + inline void swap ( + queue_kernel_c& a, + queue_kernel_c& b + ) { a.swap(b); } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename queue_base + > + void queue_kernel_c:: + dequeue ( + T& item + ) + { + + // make sure requires clause is not broken + DLIB_CASSERT(this->size() != 0, + "\tvoid queue::dequeue" + << "\n\tsize of queue should not be zero" + << "\n\tthis: " << this + ); + + // call the real function + queue_base::dequeue(item); + + } + +// ---------------------------------------------------------------------------------------- + + template < + typename queue_base + > + const typename queue_base::type& queue_kernel_c:: + current ( + ) const + { + // make sure requires clause is not broken + DLIB_CASSERT(this->size() != 0, + "\tconst T& queue::current" + << "\n\tsize of queue should not be zero" + << "\n\tthis: " << this + ); + + // call the real function + return queue_base::current(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename queue_base + > + typename queue_base::type& queue_kernel_c:: + current ( + ) + { + // make sure requires clause is not broken + DLIB_CASSERT(this->size() != 0, + "\tT& queue::current" + << "\n\tsize of queue should not be zero" + << "\n\tthis: " << this + ); + + // call the real function + return queue_base::current(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename queue_base + > + const typename queue_base::type& queue_kernel_c:: + element ( + ) const + { + // make sure requires clause is not broken + DLIB_CASSERT(this->current_element_valid() == true, + "\tconst T& queue::element" + << "\n\tyou can't access the current element if it doesn't exist" + << "\n\tthis: " << this + ); + + // call the real function + return queue_base::element(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename queue_base + > + typename queue_base::type& queue_kernel_c:: + element ( + ) + { + // make sure requires clause is not broken + DLIB_CASSERT(this->current_element_valid() == true, + "\tT& queue::element" + << "\n\tyou can't access the current element if it doesn't exist" + << "\n\tthis: " << this + ); + + // call the real function + return queue_base::element(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename queue_base + > + void queue_kernel_c:: + remove_any ( + T& item + ) + { + // make sure requires clause is not broken + DLIB_CASSERT( (this->size() > 0), + "\tvoid queue::remove_any" + << "\n\tsize() must be greater than zero if something is going to be removed" + << "\n\tsize(): " << this->size() + << "\n\tthis: " << this + ); + + // call the real function + queue_base::remove_any(item); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_QUEUE_KERNEl_C_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/queue/queue_sort_1.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/queue/queue_sort_1.h new file mode 100644 index 0000000..bc20dcb --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/queue/queue_sort_1.h @@ -0,0 +1,165 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_QUEUE_SORt_1_ +#define DLIB_QUEUE_SORt_1_ + +#include "queue_sort_abstract.h" +#include "../algs.h" +#include +#include "../sort.h" + +namespace dlib +{ + + template < + typename queue_base + > + class queue_sort_1 : public queue_base + { + typedef typename queue_base::type T; + + public: + + /*! + This implementation uses the QuickSort algorithm and + when the quicksort depth goes too high it uses the dlib::qsort_array() + function on the data. + !*/ + + void sort ( + ); + + template + void sort ( + const compare_type& compare + ) + { + if (this->size() > 1) + { + sort_this_queue(*this,0,compare); + } + } + + private: + + template + void sort_this_queue ( + queue_base& queue, + long depth, + const compare_type& compare + ) + /*! + ensures + each element in the queue is < the element behind it according + to compare + !*/ + { + if (queue.size() <= 1) + { + // already sorted + } + else if (queue.size() <= 29) + { + T vect[29]; + const unsigned long size = queue.size(); + for (unsigned long i = 0; i < size; ++i) + { + queue.dequeue(vect[i]); + } + isort_array(vect,0,size-1,compare); + for (unsigned long i = 0; i < size; ++i) + { + queue.enqueue(vect[i]); + } + } + else if (depth > 50) + { + std::vector vect(queue.size()); + for (unsigned long i = 0; i < vect.size(); ++i) + { + queue.dequeue(vect[i]); + } + hsort_array(vect,0,vect.size()-1,compare); + for (unsigned long i = 0; i < vect.size(); ++i) + { + queue.enqueue(vect[i]); + } + } + else + { + queue_base left, right; + T partition_element; + T temp; + // do this just to avoid a compiler warning + assign_zero_if_built_in_scalar_type(temp); + assign_zero_if_built_in_scalar_type(partition_element); + + queue.dequeue(partition_element); + + // partition queue into left and right + while (queue.size() > 0) + { + queue.dequeue(temp); + if (compare(temp , partition_element)) + { + left.enqueue(temp); + } + else + { + right.enqueue(temp); + } + } + + + long ratio; + if (left.size() > right.size()) + ratio = left.size()/(right.size()+1); // add 1 so we can't divide by zero + else + ratio = right.size()/(left.size()+1); + + sort_this_queue(left,ratio+depth,compare); + sort_this_queue(right,ratio+depth,compare); + + // combine the two queues + left.swap(queue); + queue.enqueue(partition_element); + queue.cat(right); + } + } + + + }; + + template < + typename queue_base + > + inline void swap ( + queue_sort_1& a, + queue_sort_1& b + ) { a.swap(b); } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename queue_base + > + void queue_sort_1:: + sort ( + ) + { + if (this->size() > 1) + { + sort_this_queue(*this,0,std::less()); + } + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_QUEUE_SORt_1_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/queue/queue_sort_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/queue/queue_sort_abstract.h new file mode 100644 index 0000000..54c06f4 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/queue/queue_sort_abstract.h @@ -0,0 +1,74 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_QUEUE_SORt_ABSTRACT_ +#ifdef DLIB_QUEUE_SORt_ABSTRACT_ + + +#include "queue_kernel_abstract.h" + +namespace dlib +{ + + template < + typename queue_base + > + class queue_sort : public queue_base + { + + /*! + REQUIREMENTS ON QUEUE_BASE + - is an implementation of queue/queue_kernel_abstract.h + - queue_base::type must be a type with that is comparable via operator< + + POINTERS AND REFERENCES TO INTERNAL DATA + sort() may invalidate pointers and references to internal data. + + WHAT THIS EXTENSION DOES FOR QUEUE + This gives a queue the ability to sort its contents by calling sort(). + !*/ + + + public: + + void sort ( + ); + /*! + ensures + - for all elements in #*this the ith element is <= the i+1 element + - #at_start() == true + throws + - std::bad_alloc or any exception thrown by T's constructor + data may be lost if sort() throws + !*/ + + template + void sort ( + const compare_type& compare + ); + /*! + ensures + - for all elements in #*this the ith element is <= the i+1 element + - uses compare(a,b) as the < operator. So if compare(a,b) == true + then a comes before b in the resulting ordering. + - #at_start() == true + throws + - std::bad_alloc or any exception thrown by T's constructor + data may be lost if sort() throws + !*/ + }; + + template < + template queue_base + > + inline void swap ( + queue_sort& a, + queue_sort& b + ) { a.swap(b); } + /*! + provides a global swap function + !*/ + +} + +#endif // DLIB_QUEUE_SORt_ABSTRACT_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/ref.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/ref.h new file mode 100644 index 0000000..53a37fb --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/ref.h @@ -0,0 +1,84 @@ +// Copyright (C) 2010 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_REFERENCE_WRAPpER_H_ +#define DLIB_REFERENCE_WRAPpER_H_ + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template< + typename T + > + class reference_wrapper + { + /*! + WHAT THIS OBJECT REPRESENTS + This is a simple object that just holds a reference to another object. + It is useful because it can serve as a kind of "copyable reference". + !*/ + + public: + typedef T type; + + explicit reference_wrapper(T& o) : obj(&o) {} + + operator T&() const { return *obj; } + T& get() const { return *obj; } + + private: + T* obj; + }; + +// ---------------------------------------------------------------------------------------- + + template + reference_wrapper ref( + T& obj + ) { return reference_wrapper(obj); } + /*! + ensures + - returns a reference_wrapper that contains a reference to obj. + !*/ + +// ---------------------------------------------------------------------------------------- + + template + reference_wrapper ref( + reference_wrapper obj + ) { return obj; } + /*! + ensures + - returns the given reference_wrapper object without modification + !*/ + +// ---------------------------------------------------------------------------------------- + + template + reference_wrapper cref( + const T& obj + ) { return reference_wrapper(obj); } + /*! + ensures + - returns a reference_wrapper that contains a constant reference to obj. + !*/ + +// ---------------------------------------------------------------------------------------- + + template + reference_wrapper cref( + reference_wrapper obj + ) { return cref(obj.get()); } + /*! + ensures + - converts the given reference_wrapper into a reference_wrapper that contains a + constant reference. + !*/ + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_REFERENCE_WRAPpER_H_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/revision.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/revision.h new file mode 100644 index 0000000..0c010ea --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/revision.h @@ -0,0 +1,6 @@ +#ifndef DLIB_REVISION_H +#define DLIB_MAJOR_VERSION 19 +#define DLIB_MINOR_VERSION 21 +#define DLIB_PATCH_VERSION 99 +#endif + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/serialize.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/serialize.h new file mode 100644 index 0000000..edc2a08 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/serialize.h @@ -0,0 +1,2606 @@ +// Copyright (C) 2005 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_SERIALIZe_ +#define DLIB_SERIALIZe_ + +/*! + There are two global functions in the dlib namespace that provide serialization and + deserialization support. Their signatures and specifications are as follows: + + void serialize ( + const serializable_type& item, + std::ostream& out + ); + /!* + ensures + - writes the state of item to the output stream out + - if (serializable_type implements the enumerable interface) then + - item.at_start() == true + throws + - serialization_error + This exception is thrown if there is some problem which prevents + us from successfully writing item to the output stream. + - any other exception + *!/ + + void deserialize ( + serializable_type& item, + std::istream& in + ); + /!* + ensures + - #item == a deserialized copy of the serializable_type that was + in the input stream in. + - Reads all the bytes associated with the serialized serializable_type + contained inside the input stream and no more. This means you + can serialize multiple objects to an output stream and then read + them all back in, one after another, using deserialize(). + - if (serializable_type implements the enumerable interface) then + - item.at_start() == true + throws + - serialization_error + This exception is thrown if there is some problem which prevents + us from successfully deserializing item from the input stream. + If this exception is thrown then item will have an initial value + for its type. + - any other exception + *!/ + + For convenience, you can also serialize to a file using this syntax: + serialize("your_file.dat") << some_object << another_object; + + // or to a memory buffer. + std::vector memory_buffer; + serialize(memory_buffer) << some_object << another_object; + + // or some other stream + std::ostringstream memory_buffer2; + serialize(memory_buffer2) << some_object << another_object; + + That overwrites the contents of your_file.dat with the serialized data from some_object + and another_object. Then to recall the objects from the file you can do: + deserialize("your_file.dat") >> some_object >> another_object; + // or from a memory buffer or another stream called memory_buffer. + deserialize(memory_buffer) >> some_object >> another_object; + + Finally, you can chain as many objects together using the << and >> operators as you + like. + + + This file provides serialization support to the following object types: + - The C++ base types (NOT including raw pointer) + - std::string + - std::wstring + - std::vector + - std::list + - std::forward_list + - std::array + - std::deque + - std::map + - std::unordered_map + - std::multimap + - std::unordered_multimap + - std::set + - std::unordered_set + - std::multiset + - std::unordered_multiset + - std::pair + - std::tuple + - std::complex + - std::unique_ptr + - std::shared_ptr + - dlib::uint64 + - dlib::int64 + - float_details + - enumerable where T is a serializable type + - map_pair where D and R are both serializable types. + - C style arrays of serializable types + - Google protocol buffer objects. + + This file provides deserialization support to the following object types: + - The C++ base types (NOT including raw pointers) + - std::string + - std::wstring + - std::vector + - std::list + - std::forward_list + - std::array + - std::deque + - std::map + - std::unordered_map + - std::multimap + - std::unordered_multimap + - std::set + - std::unordered_set + - std::multiset + - std::unordered_multiset + - std::pair + - std::tuple + - std::complex + - std::unique_ptr + - std::shared_ptr + - dlib::uint64 + - dlib::int64 + - float_details + - C style arrays of serializable types + - Google protocol buffer objects. + + Support for deserialization of objects which implement the enumerable or + map_pair interfaces is the responsibility of those objects. + + Note that you can deserialize an integer value to any integral type (except for a + char type) if its value will fit into the target integer type. I.e. the types + short, int, long, unsigned short, unsigned int, unsigned long, and dlib::uint64 + can all receive serialized data from each other so long as the actual serialized + value fits within the receiving integral type's range. + + Also note that for any container to be serializable the type of object it contains + must be serializable. + + FILE STREAMS + If you are serializing to and from file streams it is important to + remember to set the file streams to binary mode using the std::ios::binary + flag. + + + INTEGRAL SERIALIZATION FORMAT + All C++ integral types (except the char types) are serialized to the following + format: + The first byte is a control byte. It tells you if the serialized number is + positive or negative and also tells you how many of the following bytes are + part of the number. The absolute value of the number is stored in little + endian byte order and follows the control byte. + + The control byte: + The high order bit of the control byte is a flag that tells you if the + encoded number is negative or not. It is set to 1 when the number is + negative and 0 otherwise. + The 4 low order bits of the control byte represent an unsigned number + and tells you how many of the following bytes are part of the encoded + number. + + bool SERIALIZATION FORMAT + A bool value is serialized as the single byte character '1' or '0' in ASCII. + Where '1' indicates true and '0' indicates false. + + FLOATING POINT SERIALIZATION FORMAT + To serialize a floating point value we convert it into a float_details object and + then serialize the exponent and mantissa values using dlib's integral serialization + format. Therefore, the output is first the exponent and then the mantissa. Note that + the mantissa is a signed integer (i.e. there is not a separate sign bit). + + + MAKING YOUR OWN CUSTOM OBJECTS SERIALIZABLE + Suppose you create your own type, my_custom_type, and you want it to be serializable. I.e. + you want to be able to use the tools above to save and load it. E.g. maybe you have a + std::vector you wish to save. + + To make my_custom_type properly serializable all you have to do is define global serialize + and deserialize functions **IN THE SAME NAMESPACE AS MY_CUSTOM_TYPE**. You must define them + in your namespace so that argument dependent lookup will be able to find them. So your code + might look like this: + + namespace your_namespace + { + struct my_custom_type + { + int a; + float b; + std::vector c; + }; + void serialize (const my_custom_type& item, std::ostream& out); + void deserialize (my_custom_type& item, std::istream& in); + } + + That's all you need to do. You may optionally avail yourself of the + DLIB_DEFINE_DEFAULT_SERIALIZATION macro, which generates global friend serialize and + deserialize functions for you. In that case you would do this instead: + + namespace your_namespace + { + struct my_custom_type + { + int a; + float b; + std::vector c; + + DLIB_DEFINE_DEFAULT_SERIALIZATION(my_custom_type, a, b, c); + }; + } + +!*/ + + +#include "algs.h" +#include "assert.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "uintn.h" +#include "interfaces/enumerable.h" +#include "interfaces/map_pair.h" +#include "enable_if.h" +#include "unicode.h" +#include "byte_orderer.h" +#include "float_details.h" +#include "vectorstream.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class serialization_error : public error + { + /*! + WHAT THIS OBJECT REPRESENTS + This is the exception object. It is thrown if serialization or + deserialization fails. + !*/ + + public: + serialization_error(const std::string& e):error(e) {} + }; + + + void check_serialized_version( + const std::string& expected_version, + std::istream& in + ); + /*! + ensures + - Deserializes a string from in and if it doesn't match expected_version we + throw serialization_error. + !*/ + +// ---------------------------------------------------------------------------------------- + + /*!A ramdump information !*/ + template + struct ramdump_t + { + /*! + WHAT THIS OBJECT REPRESENTS + This is a type decoration used to indicate that serialization should be + done by simply dumping the memory of some object to disk as fast as + possible without any sort of conversions. This means that the data written + will be "non-portable" in the sense that the format output by a RAM dump + may depend on things like the endianness of your CPU or settings of certain + compiler switches. + + You use this object like this: + serialize("yourfile.dat") << ramdump(yourobject); + deserialize("yourfile.dat") >> ramdump(yourobject); + or + serialize(ramdump(yourobject), out); + deserialize(ramdump(yourobject), in); + + Also, not all objects have a ramdump mode. If you try to use ramdump on an + object that does not define a serialization dump for ramdump you will get a + compiler error. + !*/ + ramdump_t(T& item_) : item(item_) {} + T& item; + }; + + // This function just makes a ramdump that wraps an object. + template + ramdump_t::type> ramdump(T&& item) + { + return ramdump_t::type>(item); + } + + + template < + typename T + > + void serialize ( + const ramdump_t& item_, + std::ostream& out + ) + { + // Move the const from inside the ramdump_t template to outside so we can bind + // against a serialize() call that takes just a const ramdump_t. Doing this + // saves you from needing to write multiple overloads of serialize() to handle + // these different const placement cases. + const auto temp = ramdump(const_cast(item_.item)); + serialize(temp, out); + } + +// ---------------------------------------------------------------------------------------- + + namespace ser_helper + { + + template < + typename T + > + typename enable_if_c::is_signed,bool>::type pack_int ( + T item, + std::ostream& out + ) + /*! + requires + - T is a signed integral type + ensures + - if (no problems occur serializing item) then + - writes item to out + - returns false + - else + - returns true + !*/ + { + COMPILE_TIME_ASSERT(sizeof(T) <= 8); + unsigned char buf[9]; + unsigned char size = sizeof(T); + unsigned char neg; + if (item < 0) + { + neg = 0x80; + item *= -1; + } + else + { + neg = 0; + } + + for (unsigned char i = 1; i <= sizeof(T); ++i) + { + buf[i] = static_cast(item&0xFF); + item >>= 8; + if (item == 0) { size = i; break; } + } + + std::streambuf* sbuf = out.rdbuf(); + buf[0] = size|neg; + if (sbuf->sputn(reinterpret_cast(buf),size+1) != size+1) + { + out.setstate(std::ios::eofbit | std::ios::badbit); + return true; + } + + return false; + } + + // ------------------------------------------------------------------------------------ + + template < + typename T + > + typename enable_if_c::is_signed,bool>::type unpack_int ( + T& item, + std::istream& in + ) + /*! + requires + - T is a signed integral type + ensures + - if (there are no problems deserializing item) then + - returns false + - #item == the value stored in in + - else + - returns true + + !*/ + { + COMPILE_TIME_ASSERT(sizeof(T) <= 8); + + + unsigned char buf[8]; + unsigned char size; + bool is_negative; + + std::streambuf* sbuf = in.rdbuf(); + + item = 0; + int ch = sbuf->sbumpc(); + if (ch != EOF) + { + size = static_cast(ch); + } + else + { + in.setstate(std::ios::badbit); + return true; + } + + if (size&0x80) + is_negative = true; + else + is_negative = false; + size &= 0x0F; + + // check if the serialized object is too big + if (size > (unsigned long)tmin::value || size == 0) + { + return true; + } + + if (sbuf->sgetn(reinterpret_cast(&buf),size) != size) + { + in.setstate(std::ios::badbit); + return true; + } + + + for (unsigned char i = size-1; true; --i) + { + item <<= 8; + item |= buf[i]; + if (i == 0) + break; + } + + if (is_negative) + item *= -1; + + + return false; + } + + // ------------------------------------------------------------------------------------ + + template < + typename T + > + typename disable_if_c::is_signed,bool>::type pack_int ( + T item, + std::ostream& out + ) + /*! + requires + - T is an unsigned integral type + ensures + - if (no problems occur serializing item) then + - writes item to out + - returns false + - else + - returns true + !*/ + { + COMPILE_TIME_ASSERT(sizeof(T) <= 8); + unsigned char buf[9]; + unsigned char size = sizeof(T); + + for (unsigned char i = 1; i <= sizeof(T); ++i) + { + buf[i] = static_cast(item&0xFF); + item >>= 8; + if (item == 0) { size = i; break; } + } + + std::streambuf* sbuf = out.rdbuf(); + buf[0] = size; + if (sbuf->sputn(reinterpret_cast(buf),size+1) != size+1) + { + out.setstate(std::ios::eofbit | std::ios::badbit); + return true; + } + + return false; + } + + // ------------------------------------------------------------------------------------ + + template < + typename T + > + typename disable_if_c::is_signed,bool>::type unpack_int ( + T& item, + std::istream& in + ) + /*! + requires + - T is an unsigned integral type + ensures + - if (there are no problems deserializing item) then + - returns false + - #item == the value stored in in + - else + - returns true + + !*/ + { + COMPILE_TIME_ASSERT(sizeof(T) <= 8); + + unsigned char buf[8]; + unsigned char size; + + item = 0; + + std::streambuf* sbuf = in.rdbuf(); + int ch = sbuf->sbumpc(); + if (ch != EOF) + { + size = static_cast(ch); + } + else + { + in.setstate(std::ios::badbit); + return true; + } + + + // mask out the 3 reserved bits + size &= 0x8F; + + // check if an error occurred + if (size > (unsigned long)tmin::value || size == 0) + return true; + + + if (sbuf->sgetn(reinterpret_cast(&buf),size) != size) + { + in.setstate(std::ios::badbit); + return true; + } + + for (unsigned char i = size-1; true; --i) + { + item <<= 8; + item |= buf[i]; + if (i == 0) + break; + } + + return false; + } + + } + +// ---------------------------------------------------------------------------------------- + + #define USE_DEFAULT_INT_SERIALIZATION_FOR(T) \ + inline void serialize (const T& item, std::ostream& out) \ + { if (ser_helper::pack_int(item,out)) throw serialization_error("Error serializing object of type " + std::string(#T)); } \ + inline void deserialize (T& item, std::istream& in) \ + { if (ser_helper::unpack_int(item,in)) throw serialization_error("Error deserializing object of type " + std::string(#T)); } + + template + inline bool pack_byte ( + const T& ch, + std::ostream& out + ) + { + std::streambuf* sbuf = out.rdbuf(); + return (sbuf->sputc((char)ch) == EOF); + } + + template + inline bool unpack_byte ( + T& ch, + std::istream& in + ) + { + std::streambuf* sbuf = in.rdbuf(); + int temp = sbuf->sbumpc(); + if (temp != EOF) + { + ch = static_cast(temp); + return false; + } + else + { + return true; + } + } + + #define USE_DEFAULT_BYTE_SERIALIZATION_FOR(T) \ + inline void serialize (const T& item,std::ostream& out) \ + { if (pack_byte(item,out)) throw serialization_error("Error serializing object of type " + std::string(#T)); } \ + inline void deserialize (T& item, std::istream& in) \ + { if (unpack_byte(item,in)) throw serialization_error("Error deserializing object of type " + std::string(#T)); } + +// ---------------------------------------------------------------------------------------- + + USE_DEFAULT_INT_SERIALIZATION_FOR(short) + USE_DEFAULT_INT_SERIALIZATION_FOR(int) + USE_DEFAULT_INT_SERIALIZATION_FOR(long) + USE_DEFAULT_INT_SERIALIZATION_FOR(unsigned short) + USE_DEFAULT_INT_SERIALIZATION_FOR(unsigned int) + USE_DEFAULT_INT_SERIALIZATION_FOR(unsigned long) + USE_DEFAULT_INT_SERIALIZATION_FOR(uint64) + USE_DEFAULT_INT_SERIALIZATION_FOR(int64) + + USE_DEFAULT_BYTE_SERIALIZATION_FOR(char) + USE_DEFAULT_BYTE_SERIALIZATION_FOR(signed char) + USE_DEFAULT_BYTE_SERIALIZATION_FOR(unsigned char) + + // Don't define serialization for wchar_t when using visual studio and + // _NATIVE_WCHAR_T_DEFINED isn't defined since if it isn't they improperly set + // wchar_t to be a typedef rather than its own type as required by the C++ + // standard. +#if !defined(_MSC_VER) || _NATIVE_WCHAR_T_DEFINED + USE_DEFAULT_INT_SERIALIZATION_FOR(wchar_t) +#endif + +// ---------------------------------------------------------------------------------------- + + inline void serialize( + const float_details& item, + std::ostream& out + ) + { + serialize(item.mantissa, out); + serialize(item.exponent, out); + } + + inline void deserialize( + float_details& item, + std::istream& in + ) + { + deserialize(item.mantissa, in); + deserialize(item.exponent, in); + } + +// ---------------------------------------------------------------------------------------- + + template + inline void serialize_floating_point ( + const T& item, + std::ostream& out + ) + { + try + { + float_details temp = item; + serialize(temp, out); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing a floating point number."); } + } + + template + inline bool old_deserialize_floating_point ( + T& item, + std::istream& in + ) + { + std::ios::fmtflags oldflags = in.flags(); + in.flags(static_cast(0)); + std::streamsize ss = in.precision(35); + if (in.peek() == 'i') + { + item = std::numeric_limits::infinity(); + in.get(); + in.get(); + in.get(); + } + else if (in.peek() == 'n') + { + item = -std::numeric_limits::infinity(); + in.get(); + in.get(); + in.get(); + in.get(); + } + else if (in.peek() == 'N') + { + item = std::numeric_limits::quiet_NaN(); + in.get(); + in.get(); + in.get(); + } + else + { + in >> item; + } + in.flags(oldflags); + in.precision(ss); + return (in.get() != ' '); + } + + template + inline void deserialize_floating_point ( + T& item, + std::istream& in + ) + { + // check if the serialized data uses the older ASCII based format. We can check + // this easily because the new format starts with the integer control byte which + // always has 0 bits in the positions corresponding to the bitmask 0x70. Moreover, + // since the previous format used ASCII numbers we know that no valid bytes can + // have bit values of one in the positions indicated 0x70. So this test looks at + // the first byte and checks if the serialized data uses the old format or the new + // format. + if ((in.rdbuf()->sgetc()&0x70) == 0) + { + try + { + // Use the fast and compact binary serialization format. + float_details temp; + deserialize(temp, in); + item = temp; + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing a floating point number."); } + } + else + { + if (old_deserialize_floating_point(item, in)) + throw serialization_error("Error deserializing a floating point number."); + } + } + + inline void serialize ( const float& item, std::ostream& out) + { + serialize_floating_point(item,out); + } + + inline void deserialize (float& item, std::istream& in) + { + deserialize_floating_point(item,in); + } + + inline void serialize ( const double& item, std::ostream& out) + { + serialize_floating_point(item,out); + } + + inline void deserialize (double& item, std::istream& in) + { + deserialize_floating_point(item,in); + } + + inline void serialize ( const long double& item, std::ostream& out) + { + serialize_floating_point(item,out); + } + + inline void deserialize ( long double& item, std::istream& in) + { + deserialize_floating_point(item,in); + } + +// ---------------------------------------------------------------------------------------- +// prototypes + + template + void serialize ( + const std::map& item, + std::ostream& out + ); + + template + void deserialize ( + std::map& item, + std::istream& in + ); + + template + void serialize ( + const std::unordered_map& item, + std::ostream& out + ); + + template + void deserialize ( + std::unordered_map& item, + std::istream& in + ); + + template + void serialize ( + const std::multimap& item, + std::ostream& out + ); + + template + void deserialize ( + std::multimap& item, + std::istream& in + ); + + template + void serialize ( + const std::unordered_multimap& item, + std::ostream& out + ); + + template + void deserialize ( + std::unordered_multimap& item, + std::istream& in + ); + + template + void serialize ( + const std::set& item, + std::ostream& out + ); + + template + void deserialize ( + std::set& item, + std::istream& in + ); + + template + void serialize ( + const std::unordered_set& item, + std::ostream& out + ); + + template + void deserialize ( + std::unordered_set& item, + std::istream& in + ); + + template + void serialize ( + const std::multiset& item, + std::ostream& out + ); + + template + void deserialize ( + std::multiset& item, + std::istream& in + ); + + template + void serialize ( + const std::unordered_multiset& item, + std::ostream& out + ); + + template + void deserialize ( + std::unordered_multiset& item, + std::istream& in + ); + + template + void serialize ( + const std::vector& item, + std::ostream& out + ); + + template + void deserialize ( + std::vector& item, + std::istream& in + ); + + template + void serialize ( + const std::list& item, + std::ostream& out + ); + + template + void deserialize ( + std::list& item, + std::istream& in + ); + + template + void serialize ( + const std::forward_list& item, + std::ostream& out + ); + + template + void deserialize ( + std::forward_list& item, + std::istream& in + ); + + template + void serialize ( + const std::deque& item, + std::ostream& out + ); + + template + void deserialize ( + std::deque& item, + std::istream& in + ); + + template + void serialize ( + const std::tuple& item, + std::ostream& out + ); + + template + void deserialize ( + std::tuple& item, + std::istream& in + ); + + template + void serialize ( + const std::unique_ptr& item, + std::ostream& out + ); + + template + void deserialize ( + std::unique_ptr& item, + std::istream& in + ); + + template + void serialize ( + const std::shared_ptr& item, + std::ostream& out + ); + + template + void deserialize ( + std::shared_ptr& item, + std::istream& in + ); + + inline void serialize ( + const std::string& item, + std::ostream& out + ); + + inline void deserialize ( + std::string& item, + std::istream& in + ); + + inline void serialize ( + const std::wstring& item, + std::ostream& out + ); + + inline void deserialize ( + std::wstring& item, + std::istream& in + ); + + inline void serialize ( + const ustring& item, + std::ostream& out + ); + + inline void deserialize ( + ustring& item, + std::istream& in + ); + + template < + typename T + > + inline void serialize ( + const enumerable& item, + std::ostream& out + ); + + template < + typename domain, + typename range + > + inline void serialize ( + const map_pair& item, + std::ostream& out + ); + + template < + typename T, + size_t length + > + inline void serialize ( + const T (&array)[length], + std::ostream& out + ); + + template < + typename T, + size_t length + > + inline void deserialize ( + T (&array)[length], + std::istream& in + ); + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + inline void serialize ( + bool item, + std::ostream& out + ) + { + if (item) + out << '1'; + else + out << '0'; + + if (!out) + throw serialization_error("Error serializing object of type bool"); + } + + inline void deserialize ( + bool& item, + std::istream& in + ) + { + int ch = in.get(); + if (ch != EOF) + { + if (ch == '1') + item = true; + else if (ch == '0') + item = false; + else + throw serialization_error("Error deserializing object of type bool"); + } + else + { + throw serialization_error("Error deserializing object of type bool"); + } + } + +// ---------------------------------------------------------------------------------------- + + template + void serialize ( + const std::pair& item, + std::ostream& out + ) + { + try + { + serialize(item.first,out); + serialize(item.second,out); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing object of type std::pair"); } + } + + template + void deserialize ( + std::pair& item, + std::istream& in + ) + { + try + { + deserialize(item.first,in); + deserialize(item.second,in); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing object of type std::pair"); } + } + +// ---------------------------------------------------------------------------------------- + + template + inline typename std::enable_if::type + for_each_in_tuple(std::tuple&, FuncT) + {} + + template + inline typename std::enable_if::type + for_each_in_tuple(std::tuple& t, FuncT f) + { + f(std::get(t)); + for_each_in_tuple(t, f); + } + + template + inline typename std::enable_if::type + for_each_in_tuple(const std::tuple&, FuncT) + {} + + template + inline typename std::enable_if::type + for_each_in_tuple(const std::tuple& t, FuncT f) + { + f(std::get(t)); + for_each_in_tuple(t, f); + } + + struct serialize_tuple_helper + { + serialize_tuple_helper(std::ostream& out_) : out(out_) {} + + template + void operator()(const T& item) + { + serialize(item, out); + } + + std::ostream& out; + }; + + struct deserialize_tuple_helper + { + deserialize_tuple_helper(std::istream& in_) : in(in_) {} + + template + void operator()(T& item) + { + deserialize(item, in); + } + + std::istream& in; + }; + + template + void serialize ( + const std::tuple& item, + std::ostream& out + ) + { + try + { + for_each_in_tuple(item, serialize_tuple_helper(out)); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing object of type std::tuple"); } + } + + template + void deserialize ( + std::tuple& item, + std::istream& in + ) + { + try + { + for_each_in_tuple(item, deserialize_tuple_helper(in)); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing object of type std::tuple"); } + } + +// ---------------------------------------------------------------------------------------- + + template + void serialize ( + const std::map& item, + std::ostream& out + ) + { + try + { + const unsigned long size = static_cast(item.size()); + + serialize(size,out); + typename std::map::const_iterator i; + for (i = item.begin(); i != item.end(); ++i) + { + serialize(i->first,out); + serialize(i->second,out); + } + + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing object of type std::map"); } + } + + template + void deserialize ( + std::map& item, + std::istream& in + ) + { + try + { + item.clear(); + + unsigned long size; + deserialize(size,in); + domain d; + range r; + for (unsigned long i = 0; i < size; ++i) + { + deserialize(d,in); + deserialize(r,in); + item[d] = r; + } + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing object of type std::map"); } + } + +// ---------------------------------------------------------------------------------------- + + template + void serialize ( + const std::unordered_map& item, + std::ostream& out + ) + { + try + { + serialize(item.size(),out); + for (const auto& x : item) + { + serialize(x.first,out); + serialize(x.second,out); + } + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing object of type std::unordered_map"); } + } + + template + void deserialize ( + std::unordered_map& item, + std::istream& in + ) + { + try + { + item.clear(); + std::size_t size; + deserialize(size,in); + domain d; + range r; + for (unsigned long i = 0; i < size; ++i) + { + deserialize(d,in); + deserialize(r,in); + item[d] = r; + } + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing object of type std::unordered_map"); } + } + +// ---------------------------------------------------------------------------------------- + + template + void serialize ( + const std::multimap& item, + std::ostream& out + ) + { + try + { + serialize(item.size(),out); + for (const auto& x : item) + { + serialize(x.first,out); + serialize(x.second,out); + } + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing object of type std::multimap"); } + } + + template + void deserialize ( + std::multimap& item, + std::istream& in + ) + { + try + { + item.clear(); + std::size_t size; + deserialize(size,in); + domain d; + range r; + for (unsigned long i = 0; i < size; ++i) + { + deserialize(d,in); + deserialize(r,in); + item.insert({d,r}); + } + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing object of type std::multimap"); } + } + +// ---------------------------------------------------------------------------------------- + + template + void serialize ( + const std::unordered_multimap& item, + std::ostream& out + ) + { + try + { + serialize(item.size(),out); + for (const auto& x : item) + { + serialize(x.first,out); + serialize(x.second,out); + } + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing object of type std::unordered_multimap"); } + } + + template + void deserialize ( + std::unordered_multimap& item, + std::istream& in + ) + { + try + { + item.clear(); + std::size_t size; + deserialize(size,in); + domain d; + range r; + for (unsigned long i = 0; i < size; ++i) + { + deserialize(d,in); + deserialize(r,in); + item.insert({d,r}); + } + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing object of type std::unordered_multimap"); } + } + +// ---------------------------------------------------------------------------------------- + + template + void serialize ( + const std::set& item, + std::ostream& out + ) + { + try + { + const unsigned long size = static_cast(item.size()); + + serialize(size,out); + typename std::set::const_iterator i; + for (i = item.begin(); i != item.end(); ++i) + { + serialize(*i,out); + } + + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing object of type std::set"); } + } + + template + void deserialize ( + std::set& item, + std::istream& in + ) + { + try + { + item.clear(); + + unsigned long size; + deserialize(size,in); + domain d; + for (unsigned long i = 0; i < size; ++i) + { + deserialize(d,in); + item.insert(d); + } + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing object of type std::set"); } + } + +// ---------------------------------------------------------------------------------------- + + template + void serialize ( + const std::unordered_set& item, + std::ostream& out + ) + { + try + { + serialize(item.size(),out); + for (const auto& x : item) + serialize(x,out); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing object of type std::unordered_set"); } + } + + template + void deserialize ( + std::unordered_set& item, + std::istream& in + ) + { + try + { + item.clear(); + std::size_t size; + deserialize(size,in); + domain d; + for (unsigned long i = 0; i < size; ++i) + { + deserialize(d,in); + item.insert(d); + } + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing object of type std::unordered_set"); } + } + +// ---------------------------------------------------------------------------------------- + + template + void serialize ( + const std::multiset& item, + std::ostream& out + ) + { + try + { + serialize(item.size(),out); + for (const auto& x : item) + serialize(x,out); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing object of type std::multiset"); } + } + + template + void deserialize ( + std::multiset& item, + std::istream& in + ) + { + try + { + item.clear(); + std::size_t size; + deserialize(size,in); + domain d; + for (unsigned long i = 0; i < size; ++i) + { + deserialize(d,in); + item.insert(d); + } + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing object of type std::multiset"); } + } + +// ---------------------------------------------------------------------------------------- + + template + void serialize ( + const std::unordered_multiset& item, + std::ostream& out + ) + { + try + { + serialize(item.size(),out); + for (const auto& x : item) + serialize(x,out); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing object of type std::unordered_multiset"); } + } + + template + void deserialize ( + std::unordered_multiset& item, + std::istream& in + ) + { + try + { + item.clear(); + std::size_t size; + deserialize(size,in); + domain d; + for (unsigned long i = 0; i < size; ++i) + { + deserialize(d,in); + item.insert(d); + } + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing object of type std::unordered_multiset"); } + } + +// ---------------------------------------------------------------------------------------- + + template + void serialize ( + const std::vector& item, + std::ostream& out + ) + { + std::vector temp(item.size()); + for (unsigned long i = 0; i < item.size(); ++i) + { + if (item[i]) + temp[i] = '1'; + else + temp[i] = '0'; + } + serialize(temp, out); + } + + template + void deserialize ( + std::vector& item, + std::istream& in + ) + { + std::vector temp; + deserialize(temp, in); + item.resize(temp.size()); + for (unsigned long i = 0; i < temp.size(); ++i) + { + if (temp[i] == '1') + item[i] = true; + else + item[i] = false; + } + } + +// ---------------------------------------------------------------------------------------- + + template + void serialize ( + const std::vector& item, + std::ostream& out + ) + { + try + { + const unsigned long size = static_cast(item.size()); + + serialize(size,out); + for (unsigned long i = 0; i < item.size(); ++i) + serialize(item[i],out); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing object of type std::vector"); } + } + + template + void deserialize ( + std::vector& item, + std::istream& in + ) + { + try + { + unsigned long size; + deserialize(size,in); + item.resize(size); + for (unsigned long i = 0; i < size; ++i) + deserialize(item[i],in); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing object of type std::vector"); } + } + +// ---------------------------------------------------------------------------------------- + + template + void serialize ( + const std::vector& item, + std::ostream& out + ) + { + try + { + const unsigned long size = static_cast(item.size()); + serialize(size,out); + if (item.size() != 0) + out.write(&item[0], item.size()); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing object of type std::vector"); } + } + + template + void deserialize ( + std::vector& item, + std::istream& in + ) + { + try + { + unsigned long size; + deserialize(size,in); + item.resize(size); + if (item.size() != 0) + in.read(&item[0], item.size()); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing object of type std::vector"); } + } + +// ---------------------------------------------------------------------------------------- + + template + void serialize ( + const std::vector& item, + std::ostream& out + ) + { + try + { + const unsigned long size = static_cast(item.size()); + serialize(size,out); + if (item.size() != 0) + out.write((char*)&item[0], item.size()); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing object of type std::vector"); } + } + + template + void deserialize ( + std::vector& item, + std::istream& in + ) + { + try + { + unsigned long size; + deserialize(size,in); + item.resize(size); + if (item.size() != 0) + in.read((char*)&item[0], item.size()); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing object of type std::vector"); } + } + +// ---------------------------------------------------------------------------------------- + + template + void serialize ( + const std::list& item, + std::ostream& out + ) + { + try + { + const unsigned long size = static_cast(item.size()); + serialize(size,out); + for (const auto& x : item) + serialize(x, out); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing object of type std::list"); } + } + + template + void deserialize ( + std::list& item, + std::istream& in + ) + { + try + { + unsigned long size; + deserialize(size, in); + item.resize(size); + for (auto& x : item) + deserialize(x, in); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing object of type std::list"); } + } + +// ---------------------------------------------------------------------------------------- + + template + void serialize ( + const std::forward_list& item, + std::ostream& out + ) + { + try + { + const unsigned long size = std::distance(item.begin(), item.end()); + serialize(size,out); + for (const auto& x : item) + serialize(x, out); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing object of type std::forward_list"); } + } + + template + void deserialize ( + std::forward_list& item, + std::istream& in + ) + { + try + { + unsigned long size; + deserialize(size,in); + item.resize(size); + for (auto& x : item) + deserialize(x,in); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing object of type std::forward_list"); } + } + +// ---------------------------------------------------------------------------------------- + + template + void serialize ( + const std::deque& item, + std::ostream& out + ) + { + try + { + const unsigned long size = static_cast(item.size()); + + serialize(size,out); + for (unsigned long i = 0; i < item.size(); ++i) + serialize(item[i],out); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing object of type std::deque"); } + } + + template + void deserialize ( + std::deque& item, + std::istream& in + ) + { + try + { + unsigned long size; + deserialize(size,in); + item.resize(size); + for (unsigned long i = 0; i < size; ++i) + deserialize(item[i],in); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing object of type std::deque"); } + } + +// ---------------------------------------------------------------------------------------- + + inline void serialize ( + const std::string& item, + std::ostream& out + ) + { + const unsigned long size = static_cast(item.size()); + try{ serialize(size,out); } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing object of type std::string"); } + + out.write(item.c_str(),size); + if (!out) throw serialization_error("Error serializing object of type std::string"); + } + + inline void deserialize ( + std::string& item, + std::istream& in + ) + { + unsigned long size; + try { deserialize(size,in); } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing object of type std::string"); } + + item.resize(size); + if (size != 0) + { + in.read(&item[0],size); + if (!in) throw serialization_error("Error deserializing object of type std::string"); + } + } + +// ---------------------------------------------------------------------------------------- + + inline void serialize ( + const std::wstring& item, + std::ostream& out + ) + { + const unsigned long size = static_cast(item.size()); + try{ serialize(size,out); } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing object of type std::wstring"); } + + for (unsigned long i = 0; i < item.size(); ++i) + serialize(item[i], out); + if (!out) throw serialization_error("Error serializing object of type std::wstring"); + } + + inline void deserialize ( + std::wstring& item, + std::istream& in + ) + { + unsigned long size; + try { deserialize(size,in); } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing object of type std::wstring"); } + + item.resize(size); + for (unsigned long i = 0; i < item.size(); ++i) + deserialize(item[i],in); + + if (!in) throw serialization_error("Error deserializing object of type std::wstring"); + } + +// ---------------------------------------------------------------------------------------- + + inline void serialize ( + const ustring& item, + std::ostream& out + ) + { + const unsigned long size = static_cast(item.size()); + try{ serialize(size,out); } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing object of type ustring"); } + + for (unsigned long i = 0; i < item.size(); ++i) + serialize(item[i], out); + if (!out) throw serialization_error("Error serializing object of type ustring"); + } + + inline void deserialize ( + ustring& item, + std::istream& in + ) + { + unsigned long size; + try { deserialize(size,in); } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing object of type ustring"); } + + item.resize(size); + for (unsigned long i = 0; i < item.size(); ++i) + deserialize(item[i],in); + + if (!in) throw serialization_error("Error deserializing object of type ustring"); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + inline void serialize ( + const enumerable& item, + std::ostream& out + ) + { + try + { + item.reset(); + serialize(item.size(),out); + while (item.move_next()) + serialize(item.element(),out); + item.reset(); + } + catch (serialization_error& e) + { + throw serialization_error(e.info + "\n while serializing object of type enumerable"); + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename domain, + typename range + > + inline void serialize ( + const map_pair& item, + std::ostream& out + ) + { + try + { + serialize(item.key(),out); + serialize(item.value(),out); + } + catch (serialization_error& e) + { + throw serialization_error(e.info + "\n while serializing object of type map_pair"); + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + size_t length + > + inline void serialize ( + const T (&array)[length], + std::ostream& out + ) + { + try + { + serialize(length,out); + for (size_t i = 0; i < length; ++i) + serialize(array[i],out); + } + catch (serialization_error& e) + { + throw serialization_error(e.info + "\n while serializing a C style array"); + } + } + + template < + size_t length + > + inline void serialize ( + const char (&array)[length], + std::ostream& out + ) + { + if (length != 0 && array[length-1] == '\0') + { + // If this is a null terminated string then don't serialize the trailing null. + // We do this so that the serialization format for C-strings is the same as + // std::string. + serialize(length-1, out); + out.write(array, length-1); + if (!out) + throw serialization_error("Error serializing a C-style string"); + } + else + { + try + { + serialize(length,out); + } + catch (serialization_error& e) + { + throw serialization_error(e.info + "\n while serializing a C style array"); + } + if (length != 0) + out.write(array, length); + if (!out) + throw serialization_error("Error serializing a C-style string"); + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + size_t length + > + inline void deserialize ( + T (&array)[length], + std::istream& in + ) + { + size_t size; + try + { + deserialize(size,in); + if (size == length) + { + for (size_t i = 0; i < length; ++i) + deserialize(array[i],in); + } + } + catch (serialization_error& e) + { + throw serialization_error(e.info + "\n while deserializing a C style array"); + } + + if (size != length) + throw serialization_error("Error deserializing a C style array, lengths do not match"); + } + + template < + size_t length + > + inline void deserialize ( + char (&array)[length], + std::istream& in + ) + { + size_t size; + try + { + deserialize(size,in); + } + catch (serialization_error& e) + { + throw serialization_error(e.info + "\n while deserializing a C style array"); + } + + if (size == length) + { + in.read(array, size); + if (!in) + throw serialization_error("Error deserializing a C-style array"); + } + else if (size+1 == length) + { + // In this case we are deserializing a C-style array so we need to add the null + // terminator. + in.read(array, size); + array[size] = '\0'; + if (!in) + throw serialization_error("Error deserializing a C-style string"); + } + else + { + throw serialization_error("Error deserializing a C style array, lengths do not match"); + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + size_t N + > + inline void serialize ( + const std::array& array, + std::ostream& out + ) + { + typedef T c_array_type[N]; + serialize(*(const c_array_type*)array.data(), out); + } + + template < + typename T, + size_t N + > + inline void deserialize ( + std::array& array, + std::istream& in + ) + { + typedef T c_array_type[N]; + deserialize(*(c_array_type*)array.data(), in); + } + + template < + typename T + > + inline void serialize ( + const std::array& /*array*/, + std::ostream& out + ) + { + size_t N = 0; + serialize(N, out); + } + + template < + typename T + > + inline void deserialize ( + std::array& /*array*/, + std::istream& in + ) + { + size_t N; + deserialize(N, in); + if (N != 0) + { + std::ostringstream sout; + sout << "Expected std::array of size 0 but found a size of " << N; + throw serialization_error(sout.str()); + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + inline void serialize ( + const std::complex& item, + std::ostream& out + ) + { + try + { + serialize(item.real(),out); + serialize(item.imag(),out); + } + catch (serialization_error& e) + { + throw serialization_error(e.info + "\n while serializing an object of type std::complex"); + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + inline void deserialize ( + std::complex& item, + std::istream& in + ) + { + try + { + T real, imag; + deserialize(real,in); + deserialize(imag,in); + item = std::complex(real,imag); + } + catch (serialization_error& e) + { + throw serialization_error(e.info + "\n while deserializing an object of type std::complex"); + } + } + +// ---------------------------------------------------------------------------------------- + + template + void serialize ( + const std::unique_ptr& item, + std::ostream& out + ) + { + try + { + bool is_non_empty = item != nullptr; + serialize(is_non_empty, out); + if (is_non_empty) + serialize(*item, out); + } + catch (serialization_error& e) + { + throw serialization_error(e.info + "\n while serializing an object of type std::unique_ptr"); + } + } + + template + void deserialize ( + std::unique_ptr& item, + std::istream& in + ) + { + try + { + //when deserializing unique_ptr, this is fresh state, so reset the pointers, even if item is non-empty + bool is_non_empty; + deserialize(is_non_empty, in); + item.reset(is_non_empty ? new T() : nullptr); //can't use make_unique since dlib does not use C++14 as a minimum requirement. + + if (is_non_empty) + deserialize(*item, in); + } + catch (serialization_error& e) + { + throw serialization_error(e.info + "\n while deserializing an object of type std::unique_ptr"); + } + } + +// ---------------------------------------------------------------------------------------- + + template + void serialize ( + const std::shared_ptr& item, + std::ostream& out + ) + { + try + { + bool is_non_empty = item != nullptr; + serialize(is_non_empty, out); + if (is_non_empty) + serialize(*item, out); + } + catch (serialization_error& e) + { + throw serialization_error(e.info + "\n while serializing an object of type std::shared_ptr"); + } + } + + template + void deserialize ( + std::shared_ptr& item, + std::istream& in + ) + { + try + { + //when deserializing shared_ptr, this is fresh state, so reset the pointers, even if item is non-empty + bool is_non_empty; + deserialize(is_non_empty, in); + item = is_non_empty ? std::make_shared() : nullptr; + + if (is_non_empty) + deserialize(*item, in); + } + catch (serialization_error& e) + { + throw serialization_error(e.info + "\n while deserializing an object of type std::shared_ptr"); + } + } + +// ---------------------------------------------------------------------------------------- + + class proxy_serialize + { + public: + explicit proxy_serialize ( + const std::string& filename + ) : fout_optional_owning_ptr(new std::ofstream(filename.c_str(), std::ios::binary)), + fout(*fout_optional_owning_ptr) + { + if (!fout) + throw serialization_error("Unable to open " + filename + " for writing."); + } + + explicit proxy_serialize ( + std::vector& buf + ) : fout_optional_owning_ptr(new vectorstream(buf)), + fout(*fout_optional_owning_ptr) + { + } + + explicit proxy_serialize ( + std::ostream& ss + ) : fout_optional_owning_ptr(nullptr), + fout(ss) + {} + + template + inline proxy_serialize& operator<<(const T& item) + { + serialize(item, fout); + return *this; + } + + private: + std::unique_ptr fout_optional_owning_ptr; + std::ostream& fout; + }; + + class proxy_deserialize + { + public: + explicit proxy_deserialize ( + const std::string& filename_ + ) : filename(filename_), + fin_optional_owning_ptr(new std::ifstream(filename.c_str(), std::ios::binary)), + fin(*fin_optional_owning_ptr) + { + if (!fin) + throw serialization_error("Unable to open " + filename + " for reading."); + init(); + } + + explicit proxy_deserialize ( + std::vector& buf + ) : fin_optional_owning_ptr(new vectorstream(buf)), + fin(*fin_optional_owning_ptr) + { + init(); + } + + explicit proxy_deserialize ( + std::istream& ss + ) : fin_optional_owning_ptr(nullptr), + fin(ss) + { + init(); + } + + template + inline proxy_deserialize& operator>>(T& item) + { + return doit(item); + } + + template + inline proxy_deserialize& operator>>(ramdump_t&& item) + { + return doit(std::move(item)); + } + + private: + + void init() + { + // read the file header into a buffer and then seek back to the start of the + // file. + fin.read(file_header,4); + fin.clear(); + fin.seekg(0); + } + + private: + + template + inline proxy_deserialize& doit(T&& item) + { + try + { + if (fin.peek() == EOF) + throw serialization_error("No more objects were in the stream!"); + deserialize(std::forward(item), fin); + } + catch (serialization_error& e) + { + std::string suffix; + if (looks_like_a_compressed_file()) + suffix = "\n *** THIS LOOKS LIKE A COMPRESSED FILE. DID YOU FORGET TO DECOMPRESS IT? *** \n"; + + const std::string stream_description = filename.empty() ? "stream" : "file '" + filename + "'"; + + if (objects_read == 0) + { + throw serialization_error("An error occurred while trying to read the first" + " object from the " + stream_description + ".\nERROR: " + e.info + "\n" + suffix); + } + else if (objects_read == 1) + { + throw serialization_error("An error occurred while trying to read the second" + " object from the " + stream_description + ".\nERROR: " + e.info + "\n" + suffix); + } + else if (objects_read == 2) + { + throw serialization_error("An error occurred while trying to read the third" + " object from the " + stream_description + ".\nERROR: " + e.info + "\n" + suffix); + } + else + { + throw serialization_error("An error occurred while trying to read the " + + std::to_string(objects_read+1) + "th object from the " + stream_description + ".\nERROR: " + e.info + "\n" + suffix); + } + } + ++objects_read; + return *this; + } + + int objects_read = 0; + const std::string filename = ""; + std::unique_ptr fin_optional_owning_ptr; + std::istream& fin; + + // We don't need to look at the file header. However, it's here because people + // keep posting questions to the dlib forums asking why they get file load errors. + // Then it turns out that the problem is they have a compressed file that NEEDS TO + // BE DECOMPRESSED by bzip2 or whatever and the reason they are getting + // deserialization errors is because they didn't decompress the file. So we are + // going to check if this file looks like a compressed file and if so then emit an + // error message telling them to unzip the file. :( + char file_header[4] = {0,0,0,0}; + + bool looks_like_a_compressed_file( + ) const + { + if (file_header[0] == 'B' && file_header[1] == 'Z' && file_header[2] == 'h' && + ('0' <= file_header[3] && file_header[3] <= '9') ) + { + return true; + } + + return false; + } + }; + + inline proxy_serialize serialize(const std::string& filename) + { return proxy_serialize(filename); } + inline proxy_serialize serialize(std::ostream& ss) + { return proxy_serialize(ss); } + inline proxy_serialize serialize(std::vector& buf) + { return proxy_serialize(buf); } + inline proxy_deserialize deserialize(const std::string& filename) + { return proxy_deserialize(filename); } + inline proxy_deserialize deserialize(std::istream& ss) + { return proxy_deserialize(ss); } + inline proxy_deserialize deserialize(std::vector& buf) + { return proxy_deserialize(buf); } + +// ---------------------------------------------------------------------------------------- + +} + +// forward declare the MessageLite object so we can reference it below. +namespace google +{ + namespace protobuf + { + class MessageLite; + } +} + +namespace dlib +{ + + /*!A is_protocol_buffer + This is a template that tells you if a type is a Google protocol buffer object. + !*/ + + template + struct is_protocol_buffer + { + static const bool value = false; + }; + + template + struct is_protocol_buffer >::type > + { + static const bool value = true; + }; + + template + typename enable_if >::type serialize(const T& item, std::ostream& out) + { + // Note that Google protocol buffer messages are not self delimiting + // (see https://developers.google.com/protocol-buffers/docs/techniques) + // This means they don't record their length or where they end, so we have + // to record this information ourselves. So we save the size as a little endian 32bit + // integer prefixed onto the front of the message. + + byte_orderer bo; + + // serialize into temp string + std::string temp; + if (!item.SerializeToString(&temp)) + throw dlib::serialization_error("Error while serializing a Google Protocol Buffer object."); + if (temp.size() > std::numeric_limits::max()) + throw dlib::serialization_error("Error while serializing a Google Protocol Buffer object, message too large."); + + // write temp to the output stream + uint32 size = static_cast(temp.size()); + bo.host_to_little(size); + out.write((char*)&size, sizeof(size)); + out.write(temp.c_str(), temp.size()); + } + + template + typename enable_if >::type deserialize(T& item, std::istream& in) + { + // Note that Google protocol buffer messages are not self delimiting + // (see https://developers.google.com/protocol-buffers/docs/techniques) + // This means they don't record their length or where they end, so we have + // to record this information ourselves. So we save the size as a little endian 32bit + // integer prefixed onto the front of the message. + + byte_orderer bo; + + uint32 size = 0; + // read the size + in.read((char*)&size, sizeof(size)); + bo.little_to_host(size); + if (!in || size == 0) + throw dlib::serialization_error("Error while deserializing a Google Protocol Buffer object."); + + // read the bytes into temp + std::string temp; + temp.resize(size); + in.read(&temp[0], size); + + // parse temp into item + if (!in || !item.ParseFromString(temp)) + { + throw dlib::serialization_error("Error while deserializing a Google Protocol Buffer object."); + } + } + +// ---------------------------------------------------------------------------------------- + + inline void check_serialized_version(const std::string& expected_version, std::istream& in) + { + std::string version; + deserialize(version, in); + if (version != expected_version) + { + throw serialization_error("Unexpected version '"+version+ + "' found while deserializing object. Expected version to be '"+expected_version+"'."); + } + } + +// ---------------------------------------------------------------------------------------- + + template + inline void serialize_these(std::ostream& out, const T& x) + { + using dlib::serialize; + serialize(x, out); + } + + template + inline void serialize_these(std::ostream& out, const T& x, const Rest& ... rest) + { + serialize_these(out, x); + serialize_these(out, rest...); + } + + template + inline void deserialize_these(std::istream& in, T& x) + { + using dlib::deserialize; + deserialize(x, in); + } + + template + inline void deserialize_these(std::istream& in, T& x, Rest& ... rest) + { + deserialize_these(in, x); + deserialize_these(in, rest...); + } + + #define DLIB_DEFINE_DEFAULT_SERIALIZATION(Type, ...) \ + void serialize_to(std::ostream& out) const \ + { \ + using dlib::serialize; \ + using dlib::serialize_these; \ + try \ + { \ + /* Write a version header so that if, at a later time, */ \ + /* you realize you need to change the serialization */ \ + /* format you can identify which version of the format */ \ + /* you are encountering when reading old files. */ \ + int version = 1; \ + serialize(version, out); \ + serialize_these(out, __VA_ARGS__); \ + } \ + catch (dlib::serialization_error& e) \ + { \ + throw dlib::serialization_error(e.info + "\n while serializing object of type " #Type); \ + } \ + } \ + \ + void deserialize_from(std::istream& in) \ + { \ + using dlib::deserialize; \ + using dlib::deserialize_these; \ + try \ + { \ + int version = 0; \ + deserialize(version, in); \ + if (version != 1) \ + throw dlib::serialization_error("Unexpected version found while deserializing " #Type); \ + deserialize_these(in, __VA_ARGS__); \ + } \ + catch (dlib::serialization_error& e) \ + { \ + throw dlib::serialization_error(e.info + "\n while deserializing object of type " #Type); \ + } \ + } \ + inline friend void serialize(const Type& item, std::ostream& out) \ + { \ + item.serialize_to(out); \ + } \ + inline friend void deserialize(Type& item, std::istream& in) \ + { \ + item.deserialize_from(in); \ + } +} + +#endif // DLIB_SERIALIZe_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/set.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/set.h new file mode 100644 index 0000000..bec6932 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/set.h @@ -0,0 +1,74 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_SEt_ +#define DLIB_SEt_ + +#include "set/set_kernel_1.h" +#include "set/set_kernel_c.h" + + + +#include "binary_search_tree.h" + +#include "set/set_compare_1.h" + +#include "algs.h" +#include + +namespace dlib +{ + + template < + typename T, + typename mem_manager = default_memory_manager, + typename compare = std::less + > + class set + { + set() {} + + + + + + typedef typename binary_search_tree::kernel_1a + binary_search_tree_1; + + typedef typename binary_search_tree::kernel_2a + binary_search_tree_2; + + public: + + //----------- kernels --------------- + + // kernel_1a + typedef set_kernel_1 + kernel_1a; + typedef set_kernel_c + kernel_1a_c; + + // kernel_1b + typedef set_kernel_1 + kernel_1b; + typedef set_kernel_c + kernel_1b_c; + + + //---------- extensions ------------ + + // compare extensions + typedef set_compare_1 + compare_1a; + typedef set_compare_1 + compare_1a_c; + + typedef set_compare_1 + compare_1b; + typedef set_compare_1 + compare_1b_c; + + }; +} + +#endif // DLIB_SEt_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/set/set_compare_1.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/set/set_compare_1.h new file mode 100644 index 0000000..d4b5e76 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/set/set_compare_1.h @@ -0,0 +1,122 @@ +// Copyright (C) 2005 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_SET_COMPARe_1_ +#define DLIB_SET_COMPARe_1_ + +#include "set_compare_abstract.h" + +#include "../algs.h" + + + +namespace dlib +{ + + template < + typename set_base + > + class set_compare_1 : public set_base + { + + public: + + bool operator< ( + const set_compare_1& rhs + ) const; + + bool operator== ( + const set_compare_1& rhs + ) const; + + }; + + + template < + typename set_base + > + inline void swap ( + set_compare_1& a, + set_compare_1& b + ) { a.swap(b); } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename set_base + > + bool set_compare_1:: + operator< ( + const set_compare_1& rhs + ) const + { + bool result = false; + if (set_base::size() < rhs.size()) + result = true; + + if (set_base::size() == rhs.size()) + { + rhs.reset(); + set_base::reset(); + while (rhs.move_next()) + { + set_base::move_next(); + if (set_base::element() < rhs.element()) + { + result = true; + break; + } + else if (rhs.element() < set_base::element()) + { + break; + } + } + } + + set_base::reset(); + rhs.reset(); + + return result; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename set_base + > + bool set_compare_1:: + operator== ( + const set_compare_1& rhs + ) const + { + bool result = true; + if (set_base::size() != rhs.size()) + result = false; + + + rhs.reset(); + set_base::reset(); + while (rhs.move_next() && set_base::move_next()) + { + if (!(rhs.element() == set_base::element())) + { + result = false; + break; + } + } + + set_base::reset(); + rhs.reset(); + + return result; + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_SET_COMPARe_1_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/set/set_compare_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/set/set_compare_abstract.h new file mode 100644 index 0000000..ff06218 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/set/set_compare_abstract.h @@ -0,0 +1,96 @@ +// Copyright (C) 2005 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_SET_COMPARe_ABSTRACT_ +#ifdef DLIB_SET_COMPARe_ABSTRACT_ + +#include "set_kernel_abstract.h" + +#include "../algs.h" + + +namespace dlib +{ + + template < + typename set_base + > + class set_compare : public set_base + { + + /*! + REQUIREMENTS ON set_base + must be an implementation of set/set_kernel_abstract.h + + POINTERS AND REFERENCES TO INTERNAL DATA + operator== and operator< invalidate pointers or references to + data members. + + WHAT THIS EXTENSION DOES FOR set + This gives a set the ability to compare itself to other + sets using the < and == operators. + + The < operator is conceptually weird for sets. It is useful + though because it allows you to make sets of sets since + sets require that their containing type implement operator<. + + Also note that it is the case that for any two sets a and b + if (a rhs.size()) then + - returns false + - else + - returns true if there exists an integer j such that 0 <= j < size() + and for all integers i such that 0 <= i < j where it is true that + (*this)[i] == rhs[i] and (*this)[j] < rhs[j] + - returns false if there is no j that will satisfy the above conditions. + !*/ + + bool operator== ( + const set_compare& rhs + ) const; + /*! + ensures + - #at_start() == true + - returns true if *this and rhs contain the same elements. + returns false otherwise. + !*/ + }; + + + template < + typename set_base + > + inline void swap ( + set_compare& a, + set_compare& b + ) { a.swap(b); } + /*! + provides a global swap function + !*/ + +} + +#endif // DLIB_SET_COMPARe_ABSTRACT_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/set/set_kernel_1.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/set/set_kernel_1.h new file mode 100644 index 0000000..ccd58f4 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/set/set_kernel_1.h @@ -0,0 +1,372 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_SET_KERNEl_1_ +#define DLIB_SET_KERNEl_1_ + +#include "set_kernel_abstract.h" +#include "../algs.h" +#include "../interfaces/enumerable.h" +#include "../interfaces/remover.h" +#include "../serialize.h" + +namespace dlib +{ + + template < + typename T, + typename bst_base, + typename mem_manager = default_memory_manager + > + class set_kernel_1 : public enumerable, + public asc_remover + { + + /*! + REQUIREMENTS ON bst_base + bst_base is instantiated with and + implements binray_search_tree/binary_search_tree_kernel_abstract.h + + INITIAL VALUE + bst has its initial value + + CONVENTION + bst.size() == the number of elements in the set and + the elements in the set are stored in bst + !*/ + + + public: + + typedef T type; + typedef typename bst_base::compare_type compare_type; + typedef mem_manager mem_manager_type; + + set_kernel_1( + ) + { + } + + virtual ~set_kernel_1( + ) + {} + + inline void clear( + ); + + inline void add ( + T& item + ); + + inline bool is_member ( + const T& item + ) const; + + inline void remove ( + const T& item, + T& item_copy + ); + + inline void destroy ( + const T& item + ); + + inline void swap ( + set_kernel_1& item + ); + + // functions from the remover interface + inline void remove_any ( + T& item + ); + + // functions from the enumerable interface + inline size_t size ( + ) const; + + inline bool at_start ( + ) const; + + inline void reset ( + ) const; + + inline bool current_element_valid ( + ) const; + + inline const T& element ( + ) const; + + + inline const T& element ( + ); + + inline bool move_next ( + ) const; + + + private: + + bst_base bst; + char junk; + + // restricted functions + set_kernel_1(set_kernel_1&); + set_kernel_1& operator=(set_kernel_1&); + + }; + + template < + typename T, + typename bst_base, + typename mem_manager + > + inline void swap ( + set_kernel_1& a, + set_kernel_1& b + ) { a.swap(b); } + + template < + typename T, + typename bst_base, + typename mem_manager + > + void deserialize ( + set_kernel_1& item, + std::istream& in + ) + { + try + { + item.clear(); + unsigned long size; + deserialize(size,in); + T temp; + for (unsigned long i = 0; i < size; ++i) + { + deserialize(temp,in); + item.add(temp); + } + } + catch (serialization_error& e) + { + item.clear(); + throw serialization_error(e.info + "\n while deserializing object of type set_kernel_1"); + } + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename bst_base, + typename mem_manager + > + void set_kernel_1:: + clear ( + ) + { + bst.clear(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename bst_base, + typename mem_manager + > + void set_kernel_1:: + add ( + T& item + ) + { + bst.add(item,junk); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename bst_base, + typename mem_manager + > + bool set_kernel_1:: + is_member( + const T& item + ) const + { + return (bst[item] != 0); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename bst_base, + typename mem_manager + > + void set_kernel_1:: + remove_any ( + T& item + ) + { + bst.remove_any(item,junk); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename bst_base, + typename mem_manager + > + void set_kernel_1:: + remove( + const T& item, + T& item_copy + ) + { + bst.remove(item,item_copy,junk); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename bst_base, + typename mem_manager + > + void set_kernel_1:: + destroy( + const T& item + ) + { + bst.destroy(item); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename bst_base, + typename mem_manager + > + size_t set_kernel_1:: + size ( + ) const + { + return bst.size(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename bst_base, + typename mem_manager + > + void set_kernel_1:: + swap ( + set_kernel_1& item + ) + { + bst.swap(item.bst); + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // enumerable function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename bst_base, + typename mem_manager + > + bool set_kernel_1:: + at_start ( + ) const + { + return bst.at_start(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename bst_base, + typename mem_manager + > + void set_kernel_1:: + reset ( + ) const + { + bst.reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename bst_base, + typename mem_manager + > + bool set_kernel_1:: + current_element_valid ( + ) const + { + return bst.current_element_valid(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename bst_base, + typename mem_manager + > + const T& set_kernel_1:: + element ( + ) const + { + return bst.element().key(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename bst_base, + typename mem_manager + > + const T& set_kernel_1:: + element ( + ) + { + return bst.element().key(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename bst_base, + typename mem_manager + > + bool set_kernel_1:: + move_next ( + ) const + { + return bst.move_next(); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_SET_KERNEl_1_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/set/set_kernel_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/set/set_kernel_abstract.h new file mode 100644 index 0000000..72a0a98 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/set/set_kernel_abstract.h @@ -0,0 +1,192 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_SET_KERNEl_ABSTRACT_ +#ifdef DLIB_SET_KERNEl_ABSTRACT_ + +#include "../interfaces/enumerable.h" +#include "../interfaces/remover.h" +#include "../serialize.h" +#include "../algs.h" +#include + +namespace dlib +{ + + template < + typename T, + typename mem_manager = default_memory_manager, + typename compare = std::less + > + class set : public enumerable, + public asc_remover + { + + /*! + REQUIREMENTS ON T + T must be comparable by compare where compare is a functor compatible with std::less and + T must be swappable by a global swap() and + T must have a default constructor + + REQUIREMENTS ON mem_manager + must be an implementation of memory_manager/memory_manager_kernel_abstract.h or + must be an implementation of memory_manager_global/memory_manager_global_kernel_abstract.h or + must be an implementation of memory_manager_stateless/memory_manager_stateless_kernel_abstract.h + mem_manager::type can be set to anything. + + POINTERS AND REFERENCES TO INTERNAL DATA + swap() and is_member() functions do not invalidate pointers + or references to internal data. + All other functions have no such guarantee. + + INITIAL VALUE + size() == 0 + + ENUMERATION ORDER + The enumerator will iterate over the elements in the set in + ascending order according to the compare functor. + (i.e. the elements are enumerated in sorted order) + + WHAT THIS OBJECT REPRESENTS + set contains items of type T + + This object represents an unaddressed collection of items. + Every element in a set is unique. + + definition of equivalent: + a is equivalent to b if + a < b == false and + b < a == false + !*/ + + public: + + typedef T type; + typedef compare compare_type; + typedef mem_manager mem_manager_type; + + set( + ); + /*! + ensures + - #*this is properly initialized + throws + - std::bad_alloc or any exception thrown by T's constructor + !*/ + + virtual ~set( + ); + /*! + ensures + - all memory associated with *this has been released + !*/ + + void clear( + ); + /*! + ensures + - #*this has its initial value + throws + - std::bad_alloc or any exception thrown by T's constructor + if this exception is thrown then *this is unusable + until clear() is called and succeeds + !*/ + + void add ( + T& item + ); + /*! + requires + - is_member(item) == false + ensures + - #is_member(item) == true + - #item has an initial value for its type + - #size() == size() + 1 + - #at_start() == true + throws + - std::bad_alloc or any exception thrown by T's constructor + if add() throws then it has no effect + !*/ + + bool is_member ( + const T& item + ) const; + /*! + ensures + - returns whether or not there is an element in *this equivalent to + item + !*/ + + void remove ( + const T& item, + T& item_copy + ); + /*! + requires + - is_member(item) == true + - &item != &item_copy (i.e. item and item_copy cannot be the same + variable) + ensures + - #is_member(item) == false + - the element in *this equivalent to item has been removed and + swapped into #item_copy + - #size() == size() - 1 + - #at_start() == true + !*/ + + void destroy ( + const T& item + ); + /*! + requires + - is_member(item) == true + ensures + - #is_member(item) == false + - #size() == size() - 1 + - #at_start() == true + !*/ + + void swap ( + set& item + ); + /*! + ensures + - swaps *this and item + !*/ + + private: + + // restricted functions + set(set&); // copy constructor + set& operator=(set&); // assignment operator + + }; + + template < + typename T, + typename mem_manager, + typename compare + > + inline void swap ( + set& a, + set& b + ) { a.swap(b); } + /*! + provides a global swap function + !*/ + + template < + typename T, + typename mem_manager, + typename compare + > + void deserialize ( + set& item, + std::istream& in + ); + /*! + provides deserialization support + !*/ +} + +#endif // DLIB_SET_KERNEl_ABSTRACT_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/set/set_kernel_c.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/set/set_kernel_c.h new file mode 100644 index 0000000..679f9fa --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/set/set_kernel_c.h @@ -0,0 +1,194 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_SET_KERNEl_C_ +#define DLIB_SET_KERNEl_C_ + +#include "set_kernel_abstract.h" +#include "../algs.h" +#include "../assert.h" + +namespace dlib +{ + + template < + typename set_base + > + class set_kernel_c : public set_base + { + typedef typename set_base::type T; + public: + + void add ( + T& item + ); + + void remove_any ( + T& item + ); + + void remove ( + const T& item, + T& item_copy + ); + + void destroy ( + const T& item + ); + + const T& element ( + ); + + const T& element ( + ) const; + }; + + + template < + typename set_base + > + inline void swap ( + set_kernel_c& a, + set_kernel_c& b + ) { a.swap(b); } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename set_base + > + void set_kernel_c:: + add( + T& item + ) + { + // make sure requires clause is not broken + DLIB_CASSERT( !this->is_member(item), + "\tvoid set::add" + << "\n\titem being added must not already be in the set" + << "\n\tthis: " << this + ); + + // call the real function + set_base::add(item); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename set_base + > + void set_kernel_c:: + remove ( + const T& item, + T& item_copy + ) + { + // make sure requires clause is not broken + DLIB_CASSERT( this->is_member(item) && + (static_cast(&item) != static_cast(&item_copy)), + "\tvoid set::remove" + << "\n\titem should be in the set if it's going to be removed" + << "\n\tthis: " << this + << "\n\t&item: " << &item + << "\n\t&item_copy: " << &item_copy + << "\n\tis_member(item): " << (this->is_member(item)?"true":"false") + ); + + // call the real function + set_base::remove(item,item_copy); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename set_base + > + void set_kernel_c:: + destroy ( + const T& item + ) + { + // make sure requires clause is not broken + DLIB_CASSERT( this->is_member(item), + "\tvoid set::destroy" + << "\n\titem should be in the set if it's going to be removed" + << "\n\tthis: " << this + << "\n\t&item: " << &item + ); + + // call the real function + set_base::destroy(item); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename set_base + > + void set_kernel_c:: + remove_any ( + T& item + ) + { + // make sure requires clause is not broken + DLIB_CASSERT( this->size() != 0, + "\tvoid set::remove_any" + << "\n\tsize must be greater than zero if an item is to be removed" + << "\n\tthis: " << this + ); + + // call the real function + set_base::remove_any(item); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename set_base + > + const typename set_base::type& set_kernel_c:: + element ( + ) const + { + // make sure requires clause is not broken + DLIB_CASSERT(this->current_element_valid() == true, + "\tconst T& set::element() const" + << "\n\tyou can't access the current element if it doesn't exist" + << "\n\tthis: " << this + ); + + // call the real function + return set_base::element(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename set_base + > + const typename set_base::type& set_kernel_c:: + element ( + ) + { + // make sure requires clause is not broken + DLIB_CASSERT(this->current_element_valid() == true, + "\tconst T& set::element" + << "\n\tyou can't access the current element if it doesn't exist" + << "\n\tthis: " << this + ); + + // call the real function + return set_base::element(); + } + +// ---------------------------------------------------------------------------------------- + + +} + +#endif // DLIB_SET_KERNEl_C_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sliding_buffer.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sliding_buffer.h new file mode 100644 index 0000000..fb89e1b --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sliding_buffer.h @@ -0,0 +1,38 @@ +// Copyright (C) 2004 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_SLIDING_BUFFEr_ +#define DLIB_SLIDING_BUFFEr_ + + +#include "sliding_buffer/sliding_buffer_kernel_1.h" +#include "sliding_buffer/sliding_buffer_kernel_c.h" +#include "sliding_buffer/circular_buffer.h" + + + +namespace dlib +{ + + template < + typename T + > + class sliding_buffer + { + + sliding_buffer() {} + public: + + //----------- kernels --------------- + + // kernel_1a + typedef sliding_buffer_kernel_1 + kernel_1a; + typedef sliding_buffer_kernel_c + kernel_1a_c; + + + }; +} + +#endif // DLIB_SLIDING_BUFFEr_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sliding_buffer/circular_buffer.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sliding_buffer/circular_buffer.h new file mode 100644 index 0000000..4fcc922 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sliding_buffer/circular_buffer.h @@ -0,0 +1,235 @@ +// Copyright (C) 2012 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_CIRCULAR_BuFFER_Hh_ +#define DLIB_CIRCULAR_BuFFER_Hh_ + +#include "circular_buffer_abstract.h" +#include +#include "../algs.h" +#include "../serialize.h" +#include "../matrix/matrix_mat.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + class circular_buffer + { + public: + typedef default_memory_manager mem_manager_type; + typedef T value_type; + typedef T type; + + circular_buffer() + { + } + + explicit circular_buffer(unsigned long s) + { + resize(s); + } + + void clear ( + ) + { + offset = 0; + data.clear(); + } + + T& operator[] ( unsigned long i) + { + DLIB_ASSERT(i < size(), + "\t T& circular_buffer::operator[](i)" + << "\n\t You have supplied an invalid index" + << "\n\t this: " << this + << "\n\t i: " << i + << "\n\t size(): " << size() + ); + return data[(i+offset)%data.size()]; + } + + const T& operator[] ( unsigned long i) const + { + DLIB_ASSERT(i < size(), + "\t const T& circular_buffer::operator[](i)" + << "\n\t You have supplied an invalid index" + << "\n\t this: " << this + << "\n\t i: " << i + << "\n\t size(): " << size() + ); + return data[(i+offset)%data.size()]; + } + + void resize(unsigned long size) + { + offset = 0; + data.resize(size); + } + + void assign( + unsigned long size, + const T& value + ) + { + offset = 0; + data.assign(size,value); + } + + unsigned long size() const { return data.size(); } + + void push_front(const T& value) + { + if (data.size() != 0) + { + offset = (offset - 1 + data.size())%data.size(); + data[offset] = value; + } + } + + void push_back(const T& value) + { + if (data.size() != 0) + { + data[offset] = value; + offset = (offset + 1 + data.size())%data.size(); + } + } + + T& front( + ) + { + DLIB_CASSERT(size() > 0, + "\t T& circular_buffer::front()" + << "\n\t You can't call front() on an empty circular_buffer" + << "\n\t this: " << this + ); + return (*this)[0]; + } + + const T& front( + ) const + { + DLIB_CASSERT(size() > 0, + "\t const T& circular_buffer::front()" + << "\n\t You can't call front() on an empty circular_buffer" + << "\n\t this: " << this + ); + return (*this)[0]; + } + + T& back( + ) + { + DLIB_CASSERT(size() > 0, + "\t T& circular_buffer::back()" + << "\n\t You can't call back() on an empty circular_buffer" + << "\n\t this: " << this + ); + return (*this)[size()-1]; + } + + const T& back( + ) const + { + DLIB_CASSERT(size() > 0, + "\t const T& circular_buffer::back()" + << "\n\t You can't call back() on an empty circular_buffer" + << "\n\t this: " << this + ); + return (*this)[size()-1]; + } + + void swap( circular_buffer& item) + { + std::swap(item.offset, offset); + data.swap(item.data); + } + + + private: + std::vector data; + + unsigned long offset = 0; + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void swap ( + circular_buffer& a, + circular_buffer& b + ) { a.swap(b); } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void serialize ( + const circular_buffer& item, + std::ostream& out + ) + { + try + { + serialize(item.size(),out); + for (unsigned long i = 0; i < item.size(); ++i) + serialize(item[i],out); + } + catch (serialization_error& e) + { + throw serialization_error(e.info + "\n while serializing object of type circular_buffer"); + } + + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void deserialize ( + circular_buffer& item, + std::istream& in + ) + { + try + { + unsigned long size; + deserialize(size,in); + item.resize(size); + for (unsigned long i = 0; i < size; ++i) + deserialize(item[i],in); + } + catch (serialization_error& e) + { + item.clear(); + throw serialization_error(e.info + "\n while deserializing object of type circular_buffer"); + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + const matrix_op > > mat ( + const circular_buffer& m + ) + { + typedef op_array_to_mat > op; + return matrix_op(op(m)); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_CIRCULAR_BuFFER_Hh_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sliding_buffer/circular_buffer_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sliding_buffer/circular_buffer_abstract.h new file mode 100644 index 0000000..dc9f35c --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sliding_buffer/circular_buffer_abstract.h @@ -0,0 +1,257 @@ +// Copyright (C) 2012 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_CIRCULAR_BuFFER_ABSTRACT_Hh_ +#ifdef DLIB_CIRCULAR_BuFFER_ABSTRACT_Hh_ + +#include "../algs.h" +#include "../serialize.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + class circular_buffer + { + /*! + REQUIREMENTS ON T + T must have a default constructor and be copyable. + + POINTERS AND REFERENCES TO INTERNAL DATA + swap(), size(), front(), back(), and operator[] functions do + not invalidate pointers or references to internal data. + All other functions have no such guarantee. + + INITIAL VALUE + - size() == 0 + + WHAT THIS OBJECT REPRESENTS + This object is a circular buffer of objects of type T. This means + that when objects are pushed onto one of its ends it does not grow + in size. Instead, it shifts all elements over one to make room for + the new element and the element at the opposing end falls off the + buffer and is lost. + !*/ + + public: + typedef default_memory_manager mem_manager_type; + typedef T value_type; + typedef T type; + + circular_buffer( + ); + /*! + ensures + - #size() == 0 + - this object is properly initialized + !*/ + + explicit circular_buffer( + unsigned long s + ); + /*! + ensures + - #size() == s + - this object is properly initialized + !*/ + + void clear ( + ); + /*! + ensures + - this object has its initial value + - #size() == 0 + !*/ + + T& operator[] ( + unsigned long i + ) const; + /*! + requires + - i < size() + ensures + - returns a non-const reference to the i-th element of this circular buffer + !*/ + + const T& operator[] ( + unsigned long i + ) const; + /*! + requires + - i < size() + ensures + - returns a const reference to the i-th element of this circular buffer + !*/ + + void resize( + unsigned long new_size + ); + /*! + ensures + - #size() == new_size + !*/ + + void assign( + unsigned long new_size, + const T& value + ); + /*! + ensures + - #size() == new_size + - for all valid i: + - (*this)[i] == value + !*/ + + unsigned long size( + ) const; + /*! + ensures + - returns the number of elements in this circular buffer + !*/ + + T& front( + ); + /*! + requires + - size() > 0 + ensures + - returns a reference to (*this)[0] + !*/ + + const T& front( + ) const; + /*! + requires + - size() > 0 + ensures + - returns a const reference to (*this)[0] + !*/ + + T& back( + ); + /*! + requires + - size() > 0 + ensures + - returns a reference to (*this)[size()-1] + !*/ + + const T& back( + ) const; + /*! + requires + - size() > 0 + ensures + - returns a const reference to (*this)[size()-1] + !*/ + + void push_front( + const T& value + ); + /*! + ensures + - #size() == size() + (i.e. the size of this object does not change) + - if (size() != 0) then + - #front() == value + - all items are shifted over such that, + - #(*this)[1] == (*this)[0] + - #(*this)[2] == (*this)[1] + - #(*this)[3] == (*this)[2] + - etc. + - back() is shifted out of the circular buffer + - else + - This function has no effect on this object + !*/ + + void push_back( + const T& value + ); + /*! + ensures + - #size() == size() + (i.e. the size of this object does not change) + - if (size() != 0) then + - #back() == value + - all items are shifted over such that, + - front() is shifted out of the circular buffer + - #(*this)[0] == (*this)[1] + - #(*this)[1] == (*this)[2] + - #(*this)[2] == (*this)[3] + - etc. + - else + - This function has no effect on this object + !*/ + + void swap ( + circular_buffer& item + ); + /*! + ensures + - swaps *this with item + !*/ + + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void swap ( + circular_buffer& a, + circular_buffer& b + ) { a.swap(b); } + /*! + provides a global swap function + !*/ + + template < + typename T + > + void serialize ( + const circular_buffer& item, + std::ostream& out + ); + /*! + provides serialization support + !*/ + + template < + typename T + > + void deserialize ( + circular_buffer& item, + std::istream& in + ); + /*! + provides deserialization support + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + const matrix_exp mat ( + const circular_buffer& m + ); + /*! + ensures + - returns a matrix R such that: + - is_col_vector(R) == true + - R.size() == m.size() + - for all valid r: + R(r) == m[r] + !*/ + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_CIRCULAR_BuFFER_ABSTRACT_Hh_ + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sliding_buffer/sliding_buffer_kernel_1.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sliding_buffer/sliding_buffer_kernel_1.h new file mode 100644 index 0000000..9e51f17 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sliding_buffer/sliding_buffer_kernel_1.h @@ -0,0 +1,227 @@ +// Copyright (C) 2004 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_SLIDING_BUFFER_KERNEl_1_ +#define DLIB_SLIDING_BUFFER_KERNEl_1_ + +#include "sliding_buffer_kernel_abstract.h" +#include "../algs.h" +#include "../interfaces/enumerable.h" +#include "../serialize.h" + +namespace dlib +{ + + template < + typename T + > + class sliding_buffer_kernel_1 : public enumerable + { + /*! + INITIAL VALUE + - buffer_size == 0 + - buffer == 0 + - buffer_start == 0 + - current == 0 + - at_start_ == true + + CONVENTION + - buffer_size == size() + + - element() == (*this)[current] + - current_element_valid() == (current < buffer_size) && at_start_ == false + - at_start() == at_start_ + + - if (buffer_size != 0) then + - buffer[(buffer_start+i)&(mask)] == operator[](i) + - mask == buffer_size-1 + - else + - buffer == 0 + - buffer_size == 0 + !*/ + + public: + + typedef T type; + + sliding_buffer_kernel_1 ( + ) : + buffer_start(0), + buffer_size(0), + buffer(0), + current(0), + at_start_(true) + {} + + virtual ~sliding_buffer_kernel_1 ( + ) { if (buffer) delete [] buffer; } + + void clear( + ) + { + buffer_size = 0; + if (buffer) delete [] buffer; + buffer = 0; + at_start_ = true; + current = 0; + } + + void set_size ( + unsigned long exp_size + ) + { + at_start_ = true; + if (buffer) delete [] buffer; + buffer_size = 1; + while (exp_size != 0) + { + --exp_size; + buffer_size <<= 1; + } + mask = buffer_size-1; + try { buffer = new T[buffer_size]; } + catch (...) { buffer = 0; buffer_size = 0; throw; } + } + + size_t size ( + ) const { return buffer_size; } + + void rotate_left ( + unsigned long amount + ) { buffer_start = ((buffer_start-amount)&mask); at_start_ = true; } + + void rotate_right ( + unsigned long amount + ) { buffer_start = ((buffer_start+amount)&mask); at_start_ = true;} + + const T& operator[] ( + unsigned long index + ) const { return buffer[(buffer_start+index)&mask]; } + + T& operator[] ( + unsigned long index + ) { return buffer[(buffer_start+index)&mask]; } + + unsigned long get_element_id( + unsigned long index + ) const { return ((buffer_start+index)&mask); } + + unsigned long get_element_index ( + unsigned long element_id + ) const { return ((element_id-buffer_start)&mask);} + + void swap ( + sliding_buffer_kernel_1& item + ) + { + exchange(buffer_start,item.buffer_start); + exchange(buffer_size,item.buffer_size); + exchange(buffer,item.buffer); + exchange(mask,item.mask); + exchange(current,item.current); + exchange(at_start_,item.at_start_); + } + + + bool at_start ( + ) const { return at_start_; } + + void reset ( + ) const { at_start_ = true; } + + bool current_element_valid ( + ) const { return (current < buffer_size) && (at_start_ == false); } + + const T& element ( + ) const { return (*this)[current]; } + + T& element ( + ) { return (*this)[current]; } + + bool move_next ( + ) const + { + if (at_start_ == false) + { + if (current+1 < buffer_size) + { + ++current; + return true; + } + else + { + current = buffer_size; + return false; + } + } + else + { + at_start_ = false; + current = 0; + return (buffer_size != 0); + } + } + + + private: + + // data members + unsigned long buffer_start; + unsigned long buffer_size; + T* buffer; + unsigned long mask; + + + mutable unsigned long current; + mutable bool at_start_; + + // restricted functions + sliding_buffer_kernel_1(sliding_buffer_kernel_1&); // copy constructor + sliding_buffer_kernel_1& operator=(sliding_buffer_kernel_1&); // assignment operator + + }; + + template < + typename T + > + inline void swap ( + sliding_buffer_kernel_1& a, + sliding_buffer_kernel_1& b + ) { a.swap(b); } + + template < + typename T + > + void deserialize ( + sliding_buffer_kernel_1& item, + std::istream& in + ) + { + try + { + item.clear(); + unsigned long size; + deserialize(size,in); + if (size > 0) + { + int count = 0; + while (size != 1) + { + size /= 2; + ++count; + } + item.set_size(count); + + for (unsigned long i = 0; i < item.size(); ++i) + deserialize(item[i],in); + } + } + catch (serialization_error& e) + { + item.clear(); + throw serialization_error(e.info + "\n while deserializing object of type sliding_buffer_kernel_1"); + } + } +} + +#endif // DLIB_SLIDING_BUFFER_KERNEl_1_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sliding_buffer/sliding_buffer_kernel_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sliding_buffer/sliding_buffer_kernel_abstract.h new file mode 100644 index 0000000..687a9e8 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sliding_buffer/sliding_buffer_kernel_abstract.h @@ -0,0 +1,205 @@ +// Copyright (C) 2004 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_SLIDING_BUFFER_KERNEl_ABSTRACT_ +#ifdef DLIB_SLIDING_BUFFER_KERNEl_ABSTRACT_ + +#include "../algs.h" +#include "../interfaces/enumerable.h" +#include "../serialize.h" + +namespace dlib +{ + + template < + typename T + > + class sliding_buffer : public enumerable + { + /*! + REQUIREMENTS ON T + T must have a default constructor + + INITIAL VALUE + size() == 0 + + ENUMERATION ORDER + The enumerator will iterate over the elements of the sliding_buffer in the + order (*this)[0], (*this)[1], (*this)[2], ... + + WHAT THIS OBJECT REPRESENTS + This object represents an array of T objects. The main + feature of this object is its ability to rotate its contents + left or right. An example will make it clear. + + suppose we have the following buffer (assuming T is a char): + "some data!" <-- the data in the buffer + 9876543210 <-- the index numbers associated with each character + + applying rotate_left(2) to this buffer would give us + "me data!so" + 9876543210 + + if instead of calling rotate_left we call rotate_right(3) instead we would have + "ta!some da" + 9876543210 + + Also note that unless specified otherwise, no member functions + of this object throw exceptions. + !*/ + + public: + + typedef T type; + + sliding_buffer ( + ); + /*! + ensures + - #*this is properly initialized + throws + - std::bad_alloc or any exception thrown by T's constructor. + !*/ + + virtual ~sliding_buffer ( + ); + /*! + ensures + - any resources associated with *this have been released + !*/ + + void clear( + ); + /*! + ensures + - #*this has its initial value + throws + - std::bad_alloc or any exception thrown by T's constructor. + if this exception is thrown then #*this is unusable + until clear() is called and succeeds + !*/ + + void set_size ( + unsigned long exp_size + ); + /*! + requires + - 0 < exp_size < 32 + ensures + - #size() == 2^exp_size + - the value of all elements in the buffer are undefined + - #at_start() == true + throws + - std::bad_alloc or any exception thrown by T's constructor. + if this exception is thrown then #size() == 0 + !*/ + + void rotate_left ( + unsigned long amount + ); + /*! + ensures + - for all i where 0 <= i < size(): + (#*this)[i] == (*this)[(i-amount)&(size()-1)] + i.e. rotates the contents of *this left by amount spaces + - #at_start() == true + !*/ + + void rotate_right ( + unsigned long amount + ); + /*! + ensures + - for all i where 0 <= i < size(): + (#*this)[i] == (*this)[(i+amount)&(size()-1)] + i.e. rotates the contents of *this right by amount spaces + - #at_start() == true + !*/ + + unsigned long get_element_id ( + unsigned long index + ) const; + /*! + requires + - index < size() + ensures + - returns an element id number that uniquely references the element at + the given index. (you can use this id to locate the new position of + an element after the buffer has been rotated) + - returned value is < size() + !*/ + + unsigned long get_element_index ( + unsigned long element_id + ) const; + /*! + require + - element_id < size() + ensures + - returns the index of the element with the given element_id. + ( (*this)[get_element_index(element_id)] will always refer to the same element + no matter where it has been rotated to) + - returned value is < size() + !*/ + + const T& operator[] ( + unsigned long index + ) const; + /*! + requires + - index < size() + ensures + - returns a const reference to the element in *this at position index + !*/ + + T& operator[] ( + unsigned long index + ); + /*! + requires + - index < size() + ensures + - returns a reference to the element in *this at position index + !*/ + + void swap ( + sliding_buffer& item + ); + /*! + ensures + - swaps *this and item + !*/ + + private: + + // restricted functions + sliding_buffer(sliding_buffer&); // copy constructor + sliding_buffer& operator=(sliding_buffer&); // assignment operator + + }; + + template < + typename T + > + void swap ( + sliding_buffer& a, + sliding_buffer& b + ) { a.swap(b); } + /*! + provides a global swap function + !*/ + + template < + typename T + > + void deserialize ( + sliding_buffer& item, + std::istream& in + ); + /*! + provides deserialization support + !*/ + +} + +#endif // DLIB_SLIDING_BUFFER_KERNEl_ABSTRACT_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sliding_buffer/sliding_buffer_kernel_c.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sliding_buffer/sliding_buffer_kernel_c.h new file mode 100644 index 0000000..a7330e4 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sliding_buffer/sliding_buffer_kernel_c.h @@ -0,0 +1,222 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_SLIDING_BUFFER_KERNEl_C_ +#define DLIB_SLIDING_BUFFER_KERNEl_C_ + +#include "sliding_buffer_kernel_abstract.h" +#include "../algs.h" +#include "../assert.h" +#include + +namespace dlib +{ + + template < + typename sb_base + > + class sliding_buffer_kernel_c : public sb_base + { + typedef typename sb_base::type T; + + public: + void set_size ( + unsigned long exp_size + ); + + const T& operator[] ( + unsigned long index + ) const; + + T& operator[] ( + unsigned long index + ); + + unsigned long get_element_id ( + unsigned long index + ) const; + + unsigned long get_element_index ( + unsigned long element_id + ) const; + + const T& element ( + ) const; + + T& element ( + ); + + + }; + + template < + typename sb_base + > + inline void swap ( + sliding_buffer_kernel_c& a, + sliding_buffer_kernel_c& b + ) { a.swap(b); } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename sb_base + > + void sliding_buffer_kernel_c:: + set_size ( + unsigned long exp_size + ) + { + // make sure requires clause is not broken + DLIB_CASSERT( 0 < exp_size && exp_size < 32, + "\tvoid sliding_buffer::set_size(unsigned long)" + << "\n\texp_size must be some number between 1 and 31" + << "\n\tthis: " << this + << "\n\texp_size: " << exp_size + ); + + // call the real function + sb_base::set_size(exp_size); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename sb_base + > + unsigned long sliding_buffer_kernel_c:: + get_element_id ( + unsigned long index + ) const + { + // make sure requires clause is not broken + DLIB_CASSERT( index < this->size(), + "\tunsigned long sliding_buffer::get_element_id(unsigned long) const" + << "\n\tindex must be in the range 0 to size()-1" + << "\n\tthis: " << this + << "\n\tsize(): " << this->size() + << "\n\tindex: " << index + ); + + // call the real function + return sb_base::get_element_id(index); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename sb_base + > + unsigned long sliding_buffer_kernel_c:: + get_element_index ( + unsigned long element_id + ) const + { + // make sure requires clause is not broken + DLIB_CASSERT( element_id < this->size(), + "\tunsigned long sliding_buffer::get_element_index(unsigned long) const" + << "\n\tid must be in the range 0 to size()-1" + << "\n\tthis: " << this + << "\n\tsize(): " << this->size() + << "\n\tid: " << element_id + ); + + // call the real function + return sb_base::get_element_index(element_id); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename sb_base + > + const typename sb_base::type& sliding_buffer_kernel_c:: + operator[] ( + unsigned long index + ) const + { + // make sure requires clause is not broken + DLIB_CASSERT( index < this->size(), + "\tconst T& sliding_buffer::operator[](unsigned long) const" + << "\n\tindex must be in the range 0 to size()-1" + << "\n\tthis: " << this + << "\n\tsize(): " << this->size() + << "\n\tindex: " << index + ); + + // call the real function + return sb_base::operator[](index); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename sb_base + > + typename sb_base::type& sliding_buffer_kernel_c:: + operator[] ( + unsigned long index + ) + { + // make sure requires clause is not broken + DLIB_CASSERT( index < this->size(), + "\tT& sliding_buffer::operator[](unsigned long)" + << "\n\tindex must be in the range 0 to size()-1" + << "\n\tthis: " << this + << "\n\tsize(): " << this->size() + << "\n\tindex: " << index + ); + + // call the real function + return sb_base::operator[](index); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename sb_base + > + const typename sb_base::type& sliding_buffer_kernel_c:: + element ( + ) const + { + // make sure requires clause is not broken + DLIB_CASSERT(this->current_element_valid() == true, + "\tconst T& sliding_buffer::element" + << "\n\tyou can't access the current element if it doesn't exist" + << "\n\tthis: " << this + ); + + // call the real function + return sb_base::element(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename sb_base + > + typename sb_base::type& sliding_buffer_kernel_c:: + element ( + ) + { + // make sure requires clause is not broken + DLIB_CASSERT(this->current_element_valid() == true, + "\tT& sliding_buffer::element" + << "\n\tyou can't access the current element if it doesn't exist" + << "\n\tthis: " << this + ); + + // call the real function + return sb_base::element(); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_SLIDING_BUFFER_KERNEl_C_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets.h new file mode 100644 index 0000000..e253587 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets.h @@ -0,0 +1,20 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_SOCKETs_ +#define DLIB_SOCKETs_ + +#include "platform.h" + + +#ifdef WIN32 +#include "sockets/windows.h" +#endif + +#ifndef WIN32 +#include "sockets/posix.h" +#endif + +#include "sockets/sockets_extensions.h" + +#endif // DLIB_SOCKETs_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets/posix.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets/posix.h new file mode 100644 index 0000000..d736a20 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets/posix.h @@ -0,0 +1,6 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_SOCKETS_KERNEl_1_ +#include "sockets_kernel_2.h" +#endif + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets/sockets_extensions.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets/sockets_extensions.h new file mode 100644 index 0000000..9faa34e --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets/sockets_extensions.h @@ -0,0 +1,151 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_SOCKETS_EXTENSIONs_ +#define DLIB_SOCKETS_EXTENSIONs_ + +#include +#include +#include + +#include "../sockets.h" +#include "../smart_pointers/scoped_ptr.h" +#include "sockets_extensions_abstract.h" + + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class invalid_network_address : public dlib::error + { + public: + invalid_network_address(const std::string& msg) : dlib::error(msg) {}; + }; + +// ---------------------------------------------------------------------------------------- + + struct network_address + { + network_address() : port(0){} + + network_address( + const std::string& full_address + ); + + network_address ( + const char* full_address + ) + { + *this = network_address(std::string(full_address)); + } + + network_address( + const std::string& host_address_, + const unsigned short port_ + ) : host_address(host_address_), port(port_) {} + + std::string host_address; + unsigned short port; + }; + +// ---------------------------------------------------------------------------------------- + + inline bool operator < ( + const network_address& a, + const network_address& b + ) + { + if (a.host_address < b.host_address) + return true; + else if (a.host_address > b.host_address) + return false; + else if (a.port < b.port) + return true; + else + return false; + } + + inline bool operator== ( + const network_address& a, + const network_address& b + ) { return a.host_address == b.host_address && a.port == b.port; } + + inline bool operator != ( + const network_address& a, + const network_address& b + ) { return !(a == b); } + +// ---------------------------------------------------------------------------------------- + + void serialize( + const network_address& item, + std::ostream& out + ); + + void deserialize( + network_address& item, + std::istream& in + ); + + std::ostream& operator<< ( + std::ostream& out, + const network_address& item + ); + + std::istream& operator>> ( + std::istream& in, + network_address& item + ); + +// ---------------------------------------------------------------------------------------- + + connection* connect ( + const std::string& host_or_ip, + unsigned short port + ); + +// ---------------------------------------------------------------------------------------- + + connection* connect ( + const network_address& addr + ); + +// ---------------------------------------------------------------------------------------- + + connection* connect ( + const std::string& host_or_ip, + unsigned short port, + unsigned long timeout + ); + +// ---------------------------------------------------------------------------------------- + + bool is_ip_address ( + std::string ip + ); + +// ---------------------------------------------------------------------------------------- + + void close_gracefully ( + connection* con, + unsigned long timeout = 500 + ); + +// ---------------------------------------------------------------------------------------- + + void close_gracefully ( + std::unique_ptr& con, + unsigned long timeout = 500 + ); + +// ---------------------------------------------------------------------------------------- + +} + +#ifdef NO_MAKEFILE +#include "sockets_extensions.cpp" +#endif + +#endif // DLIB_SOCKETS_EXTENSIONs_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets/sockets_extensions_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets/sockets_extensions_abstract.h new file mode 100644 index 0000000..194c22a --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets/sockets_extensions_abstract.h @@ -0,0 +1,300 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_SOCKETS_EXTENSIONs_ABSTRACT_ +#ifdef DLIB_SOCKETS_EXTENSIONs_ABSTRACT_ + +#include +#include + +#include "sockets_kernel_abstract.h" +#include "../error.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class invalid_network_address : public dlib::error + { + /*! + WHAT THIS OBJECT REPRESENTS + This is the exception thrown by network_address's constructor if the + input is invalid. + !*/ + }; + +// ---------------------------------------------------------------------------------------- + + struct network_address + { + /*! + WHAT THIS OBJECT REPRESENTS + This object is simply a container for two things: + - A host machine address which is either an IP address or DNS name + for a machine. + - A port number. + + Together, these things define a machine and port on that machine. + !*/ + + network_address( + ); + /*! + ensures + - host_address == "" + - #port == 0 + !*/ + + network_address( + const std::string& full_address + ); + /*! + ensures + - interprets full_address as a network address of the form: + host_address:port + and assigns each part into #host_address and #port. For example, + network_address("localhost:80") would result in a network_address + object where host_address was "localhost" and port was 80. + throws + - invalid_network_address + This exception is thrown if the full_address string can't be + interpreted as a valid network address. + !*/ + + network_address ( + const char* full_address + ); + /*! + requires + - full_address == a valid pointer to a null terminated string + ensures + - Invoking this constructor is equivalent to performing + network_address(std::string(full_address)) + !*/ + + network_address( + const std::string& host_address_, + const unsigned short port_ + ); + /*! + ensures + - #host_address == host_address_ + - #port == port_ + !*/ + + + std::string host_address; + unsigned short port; + }; + +// ---------------------------------------------------------------------------------------- + + inline bool operator < ( + const network_address& a, + const network_address& b + ); + /*! + ensures + - provides a total ordering over network_address objects so you can use them in + the standard associative containers. The ordering is defined such that if + you sorted network addresses they would sort first on the host_address string + and then, for network_address objects with equal host_address, they would + sort on the port number + !*/ + + inline bool operator== ( + const network_address& a, + const network_address& b + ); + /*! + ensures + - returns true if a and b contain exactly the same address and false otherwise. + That is, the following must be true for this function to return true: + - a.host_address == b.host_address + - a.port == b.port + Note that this means that two addresses which are logically equivalent but + written differently will not compare equal. For example, suppose example.com + has the IP address 10.1.1.1. Then network_address("10.1.1.1:80") and + network_address("example.com:80") really refer to the same network resource + but will nevertheless not compare equal since. + !*/ + + inline bool operator != ( + const network_address& a, + const network_address& b + ); + /*! + ensures + - returns !(a == b) + !*/ + +// ---------------------------------------------------------------------------------------- + + void serialize( + const network_address& item, + std::ostream& out + ); + /*! + ensures + - provides serialization support + !*/ + + void deserialize( + network_address& item, + std::istream& in + ); + /*! + ensures + - provides deserialization support + !*/ + + std::ostream& operator<< ( + std::ostream& out, + const network_address& item + ); + /*! + ensures + - writes the given network_address to the output stream. The format is the + host_address, then a colon, then the port number. So for example: + cout << network_address("localhost", 80); + would print: + localhost:80 + - returns #out + !*/ + + std::istream& operator>> ( + std::istream& in, + network_address& item + ); + /*! + ensures + - reads a network_address from the given input stream. The expected format is + the same as the one used to print them by the above operator<<() routine. + - returns #in + - if (there is an error reading the network_address) then + - #in.good() == false + !*/ + +// ---------------------------------------------------------------------------------------- + + connection* connect ( + const std::string& host_or_ip, + unsigned short port + ); + /*! + ensures + - returns a connection object that is connected to the given host at the + given port + throws + - dlib::socket_error + This exception is thrown if there is some problem that prevents us from + creating the connection + - std::bad_alloc + !*/ + +// ---------------------------------------------------------------------------------------- + + connection* connect ( + const network_address& addr + ); + /*! + ensures + - returns connect(addr.host_address, addr_port); + !*/ + +// ---------------------------------------------------------------------------------------- + + connection* connect ( + const std::string& host_or_ip, + unsigned short port, + unsigned long timeout + ); + /*! + ensures + - returns a connection object that is connected to the given host at the + given port. + - blocks for at most timeout milliseconds + throws + - dlib::socket_error + This exception is thrown if there is some problem that prevents us from + creating the connection or if timeout milliseconds elapses before the + connect is successful. + - std::bad_alloc + !*/ + +// ---------------------------------------------------------------------------------------- + + + bool is_ip_address ( + std::string ip + ); + /*! + ensures + - if (ip is a valid ip address) then + - returns true + - else + - returns false + !*/ + +// ---------------------------------------------------------------------------------------- + + void close_gracefully ( + connection* con, + unsigned long timeout = 500 + ); + /*! + requires + - con == a valid pointer to a connection object or 0 + ensures + - This function does nothing if con == 0, otherwise it performs the following: + - performs a graceful close of the given connection and if it takes longer + than timeout milliseconds to complete then forces the connection closed. + - Specifically, a graceful close means that the outgoing part of con is + closed (a FIN is sent) and then we wait for the other end to to close + their end of the connection. This way any data still on its way to + the other end of the connection will be received properly. + - This function will block until the graceful close is completed or we + timeout. + - calls "delete con;". Thus con is no longer a valid pointer after this + function has finished. + throws + - std::bad_alloc or dlib::thread_error + If either of these exceptions are thrown con will still be closed via + "delete con;" + !*/ + +// ---------------------------------------------------------------------------------------- + + void close_gracefully ( + std::unique_ptr& con, + unsigned long timeout = 500 + ); + /*! + requires + - con == a valid pointer to a connection object or con.get() == 0 + ensures + - This function does nothing if con.get() == 0, otherwise it performs the + following: + - performs a graceful close of the given connection and if it takes longer + than timeout milliseconds to complete then forces the connection closed. + - Specifically, a graceful close means that the outgoing part of con is + closed (a FIN is sent) and then we wait for the other end to to close + their end of the connection. This way any data still on its way to + the other end of the connection will be received properly. + - This function will block until the graceful close is completed or we + timeout. + - #con.get() == 0. Thus con is no longer a valid pointer after this + function has finished. + throws + - std::bad_alloc or dlib::thread_error + If either of these exceptions are thrown con will still be closed and + deleted (i.e. #con.get() == 0). + !*/ + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_SOCKETS_EXTENSIONs_ABSTRACT_ + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets/sockets_kernel_1.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets/sockets_kernel_1.h new file mode 100644 index 0000000..5fb73ec --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets/sockets_kernel_1.h @@ -0,0 +1,351 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net), Miguel Grinberg +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_SOCKETS_KERNEl_1_ +#define DLIB_SOCKETS_KERNEl_1_ + +#ifdef DLIB_ISO_CPP_ONLY +#error "DLIB_ISO_CPP_ONLY is defined so you can't use this OS dependent code. Turn DLIB_ISO_CPP_ONLY off if you want to use it." +#endif + +#include "sockets_kernel_abstract.h" + +#include +#include + +#include "../algs.h" +#include "../threads.h" +#include "../uintn.h" + + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + // forward declarations + class socket_factory; + class listener; + class SOCKET_container; + +// ---------------------------------------------------------------------------------------- + + // lookup functions + + int + get_local_hostname ( + std::string& hostname + ); + +// ----------------- + + int + hostname_to_ip ( + const std::string& hostname, + std::string& ip, + int n = 0 + ); + +// ----------------- + + int + ip_to_hostname ( + const std::string& ip, + std::string& hostname + ); + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // connection object +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + class connection + { + /*! + INITIAL_VALUE + - sd == false + - sdo == false + - sdr == 0 + + CONVENTION + - connection_socket == the socket handle for this connection. + - connection_foreign_port == the port that foreign host is using for + this connection. + - connection_foreign_ip == a string containing the IP address of the + foreign host. + - connection_local_port == the port that the local host is using for + this connection. + - connection_local_ip == a string containing the IP address of the + local interface being used by this connection. + + - sd == if shutdown() has been called then true else false. + - sdo == if shutdown_outgoing() has been called then true else false. + - sdr == the return value of shutdown() if it has been called. if it + hasn't been called then 0. + + !*/ + + friend class listener; // make listener a friend of connection + // make create_connection a friend of connection + friend int create_connection ( + connection*& new_connection, + unsigned short foreign_port, + const std::string& foreign_ip, + unsigned short local_port, + const std::string& local_ip + ); + + public: + + ~connection ( + ); + + void* user_data; + + long write ( + const char* buf, + long num + ); + + long read ( + char* buf, + long num + ); + + long read ( + char* buf, + long num, + unsigned long timeout + ); + + unsigned short get_local_port ( + ) const { return connection_local_port; } + + unsigned short get_foreign_port ( + ) const { return connection_foreign_port; } + + const std::string& get_local_ip ( + ) const { return connection_local_ip; } + + const std::string& get_foreign_ip ( + ) const { return connection_foreign_ip; } + + int shutdown_outgoing ( + ); + + int shutdown ( + ); + + // I would use SOCKET here but I don't want to include the windows + // header files since they bring in a bunch of unpleasantness. So + // I'm doing this instead which should ultimately be the same type + // as the SOCKET win the windows API. + typedef unsigned_type::type socket_descriptor_type; + + int disable_nagle( + ); + + socket_descriptor_type get_socket_descriptor ( + ) const; + + private: + + bool readable ( + unsigned long timeout + ) const; + /*! + requires + - timeout < 2000000 + ensures + - returns true if a read call on this connection will not block. + - returns false if a read call on this connection will block or if + there was an error. + !*/ + + bool sd_called ( + )const + /*! + ensures + - returns true if shutdown() has been called else + returns false + !*/ + { + sd_mutex.lock(); + bool temp = sd; + sd_mutex.unlock(); + return temp; + } + + bool sdo_called ( + )const + /*! + ensures + - returns true if shutdown_outgoing() or shutdown() has been called + else returns false + !*/ + { + sd_mutex.lock(); + bool temp = false; + if (sdo || sd) + temp = true; + sd_mutex.unlock(); + return temp; + } + + + // data members + SOCKET_container& connection_socket; + const unsigned short connection_foreign_port; + const std::string connection_foreign_ip; + const unsigned short connection_local_port; + const std::string connection_local_ip; + + bool sd; // called shutdown + bool sdo; // called shutdown_outgoing + int sdr; // return value for shutdown + mutex sd_mutex; // a lock for the three above vars + + + connection( + SOCKET_container sock, + unsigned short foreign_port, + const std::string& foreign_ip, + unsigned short local_port, + const std::string& local_ip + ); + /*! + requires + sock is a socket handle and + sock is the handle for the connection between foreign_ip:foreign_port + and local_ip:local_port + ensures + *this is initialized correctly with the above parameters + !*/ + + + // restricted functions + connection(connection&); // copy constructor + connection& operator=(connection&); // assignment operator + }; + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // listener object +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + class listener + { + /*! + CONVENTION + if (inaddr_any == false) + { + listening_ip == a string containing the address the listener is + listening on + } + else + { + the listener is listening on all interfaces + } + + listening_port == the port the listener is listening on + listening_socket == the listening socket handle for this object + !*/ + + // make the create_listener a friend of listener + friend int create_listener ( + listener*& new_listener, + unsigned short port, + const std::string& ip + ); + + public: + + ~listener ( + ); + + int accept ( + connection*& new_connection, + unsigned long timeout = 0 + ); + + int accept ( + std::unique_ptr& new_connection, + unsigned long timeout = 0 + ); + + unsigned short get_listening_port ( + ) { return listening_port; } + + const std::string& get_listening_ip ( + ) { return listening_ip; } + + private: + + // data members + SOCKET_container& listening_socket; + const unsigned short listening_port; + const std::string listening_ip; + const bool inaddr_any; + + listener( + SOCKET_container sock, + unsigned short port, + const std::string& ip + ); + /*! + requires + sock is a socket handle and + sock is listening on the port and ip(may be "") indicated in the + above parameters + ensures + *this is initialized correctly with the above parameters + !*/ + + + // restricted functions + listener(listener&); // copy constructor + listener& operator=(listener&); // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + + int create_listener ( + listener*& new_listener, + unsigned short port, + const std::string& ip = "" + ); + + int create_connection ( + connection*& new_connection, + unsigned short foreign_port, + const std::string& foreign_ip, + unsigned short local_port = 0, + const std::string& local_ip = "" + ); + + int create_listener ( + std::unique_ptr& new_listener, + unsigned short port, + const std::string& ip = "" + ); + + int create_connection ( + std::unique_ptr& new_connection, + unsigned short foreign_port, + const std::string& foreign_ip, + unsigned short local_port = 0, + const std::string& local_ip = "" + ); + +// ---------------------------------------------------------------------------------------- + + +} + +#ifdef NO_MAKEFILE +#include "sockets_kernel_1.cpp" +#endif + +#endif // DLIB_SOCKETS_KERNEl_1_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets/sockets_kernel_2.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets/sockets_kernel_2.h new file mode 100644 index 0000000..f3bc94e --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets/sockets_kernel_2.h @@ -0,0 +1,396 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net), Miguel Grinberg +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_SOCKETS_KERNEl_2_ +#define DLIB_SOCKETS_KERNEl_2_ + +#ifdef DLIB_ISO_CPP_ONLY +#error "DLIB_ISO_CPP_ONLY is defined so you can't use this OS dependent code. Turn DLIB_ISO_CPP_ONLY off if you want to use it." +#endif + +#include "../platform.h" + +#include "sockets_kernel_abstract.h" + +#define _BSD_SOCKLEN_T_ + +#include +#include +#include + +#include +#include +#include + +#ifndef HPUX +#include +#endif +#include +#include +#include +#include +#include +#include + +#include + +#include "../threads.h" +#include "../algs.h" + + + + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + // forward declarations + class socket_factory; + class listener; + +// ---------------------------------------------------------------------------------------- + + // lookup functions + + int + get_local_hostname ( + std::string& hostname + ); + +// ----------------- + + int + hostname_to_ip ( + const std::string& hostname, + std::string& ip, + int n = 0 + ); + +// ----------------- + + int + ip_to_hostname ( + const std::string& ip, + std::string& hostname + ); + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // connection object +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + class connection + { + /*! + INITIAL_VALUE + sd == false + sdo == false + sdr == 0 + + + CONVENTION + connection_socket == the socket handle for this connection. + connection_foreign_port == the port that foreign host is using for + this connection + connection_foreign_ip == a string containing the IP address of the + foreign host + connection_local_port == the port that the local host is using for + this connection + connection_local_ip == a string containing the IP address of the + local interface being used by this connection + + sd == if shutdown() has been called then true + else false + sdo == if shutdown_outgoing() has been called then true + else false + sdr == the return value of shutdown() if it has been + called. if it hasn't been called then 0 + + + !*/ + + friend class listener; // make listener a friend of connection + // make create_connection a friend of connection + friend int create_connection ( + connection*& new_connection, + unsigned short foreign_port, + const std::string& foreign_ip, + unsigned short local_port, + const std::string& local_ip + ); + + public: + + ~connection(); + + void* user_data; + + long write ( + const char* buf, + long num + ); + + long read ( + char* buf, + long num + ); + + long read ( + char* buf, + long num, + unsigned long timeout + ); + + int get_local_port ( + ) const { return connection_local_port; } + + int get_foreign_port ( + ) const { return connection_foreign_port; } + + const std::string& get_local_ip ( + ) const { return connection_local_ip; } + + const std::string& get_foreign_ip ( + ) const { return connection_foreign_ip; } + + int shutdown_outgoing ( + ) + { + sd_mutex.lock(); + if (sdo || sd) + { + sd_mutex.unlock(); + return sdr; + } + sdo = true; + sdr = ::shutdown(connection_socket,SHUT_WR); + int temp = sdr; + sd_mutex.unlock(); + return temp; + } + + int shutdown ( + ) + { + sd_mutex.lock(); + if (sd) + { + sd_mutex.unlock(); + return sdr; + } + sd = true; + sdr = ::shutdown(connection_socket,SHUT_RDWR); + int temp = sdr; + sd_mutex.unlock(); + return temp; + } + + int disable_nagle( + ); + + typedef int socket_descriptor_type; + + socket_descriptor_type get_socket_descriptor ( + ) const { return connection_socket; } + + private: + + bool readable ( + unsigned long timeout + ) const; + /*! + requires + - timeout < 2000000 + ensures + - returns true if a read call on this connection will not block. + - returns false if a read call on this connection will block or if + there was an error. + !*/ + + bool sd_called ( + )const + /*! + ensures + - returns true if shutdown() has been called else + - returns false + !*/ + { + sd_mutex.lock(); + bool temp = sd; + sd_mutex.unlock(); + return temp; + } + + bool sdo_called ( + )const + /*! + ensures + - returns true if shutdown_outgoing() or shutdown() has been called + else returns false + !*/ + { + sd_mutex.lock(); + bool temp = false; + if (sdo || sd) + temp = true; + sd_mutex.unlock(); + return temp; + } + + + // data members + int connection_socket; + const int connection_foreign_port; + const std::string connection_foreign_ip; + const int connection_local_port; + const std::string connection_local_ip; + + bool sd; // called shutdown + bool sdo; // called shutdown_outgoing + int sdr; // return value for shutdown + mutex sd_mutex; // a lock for the three above vars + + connection( + int sock, + int foreign_port, + const std::string& foreign_ip, + int local_port, + const std::string& local_ip + ); + /*! + requires + - sock is a socket handle + - sock is the handle for the connection between foreign_ip:foreign_port + and local_ip:local_port + ensures + - *this is initialized correctly with the above parameters + !*/ + + + // restricted functions + connection(); + connection(connection&); // copy constructor + connection& operator=(connection&); // assignement opertor + }; + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // listener object +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + class listener + { + /*! + CONVENTION + if (inaddr_any == false) + { + listening_ip == a string containing the address the listener is + listening on + } + else + { + the listener is listening on all interfaces + } + + listening_port == the port the listener is listening on + listening_socket == the listening socket handle for this object + !*/ + + // make the create_listener a friend of listener + friend int create_listener ( + listener*& new_listener, + unsigned short port, + const std::string& ip + ); + + public: + + ~listener(); + + int accept ( + connection*& new_connection, + unsigned long timeout = 0 + ); + + int accept ( + std::unique_ptr& new_connection, + unsigned long timeout = 0 + ); + + int get_listening_port ( + ) const { return listening_port; } + + const std::string& get_listening_ip ( + ) const { return listening_ip; } + + private: + + // data members + int listening_socket; + const int listening_port; + const std::string listening_ip; + const bool inaddr_any; + + listener( + int sock, + int port, + const std::string& ip + ); + /*! + requires + - sock is a socket handle + - sock is listening on the port and ip(may be "") indicated in the above + parameters + ensures + - *this is initialized correctly with the above parameters + !*/ + + + // restricted functions + listener(); + listener(listener&); // copy constructor + listener& operator=(listener&); // assignement opertor + }; + +// ---------------------------------------------------------------------------------------- + + int create_listener ( + listener*& new_listener, + unsigned short port, + const std::string& ip = "" + ); + + int create_connection ( + connection*& new_connection, + unsigned short foreign_port, + const std::string& foreign_ip, + unsigned short local_port = 0, + const std::string& local_ip = "" + ); + + int create_listener ( + std::unique_ptr& new_listener, + unsigned short port, + const std::string& ip = "" + ); + + int create_connection ( + std::unique_ptr& new_connection, + unsigned short foreign_port, + const std::string& foreign_ip, + unsigned short local_port = 0, + const std::string& local_ip = "" + ); + +// ---------------------------------------------------------------------------------------- + +} + +#ifdef NO_MAKEFILE +#include "sockets_kernel_2.cpp" +#endif + +#endif // DLIB_SOCKETS_KERNEl_2_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets/sockets_kernel_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets/sockets_kernel_abstract.h new file mode 100644 index 0000000..d4571ac --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets/sockets_kernel_abstract.h @@ -0,0 +1,495 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_SOCKETS_KERNEl_ABSTRACT_ +#ifdef DLIB_SOCKETS_KERNEl_ABSTRACT_ + +#include +#include "../threads.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + /*! + GENERAL COMMENTS: + Nothing in here will throw exceptions. + + All ip address strings in this file refer to IPv4 addresses. For + example "192.168.1.1" + + Timeouts: + All timeout values are measured in milliseconds but you are not + guaranteed to have that level of resolution. The actual resolution + is implementation defined. + + GENERAL WARNING + Don't call any of these functions or make any of these objects + before main() has been entered. + + EXCEPTIONS + Unless specified otherwise, nothing in this file throws exceptions. + !*/ + +// ---------------------------------------------------------------------------------------- + + // LOOKUP FUNCTIONS + + // all lookup functions are thread-safe + + int get_local_hostname ( + std::string& hostname + ); + /*! + ensures + - if (#get_local_hostname() == 0) then + - #hostname == a string containing the hostname of the local computer + + - returns 0 upon success + - returns OTHER_ERROR upon failure and in this case #hostname's value + is undefined + !*/ + +// ----------------- + + int hostname_to_ip ( + const std::string& hostname, + std::string& ip, + int n = 0 + ); + /*! + requires + - n >= 0 + ensures + - if (#hostname_to_ip() == 0) then + - #ip == string containing the nth ip address associated with the hostname + + - returns 0 upon success + - returns OTHER_ERROR upon failure + !*/ + +// ----------------- + + int ip_to_hostname ( + const std::string& ip, + std::string& hostname + ); + /*! + ensures + - if (#ip_to_hostname() == 0) then + - #hostname == string containing the hostname associated with ip + + - returns 0 upon success + - returns OTHER_ERROR upon failure + !*/ + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // + // socket creation functions + // + // The following functions are guaranteed to be thread-safe + // +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + int create_listener ( + listener*& new_listener, + unsigned short port, + const std::string& ip = "" + ); + /*! + requires + - 0 <= port <= 65535 + ensures + - if (#create_listener() == 0) then + - #new_listener == a pointer to a listener object that is listening on + the specified port and ip for an incoming connection + - if (ip == "") then + - the new listener will be listening on all interfaces + - if (port == 0) then + - the operating system will assign a free port to listen on + + + - returns 0 if create_listener was successful + - returns PORTINUSE if the specified local port was already in use + - returns OTHER_ERROR if some other error occurred + !*/ + + int create_listener ( + std::unique_ptr& new_listener, + unsigned short port, + const std::string& ip = "" + ); + /*! + This function is just an overload of the above function but it gives you a + std::unique_ptr smart pointer instead of a C pointer. + !*/ + + int create_connection ( + connection*& new_connection, + unsigned short foreign_port, + const std::string& foreign_ip, + unsigned short local_port = 0, + const std::string& local_ip = "" + ); + /*! + requires + - 0 < foreign_port <= 65535 + - 0 <= local_port <= 65535 + ensures + - if (#create_connection() == 0) then + - #new_connection == a pointer to a connection object that is connected + to foreign_ip on port foreign_port and is using the local interface + local_ip and local port local_port + - #new_connection->user_data == 0 + - if (local_ip == "") then + - the operating system will chose this for you + - if (local_port == 0) then + - the operating system will chose this for you + + - returns 0 if create_connection was successful + - returns PORTINUSE if the specified local port was already in use + - returns OTHER_ERROR if some other error occurred + !*/ + + int create_connection ( + std::unique_ptr& new_connection, + unsigned short foreign_port, + const std::string& foreign_ip, + unsigned short local_port = 0, + const std::string& local_ip = "" + ); + /*! + This function is just an overload of the above function but it gives you a + std::unique_ptr smart pointer instead of a C pointer. + !*/ + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // connection object +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + class connection + { + /*! + WHAT THIS OBJECT REPRESENTS + This object represents a TCP connection. + + Instances of this class can only be created by using the + create_connection function or listener class defined below. + + NOTE: + A connection object must ALWAYS be closed (delete the pointer to the + connection) or it will cause a resource leak. + + Note also that all errors indicated by a return code of OTHER_ERROR + are fatal so if one occurs the connection should just be closed. + + CLOSING A CONNECTION + Note that if ~connection() or shutdown() is called before the remote client + has received all sent data it is possible that the data will be lost. To + avoid this you should call the close_gracefully() function to close your + connections (unless you actually do want to immediately dispose of a + connection and don't care about the data). + (example: close_gracefully(con); // close con gracefully but force it closed + // if it takes more than 500 milliseconds.) + + THREAD SAFETY + - It is always safe to call shutdown() or shutdown_outgoing(). + - you may NOT call any function more than once at a time (except the + shutdown functions). + - do not call read() more than once at a time + - do not call write() more than once at a time + - You can safely call shutdown or shutdown_outgoing in conjunction with + the read/write functions. + This is helpful if you want to unblock another thread that is + blocking on a read/write operation. Shutting down the connection + will cause the read/write functions to return a value of SHUTDOWN. + + OUT-OF-BAND DATA: + All out-of-band data will be put inline into the normal data stream. + This means that you can read any out-of-band data via calls to read(). + (i.e. the SO_OOBINLINE socket option will be set) + !*/ + + public: + + ~connection ( + ); + /*! + requires + - no other threads are using this connection object + ensures + - closes the connection (this is an abrupt non-graceful close) + - frees the resources used by this object + !*/ + + void* user_data; + /*! + This pointer is provided so that the client programmer may easily associate + some data with a connection object. You can really do whatever you want + with it. Initially user_data is 0. + !*/ + + long write ( + const char* buf, + long num + ); + /*! + requires + - num > 0 + - buf points to an array of at least num bytes + ensures + - will block until ONE of the following occurs: + - num bytes from buf have been written to the connection + - an error has occurred + - the outgoing channel of the connection has been shutdown locally + + - returns num if write succeeded + - returns OTHER_ERROR if there was an error (this could be due to a + connection close) + - returns SHUTDOWN if the outgoing channel of the connection has been + shutdown locally + !*/ + + long read ( + char* buf, + long num + ); + /*! + requires + - num > 0 + - buf points to an array of at least num bytes + ensures + - read() will not read more than num bytes of data into #buf + - read blocks until ONE of the following happens: + - there is some data available and it has been written into #buf + - the remote end of the connection is closed + - an error has occurred + - the connection has been shutdown locally + + - returns the number of bytes read into #buf if there was any data. + - returns 0 if the connection has ended/terminated and there is no more data. + - returns OTHER_ERROR if there was an error. + - returns SHUTDOWN if the connection has been shutdown locally + !*/ + + long read ( + char* buf, + long num, + unsigned long timeout + ); + /*! + requires + - num > 0 + - buf points to an array of at least num bytes + - timeout < 2000000 + ensures + - read() will not read more than num bytes of data into #buf + - if (timeout > 0) then read() blocks until ONE of the following happens: + - there is some data available and it has been written into #buf + - the remote end of the connection is closed + - an error has occurred + - the connection has been shutdown locally + - timeout milliseconds has elapsed + - else + - read() does not block + + - returns the number of bytes read into #buf if there was any data. + - returns 0 if the connection has ended/terminated and there is no more data. + - returns TIMEOUT if timeout milliseconds elapsed before we got any data. + - returns OTHER_ERROR if there was an error. + - returns SHUTDOWN if the connection has been shutdown locally + !*/ + + unsigned short get_local_port ( + ) const; + /*! + ensures + - returns the local port number for this connection + !*/ + + unsigned short get_foreign_port ( + ) const; + /*! + ensures + - returns the foreign port number for this connection + !*/ + + const std::string& get_local_ip ( + ) const; + /*! + ensures + - returns the IP of the local interface this connection is using + !*/ + + const std::string& get_foreign_ip ( + ) const; + /*! + ensures + - returns the IP of the foreign host for this connection + !*/ + + int shutdown ( + ); + /*! + ensures + - if (#shutdown() == 0 && connection was still open) then + - terminates the connection but does not free the resources for the + connection object + + - any read() or write() calls on this connection will return immediately + with the code SHUTDOWN. + + - returns 0 upon success + - returns OTHER_ERROR if there was an error + !*/ + + int shutdown_outgoing ( + ); + /*! + ensures + - if (#shutdown_outgoing() == 0 && outgoing channel was still open) then + - sends a FIN to indicate that no more data will be sent on this + connection but leaves the receive half of the connection open to + receive more data from the other host + + - any calls to write() will return immediately with the code SHUTDOWN. + + - returns 0 upon success + - returns OTHER_ERROR if there was an error + !*/ + + int disable_nagle( + ); + /*! + ensures + - Sets the TCP_NODELAY socket option to disable Nagle's algorithm. + This can sometimes reduce transmission latency, however, in almost + all normal cases you don't want to mess with this as the default + setting is usually appropriate. + + - returns 0 upon success + - returns OTHER_ERROR if there was an error + !*/ + + typedef platform_specific_type socket_descriptor_type; + socket_descriptor_type get_socket_descriptor ( + ) const; + /*! + ensures + - returns the underlying socket descriptor for this connection + object. The reason you might want access to this is to + pass it to some other library that requires a socket file + descriptor. However, if you do this then you probably shouldn't + use the dlib::connection read() and write() anymore since + whatever you are doing with the socket descriptor is probably + doing I/O with the socket. + !*/ + + private: + // restricted functions + connection(); + connection(connection&); // copy constructor + connection& operator=(connection&); // assignment operator + + }; + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // listener object +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + class listener + { + /*! + WHAT THIS OBJECT REPRESENTS + This object represents a TCP socket waiting for incoming connections. + Calling accept returns a pointer to any new incoming connections on its + port. + + Instances of this class can only be created by using the + create_listener function defined below. + + NOTE: + A listener object must ALWAYS be closed (delete the pointer to it) or + it will cause a resource leak. + + Note also that all errors indicated by a return code of OTHER_ERROR + are fatal so if one occurs the listener should be closed. + + THREAD SAFETY + None of the functions in this object are guaranteed to be thread-safe. + This means that you must serialize all access to this object. + !*/ + + public: + + ~listener ( + ); + /*! + requires + - no other threads are using this listener object + ensures + - closes the listener + - frees the resources used by this object + !*/ + + int accept ( + connection*& new_connection, + unsigned long timeout = 0 + ); + /*! + requires + - timeout < 2000000 + ensures + - blocks until a new connection is ready or timeout milliseconds have + elapsed. + - #new_connection == a pointer to the new connection object + - #new_connection->user_data == 0 + - if (timeout == 0) then + - the timeout argument is ignored + + - returns 0 if accept() was successful + - returns TIMEOUT if timeout milliseconds have elapsed + - returns OTHER_ERROR if an error has occurred + !*/ + + int accept ( + std::unique_ptr& new_connection, + unsigned long timeout = 0 + ); + /*! + This function is just an overload of the above function but it gives you a + std::unique_ptr smart pointer instead of a C pointer. + !*/ + + unsigned short get_listening_port ( + ) const; + /*! + ensures + - returns the port number that this object is listening on + !*/ + + const std::string& get_listening_ip ( + ) const; + /*! + ensures + - returns a string containing the IP (e.g. "127.0.0.1") of the + interface this object is listening on + - returns "" if it is accepting connections on all interfaces + !*/ + + private: + // restricted functions + listener(); + listener(listener&); // copy constructor + listener& operator=(listener&); // assignment operator + }; +} + +#endif // DLIB_SOCKETS_KERNEl_ABSTRACT_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets/windows.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets/windows.h new file mode 100644 index 0000000..85b7fd8 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sockets/windows.h @@ -0,0 +1,6 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_SOCKETS_KERNEl_2_ +#include "sockets_kernel_1.h" +#endif + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sort.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sort.h new file mode 100644 index 0000000..c798372 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sort.h @@ -0,0 +1,490 @@ +// Copyright (C) 2005 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_SORt_ +#define DLIB_SORt_ + +#include "algs.h" +#include + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename compare + > + inline void qsort_array ( + T& array, + unsigned long left, + unsigned long right, + const compare& comp + ); + /*! + requires + - T implements operator[] + - the items in array must be comparable by comp where comp is a function + object with the same syntax as std::less<> + - the items in array must be swappable by a global swap() + - left and right are within the bounds of array + i.e. array[left] and array[right] are valid elements + - left <= right + ensures + - for all elements in #array between and including left and right the + ith element is < the i+1 element + - sorts using a quick sort algorithm + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename compare + > + void hsort_array ( + T& array, + unsigned long left, + unsigned long right, + const compare& comp + ); + /*! + requires + - T implements operator[] + - the items in array must be comparable by comp where comp is a function + object with the same syntax as std::less<> + - the items in array must be swappable by a global swap() + - left and right are within the bounds of array + i.e. array[left] and array[right] are valid elements + - left <= right + ensures + - for all elements in #array between and including left and right the + ith element is < the i+1 element + - sorts using a heapsort algorithm + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename compare + > + void isort_array ( + T& array, + unsigned long left, + unsigned long right, + const compare& comp + ); + /*! + requires + - T implements operator[] + - the items in array must be comparable by comp where comp is a function + object with the same syntax as std::less<> + - the items in array must be swappable by a global swap() + - left and right are within the bounds of array + i.e. array[left] and array[right] are valid elements + - left <= right + ensures + - for all elements in #array between and including left and right the + ith element is < the i+1 element + - sorts using an insertion sort algorithm + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + inline void qsort_array ( + T& array, + unsigned long left, + unsigned long right + ); + /*! + requires + - T implements operator[] + - the items in array must be comparable by std::less + - the items in array must be swappable by a global swap() + - left and right are within the bounds of array + i.e. array[left] and array[right] are valid elements + - left <= right + ensures + - for all elements in #array between and including left and right the + ith element is < the i+1 element + - sorts using a quick sort algorithm + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void hsort_array ( + T& array, + unsigned long left, + unsigned long right + ); + /*! + requires + - T implements operator[] + - the items in array must be comparable by std::less + - the items in array must be swappable by a global swap() + - left and right are within the bounds of array + i.e. array[left] and array[right] are valid elements + - left <= right + ensures + - for all elements in #array between and including left and right the + ith element is < the i+1 element + - sorts using a heapsort algorithm + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void isort_array ( + T& array, + unsigned long left, + unsigned long right + ); + /*! + requires + - T implements operator[] + - the items in array must be comparable by std::less + - the items in array must be swappable by a global swap() + - left and right are within the bounds of array + i.e. array[left] and array[right] are valid elements + - left <= right + ensures + - for all elements in #array between and including left and right the + ith element is < the i+1 element + - sorts using an insertion sort algorithm + !*/ + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// IMPLEMENTATION DETAILS +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + namespace sort_helpers + { + template + inline const std::less comp (const T&) + { + return std::less(); + } + + template < + typename T, + typename Y, + typename compare + > + inline unsigned long qsort_partition ( + T& array, + Y& pivot, + const unsigned long left, + const unsigned long right, + const compare& comp + ) + /*! + requires + - &pivot == &array[right] + - T implements operator[] + - the items in array must be comparable by comp + - left and right are within the bounts of the array + - left < right + ensures + - returns a number called partition_element such that: + - left <= partition_element <= right + - all elements in #array < #array[partition_element] have + indices >= left and < partition_element + - all elements in #array > #array[partition_element] have + indices > partition_element and <= right + !*/ + { + DLIB_ASSERT (&pivot == &array[right] && left < right, + "\tunsigned long qsort_partition()" + << "\n\t&pivot: " << &pivot + << "\n\t&array[right]: " << &array[right] + << "\n\tleft: " << left + << "\n\tright: " << right ); + + exchange(array[(right-left)/2 +left],pivot); + + unsigned long i = left; + for (unsigned long j = left; j < right; ++j) + { + if (comp(array[j] , pivot)) + { + swap(array[i],array[j]); + ++i; + } + } + exchange(array[i],pivot); + + return i; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename compare + > + void qsort_array_main ( + T& array, + const unsigned long left, + const unsigned long right, + unsigned long depth_check, + const compare& comp + ) + /*! + requires + - T implements operator[] + - the items in array must be comparable by comp + - the items in array must be swappable by a global swap() + - left and right are within the bounds of array + i.e. array[left] and array[right] are valid elements + ensures + - for all elements in #array between and including left and right the + ith element is < the i+1 element + - will only recurse about as deep as log(depth_check) calls + - sorts using a quick sort algorithm + !*/ + { + if ( left < right) + { + if (right-left < 30 || depth_check == 0) + { + hsort_array(array,left,right,comp); + } + else + { + // The idea here is to only let quick sort go about log(N) + // calls deep before it kicks into something else. + depth_check >>= 1; + depth_check += (depth_check>>4); + + unsigned long partition_element = + qsort_partition(array,array[right],left,right,comp); + + if (partition_element > 0) + qsort_array_main(array,left,partition_element-1,depth_check,comp); + qsort_array_main(array,partition_element+1,right,depth_check,comp); + } + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename compare + > + void heapify ( + T& array, + const unsigned long start, + const unsigned long end, + unsigned long i, + const compare& comp + ) + /*! + requires + - T implements operator[] + - the items in array must be comparable by comp + - the items in array must be swappable by a global swap() + - start, end, and i are within the bounds of array + i.e. array[start], array[end], and array[i] are valid elements + - start <= i <= end + - array[i/2] is a max heap + - array[i/2+1] is a max heap + - start and end specify the range of the array we are working with. + ensures + - array[i] is now a max heap + !*/ + { + DLIB_ASSERT (start <= i && i <= end, + "\tvoid heapify()" + << "\n\tstart: " << start + << "\n\tend: " << end + << "\n\ti: " << i ); + + bool keep_going = true; + unsigned long left; + unsigned long right; + unsigned long largest; + while (keep_going) + { + keep_going = false; + left = (i<<1)+1-start; + right = left+1; + + if (left <= end && comp(array[i] , array[left])) + largest = left; + else + largest = i; + + if (right <= end && comp(array[largest] , array[right])) + largest = right; + + if (largest != i) + { + exchange(array[i],array[largest]); + i = largest; + keep_going = true; + } + } + } + +// ---------------------------------------------------------------------------------------- + } +// ---------------------------------------------------------------------------------------- + + + template < + typename T + > + inline void qsort_array ( + T& array, + unsigned long left, + unsigned long right + ) + { + using namespace sort_helpers; + qsort_array(array,left,right,comp(array[left])); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void hsort_array ( + T& array, + unsigned long left, + unsigned long right + ) + { + using namespace sort_helpers; + hsort_array(array,left,right,comp(array[left])); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void isort_array ( + T& array, + unsigned long left, + unsigned long right + ) + { + using namespace sort_helpers; + isort_array(array,left,right,comp(array[left])); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename compare + > + void isort_array ( + T& array, + const unsigned long left, + const unsigned long right, + const compare& comp + ) + { + DLIB_ASSERT (left <= right, + "\tvoid isort_array()" + << "\n\tleft: " << left + << "\n\tright: " << right ); + using namespace sort_helpers; + + unsigned long pos; + for (unsigned long i = left+1; i <= right; ++i) + { + // everything from left to i-1 is sorted. + pos = i; + for (unsigned long j = i-1; comp(array[pos] , array[j]); --j) + { + exchange(array[pos],array[j]); + pos = j; + + if (j == left) + break; + } + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename compare + > + void qsort_array ( + T& array, + const unsigned long left, + const unsigned long right, + const compare& comp + ) + { + DLIB_ASSERT (left <= right, + "\tvoid qsort_array()" + << "\n\tleft: " << left + << "\n\tright: " << right ); + + sort_helpers::qsort_array_main(array,left,right,right-left,comp); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename compare + > + void hsort_array ( + T& array, + const unsigned long left, + const unsigned long right, + const compare& comp + ) + { + DLIB_ASSERT (left <= right, + "\tvoid hsort_array()" + << "\n\tleft: " << left + << "\n\tright: " << right ); + + if (right-left < 30) + { + isort_array(array,left,right,comp); + return; + } + + // turn array into a max heap + for (unsigned long i = left+((right-left)>>1);; --i) + { + sort_helpers::heapify(array,left,right,i,comp); + if (i == left) + break; + } + + // now sort the array + for (unsigned long i = right; i > left;) + { + exchange(array[i],array[left]); + sort_helpers::heapify(array,left,--i,left,comp); + } + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_SORt_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sparse_vector.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sparse_vector.h new file mode 100644 index 0000000..4be6a3a --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sparse_vector.h @@ -0,0 +1,10 @@ +// Copyright (C) 2012 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_SPaRSE_VECTOR_Hh_ +#define DLIB_SPaRSE_VECTOR_Hh_ + +#include "svm/sparse_vector.h" + +#endif // DLIB_SPaRSE_VECTOR_Hh_ + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sstream b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sstream new file mode 100644 index 0000000..eb0e59e --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/sstream @@ -0,0 +1 @@ +#include "dlib_include_path_tutorial.txt" diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stack.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stack.h new file mode 100644 index 0000000..58f2c5a --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stack.h @@ -0,0 +1,34 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_STACk_ +#define DLIB_STACk_ + +#include "stack/stack_kernel_1.h" +#include "stack/stack_kernel_c.h" +#include "algs.h" + +namespace dlib +{ + + template < + typename T, + typename mem_manager = default_memory_manager + > + class stack + { + stack() {} + public: + + //----------- kernels --------------- + + // kernel_1a + typedef stack_kernel_1 + kernel_1a; + typedef stack_kernel_c + kernel_1a_c; + + }; +} + +#endif // DLIB_STACk_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stack/stack_kernel_1.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stack/stack_kernel_1.h new file mode 100644 index 0000000..d67992e --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stack/stack_kernel_1.h @@ -0,0 +1,504 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_STACK_KERNEl_1_ +#define DLIB_STACK_KERNEl_1_ + +#include "stack_kernel_abstract.h" +#include "../algs.h" +#include "../interfaces/enumerable.h" +#include "../interfaces/remover.h" +#include "../serialize.h" + +namespace dlib +{ + + template < + typename T, + typename mem_manager = default_memory_manager + > + class stack_kernel_1 : public enumerable, + public remover + { + + /*! + INITIAL VALUE + stack_size == 0 + top == 0 + current_element == 0 + _at_start == true + + + CONVENTION + at_start() == _at_start + current_element_valid() == (current_element != 0) + if (current_element != 0) then + element() == current_element->item + + stack_size == the number of elements in the stack. + Each node points to the next node to be poped off the stack. + The last node in the list has its next pointer is set to 0. + + if (size == 0) + { + top == 0 + } + else + { + top == pointer to the last element added to the stack + } + !*/ + + struct node + { + node* next; + T item; + }; + + public: + + typedef T type; + typedef mem_manager mem_manager_type; + + stack_kernel_1( + ): + top(0), + stack_size(0), + current_element(0), + _at_start(true) + {} + + virtual ~stack_kernel_1( + ); + + inline void clear( + ); + + inline void push( + T& item + ); + + void pop( + T& item + ); + + T& current( + ); + + const T& current( + ) const; + + inline void swap ( + stack_kernel_1& item + ); + + // functions from the remover interface + inline void remove_any ( + T& item + ); + + // functions from the enumerable interface + inline size_t size ( + ) const; + + inline bool at_start ( + ) const; + + inline void reset ( + ) const; + + bool current_element_valid ( + ) const; + + inline const T& element ( + ) const; + + inline T& element ( + ); + + bool move_next ( + ) const; + + private: + + void delete_elements_in_stack( + node*& top + ); + /*! + requires + - top points to the top of the stack + ensures + - all memory has been freed + - #top = 0 + !*/ + + + // data members + typename mem_manager::template rebind::other pool; + node* top; + unsigned long stack_size; + mutable node* current_element; + mutable bool _at_start; + + + // restricted functions + stack_kernel_1(stack_kernel_1&); // copy constructor + stack_kernel_1& operator=(stack_kernel_1&); // assignment operator + + }; + + + template < + typename T, + typename mem_manager + > + inline void swap ( + stack_kernel_1& a, + stack_kernel_1& b + ) { a.swap(b); } + + template < + typename T, + typename mem_manager + > + void deserialize ( + stack_kernel_1& item, + std::istream& in + ) + { + try + { + item.clear(); + unsigned long size; + deserialize(size,in); + T temp = T(); + stack_kernel_1 temp_stack; + for (unsigned long i = 0; i < size; ++i) + { + deserialize(temp,in); + temp_stack.push(temp); + } + while (temp_stack.size() > 0) + { + temp_stack.pop(temp); + item.push(temp); + } + } + catch (serialization_error& e) + { + item.clear(); + throw serialization_error(e.info + "\n while deserializing object of type stack_kernel_1"); + } + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + stack_kernel_1:: + ~stack_kernel_1( + ) + { + delete_elements_in_stack(top); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + void stack_kernel_1:: + clear( + ) + { + if (stack_size != 0) + { + delete_elements_in_stack(top); + stack_size = 0; + } + reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + T& stack_kernel_1:: + current( + ) + { + return top->item; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + const T& stack_kernel_1:: + current( + ) const + { + return top->item; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + void stack_kernel_1:: + swap( + stack_kernel_1& item + ) + { + pool.swap(item.pool); + + // declare temp variables + node* top_temp; + unsigned long stack_size_temp; + + // swap stack_size variables + stack_size_temp = item.stack_size; + item.stack_size = stack_size; + stack_size = stack_size_temp; + + // swap top pointers + top_temp = item.top; + item.top = top; + top = top_temp; + + exchange(current_element,item.current_element); + exchange(_at_start,item._at_start); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + void stack_kernel_1:: + push( + T& item + ) + { + // allocate memory for new node + node* new_node = pool.allocate(); + + // swap item into new_node + exchange(new_node->item,item); + + // put new_node into stack + new_node->next = top; + top = new_node; + ++stack_size; + + reset(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + void stack_kernel_1:: + pop( + T& item + ) + { + node* old_node = top; + top = top->next; + + // swap the item from the stack into item + exchange(old_node->item,item); + + // free the memory + pool.deallocate(old_node); + --stack_size; + + reset(); + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // private member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + void stack_kernel_1:: + delete_elements_in_stack( + node*& top + ) + { + node* temp; + while (top != 0) + { + temp = top->next; + pool.deallocate(top); + top = temp; + } + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // enumerable function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + size_t stack_kernel_1:: + size ( + ) const + { + return stack_size; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + bool stack_kernel_1:: + at_start ( + ) const + { + return _at_start; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + void stack_kernel_1:: + reset ( + ) const + { + _at_start = true; + current_element = 0; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + bool stack_kernel_1:: + current_element_valid ( + ) const + { + return current_element != 0; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + const T& stack_kernel_1:: + element ( + ) const + { + return current_element->item; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + T& stack_kernel_1:: + element ( + ) + { + return current_element->item; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + bool stack_kernel_1:: + move_next ( + ) const + { + if (!_at_start) + { + if (current_element) + { + current_element = current_element->next; + if (current_element) + return true; + else + return false; + } + else + { + return false; + } + } + else + { + _at_start = false; + if (stack_size) + { + current_element = top; + return true; + } + else + { + return false; + } + } + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // remover function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename mem_manager + > + void stack_kernel_1:: + remove_any ( + T& item + ) + { + pop(item); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_STACK_KERNEl_1_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stack/stack_kernel_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stack/stack_kernel_abstract.h new file mode 100644 index 0000000..d86cc06 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stack/stack_kernel_abstract.h @@ -0,0 +1,180 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_STACK_KERNEl_ABSTRACT_ +#ifdef DLIB_STACK_KERNEl_ABSTRACT_ + +#include "../interfaces/enumerable.h" +#include "../interfaces/remover.h" +#include "../serialize.h" +#include "../algs.h" + +namespace dlib +{ + + template < + typename T, + typename mem_manager = default_memory_manager + > + class stack : public enumerable, + public remover + { + + /*! + REQUIREMENTS ON T + T must be swappable by a global swap() and + T must have a default constructor + + REQUIREMENTS ON mem_manager + must be an implementation of memory_manager/memory_manager_kernel_abstract.h or + must be an implementation of memory_manager_global/memory_manager_global_kernel_abstract.h or + must be an implementation of memory_manager_stateless/memory_manager_stateless_kernel_abstract.h + mem_manager::type can be set to anything. + + POINTERS AND REFERENCES TO INTERNAL DATA + swap() and current() functions do not invalidate pointers + or references to internal data. + All other functions have no such guarantee. + + INITIAL VALUE + size() == 0 + + ENUMERATION ORDER + The enumerator will iterate over the elements in the stack in the + same order they would be removed in by repeated calls to pop(). + (e.g. current() would be the first element enumerated) + + WHAT THIS OBJECT REPRESENTS + This is a last in first out stack containing items of type T. + + e.g. if the stack is {b,c,d,e} then a is put in + the stack becomes {a,b,c,d,e} and then pop takes a back out + returning the stack to {b,c,d,e} + + Also note that unless specified otherwise, no member functions + of this object throw exceptions. + !*/ + + public: + + typedef T type; + typedef mem_manager mem_manager_type; + + stack ( + ); + /*! + ensures + - #*this is properly initialized + throws + - std::bad_alloc or any exception thrown by T's constructor + !*/ + + virtual ~stack ( + ); + /*! + ensures + - all memory associated with *this has been released + !*/ + + void clear( + ); + /*! + ensures + - #*this has its initial value + throws + - std::bad_alloc or any exception thrown by T's constructor + if this exception is thrown then *this is unusable + until clear() is called and succeeds + !*/ + + void push ( + T& item + ); + /*! + ensures + - item has been swapped onto the top of the stack + - #current() == item + - #item has an initial value for its type + - #size() == size() + 1 + - #at_start() == true + throws + - std::bad_alloc or any exception thrown by T's constructor + if push() throws then it has no effect + !*/ + + void pop ( + T& item + ); + /*! + requires + - size() != 0 + ensures + - #size() == size() - 1 + - #item == current() + i.e. the top element of *this has been removed and swapped + into #item + - #at_start() == true + !*/ + + T& current ( + ); + /*! + requires + - size() != 0 + ensures + - returns a const reference to the element at the top of *this + !*/ + + const T& current ( + ) const; + /*! + requires + - size() != 0 + ensures + - returns a non-const reference to the element at the top of *this + !*/ + + void swap ( + stack& item + ); + /*! + ensures + - swaps *this and item + !*/ + + + private: + + // restricted functions + stack(stack&); // copy constructor + stack& operator=(stack&); // assignment operator + + }; + + + template < + typename T, + typename mem_manager + > + inline void swap ( + stack& a, + stack& b + ) { a.swap(b); } + /*! + provides a global swap function + !*/ + + template < + typename T, + typename mem_manager + > + void deserialize ( + stack& item, + std::istream& in + ); + /*! + provides deserialization support + !*/ +} + +#endif // DLIB_STACK_KERNEl_ABSTRACT_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stack/stack_kernel_c.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stack/stack_kernel_c.h new file mode 100644 index 0000000..ec8642a --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stack/stack_kernel_c.h @@ -0,0 +1,189 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_STACK_KERNEl_C_ +#define DLIB_STACK_KERNEl_C_ + +#include "stack_kernel_abstract.h" +#include "../algs.h" +#include "../assert.h" + +namespace dlib +{ + + template < + typename stack_base + > + class stack_kernel_c : public stack_base + { + typedef typename stack_base::type T; + public: + void pop( + T& item + ); + + T& current( + ); + + const T& current( + ) const; + + const T& element( + ) const; + + T& element( + ); + + void remove_any ( + T& item + ); + + }; + + + template < + typename stack_base + > + inline void swap ( + stack_kernel_c& a, + stack_kernel_c& b + ) { a.swap(b); } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename stack_base + > + void stack_kernel_c:: + pop( + T& item + ) + { + + // make sure requires clause is not broken + DLIB_CASSERT(this->size() != 0, + "\tvoid stack::pop" + << "\n\tsize of stack should not be zero" + << "\n\tthis: " << this + ); + + // call the real function + stack_base::pop(item); + + } + +// ---------------------------------------------------------------------------------------- + + template < + typename stack_base + > + const typename stack_base::type& stack_kernel_c:: + current( + ) const + { + // make sure requires clause is not broken + DLIB_CASSERT(this->size() != 0, + "\tconst T& stack::current" + << "\n\tsize of stack should not be zero" + << "\n\tthis: " << this + ); + + // call the real function + return stack_base::current(); + + } + +// ---------------------------------------------------------------------------------------- + + template < + typename stack_base + > + typename stack_base::type& stack_kernel_c:: + current( + ) + { + // make sure requires clause is not broken + DLIB_CASSERT(this->size() != 0, + "\tT& stack::current" + << "\n\tsize of stack should not be zero" + << "\n\tthis: " << this + ); + + // call the real function + return stack_base::current(); + + } + +// ---------------------------------------------------------------------------------------- + + template < + typename stack_base + > + typename stack_base::type& stack_kernel_c:: + element( + ) + { + // make sure requires clause is not broken + DLIB_CASSERT(this->current_element_valid(), + "\tT& stack::element" + << "\n\tThe current element must be valid if you are to access it." + << "\n\tthis: " << this + ); + + // call the real function + return stack_base::element(); + + } + +// ---------------------------------------------------------------------------------------- + + template < + typename stack_base + > + const typename stack_base::type& stack_kernel_c:: + element( + ) const + { + // make sure requires clause is not broken + DLIB_CASSERT(this->current_element_valid(), + "\tconst T& stack::element" + << "\n\tThe current element must be valid if you are to access it." + << "\n\tthis: " << this + ); + + // call the real function + return stack_base::element(); + + } + +// ---------------------------------------------------------------------------------------- + + template < + typename stack_base + > + void stack_kernel_c:: + remove_any ( + T& item + ) + { + // make sure requires clause is not broken + DLIB_CASSERT( (this->size() > 0), + "\tvoid stack::remove_any" + << "\n\tsize() must be greater than zero if something is going to be removed" + << "\n\tsize(): " << this->size() + << "\n\tthis: " << this + ); + + // call the real function + stack_base::remove_any(item); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_STACK_KERNEl_C_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stack_trace.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stack_trace.h new file mode 100644 index 0000000..aacbeb7 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stack_trace.h @@ -0,0 +1,118 @@ +// Copyright (C) 2008 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_STACK_TRACe_ +#define DLIB_STACK_TRACe_ + +/*! + This file defines 3 things. Two of them are preprocessor macros that + enable you to tag functions with the dlib stack trace watcher. The + third thing is a function named get_stack_trace() which returns the + current stack trace in std::string form. + + To enable the stack trace you must #define DLIB_ENABLE_STACK_TRACE. + When this #define isn't set then the 3 things described above + still exist but they don't do anything. + + Also note that when the stack trace is enabled it changes the DLIB_ASSERT + and DLIB_CASSERT macros so that they print stack traces when + an assert fails. + + See the following example program for details: + + #include + #include + + void funct2() + { + // put this macro at the top of each function you would + // like to appear in stack traces + DLIB_STACK_TRACE; + + // you may print the current stack trace as follows. + std::cout << dlib::get_stack_trace() << endl; + } + + void funct() + { + // This alternate form of DLIB_STACK_TRACE allows you to specify + // the string used to name the current function. The other form + // will usually output an appropriate function name automatically + // so this may not be needed. + DLIB_STACK_TRACE_NAMED("funct"); + funct2(); + } + + int main() + { + funct(); + } +!*/ + + +#include +#include "assert.h" + +// only setup the stack trace stuff if the asserts are enabled (which happens in debug mode +// basically). Also, this stuff doesn't work if you use NO_MAKEFILE +#if defined(DLIB_ENABLE_STACK_TRACE) +#ifdef NO_MAKEFILE +#error "You can't use the dlib stack trace stuff and NO_MAKEFILE at the same time" +#endif + +namespace dlib +{ + const std::string get_stack_trace(); +} + +// redefine the DLIB_CASSERT macro to include the stack trace +#undef DLIBM_CASSERT +#define DLIBM_CASSERT(_exp,_message) \ + {if ( !(_exp) ) \ + { \ + std::ostringstream dlib_o_out; \ + dlib_o_out << "\n\nError occurred at line " << __LINE__ << ".\n"; \ + dlib_o_out << "Error occurred in file " << __FILE__ << ".\n"; \ + dlib_o_out << "Error occurred in function " << DLIB_FUNCTION_NAME << ".\n\n"; \ + dlib_o_out << "Failing expression was " << #_exp << ".\n"; \ + dlib_o_out << _message << "\n\n"; \ + dlib_o_out << "Stack Trace: \n" << dlib::get_stack_trace() << "\n"; \ + dlib_assert_breakpoint(); \ + throw dlib::fatal_error(dlib::EBROKEN_ASSERT,dlib_o_out.str()); \ + }} + + + +namespace dlib +{ + + class stack_tracer + { + public: + stack_tracer ( + const char* funct_name, + const char* file_name, + const int line_number + ); + + ~stack_tracer(); + + }; +} + +#define DLIB_STACK_TRACE_NAMED(x) dlib::stack_tracer dlib_stack_tracer_object(x,__FILE__,__LINE__) +#define DLIB_STACK_TRACE dlib::stack_tracer dlib_stack_tracer_object(DLIB_FUNCTION_NAME,__FILE__,__LINE__) + +#else // don't do anything if ENABLE_ASSERTS isn't defined +#define DLIB_STACK_TRACE_NAMED(x) +#define DLIB_STACK_TRACE + +namespace dlib +{ + inline const std::string get_stack_trace() { return std::string("stack trace not enabled");} +} + +#endif + + +#endif // DLIB_STACK_TRACe_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/std_allocator.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/std_allocator.h new file mode 100644 index 0000000..b6e411c --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/std_allocator.h @@ -0,0 +1,199 @@ +// Copyright (C) 2007 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_STD_ALLOc_H_ +#define DLIB_STD_ALLOc_H_ + +#include +#include +#include "enable_if.h" +#include "algs.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + typename M + > + class std_allocator + { + /*! + REQUIREMENTS ON M + must be an implementation of memory_manager/memory_manager_kernel_abstract.h or + must be an implementation of memory_manager_global/memory_manager_global_kernel_abstract.h or + must be an implementation of memory_manager_stateless/memory_manager_stateless_kernel_abstract.h + M::type can be set to anything. + + WHAT THIS OBJECT REPRESENTS + This object is an implementation of an allocator that conforms to the C++ standard + requirements for allocator objects. The M template argument is one of the dlib + memory manager objects and this allocator implementation will do all of its memory allocations + using whatever dlib memory manager you supply. + + Thus, using this allocator object you can use any of the dlib memory manager objects with + the containers in the STL or with any other object that requires a C++ allocator object. + + It is important to note that many STL implementations make the assumption that the memory + allocated by one allocator can be freed by another. This effectively means that you should + only use a global or stateless memory manager with the std_allocator. Either that or you + have to verify that your version of the STL isn't going to try and allocate and deallocate + memory with different allocators. + !*/ + + public: + //type definitions + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef T* pointer; + typedef const T* const_pointer; + typedef T& reference; + typedef const T& const_reference; + typedef T value_type; + + //rebind std_allocator to type U + template + struct rebind { + typedef std_allocator other; + }; + + //return address of values + pointer address (reference value) const { return &value; } + + const_pointer address (const_reference value) const { return &value; } + + /*constructors and destructor + *-nothing to do because the std_allocator has no state + */ + std_allocator() throw() { } + + std_allocator(const std_allocator&) throw() { } + + template + std_allocator (const std_allocator&) throw() { } + + ~std_allocator() throw() { } + + //return maximum number of elements that can be allocated + size_type max_size () const throw() + { + //for numeric_limits see Section 4.3, page 59 + return std::numeric_limits::max() / sizeof(T); + } + + //allocate but don't initialize num elements of type T + pointer allocate ( + size_type num, + typename std_allocator::const_pointer = 0 + ) + { + return (pointer) pool.allocate_array(num*sizeof(T)); + } + + // This function is not required by the C++ standard but some versions of the STL + // distributed with gcc erroneously require it. See the bug report for further + // details: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51626 + void construct(pointer p) { return construct(p, value_type()); } + + //initialize elements of allocated storage p with value value + void construct (pointer p, const T& value) + { + //initialize memory with placement new + new((void*)p)T(value); + } + + + //destroy elements of initialized storage p + void destroy (pointer p) + { + // destroy objects by calling their destructor + p->~T(); + } + + //deallocate storage p of deleted elements + void deallocate (pointer p, size_type ) + { + pool.deallocate_array((char*)p); + } + + void swap ( + std_allocator& item + ) + { + pool.swap(item.pool); + } + + std_allocator& operator= (const std_allocator&) { return *this;} + + private: + typename M::template rebind::other pool; + }; + +// ---------------------------------------------------------------------------------------- + + template < + typename M + > + class std_allocator + { + public: + //type definitions + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef void* pointer; + typedef const void* const_pointer; + typedef void value_type; + + //rebind std_allocator to type U + template + struct rebind { + typedef std_allocator other; + }; + + }; + +// ---------------------------------------------------------------------------------------- + + template + struct std_alloc_compare + { const static bool are_interchangeable = false; }; + + template + struct std_alloc_compare >::type> + { const static bool are_interchangeable = true; }; + + template + struct std_alloc_compare::type> + { const static bool are_interchangeable = true; }; + + //return that all specializations of this std_allocator are interchangeable if they use memory_manager_global + // instances with the same mm_global_type + template + bool operator== ( + const std_allocator&, + const std_allocator& + ) throw() + { return std_alloc_compare::are_interchangeable; } + + template + bool operator!= ( + const std_allocator&, + const std_allocator& + ) throw() + { return !std_alloc_compare::are_interchangeable; } + +// ---------------------------------------------------------------------------------------- + + template + void swap ( + std_allocator& a, + std_allocator& b + ) { a.swap(b); } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_STD_ALLOc_H_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stl_checked.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stl_checked.h new file mode 100644 index 0000000..ec15aa8 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stl_checked.h @@ -0,0 +1,10 @@ +// Copyright (C) 2008 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_STL_CHECKEd_HEADER +#define DLIB_STL_CHECKEd_HEADER + +#include "stl_checked/std_vector_c.h" + +#endif // DLIB_STL_CHECKEd_HEADER + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stl_checked/std_vector_c.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stl_checked/std_vector_c.h new file mode 100644 index 0000000..d46c985 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stl_checked/std_vector_c.h @@ -0,0 +1,333 @@ +// Copyright (C) 2008 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_STD_VECTOr_C_H_ +#define DLIB_STD_VECTOr_C_H_ + +#include +#include +#include "../assert.h" +#include "std_vector_c_abstract.h" +#include "../serialize.h" +#include "../is_kind.h" + +namespace dlib +{ + + template < + typename T, + typename Allocator = std::allocator + > + class std_vector_c : public std::vector + { + typedef typename std::vector base_type; + public: + // types: + typedef typename Allocator::reference reference; + typedef typename Allocator::const_reference const_reference; + typedef typename base_type::iterator iterator; // See 23.1 + typedef typename base_type::const_iterator const_iterator; // See 23.1 + typedef typename base_type::size_type size_type; // See 23.1 + typedef typename base_type::difference_type difference_type;// See 23.1 + typedef T value_type; + typedef Allocator allocator_type; + typedef typename Allocator::pointer pointer; + typedef typename Allocator::const_pointer const_pointer; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + + // 23.2.4.1 construct/copy/destroy: + explicit std_vector_c(const Allocator& alloc= Allocator()) : base_type(alloc) {} + + explicit std_vector_c(size_type n, const T& value = T(), + const Allocator& alloc= Allocator()) : base_type(n, value, alloc) {} + + template + std_vector_c(InputIterator first, InputIterator last, + const Allocator& alloc= Allocator()) : base_type(first,last,alloc) {} + + std_vector_c(const std::vector& x) : base_type(x) {} + + std_vector_c& operator=(const std::vector& x) + { + static_cast(*this) = x; + return *this; + } + + template + void assign(InputIterator first, InputIterator last) { base_type::assign(first,last); } + void assign(size_type n, const T& u) { base_type::assign(n,u); } + allocator_type get_allocator() const { return base_type::get_allocator(); } + // iterators: + iterator begin() { return base_type::begin(); } + const_iterator begin() const { return base_type::begin(); } + iterator end() { return base_type::end(); } + const_iterator end() const { return base_type::end(); } + reverse_iterator rbegin() { return base_type::rbegin(); } + const_reverse_iterator rbegin() const { return base_type::rbegin(); } + reverse_iterator rend() { return base_type::rend(); } + const_reverse_iterator rend() const { return base_type::rend(); } + // 23.2.4.2 capacity: + size_type size() const { return base_type::size(); } + size_type max_size() const { return base_type::max_size(); } + void resize(size_type sz, T c = T()) { base_type::resize(sz,c); } + size_type capacity() const { return base_type::capacity(); } + bool empty() const { return base_type::empty(); } + void reserve(size_type n) { base_type::reserve(n); } + + // element access: + const_reference at(size_type n) const { return base_type::at(n); } + reference at(size_type n) { return base_type::at(n); } + + + // 23.2.4.3 modifiers: + void push_back(const T& x) { base_type::push_back(x); } + void swap(std_vector_c& x) { base_type::swap(x); } + void clear() { base_type::clear(); } + + + // ------------------------------------------------------ + // Things that have preconditions that should be checked. + // ------------------------------------------------------ + + reference operator[]( + size_type n + ) + { + DLIB_CASSERT(n < size(), + "\treference std_vector_c::operator[](n)" + << "\n\tYou have supplied an invalid index" + << "\n\tthis: " << this + << "\n\tn: " << n + << "\n\tsize(): " << size() + ); + return static_cast(*this)[n]; + } + + // ------------------------------------------------------ + + const_reference operator[]( + size_type n + ) const + { + DLIB_CASSERT(n < size(), + "\tconst_reference std_vector_c::operator[](n)" + << "\n\tYou have supplied an invalid index" + << "\n\tthis: " << this + << "\n\tn: " << n + << "\n\tsize(): " << size() + ); + return static_cast(*this)[n]; + } + + // ------------------------------------------------------ + + reference front( + ) + { + DLIB_CASSERT(size() > 0, + "\treference std_vector_c::front()" + << "\n\tYou can't call front() on an empty vector" + << "\n\tthis: " << this + ); + return base_type::front(); + } + + // ------------------------------------------------------ + + const_reference front( + ) const + { + DLIB_CASSERT(size() > 0, + "\tconst_reference std_vector_c::front()" + << "\n\tYou can't call front() on an empty vector" + << "\n\tthis: " << this + ); + return base_type::front(); + } + + // ------------------------------------------------------ + + reference back( + ) + { + DLIB_CASSERT(size() > 0, + "\treference std_vector_c::back()" + << "\n\tYou can't call back() on an empty vector" + << "\n\tthis: " << this + ); + return base_type::back(); + } + + // ------------------------------------------------------ + + const_reference back( + ) const + { + DLIB_CASSERT(size() > 0, + "\tconst_reference std_vector_c::back()" + << "\n\tYou can't call back() on an empty vector" + << "\n\tthis: " << this + ); + return base_type::back(); + } + + // ------------------------------------------------------ + + void pop_back( + ) + { + DLIB_CASSERT(size() > 0, + "\tconst_reference std_vector_c::pop_back()" + << "\n\tYou can't call pop_back() on an empty vector" + << "\n\tthis: " << this + ); + base_type::pop_back(); + } + + // ------------------------------------------------------ + + iterator insert( + iterator position, + const T& x + ) + { + DLIB_CASSERT( begin() <= position && position <= end(), + "\titerator std_vector_c::insert(position,x)" + << "\n\tYou have called insert() with an invalid position" + << "\n\tthis: " << this + ); + return base_type::insert(position, x); + } + + // ------------------------------------------------------ + + void insert( + iterator position, + size_type n, + const T& x + ) + { + DLIB_CASSERT( begin() <= position && position <= end(), + "\tvoid std_vector_c::insert(position,n,x)" + << "\n\tYou have called insert() with an invalid position" + << "\n\tthis: " << this + ); + base_type::insert(position, n, x); + } + + // ------------------------------------------------------ + + template + void insert( + iterator position, + InputIterator first, + InputIterator last + ) + { + DLIB_CASSERT( begin() <= position && position <= end(), + "\tvoid std_vector_c::insert(position,first,last)" + << "\n\tYou have called insert() with an invalid position" + << "\n\tthis: " << this + ); + base_type::insert(position, first, last); + } + + // ------------------------------------------------------ + + iterator erase( + iterator position + ) + { + DLIB_CASSERT( begin() <= position && position < end(), + "\titerator std_vector_c::erase(position)" + << "\n\tYou have called erase() with an invalid position" + << "\n\tthis: " << this + ); + return base_type::erase(position); + } + + // ------------------------------------------------------ + + iterator erase( + iterator first, + iterator last + ) + { + DLIB_CASSERT( begin() <= first && first <= last && last <= end(), + "\titerator std_vector_c::erase(first,last)" + << "\n\tYou have called erase() with an invalid range of iterators" + << "\n\tthis: " << this + ); + return base_type::erase(first,last); + } + + // ------------------------------------------------------ + + + }; + +// ---------------------------------------------------------------------------------------- + +// Add these swaps just to make absolutely sure the specialized swap always gets called even +// if the compiler is crappy and would otherwise mess it up. + template + void swap(std_vector_c& x, std_vector_c& y) { x.swap(y); } + + template + void swap(std::vector& x, std_vector_c& y) { x.swap(y); } + + template + void swap(std_vector_c& x, std::vector& y) { y.swap(x); } + +// ---------------------------------------------------------------------------------------- + + template + void serialize ( + const std_vector_c& item, + std::ostream& out + ) + { + try + { + const unsigned long size = static_cast(item.size()); + + serialize(size,out); + for (unsigned long i = 0; i < item.size(); ++i) + serialize(item[i],out); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing object of type std_vector_c"); } + } + +// ---------------------------------------------------------------------------------------- + + template + void deserialize ( + std_vector_c& item, + std::istream& in + ) + { + try + { + unsigned long size; + deserialize(size,in); + item.resize(size); + for (unsigned long i = 0; i < size; ++i) + deserialize(item[i],in); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing object of type std_vector_c"); } + } + +// ---------------------------------------------------------------------------------------- + + template + struct is_std_vector > { const static bool value = true; }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_STD_VECTOr_C_H_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stl_checked/std_vector_c_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stl_checked/std_vector_c_abstract.h new file mode 100644 index 0000000..2a8045c --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/stl_checked/std_vector_c_abstract.h @@ -0,0 +1,470 @@ +// Copyright (C) 2008 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_STD_VECTOr_C_ABSTRACT_H_ +#ifdef DLIB_STD_VECTOr_C_ABSTRACT_H_ + +#include +#include +#include "../assert.h" + +namespace dlib +{ + + template < + typename T, + typename Allocator = std::allocator + > + class std_vector_c : public std::vector + { + /*! + WHAT THIS OBJECT REPRESENTS + This object is a simple wrapper around the std::vector object. It + provides an identical interface but also checks the preconditions of + each member function. That is, if you violate a requires + clause the dlib::fatal_error exception is thrown. + !*/ + + typedef typename std::vector base_type; + public: + typedef typename Allocator::reference reference; + typedef typename Allocator::const_reference const_reference; + typedef typename base_type::iterator iterator; + typedef typename base_type::const_iterator const_iterator; + typedef typename base_type::size_type size_type; + typedef typename base_type::difference_type difference_type; + typedef T value_type; + typedef Allocator allocator_type; + typedef typename Allocator::pointer pointer; + typedef typename Allocator::const_pointer const_pointer; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + + explicit std_vector_c( + const Allocator& alloc = Allocator() + ); + /*! + ensures + - #get_allocator() == alloc + - #size() == 0 + !*/ + + explicit std_vector_c ( + size_type n, + const T& value = T(), + const Allocator& alloc = Allocator() + ); + /*! + ensures + - #size() == n + - #get_allocator() == alloc + - for all valid i: + - (*this)[i] == value + !*/ + + template + std_vector_c ( + InputIterator first, + InputIterator last, + const Allocator& alloc = Allocator() + ); + /*! + ensures + - #size() == std::distance(first,last) + - #get_allocator() == alloc + - std::equal(first, last, begin()) == true + !*/ + + std_vector_c( + const std::vector& x + ); + /*! + ensures + - #*this == x + !*/ + + std_vector_c& operator= ( + const std::vector& x + ); + /*! + ensures + - #*this == x + - returns #*this + !*/ + + template + void assign( + InputIterator first, + InputIterator last + ); + /*! + ensures + - #size() == std::distance(first,last) + - std::equal(first, last, begin()) == true + !*/ + + void assign( + size_type n, + const T& value + ); + /*! + ensures + - #size() == n + - for all valid i: + - (*this)[i] == value + !*/ + + allocator_type get_allocator( + ) const; + /*! + ensures + - returns the allocator used by this vector + !*/ + + iterator begin( + ); + /*! + ensures + - if (size() > 0) then + - returns an iterator referring to the first element in + this container. + - else + - returns end() + !*/ + + const_iterator begin( + ) const; + /*! + ensures + - if (size() > 0) then + - returns a const_iterator referring to the first element in + this container. + - else + - returns end() + !*/ + + iterator end( + ); + /*! + ensures + - returns an iterator that represents one past the end of + this container + !*/ + + const_iterator end( + ) const; + /*! + ensures + - returns an iterator that represents one past the end of + this container + !*/ + + reverse_iterator rbegin( + ); + /*! + ensures + - returns std::reverse_iterator(end()) + !*/ + + const_reverse_iterator rbegin( + ) const; + /*! + ensures + - returns std::reverse_iterator(end()) + !*/ + + reverse_iterator rend( + ); + /*! + ensures + - returns std::reverse_iterator(begin()) + !*/ + + const_reverse_iterator rend( + ) const; + /*! + ensures + - returns std::reverse_iterator(begin()) + !*/ + + size_type size( + ) const; + /*! + ensures + - returns end()-begin() + (i.e. returns the number of elements in this container) + !*/ + + size_type max_size( + ) const; + /*! + ensures + - returns the maximum number of elements this vector can contain + !*/ + + void resize( + size_type sz, + T c = T() + ); + /*! + ensures + - #size() == sz + - any element with index between 0 and sz - 1 which was in the + vector before the call to resize() retains its value and index. + All other elements have a value given by c. + !*/ + + size_type capacity( + ) const; + /*! + ensures + - returns the total number of elements that the vector can hold without + requiring reallocation. + !*/ + + bool empty( + ) const; + /*! + ensures + - if (size() == 0) then + - returns true + - else + - returns false + !*/ + + void reserve( + size_type n + ); + /*! + ensures + - #capacity() >= n + !*/ + + const_reference at( + size_type n + ) const; + /*! + ensures + - if (n < size()) then + - returns a const reference to (*this)[n] + - else + - throws std::out_of_range + !*/ + + reference at( + size_type n + ); + /*! + ensures + - if (n < size()) then + - returns a reference to (*this)[n] + - else + - throws std::out_of_range + !*/ + + void push_back( + const T& x + ); + /*! + ensures + - #size() == size() + 1 + - #back() == x + !*/ + + void swap( + std_vector_c& x + ); + /*! + ensures + - swaps the state of *this and x + !*/ + + void clear( + ); + /*! + ensures + - #size() == 0 + !*/ + + reference operator[]( + size_type n + ); + /*! + requires + - n < size() + ensures + - returns a reference to the nth element of this container + !*/ + + const_reference operator[]( + size_type n + ) const; + /*! + requires + - n < size() + ensures + - returns a const reference to the nth element of this container + !*/ + + reference front( + ); + /*! + requires + - size() > 0 + ensures + - returns a reference to (*this)[0] + !*/ + + const_reference front( + ) const; + /*! + requires + - size() > 0 + ensures + - returns a const reference to (*this)[0] + !*/ + + reference back( + ); + /*! + requires + - size() > 0 + ensures + - returns a reference to (*this)[size()-1] + !*/ + + const_reference back( + ) const; + /*! + requires + - size() > 0 + ensures + - returns a const reference to (*this)[size()-1] + !*/ + + void pop_back( + ); + /*! + requires + - size() > 0 + ensures + - #size() == size() - 1 + - removes the last element in the vector but leaves the others + unmodified. + !*/ + + iterator insert( + iterator position, + const T& x + ); + /*! + requires + - begin() <= position && position <= end() + (i.e. position references an element in this vector object) + ensures + - #size() == size() + 1 + - inserts a copy of x into *this before the given position + - returns an iterator that points to the copy of x inserted + into *this + !*/ + + void insert( + iterator position, + size_type n, + const T& x + ); + /*! + requires + - begin() <= position && position <= end() + (i.e. position references an element in this vector object) + ensures + - #size() == size() + n + - inserts n copies of x into *this before the given position + !*/ + + template + void insert( + iterator position, + InputIterator first, + InputIterator last + ); + /*! + requires + - begin() <= position && position <= end() + (i.e. position references an element in this vector object) + - first and last are not iterators into *this + ensures + - #size() == size() + std::distance(last,first) + - inserts copies of the range of elements [first,last) into *this + before the given position + !*/ + + iterator erase( + iterator position + ); + /*! + requires + - begin() <= position && position < end() + (i.e. position references an element in this vector object) + ensures + - #size() == size() - 1 + - removes the element in this vector referenced by position but + leaves all other elements in this vector unmodified. + - if (position < end()-1) then + - returns an iterator referencing the element immediately + following *position prior to the erase. + - else + - returns end() + !*/ + + iterator erase( + iterator first, + iterator last + ); + /*! + requires + - begin() <= first && first <= last && last <= end() + (i.e. the range [first,last) must be inside this container ) + ensures + - #size() == size() - (last-first) + - removes the elements in this vector referenced by the + iterator range [first,last) but leaves all other elements + in this vector unmodified. + - if (last < end()-1) then + - returns an iterator referencing the element immediately + following *last prior to the erase. + - else + - returns end() + !*/ + + }; + +// ---------------------------------------------------------------------------------------- + + template + void serialize ( + const std_vector_c& item, + std::ostream& out + ); + /*! + provides serialization support + !*/ + +// ---------------------------------------------------------------------------------------- + + template + void deserialize ( + std_vector_c& item, + std::istream& in + ); + /*! + provides deserialization support + !*/ + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_STD_VECTOr_C_ABSTRACT_H_ + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string.h new file mode 100644 index 0000000..671fee4 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string.h @@ -0,0 +1,9 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_STRINg_TOP_ +#define DLIB_STRINg_TOP_ + +#include "string/string.h" + +#endif // DLIB_STRINg_TOP_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string/cassert b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string/cassert new file mode 100644 index 0000000..6139ba8 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string/cassert @@ -0,0 +1 @@ +#include "../dlib_include_path_tutorial.txt" diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string/iomanip b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string/iomanip new file mode 100644 index 0000000..6139ba8 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string/iomanip @@ -0,0 +1 @@ +#include "../dlib_include_path_tutorial.txt" diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string/iosfwd b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string/iosfwd new file mode 100644 index 0000000..6139ba8 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string/iosfwd @@ -0,0 +1 @@ +#include "../dlib_include_path_tutorial.txt" diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string/iostream b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string/iostream new file mode 100644 index 0000000..6139ba8 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string/iostream @@ -0,0 +1 @@ +#include "../dlib_include_path_tutorial.txt" diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string/locale b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string/locale new file mode 100644 index 0000000..6139ba8 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string/locale @@ -0,0 +1 @@ +#include "../dlib_include_path_tutorial.txt" diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string/string.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string/string.h new file mode 100644 index 0000000..2c26021 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string/string.h @@ -0,0 +1,1004 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_STRINg_ +#define DLIB_STRINg_ + +#include "string_abstract.h" +#include +#include "../algs.h" +#include +#include +#include +#include "../error.h" +#include "../assert.h" +#include "../uintn.h" +#include +#include +#include +#include "../enable_if.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename traits, + typename alloc + > + inline const typename disable_if,std::string>::type narrow ( + const std::basic_string& str + ) + { + std::string temp; + temp.reserve(str.size()); + std::string::size_type i; + for (i = 0; i < str.size(); ++i) + { + if (zero_extend_cast(str[i]) > 255) + temp += ' '; + else + temp += zero_extend_cast(str[i]); + } + return temp; + } + + template < + typename charT, + typename traits, + typename alloc + > + inline const typename enable_if,std::string>::type narrow ( + const std::basic_string& str + ) + { + return str; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename traits, + typename alloc + > + const std::basic_string tolower ( + const std::basic_string& str + ) + { + std::basic_string temp; + + temp.resize(str.size()); + + for (typename std::basic_string::size_type i = 0; i < str.size(); ++i) + temp[i] = (char)std::tolower(str[i]); + + return temp; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename traits, + typename alloc + > + const std::basic_string toupper ( + const std::basic_string& str + ) + { + std::basic_string temp; + + temp.resize(str.size()); + + for (typename std::basic_string::size_type i = 0; i < str.size(); ++i) + temp[i] = (char)std::toupper(str[i]); + + return temp; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename traits, + typename alloc + > + bool strings_equal_ignore_case ( + const std::basic_string& str1, + const std::basic_string& str2 + ) + { + if (str1.size() != str2.size()) + return false; + + for (typename std::basic_string::size_type i = 0; i < str1.size(); ++i) + { + if (std::tolower(str1[i]) != std::tolower(str2[i])) + return false; + } + + return true; + } + + template < + typename traits, + typename alloc + > + bool strings_equal_ignore_case ( + const std::basic_string& str1, + const char* str2 + ) + { + typename std::basic_string::size_type i; + for (i = 0; i < str1.size(); ++i) + { + // if we hit the end of str2 then the strings aren't the same length + if (str2[i] == '\0') + return false; + + if (std::tolower(str1[i]) != std::tolower(str2[i])) + return false; + } + + // This happens when str2 is longer than str1 + if (str2[i] != '\0') + return false; + + return true; + } + + template < + typename traits, + typename alloc + > + bool strings_equal_ignore_case ( + const char* str1, + const std::basic_string& str2 + ) + { + return strings_equal_ignore_case(str2, str1); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename traits, + typename alloc + > + bool strings_equal_ignore_case ( + const std::basic_string& str1, + const std::basic_string& str2, + unsigned long num + ) + { + if (str1.size() != str2.size() && (str1.size() < num || str2.size() < num)) + return false; + + for (typename std::basic_string::size_type i = 0; i < str1.size() && i < num; ++i) + { + if (std::tolower(str1[i]) != std::tolower(str2[i])) + return false; + } + + return true; + } + + template < + typename traits, + typename alloc + > + bool strings_equal_ignore_case ( + const std::basic_string& str1, + const char* str2, + unsigned long num + ) + { + typename std::basic_string::size_type i; + for (i = 0; i < str1.size() && i < num; ++i) + { + // if we hit the end of str2 then the strings aren't the same length + if (str2[i] == '\0') + return false; + + if (std::tolower(str1[i]) != std::tolower(str2[i])) + return false; + } + + return true; + } + + template < + typename traits, + typename alloc + > + bool strings_equal_ignore_case ( + const char* str1, + const std::basic_string& str2, + unsigned long num + ) + { + return strings_equal_ignore_case(str2, str1, num); + } + +// ---------------------------------------------------------------------------------------- + + class cast_to_string_error : public error + { + public: + cast_to_string_error():error(ECAST_TO_STRING) {} + }; + + template < + typename T + > + const std::string cast_to_string ( + const T& item + ) + { + std::ostringstream sout; + sout << item; + if (!sout) + throw cast_to_string_error(); + return sout.str(); + } + + // don't declare this if we are using mingw because it apparently doesn't + // support iostreams with wchar_t? +#if !(defined(__MINGW32__) && (__GNUC__ < 4)) + template < + typename T + > + const std::wstring cast_to_wstring ( + const T& item + ) + { + std::basic_ostringstream sout; + sout << item; + if (!sout) + throw cast_to_string_error(); + return sout.str(); + } +#endif + +// ---------------------------------------------------------------------------------------- + + inline std::string pad_int_with_zeros ( + int i, + unsigned long width = 6 + ) + { + std::ostringstream sout; + sout << std::setw(width) << std::setfill('0') << i; + return sout.str(); + } + +// ---------------------------------------------------------------------------------------- + + class string_cast_error : public error + { + public: + string_cast_error(const std::string& str): + error(ESTRING_CAST,"string cast error: invalid string = '" + str + "'") {} + }; + + template < + typename T + > + struct string_cast_helper + { + template < typename charT, typename traits, typename alloc > + static const T cast ( + const std::basic_string& str + ) + { + using namespace std; + basic_istringstream sin(str); + T temp; + sin >> temp; + if (!sin) throw string_cast_error(narrow(str)); + if (sin.get() != std::char_traits::eof()) throw string_cast_error(narrow(str)); + return temp; + } + }; + + template + struct string_cast_helper > + { + template < typename charT, typename traits, typename alloc > + static const std::basic_string cast ( + const std::basic_string& str + ) + { + std::basic_string temp; + temp.resize(str.size()); + for (unsigned long i = 0; i < str.size(); ++i) + temp[i] = zero_extend_cast(str[i]); + return temp; + } + }; + + template <> + struct string_cast_helper + { + template < typename charT, typename traits, typename alloc > + static bool cast ( + const std::basic_string& str + ) + { + using namespace std; + if (str.size() == 1 && str[0] == '1') + return true; + if (str.size() == 1 && str[0] == '0') + return false; + if (tolower(narrow(str)) == "true") + return true; + if (tolower(narrow(str)) == "false") + return false; + + throw string_cast_error(narrow(str)); + } + }; + +#define DLIB_STRING_CAST_INTEGRAL(type) \ + template <> \ + struct string_cast_helper \ + { \ + template < typename charT, typename traits, typename alloc> \ + static type cast ( \ + const std::basic_string& str \ + ) \ + { \ + using namespace std; \ + basic_istringstream sin(str); \ + type temp; \ + if (str.size() > 2 && str[0] == _dT(charT,'0') && str[1] == _dT(charT,'x')) \ + sin >> hex >> temp; \ + else \ + sin >> temp; \ + if (!sin) throw string_cast_error(narrow(str)); \ + if (sin.get() != std::char_traits::eof()) throw string_cast_error(narrow(str)); \ + return temp; \ + } \ + }; + + DLIB_STRING_CAST_INTEGRAL(unsigned short) + DLIB_STRING_CAST_INTEGRAL(short) + DLIB_STRING_CAST_INTEGRAL(unsigned int) + DLIB_STRING_CAST_INTEGRAL(int) + DLIB_STRING_CAST_INTEGRAL(unsigned long) + DLIB_STRING_CAST_INTEGRAL(long) + DLIB_STRING_CAST_INTEGRAL(uint64) + + template < + typename T, + typename charT, + typename traits, + typename alloc + > + inline const T string_cast ( + const std::basic_string& str + ) + { + COMPILE_TIME_ASSERT(is_pointer_type::value == false); + return string_cast_helper::cast(str); + } + + template + inline const T string_cast (const char* str){ return string_cast(std::string(str)); } + template + inline const T string_cast (const wchar_t* str){ return string_cast(std::wstring(str)); } + +// ---------------------------------------------------------------------------------------- + + class string_assign + { + template < + typename charT, + typename traits, + typename alloc + > + class string_assign_helper + { + public: + string_assign_helper ( + const std::basic_string& str_ + ) : str(str_) {} + + template + operator T () const + { + return string_cast(str); + } + + private: + + const std::basic_string& str; + }; + + // ------------- + + class char_assign_helper + { + public: + char_assign_helper ( + const char* str_ + ) : str(str_) {} + + template + operator T () const + { + return string_cast(str); + } + + private: + + const char* str; + }; + + // ------------- + + class wchar_t_assign_helper + { + public: + wchar_t_assign_helper ( + const wchar_t* str_ + ) : str(str_) {} + + template + operator T () const + { + return string_cast(str); + } + + private: + + const wchar_t* str; + }; + + // ------------- + + public: + + template < + typename charT, + typename traits, + typename alloc + > + string_assign_helper operator=( + const std::basic_string& str + ) const + { + return string_assign_helper(str); + } + + char_assign_helper operator= ( + const char* str + ) const + { + return char_assign_helper(str); + } + + wchar_t_assign_helper operator= ( + const wchar_t* str + ) const + { + return wchar_t_assign_helper(str); + } + }; + + const string_assign sa = string_assign(); + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string wrap_string ( + const std::basic_string& str, + const unsigned long first_pad = 0, + const unsigned long rest_pad = 0, + const unsigned long max_per_line = 79 + ) + { + DLIB_ASSERT ( first_pad < max_per_line && rest_pad < max_per_line && + rest_pad >= first_pad, + "\tconst std::basic_string wrap_string()" + << "\n\tfirst_pad: " << first_pad + << "\n\trest_pad: " << rest_pad + << "\n\tmax_per_line: " << max_per_line ); + + using namespace std; + + basic_ostringstream sout; + basic_istringstream sin(str); + + for (unsigned long i = 0; i < rest_pad; ++i) + sout << _dT(charT," "); + const basic_string pad(sout.str()); + sout.str(_dT(charT,"")); + + for (unsigned long i = 0; i < first_pad; ++i) + sout << _dT(charT," "); + + + typename basic_string::size_type remaining = max_per_line - rest_pad; + + basic_string temp; + + sin >> temp; + while (sin) + { + if (temp.size() > remaining) + { + if (temp.size() + rest_pad >= max_per_line) + { + string::size_type i = 0; + for (; i < temp.size(); ++i) + { + sout << temp[i]; + --remaining; + if (remaining == 0) + { + sout << _dT(charT,"\n") << pad; + remaining = max_per_line - rest_pad; + } + } + } + else + { + sout << _dT(charT,"\n") << pad << temp; + remaining = max_per_line - rest_pad - temp.size(); + } + } + else if (temp.size() == remaining) + { + sout << temp; + remaining = 0; + } + else + { + sout << temp; + remaining -= temp.size(); + } + + sin >> temp; + if (remaining == 0 && sin) + { + sout << _dT(charT,"\n") << pad; + remaining = max_per_line - rest_pad; + } + else + { + sout << _dT(charT," "); + --remaining; + } + } + + return sout.str(); + } + + template < + typename charT + > + const std::basic_string wrap_string ( + const charT* str, + const unsigned long first_pad = 0, + const unsigned long rest_pad = 0, + const unsigned long max_per_line = 79 + ) { return wrap_string(std::basic_string(str),first_pad,rest_pad,max_per_line); } + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string ltrim ( + const std::basic_string& str, + const std::basic_string& trim_chars + ) + { + typedef std::basic_string string; + typename string::size_type pos = str.find_first_not_of(trim_chars); + if (pos != string::npos) + return str.substr(pos); + else + return std::basic_string(); + } + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string ltrim ( + const std::basic_string& str, + const charT* trim_chars = _dT(charT," \t\r\n") + ) { return ltrim(str,std::basic_string(trim_chars)); } + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string rtrim ( + const std::basic_string& str, + const std::basic_string& trim_chars + ) + { + typedef std::basic_string string; + + typename string::size_type pos = str.find_last_not_of(trim_chars); + if (pos != string::npos) + return str.substr(0,pos+1); + else + return std::basic_string(); + } + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string rtrim ( + const std::basic_string& str, + const charT* trim_chars = _dT(charT," \t\r\n") + ) { return rtrim(str,std::basic_string(trim_chars)); } + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string trim ( + const std::basic_string& str, + const std::basic_string& trim_chars + ) + { + typedef std::basic_string string; + typename string::size_type lpos = str.find_first_not_of(trim_chars); + if (lpos != string::npos) + { + typename string::size_type rpos = str.find_last_not_of(trim_chars); + return str.substr(lpos,rpos-lpos+1); + } + else + { + return std::basic_string(); + } + } + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string trim ( + const std::basic_string& str, + const charT* trim_chars = _dT(charT," \t\r\n") + ) { return trim(str,std::basic_string(trim_chars)); } + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string rpad ( + const std::basic_string& str, + long pad_length, + const std::basic_string& pad_string + ) + { + typedef std::basic_string string; + // if str is too big then just return str + if (pad_length <= static_cast(str.size())) + return str; + + // make the string we will padd onto the string + string P; + while (P.size() < pad_length - str.size()) + P += pad_string; + P = P.substr(0,pad_length - str.size()); + + // return the padded string + return str + P; + } + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string rpad ( + const std::basic_string& str, + long pad_length, + const charT* pad_string = _dT(charT," ") + ) { return rpad(str,pad_length,std::basic_string(pad_string)); } + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string lpad ( + const std::basic_string& str, + long pad_length, + const std::basic_string& pad_string + ) + { + typedef std::basic_string string; + // if str is too big then just return str + if (pad_length <= static_cast(str.size())) + return str; + + // make the string we will padd onto the string + string P; + while (P.size() < pad_length - str.size()) + P += pad_string; + P = P.substr(0,pad_length - str.size()); + + // return the padded string + return P + str; + } + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string lpad ( + const std::basic_string& str, + long pad_length, + const charT* pad_string = _dT(charT," ") + ) { return lpad(str,pad_length,std::basic_string(pad_string)); } + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string pad ( + const std::basic_string& str, + long pad_length, + const std::basic_string& pad_string + ) + { + const long str_size = static_cast(str.size()); + return rpad(lpad(str,(pad_length-str_size)/2 + str_size,pad_string), + pad_length, + pad_string); + } + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string pad ( + const std::basic_string& str, + long pad_length, + const charT* pad_string = _dT(charT," ") + ) { return pad(str,pad_length,std::basic_string(pad_string)); } + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string left_substr ( + const std::basic_string& str, + const std::basic_string& delim + ) + { + return str.substr(0,str.find_first_of(delim)); + } + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string left_substr ( + const std::basic_string& str, + const charT* delim = _dT(charT," \n\r\t") + ) + { + return str.substr(0,str.find_first_of(delim)); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string right_substr ( + const std::basic_string& str, + const std::basic_string& delim + ) + { + typename std::basic_string::size_type delim_pos = str.find_last_of(delim); + if (delim_pos != std::basic_string::npos) + return str.substr(delim_pos+1); + else + return _dT(charT,""); + } + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string right_substr ( + const std::basic_string& str, + const charT* delim = _dT(charT," \n\r\t") + ) + { + typename std::basic_string::size_type delim_pos = str.find_last_of(delim); + if (delim_pos != std::basic_string::npos) + return str.substr(delim_pos+1); + else + return _dT(charT,""); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename traits, + typename alloc + > + std::pair, std::basic_string > + split_on_first ( + const std::basic_string& str, + const charT* delim = _dT(charT," \n\r\t") + ) + { + typename std::basic_string::size_type delim_pos = str.find_first_of(delim); + if (delim_pos != std::basic_string::npos) + return std::make_pair(str.substr(0, delim_pos), str.substr(delim_pos+1)); + else + return std::make_pair(str, _dT(charT,"")); + } + + template < + typename charT, + typename traits, + typename alloc + > + inline std::pair, std::basic_string > + split_on_first ( + const std::basic_string& str, + const std::basic_string& delim + ) + { + return split_on_first(str, delim.c_str()); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename traits, + typename alloc + > + std::pair, std::basic_string > + split_on_last ( + const std::basic_string& str, + const charT* delim = _dT(charT," \n\r\t") + ) + { + typename std::basic_string::size_type delim_pos = str.find_last_of(delim); + if (delim_pos != std::basic_string::npos) + return std::make_pair(str.substr(0, delim_pos), str.substr(delim_pos+1)); + else + return std::make_pair(str, _dT(charT,"")); + } + + template < + typename charT, + typename traits, + typename alloc + > + inline std::pair, std::basic_string > + split_on_last ( + const std::basic_string& str, + const std::basic_string& delim + ) + { + return split_on_last(str, delim.c_str()); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename traits, + typename alloc + > + const std::vector > split ( + const std::basic_string& str, + const charT* delim = _dT(charT," \n\r\t") + ) + { + std::basic_string temp; + + std::vector > res; + + for (unsigned long i = 0; i < str.size(); ++i) + { + // check if delim contains the character str[i] + bool hit = false; + const charT* d = delim; + while (*d != '\0') + { + if (str[i] == *d) + { + hit = true; + break; + } + ++d; + } + + if (hit) + { + if (temp.size() != 0) + { + res.push_back(temp); + temp.clear(); + } + } + else + { + temp.push_back(str[i]); + } + } + + if (temp.size() != 0) + res.push_back(temp); + + return res; + } + + template < + typename charT, + typename traits, + typename alloc + > + const std::vector > split ( + const std::basic_string& str, + const std::basic_string& delim + ) + { + return split(str,delim.c_str()); + } + + inline const std::vector split ( + const char* str, + const char* delim = " \n\r\t" + ) + { + return split(std::string(str),delim); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_STRINg_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string/string_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string/string_abstract.h new file mode 100644 index 0000000..0a1ef0c --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/string/string_abstract.h @@ -0,0 +1,652 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_STRINg_ABSTRACT_ +#ifdef DLIB_STRINg_ABSTRACT_ + +#include +#include +#include +#include "../error.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class string_cast_error : public error + { + public: + string_cast_error():error(ECAST_TO_STRING) {} + }; + + template < + typename T, + typename charT, + typename traits, + typename alloc + > + const T string_cast ( + const std::basic_string& str + ); + /*! + requires + - T is not a pointer type + ensures + - returns str converted to T + throws + - string_cast_error + This exception is thrown if string_cast() is unable to convert + str into a T. Also, string_cast_error::info == str + !*/ + +// ---------------------------------------------------------------------------------------- + + class string_assign + { + /*! + WHAT THIS OBJECT REPRESENTS + This is a simple tool which provides an alternative syntax for using + the string_cast() function. It can be understood by considering + the following example: + + string_assign sa; + int val; + double dval; + + val = sa = "1234"; // executes: val = string_cast("1234"); + dval = sa = "3.141"; // executes: val = string_cast("3.141"); + + After executing, val will be equal to 1234 and dval will be 3.141. + Note that you can use string_assign to assign to any type which you could + use with string_cast(), except for std::basic_string, assigning to this + type is ambiguous for boring technical reasons. But there isn't much + point in using this tool to assign from one string to another so it doesn't + matter. + + Additionally, note that there is a global instance of this object, dlib::sa. + So you never have to create a string_assign object yourself. Finally, this + object is totally stateless and threadsafe. + !*/ + }; + + const string_assign sa = string_assign(); + +// ---------------------------------------------------------------------------------------- + + class cast_to_string_error : public error + { + public: + cast_to_string_error():error(ECAST_TO_STRING) {} + }; + + template < + typename T + > + const std::string cast_to_string ( + const T& item + ); + /*! + requires + - T is not a pointer type + ensures + - returns item converted to std::string + throws + - cast_to_string_error + This exception is thrown if cast_to_string() is unable to convert + item into a std::string. + !*/ + + template < + typename T + > + const std::wstring cast_to_wstring ( + const T& item + ); + /*! + requires + - T is not a pointer type + ensures + - returns item converted to std::wstring + throws + - cast_to_string_error + This exception is thrown if cast_to_string() is unable to convert + item into a std::string. + !*/ + +// ---------------------------------------------------------------------------------------- + + std::string pad_int_with_zeros ( + int i, + unsigned long width = 6 + ); + /*! + ensures + - converts i into a string of at least width characters in length. If + necessary, the string will be padded with leading zeros to get + to width characters. + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename traits, + typename alloc + > + const std::string narrow ( + const std::basic_string& str + ); + /*! + ensures + - returns str as a std::string by converting every character in it to a char. + Note that any characters that do not have a mapping to type char will be + converted to a space. + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string wrap_string ( + const std::basic_string& str, + const unsigned long first_pad = 0, + const unsigned long rest_pad = 0, + const unsigned long max_per_line = 79 + ); + /*! + requires + - first_pad < max_per_line + - rest_pad < max_per_line + - rest_pad >= first_pad + ensures + - returns a copy of str S such that: + - S is broken up into lines separated by the \n character. + - The first line starts with first_pad space characters. + - The second and all subsequent lines start with rest_pad space characters. + - The first line is no longer than max_per_line - (rest_pad-first_pad) characters. + - The second and all subsequent lines are no longer than max_per_line characters. + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename traits + typename alloc + > + const std::basic_string tolower ( + const std::basic_string& str + ); + /*! + ensures + - returns a copy of str S such that: + - #S.size() == str.size() + - #S[i] == std::tolower(str[i]) + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename traits, + typename alloc + > + const std::basic_string toupper ( + const std::basic_string& str + ); + /*! + ensures + - returns a copy of str S such that: + - #S.size() == str.size() + - #S[i] == std::toupper(str[i]) + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename traits, + typename alloc + > + bool strings_equal_ignore_case ( + const std::basic_string& str1, + const std::basic_string& str2 + ); + /*! + ensures + - returns tolower(str1) == tolower(str2) + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename traits, + typename alloc + > + bool strings_equal_ignore_case ( + const std::basic_string& str1, + const std::basic_string& str2, + unsigned long num + ); + /*! + ensures + - returns tolower(str1.substr(0,num)) == tolower(str2.substr(0,num)) + (i.e. only compares the first num characters) + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string ltrim ( + const std::basic_string& str, + const std::basic_string& trim_chars + ); + /*! + ensures + - returns a copy of str with any leading trim_chars + from the left side of the string removed. + !*/ + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string ltrim ( + const std::basic_string& str, + const charT* trim_chars = _dT(charT," \t\r\n") + ); + /*! + requires + - trim_chars == a valid null-terminated C string + ensures + - returns ltrim(str, std::basic_string(trim_chars)) + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string rtrim ( + const std::basic_string& str, + const std::basic_string& trim_chars + ); + /*! + ensures + - returns a copy of str with any trailing trim_chars + from the right side of the string removed. + !*/ + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string rtrim ( + const std::basic_string& str, + const charT* trim_chars = _dT(charT," \t\r\n") + ); + /*! + requires + - trim_chars == a valid null-terminated C string + ensures + - returns rtrim(str, std::basic_string(trim_chars)) + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string trim ( + const std::basic_string& str, + const std::basic_string& trim_chars + ); + /*! + ensures + - returns a copy of str with any leading or trailing trim_chars + from the ends of the string removed. + !*/ + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string trim ( + const std::basic_string& str, + const charT* trim_chars = _dT(charT," \t\r\n") + ); + /*! + requires + - trim_chars == a valid null-terminated C string + ensures + - returns trim(str, std::basic_string(trim_chars)) + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string rpad ( + const std::basic_string& str, + long pad_length, + const std::basic_string& pad_string + ); + /*! + ensures + - if (pad_length <= str.size()) then + - returns str + - else + - let P be a string defined as follows: + - P.size() == pad_length - str.size() + - P == (pad_string + pad_string + ... + pad_string).substr(0,pad_length - str.size()) + (i.e. P == a string with the above specified size that contains just + repitions of the pad_string) + - returns the string str + P + !*/ + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string rpad ( + const std::basic_string& str, + long pad_length, + const charT* pad_string = _dT(charT," ") + ); + /*! + requires + - pad_string == a valid null-terminated C string + ensures + - returns rpad(str, pad_length, std::basic_string(pad_string)) + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string lpad ( + const std::basic_string& str, + long pad_length, + const std::basic_string& pad_string + ); + /*! + ensures + - if (pad_length <= str.size()) then + - returns str + - else + - let P be a string defined as follows: + - P.size() == pad_length - str.size() + - P == (pad_string + pad_string + ... + pad_string).substr(0,pad_length - str.size()) + (i.e. P == a string with the above specified size that contains just + repitions of the pad_string) + - returns the string P + str + !*/ + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string lpad ( + const std::basic_string& str, + long pad_length, + const charT* pad_string = _dT(charT," ") + ); + /*! + requires + - pad_string == a valid null-terminated C string + ensures + - returns lpad(str, pad_length, std::basic_string(pad_string)) + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string pad ( + const std::basic_string& str, + long pad_length, + const std::basic_string& pad_string + ); + /*! + ensures + - let str_size == static_cast(str.size()) + - returns rpad( lpad(str, (pad_length-str_size)/2 + str_size, pad_string), + pad_length, + pad_string); + !*/ + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string pad ( + const std::basic_string& str, + long pad_length, + const charT* pad_string = _dT(charT," ") + ); + /*! + requires + - pad_string == a valid null-terminated C string + ensures + - returns pad(str, pad_length, std::basic_string(pad_string)) + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string left_substr ( + const std::basic_string& str, + const std::basic_string& delim + ); + /*! + ensures + - let delim_pos = str.find_first_of(delim) + - returns str.substr(0,delim_pos) + !*/ + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string left_substr ( + const std::basic_string& str, + const charT* delim = _dT(charT," \n\r\t") + ); + /*! + requires + - delim == a valid null-terminated C string + ensures + - returns left_substr(str, std::basic_string(delim)) + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename traits, + typename alloc + > + const std::basic_string right_substr ( + const std::basic_string& str, + const std::basic_string& delim + ); + /*! + ensures + - let delim_pos = str.find_last_of(delim) + - if (delim_pos == std::string::npos) then + - returns "" + - else + - returns str.substr(delim_pos+1) + !*/ + + template < + typename charT, + typename traits + typename alloc + > + const std::basic_string right_substr ( + const std::basic_string& str, + const charT* delim = _dT(charT," \n\r\t") + ); + /*! + requires + - delim == a valid null-terminated C string + ensures + - returns right_substr(str, std::basic_string(delim)) + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename traits, + typename alloc + > + std::pair, std::basic_string > + split_on_first ( + const std::basic_string& str, + const charT* delim = _dT(charT, " \n\r\t") + ); + /*! + ensures + - This function splits string into two parts, the split is based on the first + occurrence of any character from delim. + - let delim_pos = str.find_first_of(delim) + - if (delim_pos == std::string::npos) then + - returns make_pair(str,"") + - else + - return make_pair(str.substr(0, delim_pos), str.substr(delim_pos+1)); + !*/ + + template < + typename charT, + typename traits, + typename alloc + > + std::pair, std::basic_string > + split_on_first ( + const std::basic_string& str, + const std::basic_string& delim + ); + /*! + requires + - delim == a valid null-terminated C string + ensures + - returns split_on_first(str, delim.c_str()) + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename traits, + typename alloc + > + std::pair, std::basic_string > + split_on_last ( + const std::basic_string& str, + const charT* delim = _dT(charT, " \n\r\t") + ); + /*! + ensures + - This function splits string into two parts, the split is based on the last + occurrence of any character from delim. + - let delim_pos = str.find_last_of(delim) + - if (delim_pos == std::string::npos) then + - returns make_pair(str,"") + - else + - return make_pair(str.substr(0, delim_pos), str.substr(delim_pos+1)); + !*/ + + template < + typename charT, + typename traits, + typename alloc + > + std::pair, std::basic_string > + split_on_last ( + const std::basic_string& str, + const std::basic_string& delim + ); + /*! + requires + - delim == a valid null-terminated C string + ensures + - returns split_on_last(str, delim.c_str()) + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename charT, + typename traits, + typename alloc + > + const std::vector > split ( + const std::basic_string& str, + const std::basic_string& delim + ); + /*! + ensures + - Breaks the given string str into a sequence of substrings delimited + by characters in delim and returns the results. + - returns a vector V such that: + - V.size() == the number of substrings found in str. + - for all i: V[i] == The ith substring. Note that it will not contain + any delimiter characters (i.e. characters in delim). It will also + never be an empty string. + - V contains the substrings in the order in which they appear in str. + That is, V[0] contains the first substring, V[1] the second, and + so on. + !*/ + + template < + typename charT, + typename traits, + typename alloc + > + const std::vector > split ( + const std::basic_string& str, + const charT* delim = _dT(charT," \n\r\t") + ); + /*! + requires + - trim_chars == a valid null-terminated C string + ensures + - returns split(str, std::basic_string(delim)) + !*/ + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_STRINg_ABSTRACT_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/test_for_odr_violations.cpp b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/test_for_odr_violations.cpp new file mode 100644 index 0000000..f4428bc --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/test_for_odr_violations.cpp @@ -0,0 +1,47 @@ +// Copyright (C) 2014 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_TEST_FOR_ODR_VIOLATIONS_CPp_ +#define DLIB_TEST_FOR_ODR_VIOLATIONS_CPp_ + +#include "test_for_odr_violations.h" + +extern "C" +{ +// The point of this block of code is to cause a link time error that will prevent a user +// from compiling part of their application with DLIB_ASSERT enabled and part with them +// disabled since doing that would be a violation of C++'s one definition rule. +#ifdef ENABLE_ASSERTS + const int USER_ERROR__inconsistent_build_configuration__see_dlib_faq_1 = 0; +#else + const int USER_ERROR__inconsistent_build_configuration__see_dlib_faq_1_ = 0; +#endif + + +// The point of this block of code is to cause a link time error if someone builds dlib via +// cmake as a separately installable library, and therefore generates a dlib/config.h from +// cmake, but then proceeds to use the default unconfigured dlib/config.h from version +// control. It should be obvious why this is bad, if it isn't you need to read a book +// about C++. Moreover, it can only happen if someone manually copies files around and +// messes things up. If instead they run `make install` or `cmake --build . --target +// install` things will be setup correctly, which is what they should do. To summarize: DO +// NOT BUILD A STANDALONE DLIB AND THEN GO CHERRY PICKING FILES FROM THE BUILD FOLDER AND +// MIXING THEM WITH THE SOURCE FROM GITHUB. USE CMAKE'S INSTALL SCRIPTS TO INSTALL DLIB. +// Or even better, don't install dlib at all and instead build your program as shown in +// examples/CMakeLists.txt +#if defined(DLIB_NOT_CONFIGURED) && !defined(DLIB__CMAKE_GENERATED_A_CONFIG_H_FILE) + const int USER_ERROR__inconsistent_build_configuration__see_dlib_faq_2 = 0; +#endif + + + + + +#ifdef DLIB_CHECK_FOR_VERSION_MISMATCH + const int DLIB_CHECK_FOR_VERSION_MISMATCH = 0; +#endif + +} + + +#endif // DLIB_TEST_FOR_ODR_VIOLATIONS_CPp_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/test_for_odr_violations.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/test_for_odr_violations.h new file mode 100644 index 0000000..d5c5481 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/test_for_odr_violations.h @@ -0,0 +1,54 @@ +// Copyright (C) 2014 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_TEST_FOR_ODR_VIOLATIONS_H_ +#define DLIB_TEST_FOR_ODR_VIOLATIONS_H_ + +#include "assert.h" +#include "config.h" + +extern "C" +{ +// =========================>>> WHY YOU ARE GETTING AN ERROR HERE <<<========================= +// The point of this block of code is to cause a link time error that will prevent a user +// from compiling part of their application with DLIB_ASSERT enabled and part with it +// disabled since doing that would be a violation of C++'s one definition rule. So if you +// are getting an error here then you are either not enabling DLIB_ASSERT consistently +// (e.g. by compiling part of your program in a debug mode and part in a release mode) or +// you have simply forgotten to compile dlib/all/source.cpp into your application. +// =========================>>> WHY YOU ARE GETTING AN ERROR HERE <<<========================= +#ifdef ENABLE_ASSERTS + const extern int USER_ERROR__inconsistent_build_configuration__see_dlib_faq_1; + const int DLIB_NO_WARN_UNUSED dlib_check_assert_helper_variable = USER_ERROR__inconsistent_build_configuration__see_dlib_faq_1; +#endif + + + +// The point of this block of code is to cause a link time error if someone builds dlib via +// cmake as a separately installable library, and therefore generates a dlib/config.h from +// cmake, but then proceeds to use the default unconfigured dlib/config.h from version +// control. It should be obvious why this is bad, if it isn't you need to read a book +// about C++. Moreover, it can only happen if someone manually copies files around and +// messes things up. If instead they run `make install` or `cmake --build . --target +// install` things will be setup correctly, which is what they should do. To summarize: DO +// NOT BUILD A STANDALONE DLIB AND THEN GO CHERRY PICKING FILES FROM THE BUILD FOLDER AND +// MIXING THEM WITH THE SOURCE FROM GITHUB. USE CMAKE'S INSTALL SCRIPTS TO INSTALL DLIB. +// Or even better, don't install dlib at all and instead build your program as shown in +// examples/CMakeLists.txt +#if defined(DLIB_NOT_CONFIGURED) && !defined(DLIB__CMAKE_GENERATED_A_CONFIG_H_FILE) + const extern int USER_ERROR__inconsistent_build_configuration__see_dlib_faq_2; + const int DLIB_NO_WARN_UNUSED dlib_check_not_configured_helper_variable = USER_ERROR__inconsistent_build_configuration__see_dlib_faq_2; +#endif + + + +// Cause the user to get a linker error if they try to use header files from one version of +// dlib with the compiled binary from a different version of dlib. +#ifdef DLIB_CHECK_FOR_VERSION_MISMATCH + const extern int DLIB_CHECK_FOR_VERSION_MISMATCH; + const int DLIB_NO_WARN_UNUSED dlib_check_for_version_mismatch = DLIB_CHECK_FOR_VERSION_MISMATCH; +#endif + +} + +#endif // DLIB_TEST_FOR_ODR_VIOLATIONS_H_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads.h new file mode 100644 index 0000000..371a317 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads.h @@ -0,0 +1,28 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. + +#ifdef DLIB_ALL_SOURCE_END +#include "dlib_basic_cpp_build_tutorial.txt" +#endif + +#ifndef DLIB_THREADs_ +#define DLIB_THREADs_ + +#include "threads/threads_kernel.h" + +#include "threads/auto_mutex_extension.h" +#include "threads/auto_unlock_extension.h" +#include "threads/create_new_thread_extension.h" +#include "threads/multithreaded_object_extension.h" +#include "threads/rmutex_extension.h" +#include "threads/rsignaler_extension.h" +#include "threads/threaded_object_extension.h" +#include "threads/thread_specific_data_extension.h" +#include "threads/thread_function_extension.h" +#include "threads/thread_pool_extension.h" +#include "threads/read_write_mutex_extension.h" +#include "threads/parallel_for_extension.h" +#include "threads/async.h" + +#endif // DLIB_THREADs_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/async.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/async.h new file mode 100644 index 0000000..0ab9a80 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/async.h @@ -0,0 +1,118 @@ +// Copyright (C) 2016 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_AsYNC_Hh_ +#define DLIB_AsYNC_Hh_ + +// C++11 things don't work in old versions of visual studio +#if !defined( _MSC_VER) || _MSC_VER >= 1900 + +#include "async_abstract.h" +#include "thread_pool_extension.h" +#include +#include + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + namespace impl + { + template struct selector {}; + + template + void call_prom_set_value( + T& prom, + U& fun, + selector + ) + { + prom.set_value(fun()); + } + + template + void call_prom_set_value( + T& prom, + U& fun, + selector + ) + { + fun(); + prom.set_value(); + } + + template struct result_of; + +#if (__cplusplus >= 201703L || \ + (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)) && \ + __cpp_lib_is_invocable >= 201703L + template + struct result_of : std::invoke_result {}; +#else + template + struct result_of + : std::result_of {}; +#endif + } + +// ---------------------------------------------------------------------------------------- + + thread_pool& default_thread_pool(); + +// ---------------------------------------------------------------------------------------- + + template < + typename Function, + typename ...Args + > + std::future::type> async( + thread_pool& tp, + Function&& f, + Args&&... args + ) + { + auto prom = std::make_shared::type>>(); + std::future::type> ret = prom->get_future(); + using bind_t = decltype(std::bind(std::forward(f), std::forward(args)...)); + auto fun = std::make_shared(std::bind(std::forward(f), std::forward(args)...)); + tp.add_task_by_value([fun, prom]() + { + try + { + impl::call_prom_set_value(*prom, *fun, impl::selector::type>()); + } + catch(...) + { + prom->set_exception(std::current_exception()); + } + }); + return ret; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename Function, + typename ...Args + > + std::future::type> async( + Function&& f, + Args&&... args + ) + { + return async(default_thread_pool(), std::forward(f), std::forward(args)...); + } + +} + +// ---------------------------------------------------------------------------------------- + +#ifdef NO_MAKEFILE +#include "async.cpp" +#endif + +#endif +#endif // DLIB_AsYNC_Hh_ + + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/async_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/async_abstract.h new file mode 100644 index 0000000..a9fa1e4 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/async_abstract.h @@ -0,0 +1,67 @@ +// Copyright (C) 2016 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_AsYNC_ABSTRACT_Hh_ +#ifdef DLIB_AsYNC_ABSTRACT_Hh_ + +#include "thread_pool_extension_abstract.h" +#include +#include + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + thread_pool& default_thread_pool( + ); + /*! + ensures + - returns a reference to a global thread_pool. If the DLIB_NUM_THREADS + environment variable is set to an integer then the thread pool will contain + DLIB_NUM_THREADS threads, otherwise it will contain + std::thread::hardware_concurrency() threads. + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename Function, + typename ...Args + > + std::future::type> async( + thread_pool& tp, + Function&& f, + Args&&... args + ); + /*! + requires + - f must be a function and f(args...) must be a valid expression. + ensures + - This function behaves just like std::async(std::launch::async, f, args) + except that instead of spawning a new thread to process each task it submits + the task to the provided dlib::thread_pool. Therefore, dlib::async() is + guaranteed to use a bounded number of threads unlike std::async(). This also + means that calls to dlib::async() will block if there aren't any free threads + in the thread pool. + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename Function, + typename ...Args + > + std::future::type> async( + Function&& f, + Args&&... args + ); + /*! + ensures + - Calling this function is equivalent to directly calling async(default_thread_pool(), f, args...) + !*/ +} + +// ---------------------------------------------------------------------------------------- + +#endif // DLIB_AsYNC_ABSTRACT_Hh_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/auto_mutex_extension.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/auto_mutex_extension.h new file mode 100644 index 0000000..595c1b1 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/auto_mutex_extension.h @@ -0,0 +1,180 @@ +// Copyright (C) 2005 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_AUTO_MUTEX_EXTENSIOn_ +#define DLIB_AUTO_MUTEX_EXTENSIOn_ + +#include "threads_kernel.h" +#include "rmutex_extension.h" +#include "read_write_mutex_extension.h" +#include "auto_mutex_extension_abstract.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class auto_mutex + { + /*! + INITIAL VALUE + - if (m != 0) then + - the mutex pointed to by m is locked + - if (r != 0) then + - the mutex pointed to by r is locked + - if (rw != 0) then + - the mutex pointed to by rw is locked + - exactly one of r, m, or rw is not 0. + + CONVENTION + - if (m != 0) then + - the mutex pointed to by m is locked + - if (r != 0) then + - the mutex pointed to by r is locked + - if (rw != 0) then + - the mutex pointed to by rw is locked + - exactly one of r, m, or rw is not 0. + !*/ + public: + + explicit auto_mutex ( + const mutex& m_ + ) : m(&m_), + r(0), + rw(0) + { + m->lock(); + } + + explicit auto_mutex ( + const rmutex& r_ + ) : m(0), + r(&r_), + rw(0) + { + r->lock(); + } + + explicit auto_mutex ( + const read_write_mutex& rw_ + ) : m(0), + r(0), + rw(&rw_) + { + rw->lock(); + } + + void unlock() + { + if (m != 0) + { + m->unlock(); + m = 0; + } + else if (r != 0) + { + r->unlock(); + r = 0; + } + else if (rw != 0) + { + rw->unlock(); + rw = 0; + } + } + + ~auto_mutex ( + ) + { + unlock(); + } + + private: + + const mutex* m; + const rmutex* r; + const read_write_mutex* rw; + + // restricted functions + auto_mutex(auto_mutex&); // copy constructor + auto_mutex& operator=(auto_mutex&); // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + + class auto_mutex_readonly + { + public: + + explicit auto_mutex_readonly ( + const read_write_mutex& rw_ + ) : rw(rw_), _has_write_lock(false), _has_read_lock(true) + { + rw.lock_readonly(); + } + + ~auto_mutex_readonly ( + ) + { + unlock(); + } + + void lock_readonly ( + ) + { + if (!_has_read_lock) + { + unlock(); + rw.lock_readonly(); + _has_read_lock = true; + } + } + + void lock_write ( + ) + { + if (!_has_write_lock) + { + unlock(); + rw.lock(); + _has_write_lock = true; + } + } + + void unlock ( + ) + { + if (_has_write_lock) + { + rw.unlock(); + _has_write_lock = false; + } + else if (_has_read_lock) + { + rw.unlock_readonly(); + _has_read_lock = false; + } + } + + bool has_read_lock ( + ) { return _has_read_lock; } + + bool has_write_lock ( + ) { return _has_write_lock; } + + private: + + const read_write_mutex& rw; + bool _has_write_lock; + bool _has_read_lock; + + // restricted functions + auto_mutex_readonly(auto_mutex_readonly&); // copy constructor + auto_mutex_readonly& operator=(auto_mutex_readonly&); // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_AUTO_MUTEX_EXTENSIOn_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/auto_mutex_extension_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/auto_mutex_extension_abstract.h new file mode 100644 index 0000000..1990c83 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/auto_mutex_extension_abstract.h @@ -0,0 +1,185 @@ +// Copyright (C) 2005 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_AUTO_MUTEX_EXTENSIOn_ABSTRACT_ +#ifdef DLIB_AUTO_MUTEX_EXTENSIOn_ABSTRACT_ + +#include "threads_kernel_abstract.h" +#include "rmutex_extension_abstract.h" +#include "read_write_mutex_extension_abstract.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class auto_mutex + { + /*! + INITIAL VALUE + The mutex given in the constructor is locked and associated with this + object. + + WHAT THIS OBJECT REPRESENTS + This object represents a mechanism for automatically locking and unlocking + a mutex object. + !*/ + public: + + explicit auto_mutex ( + const mutex& m + ); + /*! + ensures + - #*this is properly initialized + - m will be locked + !*/ + + explicit auto_mutex ( + const rmutex& m + ); + /*! + ensures + - #*this is properly initialized + - m will be locked + !*/ + + explicit auto_mutex ( + const read_write_mutex& m + ); + /*! + ensures + - #*this is properly initialized + - m will be locked via m.lock() (i.e. a write lock will be obtained) + !*/ + + void unlock( + ); + /*! + ensures + - if (unlock() has not already been called) then + - The mutex associated with *this has been unlocked. This is useful if + you want to unlock a mutex before the auto_mutex destructor executes. + !*/ + + ~auto_mutex ( + ); + /*! + ensures + - all resources allocated by *this have been freed + - calls unlock() + !*/ + + private: + // restricted functions + auto_mutex(auto_mutex&); // copy constructor + auto_mutex& operator=(auto_mutex&); // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + + class auto_mutex_readonly + { + /*! + INITIAL VALUE + The mutex given in the constructor is locked using a read-only lock and + associated with this object. + + WHAT THIS OBJECT REPRESENTS + This object represents a mechanism for automatically locking and unlocking + a read_write_mutex object. In particular, a readonly lock is used. + !*/ + public: + + explicit auto_mutex_readonly ( + const read_write_mutex& m + ); + /*! + ensures + - #*this is properly initialized + - a readonly lock will be obtained on m using m.lock_readonly() + - #has_read_lock() == true + !*/ + + ~auto_mutex_readonly ( + ); + /*! + ensures + - all resources allocated by *this have been freed + - the mutex associated with *this has been unlocked + !*/ + + bool has_read_lock ( + ); + /*! + ensures + - returns true if this object has called read_write_mutex::lock_readonly() + on its associated mutex and has yet to release that lock. + !*/ + + bool has_write_lock ( + ); + /*! + ensures + - returns true if this object has called read_write_mutex::lock() on its + associated mutex and has yet to release that lock. + !*/ + + void lock_readonly ( + ); + /*! + ensures + - This function converts the lock on the associated mutex into a readonly lock. + Specifically: + if (!has_read_lock()) then + - if (has_write_lock()) then + - unlocks the associated mutex and then relocks it by calling + read_write_mutex::lock_readonly() + - else + - locks the associated mutex by calling read_write_mutex::lock_readonly() + - #has_read_lock() == true + - Note that the lock switch is not atomic. This means that whatever + resource is protected by the mutex might have been modified during the + call to lock_readonly(). + !*/ + + void lock_write ( + ); + /*! + ensures + - This function converts the lock on the associated mutex into a write lock. + Specifically: + if (!has_write_lock()) then + - if (has_read_lock()) then + - unlocks the associated mutex and then relocks it by calling + read_write_mutex::lock() + - else + - locks the associated mutex by calling read_write_mutex::lock() + - #has_write_lock() == true + - Note that the lock switch is not atomic. This means that whatever + resource is protected by the mutex might have been modified during the + call to lock_write(). + !*/ + + void unlock ( + ); + /*! + ensures + - if (has_read_lock() || has_write_lock()) then + - unlocks the associated mutex. This is useful if you want to unlock a + mutex before the auto_mutex_readonly destructor executes. + - #has_read_lock() == false + - #has_write_lock() == false + !*/ + + private: + // restricted functions + auto_mutex_readonly(auto_mutex_readonly&); // copy constructor + auto_mutex_readonly& operator=(auto_mutex_readonly&); // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_AUTO_MUTEX_EXTENSIOn_ABSTRACT_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/auto_unlock_extension.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/auto_unlock_extension.h new file mode 100644 index 0000000..cd1d4db --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/auto_unlock_extension.h @@ -0,0 +1,116 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_AUTO_UNLOCK_EXTENSIOn_ +#define DLIB_AUTO_UNLOCK_EXTENSIOn_ + +#include "threads_kernel.h" +#include "rmutex_extension.h" +#include "read_write_mutex_extension.h" +#include "auto_unlock_extension_abstract.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class auto_unlock + { + /*! + INITIAL VALUE + - if (m != 0) then + - the mutex pointed to by m is locked + - if (r != 0) then + - the mutex pointed to by r is locked + - if (rw != 0) then + - the mutex pointed to by rw is locked + - exactly one of r, m, or rw is not 0. + + CONVENTION + - if (m != 0) then + - the mutex pointed to by m is locked + - if (r != 0) then + - the mutex pointed to by r is locked + - if (rw != 0) then + - the mutex pointed to by rw is locked + - exactly one of r, m, or rw is not 0. + !*/ + public: + + explicit auto_unlock ( + const mutex& m_ + ) : m(&m_), + r(0), + rw(0) + {} + + explicit auto_unlock ( + const rmutex& r_ + ) : m(0), + r(&r_), + rw(0) + {} + + explicit auto_unlock ( + const read_write_mutex& rw_ + ) : m(0), + r(0), + rw(&rw_) + {} + + ~auto_unlock ( + ) + { + if (m != 0) + m->unlock(); + else if (r != 0) + r->unlock(); + else + rw->unlock(); + } + + private: + + const mutex* m; + const rmutex* r; + const read_write_mutex* rw; + + // restricted functions + auto_unlock(auto_unlock&); // copy constructor + auto_unlock& operator=(auto_unlock&); // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + + class auto_unlock_readonly + { + + public: + + explicit auto_unlock_readonly ( + const read_write_mutex& rw_ + ) : + rw(rw_) + {} + + ~auto_unlock_readonly ( + ) + { + rw.unlock_readonly(); + } + + private: + + const read_write_mutex& rw; + + // restricted functions + auto_unlock_readonly(auto_unlock_readonly&); // copy constructor + auto_unlock_readonly& operator=(auto_unlock_readonly&); // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_AUTO_UNLOCK_EXTENSIOn_ + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/auto_unlock_extension_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/auto_unlock_extension_abstract.h new file mode 100644 index 0000000..f947d48 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/auto_unlock_extension_abstract.h @@ -0,0 +1,116 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_AUTO_UNLOCK_EXTENSIOn_ABSTRACT_ +#ifdef DLIB_AUTO_UNLOCK_EXTENSIOn_ABSTRACT_ + +#include "threads_kernel_abstract.h" +#include "rmutex_extension_abstract.h" +#include "read_write_mutex_extension_abstract.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class auto_unlock + { + /*! + INITIAL VALUE + The mutex given in the constructor is associated with this object. + + WHAT THIS OBJECT REPRESENTS + This object represents a mechanism for automatically unlocking + a mutex object. It is useful when you already have a locked mutex + and want to make sure it gets unlocked even if an exception is thrown + or you quit the function at a weird spot. + !*/ + public: + + explicit auto_unlock ( + const mutex& m + ); + /*! + ensures + - #*this is properly initialized + - does not modify m in any way + !*/ + + explicit auto_unlock ( + const rmutex& m + ); + /*! + ensures + - #*this is properly initialized + - does not modify m in any way + !*/ + + explicit auto_unlock ( + const read_write_mutex& m + ); + /*! + ensures + - #*this is properly initialized + - does not modify m in any way + !*/ + + ~auto_unlock ( + ); + /*! + ensures + - all resources allocated by *this have been freed + - calls unlock() on the mutex associated with *this + !*/ + + private: + // restricted functions + auto_unlock(auto_unlock&); // copy constructor + auto_unlock& operator=(auto_unlock&); // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + + class auto_unlock_readonly + { + /*! + INITIAL VALUE + The mutex given in the constructor is associated with this object. + + WHAT THIS OBJECT REPRESENTS + This object represents a mechanism for automatically unlocking + a read_write_mutex object. It is useful when you already have a locked mutex + and want to make sure it gets unlocked even if an exception is thrown + or you quit the function at a weird spot. Note that the mutex + is unlocked by calling unlock_readonly() on it. + !*/ + public: + + explicit auto_unlock_readonly ( + const read_write_mutex& m + ); + /*! + ensures + - #*this is properly initialized + - does not modify m in any way + !*/ + + ~auto_unlock_readonly ( + ); + /*! + ensures + - all resources allocated by *this have been freed + - calls unlock_readonly() on the mutex associated with *this + !*/ + + private: + // restricted functions + auto_unlock_readonly(auto_unlock_readonly&); // copy constructor + auto_unlock_readonly& operator=(auto_unlock_readonly&); // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_AUTO_UNLOCK_EXTENSIOn_ABSTRACT_ + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/create_new_thread_extension.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/create_new_thread_extension.h new file mode 100644 index 0000000..8f419b6 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/create_new_thread_extension.h @@ -0,0 +1,46 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_CREATE_NEW_THREAD_EXTENSIOn_ +#define DLIB_CREATE_NEW_THREAD_EXTENSIOn_ + +#include "threads_kernel_abstract.h" +#include "create_new_thread_extension_abstract.h" +#include "../threads.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + void (T::*funct)() + > + inline void dlib_create_new_thread_helper ( + void* obj + ) + { + T* o = static_cast(obj); + (o->*funct)(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + void (T::*funct)() + > + inline bool create_new_thread ( + T& obj + ) + { + return create_new_thread(dlib_create_new_thread_helper,&obj); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_CREATE_NEW_THREAD_EXTENSIOn_ + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/create_new_thread_extension_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/create_new_thread_extension_abstract.h new file mode 100644 index 0000000..43fbc47 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/create_new_thread_extension_abstract.h @@ -0,0 +1,33 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_CREATE_NEW_THREAD_EXTENSIOn_ABSTRACT_ +#ifdef DLIB_CREATE_NEW_THREAD_EXTENSIOn_ABSTRACT_ + +#include "threads_kernel_abstract.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template < + typename T, + void (T::*funct)() + > + bool create_new_thread ( + T& obj + ); + /*! + ensures + - creates a new thread and calls obj.*funct() from it. + - returns true upon success and false upon failure to create the new thread. + !*/ + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_CREATE_NEW_THREAD_EXTENSIOn_ABSTRACT_ + + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/multithreaded_object_extension.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/multithreaded_object_extension.h new file mode 100644 index 0000000..9dd37fd --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/multithreaded_object_extension.h @@ -0,0 +1,153 @@ +// Copyright (C) 2007 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_MULTITHREADED_OBJECT_EXTENSIOn_ +#define DLIB_MULTITHREADED_OBJECT_EXTENSIOn_ + +#include "multithreaded_object_extension_abstract.h" +#include "threads_kernel.h" +#include "auto_mutex_extension.h" +#include "rmutex_extension.h" +#include "rsignaler_extension.h" +#include "../algs.h" +#include "../assert.h" +#include "../map.h" +#include "../member_function_pointer.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class multithreaded_object + { + /*! + INITIAL VALUE + - is_running_ == false + - should_stop_ == false + - thread_ids.size() == 0 + - dead_threads.size() == 0 + - threads_started == 0 + + CONVENTION + - number_of_threads_registered() == thread_ids.size() + dead_threads.size() + - number_of_threads_alive() == threads_started + + - is_running() == is_running_ + - should_stop() == should_stop_ + + - thread_ids == a map of current thread ids to the member function + pointers that that thread runs. + - threads_started == the number of threads that have been spawned to run + thread_helper but haven't ended yet. + + - dead_threads == a queue that contains all the member function pointers + for threads that are currently registered but not running + + - m_ == the mutex used to protect all our variables + - s == the signaler for m_ + !*/ + + public: + + multithreaded_object ( + ); + + virtual ~multithreaded_object ( + ) = 0; + + void clear ( + ); + + bool is_running ( + ) const; + + unsigned long number_of_threads_alive ( + ) const; + + unsigned long number_of_threads_registered ( + ) const; + + void wait ( + ) const; + + void start ( + ); + + void pause ( + ); + + void stop ( + ); + + protected: + + bool should_stop ( + ) const; + + template < + typename T + > + void register_thread ( + T& object, + void (T::*thread)() + ) + { + auto_mutex M(m_); + try + { + mfp mf; + mf.set(object,thread); + dead_threads.enqueue(mf); + if (is_running_) + start(); + } + catch (...) + { + is_running_ = false; + should_stop_ = true; + s.broadcast(); + throw; + } + } + + private: + + class raii_thread_helper + { + public: + raii_thread_helper(multithreaded_object& self_, thread_id_type id_); + ~raii_thread_helper(); + + multithreaded_object& self; + thread_id_type id; + }; + + void thread_helper( + ); + + typedef member_function_pointer<> mfp; + + rmutex m_; + rsignaler s; + map::kernel_2a>::kernel_1a thread_ids; + queue::kernel_2a>::kernel_1a dead_threads; + + bool is_running_; + bool should_stop_; + unsigned long threads_started; + + // restricted functions + multithreaded_object(multithreaded_object&); // copy constructor + multithreaded_object& operator=(multithreaded_object&); // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + +} + +#ifdef NO_MAKEFILE +#include "multithreaded_object_extension.cpp" +#endif + +#endif // DLIB_MULTITHREADED_OBJECT_EXTENSIOn_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/multithreaded_object_extension_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/multithreaded_object_extension_abstract.h new file mode 100644 index 0000000..e7862b7 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/multithreaded_object_extension_abstract.h @@ -0,0 +1,186 @@ +// Copyright (C) 2007 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_MULTITHREADED_OBJECT_EXTENSIOn_ABSTRACT_ +#ifdef DLIB_MULTITHREADED_OBJECT_EXTENSIOn_ABSTRACT_ + +#include "threads_kernel_abstract.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class multithreaded_object + { + /*! + INITIAL VALUE + - is_running() == false + - number_of_threads_alive() == 0 + - number_of_threads_registered() == 0 + + WHAT THIS OBJECT REPRESENTS + This object represents a multithreaded object. It is similar to + the threaded_object except it allows you to have many threads in a + single object rather than just one. To use it you inherit from it + and register the member functions in your new class that you want + to run in their own threads by calling register_thread(). Then when + you call start() it will spawn all the registered functions + in their own threads. + !*/ + + public: + + multithreaded_object ( + ); + /*! + ensures + - #*this is properly initialized + throws + - std::bad_alloc + - dlib::thread_error + the constructor may throw this exception if there is a problem + gathering resources to create threading objects. + !*/ + + virtual ~multithreaded_object ( + ) = 0; + /*! + requires + - number_of_threads_alive() == 0 + (i.e. in the destructor for the object you derive from this one you + must wait for all the threads to end.) + ensures + - all resources allocated by *this have been freed. + !*/ + + void clear( + ); + /*! + ensures + - #*this has its initial value + - blocks until all threads have terminated + throws + - std::bad_alloc or dlib::thread_error + if an exception is thrown then *this is unusable + until clear() is called and succeeds + !*/ + + bool is_running ( + ) const; + /*! + ensures + - if (number_of_threads_alive() > 0 && the threads are currently supposed to be executing) then + - returns true + - else + - returns false + !*/ + + unsigned long number_of_threads_alive ( + ) const; + /*! + ensures + - returns the number of threads that are currently alive (i.e. + the number of threads that have started but not yet terminated) + !*/ + + unsigned long number_of_threads_registered ( + ) const; + /*! + ensures + - returns the number of threads that have been registered by + calls to register_thread() + !*/ + + void wait ( + ) const; + /*! + requires + - is not called from one of this object's threads + ensures + - if (number_of_threads_alive() > 0) then + - blocks until all the threads in this object have terminated + (i.e. blocks until number_of_threads_alive() == 0) + !*/ + + void start ( + ); + /*! + ensures + - #number_of_threads_alive() == number_of_threads_registered() + - #is_running() == true + - #should_stop() == false + - all the threads registered are up and running. + throws + - std::bad_alloc or dlib::thread_error + If either of these exceptions are thrown then + #is_running() == false and should_stop() == true + !*/ + + void pause ( + ); + /*! + ensures + - #is_running() == false + !*/ + + void stop ( + ); + /*! + ensures + - #should_stop() == true + - #is_running() == false + !*/ + + protected: + + template < + typename T + > + void register_thread ( + T& object, + void (T::*thread)() + ); + /*! + requires + - (object.*thread)() forms a valid function call + - the thread function does not throw + ensures + - registers the member function pointed to by thread as one of the threads + that runs when is_running() == true + - #number_of_threads_registered() == number_of_threads_registered() + 1 + - if (is_running() == true) + - spawns this new member function in its own thread + - #number_of_threads_alive() += number_of_threads_alive() + 1 + throws + - std::bad_alloc or dlib::thread_error + If either of these exceptions are thrown then + #is_running() == false and should_stop() == true + !*/ + + bool should_stop ( + ) const; + /*! + requires + - is only called from one of the registered threads in this object + ensures + - if (is_running() == false && should_stop() == false) then + - blocks until (#is_running() == true || #should_stop() == true) + - if (this thread is supposed to terminate) then + - returns true + - else + - returns false + !*/ + + private: + + // restricted functions + multithreaded_object(multithreaded_object&); // copy constructor + multithreaded_object& operator=(multithreaded_object&); // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_MULTITHREADED_OBJECT_EXTENSIOn_ABSTRACT_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/parallel_for_extension.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/parallel_for_extension.h new file mode 100644 index 0000000..60b64b1 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/parallel_for_extension.h @@ -0,0 +1,676 @@ +// Copyright (C) 2013 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_PARALLEL_FoR_Hh_ +#define DLIB_PARALLEL_FoR_Hh_ + +#include "parallel_for_extension_abstract.h" +#include "thread_pool_extension.h" +#include "../console_progress_indicator.h" +#include "async.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + namespace impl + { + + template + class helper_parallel_for + { + public: + helper_parallel_for ( + T& obj_, + void (T::*funct_)(long) + ) : + obj(obj_), + funct(funct_) + {} + + T& obj; + void (T::*funct)(long); + + void process_block (long begin, long end) + { + for (long i = begin; i < end; ++i) + (obj.*funct)(i); + } + }; + + template + class helper_parallel_for_funct + { + public: + helper_parallel_for_funct ( + const T& funct_ + ) : funct(funct_) {} + + const T& funct; + + void run(long i) + { + funct(i); + } + }; + + template + class helper_parallel_for_funct2 + { + public: + helper_parallel_for_funct2 ( + const T& funct_ + ) : funct(funct_) {} + + const T& funct; + + void run(long begin, long end) + { + funct(begin, end); + } + }; + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template + void parallel_for_blocked ( + thread_pool& tp, + long begin, + long end, + T& obj, + void (T::*funct)(long, long), + long chunks_per_thread = 8 + ) + { + // make sure requires clause is not broken + DLIB_ASSERT(begin <= end && chunks_per_thread > 0, + "\t void parallel_for_blocked()" + << "\n\t Invalid inputs were given to this function" + << "\n\t begin: " << begin + << "\n\t end: " << end + << "\n\t chunks_per_thread: " << chunks_per_thread + ); + + if (tp.num_threads_in_pool() != 0) + { + const long num = end-begin; + const long num_workers = static_cast(tp.num_threads_in_pool()); + // How many samples to process in a single task (aim for chunks_per_thread jobs per worker) + const long block_size = std::max(1L, num/(num_workers*chunks_per_thread)); + for (long i = 0; i < num; i+=block_size) + { + tp.add_task(obj, funct, begin+i, begin+std::min(i+block_size, num)); + } + tp.wait_for_all_tasks(); + } + else + { + // Since there aren't any threads in the pool we might as well just invoke + // the function directly since that's all the thread_pool object would do. + // But doing it ourselves skips a mutex lock. + (obj.*funct)(begin, end); + } + } + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for_blocked ( + unsigned long num_threads, + long begin, + long end, + T& obj, + void (T::*funct)(long, long), + long chunks_per_thread = 8 + ) + { + // make sure requires clause is not broken + DLIB_ASSERT(begin <= end && chunks_per_thread > 0, + "\t void parallel_for_blocked()" + << "\n\t Invalid inputs were given to this function" + << "\n\t begin: " << begin + << "\n\t end: " << end + << "\n\t chunks_per_thread: " << chunks_per_thread + ); + + thread_pool tp(num_threads); + parallel_for_blocked(tp, begin, end, obj, funct, chunks_per_thread); + } + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for_blocked ( + thread_pool& tp, + long begin, + long end, + const T& funct, + long chunks_per_thread = 8 + ) + { + // make sure requires clause is not broken + DLIB_ASSERT(begin <= end && chunks_per_thread > 0, + "\t void parallel_for_blocked()" + << "\n\t Invalid inputs were given to this function" + << "\n\t begin: " << begin + << "\n\t end: " << end + << "\n\t chunks_per_thread: " << chunks_per_thread + ); + + impl::helper_parallel_for_funct2 helper(funct); + parallel_for_blocked(tp, begin, end, helper, &impl::helper_parallel_for_funct2::run, chunks_per_thread); + } + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for_blocked ( + unsigned long num_threads, + long begin, + long end, + const T& funct, + long chunks_per_thread = 8 + ) + { + // make sure requires clause is not broken + DLIB_ASSERT(begin <= end && chunks_per_thread > 0, + "\t void parallel_for_blocked()" + << "\n\t Invalid inputs were given to this function" + << "\n\t begin: " << begin + << "\n\t end: " << end + << "\n\t chunks_per_thread: " << chunks_per_thread + ); + + thread_pool tp(num_threads); + parallel_for_blocked(tp, begin, end, funct, chunks_per_thread); + } + + template + void parallel_for_blocked ( + long begin, + long end, + const T& funct, + long chunks_per_thread = 8 + ) + { + parallel_for_blocked(default_thread_pool(), begin, end, funct, chunks_per_thread); + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template + void parallel_for ( + thread_pool& tp, + long begin, + long end, + T& obj, + void (T::*funct)(long), + long chunks_per_thread = 8 + ) + { + // make sure requires clause is not broken + DLIB_ASSERT(begin <= end && chunks_per_thread > 0, + "\t void parallel_for()" + << "\n\t Invalid inputs were given to this function" + << "\n\t begin: " << begin + << "\n\t end: " << end + << "\n\t chunks_per_thread: " << chunks_per_thread + ); + + impl::helper_parallel_for helper(obj, funct); + parallel_for_blocked(tp, begin, end, helper, &impl::helper_parallel_for::process_block, chunks_per_thread); + } + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for ( + unsigned long num_threads, + long begin, + long end, + T& obj, + void (T::*funct)(long), + long chunks_per_thread = 8 + ) + { + // make sure requires clause is not broken + DLIB_ASSERT(begin <= end && chunks_per_thread > 0, + "\t void parallel_for()" + << "\n\t Invalid inputs were given to this function" + << "\n\t begin: " << begin + << "\n\t end: " << end + << "\n\t chunks_per_thread: " << chunks_per_thread + ); + + thread_pool tp(num_threads); + parallel_for(tp, begin, end, obj, funct, chunks_per_thread); + } + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for ( + thread_pool& tp, + long begin, + long end, + const T& funct, + long chunks_per_thread = 8 + ) + { + // make sure requires clause is not broken + DLIB_ASSERT(begin <= end && chunks_per_thread > 0, + "\t void parallel_for()" + << "\n\t Invalid inputs were given to this function" + << "\n\t begin: " << begin + << "\n\t end: " << end + << "\n\t chunks_per_thread: " << chunks_per_thread + ); + + impl::helper_parallel_for_funct helper(funct); + parallel_for(tp, begin, end, helper, &impl::helper_parallel_for_funct::run, chunks_per_thread); + } + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for ( + unsigned long num_threads, + long begin, + long end, + const T& funct, + long chunks_per_thread = 8 + ) + { + // make sure requires clause is not broken + DLIB_ASSERT(begin <= end && chunks_per_thread > 0, + "\t void parallel_for()" + << "\n\t Invalid inputs were given to this function" + << "\n\t begin: " << begin + << "\n\t end: " << end + << "\n\t chunks_per_thread: " << chunks_per_thread + ); + + thread_pool tp(num_threads); + parallel_for(tp, begin, end, funct, chunks_per_thread); + } + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for ( + long begin, + long end, + const T& funct, + long chunks_per_thread = 8 + ) + { + parallel_for(default_thread_pool(), begin, end, funct, chunks_per_thread); + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + namespace impl + { + template + class parfor_verbose_helper + { + public: + parfor_verbose_helper(T& obj_, void (T::*funct_)(long), long begin, long end) : + obj(obj_), funct(funct_), pbar(end-begin) + { + count = 0; + wrote_to_screen = pbar.print_status(0); + } + + ~parfor_verbose_helper() + { + if (wrote_to_screen) + std::cout << std::endl; + } + + mutable long count; + T& obj; + void (T::*funct)(long); + mutable console_progress_indicator pbar; + mutable bool wrote_to_screen; + mutex m; + + void operator()(long i) const + { + (obj.*funct)(i); + { + auto_mutex lock(m); + wrote_to_screen = pbar.print_status(++count) || wrote_to_screen; + } + } + + }; + + template + class parfor_verbose_helper3 + { + public: + parfor_verbose_helper3(T& obj_, void (T::*funct_)(long,long), long begin, long end) : + obj(obj_), funct(funct_), pbar(end-begin) + { + count = 0; + wrote_to_screen = pbar.print_status(0); + } + + ~parfor_verbose_helper3() + { + if (wrote_to_screen) + std::cout << std::endl; + } + + mutable long count; + T& obj; + void (T::*funct)(long,long); + mutable console_progress_indicator pbar; + mutable bool wrote_to_screen; + mutex m; + + void operator()(long begin, long end) const + { + (obj.*funct)(begin, end); + { + auto_mutex lock(m); + count += end-begin; + wrote_to_screen = pbar.print_status(count) || wrote_to_screen; + } + } + }; + + template + class parfor_verbose_helper2 + { + public: + parfor_verbose_helper2(const T& obj_, long begin, long end) : obj(obj_), pbar(end-begin) + { + count = 0; + wrote_to_screen = pbar.print_status(0); + } + + ~parfor_verbose_helper2() + { + if (wrote_to_screen) + std::cout << std::endl; + } + + mutable long count; + const T& obj; + mutable console_progress_indicator pbar; + mutable bool wrote_to_screen; + mutex m; + + void operator()(long i) const + { + obj(i); + { + auto_mutex lock(m); + wrote_to_screen = pbar.print_status(++count) || wrote_to_screen; + } + } + + void operator()(long begin, long end) const + { + obj(begin, end); + { + auto_mutex lock(m); + count += end-begin; + wrote_to_screen = pbar.print_status(count) || wrote_to_screen; + } + } + }; + } + + template + void parallel_for_verbose ( + thread_pool& tp, + long begin, + long end, + T& obj, + void (T::*funct)(long), + long chunks_per_thread = 8 + ) + { + // make sure requires clause is not broken + DLIB_ASSERT(begin <= end && chunks_per_thread > 0, + "\t void parallel_for_verbose()" + << "\n\t Invalid inputs were given to this function" + << "\n\t begin: " << begin + << "\n\t end: " << end + << "\n\t chunks_per_thread: " << chunks_per_thread + ); + + impl::parfor_verbose_helper helper(obj, funct, begin, end); + parallel_for(tp, begin, end, helper, chunks_per_thread); + } + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for_verbose ( + unsigned long num_threads, + long begin, + long end, + T& obj, + void (T::*funct)(long), + long chunks_per_thread = 8 + ) + { + // make sure requires clause is not broken + DLIB_ASSERT(begin <= end && chunks_per_thread > 0, + "\t void parallel_for_verbose()" + << "\n\t Invalid inputs were given to this function" + << "\n\t begin: " << begin + << "\n\t end: " << end + << "\n\t chunks_per_thread: " << chunks_per_thread + ); + + impl::parfor_verbose_helper helper(obj, funct, begin, end); + parallel_for(num_threads, begin, end, helper, chunks_per_thread); + } + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for_verbose ( + thread_pool& tp, + long begin, + long end, + const T& funct, + long chunks_per_thread = 8 + ) + { + // make sure requires clause is not broken + DLIB_ASSERT(begin <= end && chunks_per_thread > 0, + "\t void parallel_for_verbose()" + << "\n\t Invalid inputs were given to this function" + << "\n\t begin: " << begin + << "\n\t end: " << end + << "\n\t chunks_per_thread: " << chunks_per_thread + ); + + impl::parfor_verbose_helper2 helper(funct, begin, end); + parallel_for(tp, begin, end, helper, chunks_per_thread); + } + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for_verbose ( + unsigned long num_threads, + long begin, + long end, + const T& funct, + long chunks_per_thread = 8 + ) + { + // make sure requires clause is not broken + DLIB_ASSERT(begin <= end && chunks_per_thread > 0, + "\t void parallel_for_verbose()" + << "\n\t Invalid inputs were given to this function" + << "\n\t begin: " << begin + << "\n\t end: " << end + << "\n\t chunks_per_thread: " << chunks_per_thread + ); + + impl::parfor_verbose_helper2 helper(funct, begin, end); + parallel_for(num_threads, begin, end, helper, chunks_per_thread); + } + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for_verbose ( + long begin, + long end, + const T& funct, + long chunks_per_thread = 8 + ) + { + // make sure requires clause is not broken + DLIB_ASSERT(begin <= end && chunks_per_thread > 0, + "\t void parallel_for_verbose()" + << "\n\t Invalid inputs were given to this function" + << "\n\t begin: " << begin + << "\n\t end: " << end + << "\n\t chunks_per_thread: " << chunks_per_thread + ); + + impl::parfor_verbose_helper2 helper(funct, begin, end); + parallel_for(begin, end, helper, chunks_per_thread); + } + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for_blocked_verbose ( + thread_pool& tp, + long begin, + long end, + T& obj, + void (T::*funct)(long,long), + long chunks_per_thread = 8 + ) + { + // make sure requires clause is not broken + DLIB_ASSERT(begin <= end && chunks_per_thread > 0, + "\t void parallel_for_blocked_verbose()" + << "\n\t Invalid inputs were given to this function" + << "\n\t begin: " << begin + << "\n\t end: " << end + << "\n\t chunks_per_thread: " << chunks_per_thread + ); + + impl::parfor_verbose_helper3 helper(obj, funct, begin, end); + parallel_for_blocked(tp, begin, end, helper, chunks_per_thread); + } + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for_blocked_verbose ( + unsigned long num_threads, + long begin, + long end, + T& obj, + void (T::*funct)(long,long), + long chunks_per_thread = 8 + ) + { + // make sure requires clause is not broken + DLIB_ASSERT(begin <= end && chunks_per_thread > 0, + "\t void parallel_for_blocked_verbose()" + << "\n\t Invalid inputs were given to this function" + << "\n\t begin: " << begin + << "\n\t end: " << end + << "\n\t chunks_per_thread: " << chunks_per_thread + ); + + impl::parfor_verbose_helper3 helper(obj, funct, begin, end); + parallel_for_blocked(num_threads, begin, end, helper, chunks_per_thread); + } + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for_blocked_verbose ( + thread_pool& tp, + long begin, + long end, + const T& funct, + long chunks_per_thread = 8 + ) + { + // make sure requires clause is not broken + DLIB_ASSERT(begin <= end && chunks_per_thread > 0, + "\t void parallel_for_blocked_verbose()" + << "\n\t Invalid inputs were given to this function" + << "\n\t begin: " << begin + << "\n\t end: " << end + << "\n\t chunks_per_thread: " << chunks_per_thread + ); + + impl::parfor_verbose_helper2 helper(funct, begin, end); + parallel_for_blocked(tp, begin, end, helper, chunks_per_thread); + } + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for_blocked_verbose ( + unsigned long num_threads, + long begin, + long end, + const T& funct, + long chunks_per_thread = 8 + ) + { + // make sure requires clause is not broken + DLIB_ASSERT(begin <= end && chunks_per_thread > 0, + "\t void parallel_for_blocked_verbose()" + << "\n\t Invalid inputs were given to this function" + << "\n\t begin: " << begin + << "\n\t end: " << end + << "\n\t chunks_per_thread: " << chunks_per_thread + ); + + impl::parfor_verbose_helper2 helper(funct, begin, end); + parallel_for_blocked(num_threads, begin, end, helper, chunks_per_thread); + } + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for_blocked_verbose ( + long begin, + long end, + const T& funct, + long chunks_per_thread = 8 + ) + { + // make sure requires clause is not broken + DLIB_ASSERT(begin <= end && chunks_per_thread > 0, + "\t void parallel_for_blocked_verbose()" + << "\n\t Invalid inputs were given to this function" + << "\n\t begin: " << begin + << "\n\t end: " << end + << "\n\t chunks_per_thread: " << chunks_per_thread + ); + + impl::parfor_verbose_helper2 helper(funct, begin, end); + parallel_for_blocked(begin, end, helper, chunks_per_thread); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_PARALLEL_FoR_Hh_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/parallel_for_extension_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/parallel_for_extension_abstract.h new file mode 100644 index 0000000..ffd2e0c --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/parallel_for_extension_abstract.h @@ -0,0 +1,469 @@ +// Copyright (C) 2013 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_PARALLEL_FoR_ABSTRACT_Hh_ +#ifdef DLIB_PARALLEL_FoR_ABSTRACT_Hh_ + +#include "thread_pool_extension_abstract.h" +#include "async_abstract.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for_blocked ( + thread_pool& tp, + long begin, + long end, + T& obj, + void (T::*funct)(long, long), + long chunks_per_thread = 8 + ); + /*! + requires + - begin <= end + - chunks_per_thread > 0 + ensures + - This is a convenience function for submitting a block of jobs to a thread_pool. + In particular, given the half open range [begin, end), this function will + split the range into approximately tp.num_threads_in_pool()*chunks_per_thread + blocks, which it will then submit to the thread_pool. The given thread_pool + will then call (obj.*funct)() on each of the subranges. + - To be precise, suppose we have broken the range [begin, end) into the + following subranges: + - [begin[0], end[0]) + - [begin[1], end[1]) + - [begin[2], end[2]) + ... + - [begin[n], end[n]) + Then parallel_for_blocked() submits each of these subranges to tp for + processing such that (obj.*funct)(begin[i], end[i]) is invoked for all valid + values of i. Moreover, the subranges are non-overlapping and completely + cover the total range of [begin, end). + - This function will not perform any memory allocations or create any system + resources such as mutex objects. + !*/ + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for_blocked ( + unsigned long num_threads, + long begin, + long end, + T& obj, + void (T::*funct)(long, long), + long chunks_per_thread = 8 + ); + /*! + requires + - begin <= end + - chunks_per_thread > 0 + ensures + - This function is equivalent to the following block of code: + thread_pool tp(num_threads); + parallel_for_blocked(tp, begin, end, obj, funct, chunks_per_thread); + !*/ + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for_blocked ( + thread_pool& tp, + long begin, + long end, + const T& funct, + long chunks_per_thread = 8 + ); + /*! + requires + - chunks_per_thread > 0 + - begin <= end + ensures + - This is a convenience function for submitting a block of jobs to a + thread_pool. In particular, given the range [begin, end), this function will + split the range into approximately tp.num_threads_in_pool()*chunks_per_thread + blocks, which it will then submit to the thread_pool. The given thread_pool + will then call funct() on each of the subranges. + - To be precise, suppose we have broken the range [begin, end) into the + following subranges: + - [begin[0], end[0]) + - [begin[1], end[1]) + - [begin[2], end[2]) + ... + - [begin[n], end[n]) + Then parallel_for_blocked() submits each of these subranges to tp for + processing such that funct(begin[i], end[i]) is invoked for all valid values + of i. + - This function will not perform any memory allocations or create any system + resources such as mutex objects. + !*/ + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for_blocked ( + unsigned long num_threads, + long begin, + long end, + const T& funct, + long chunks_per_thread = 8 + ); + /*! + requires + - begin <= end + - chunks_per_thread > 0 + ensures + - This function is equivalent to the following block of code: + thread_pool tp(num_threads); + parallel_for_blocked(tp, begin, end, funct, chunks_per_thread); + !*/ + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for_blocked ( + long begin, + long end, + const T& funct, + long chunks_per_thread = 8 + ); + /*! + requires + - begin <= end + - chunks_per_thread > 0 + ensures + - This function is equivalent to the following block of code: + parallel_for_blocked(default_thread_pool(), begin, end, funct, chunks_per_thread); + !*/ + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template + void parallel_for ( + thread_pool& tp, + long begin, + long end, + T& obj, + void (T::*funct)(long), + long chunks_per_thread = 8 + ); + /*! + requires + - begin <= end + - chunks_per_thread > 0 + ensures + - This function is equivalent to the following function call: + parallel_for_blocked(tp, begin, end, [&](long begin_sub, long end_sub) + { + for (long i = begin_sub; i < end_sub; ++i) + (obj.*funct)(i); + }, chunks_per_thread); + - Therefore, this routine invokes (obj.*funct)(i) for all i in the range + [begin, end). However, it does so using tp.num_threads_in_pool() parallel + threads. + - This function will not perform any memory allocations or create any system + resources such as mutex objects. + !*/ + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for ( + unsigned long num_threads, + long begin, + long end, + T& obj, + void (T::*funct)(long), + long chunks_per_thread = 8 + ); + /*! + requires + - begin <= end + - chunks_per_thread > 0 + ensures + - This function is equivalent to the following block of code: + thread_pool tp(num_threads); + parallel_for(tp, begin, end, obj, funct, chunks_per_thread); + !*/ + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for ( + thread_pool& tp, + long begin, + long end, + const T& funct, + long chunks_per_thread = 8 + ); + /*! + requires + - begin <= end + - chunks_per_thread > 0 + ensures + - This function is equivalent to the following function call: + parallel_for_blocked(tp, begin, end, [&](long begin_sub, long end_sub) + { + for (long i = begin_sub; i < end_sub; ++i) + funct(i); + }, chunks_per_thread); + - Therefore, this routine invokes funct(i) for all i in the range [begin, end). + However, it does so using tp.num_threads_in_pool() parallel threads. + - This function will not perform any memory allocations or create any system + resources such as mutex objects. + !*/ + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for ( + unsigned long num_threads, + long begin, + long end, + const T& funct, + long chunks_per_thread = 8 + ); + /*! + requires + - begin <= end + - chunks_per_thread > 0 + ensures + - This function is equivalent to the following block of code: + thread_pool tp(num_threads); + parallel_for(tp, begin, end, funct, chunks_per_thread); + !*/ + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for ( + long begin, + long end, + const T& funct, + long chunks_per_thread = 8 + ); + /*! + requires + - begin <= end + - chunks_per_thread > 0 + ensures + - This function is equivalent to the following block of code: + parallel_for(default_thread_pool(), begin, end, funct, chunks_per_thread); + !*/ + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template + void parallel_for_verbose ( + thread_pool& tp, + long begin, + long end, + T& obj, + void (T::*funct)(long), + long chunks_per_thread = 8 + ); + /*! + requires + - begin <= end + - chunks_per_thread > 0 + ensures + - This function is identical to the parallel_for() routine defined above except + that it will print messages to cout showing the progress in executing the + parallel for loop. + !*/ + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for_verbose ( + unsigned long num_threads, + long begin, + long end, + T& obj, + void (T::*funct)(long), + long chunks_per_thread = 8 + ); + /*! + requires + - begin <= end + - chunks_per_thread > 0 + ensures + - This function is identical to the parallel_for() routine defined above except + that it will print messages to cout showing the progress in executing the + parallel for loop. + !*/ + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for_verbose ( + thread_pool& tp, + long begin, + long end, + const T& funct, + long chunks_per_thread = 8 + ); + /*! + requires + - begin <= end + - chunks_per_thread > 0 + ensures + - This function is identical to the parallel_for() routine defined above except + that it will print messages to cout showing the progress in executing the + parallel for loop. + !*/ + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for_verbose ( + unsigned long num_threads, + long begin, + long end, + const T& funct, + long chunks_per_thread = 8 + ); + /*! + requires + - begin <= end + - chunks_per_thread > 0 + ensures + - This function is identical to the parallel_for() routine defined above except + that it will print messages to cout showing the progress in executing the + parallel for loop. + !*/ + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for_verbose ( + long begin, + long end, + const T& funct, + long chunks_per_thread = 8 + ); + /*! + requires + - begin <= end + - chunks_per_thread > 0 + ensures + - This function is identical to the parallel_for() routine defined above except + that it will print messages to cout showing the progress in executing the + parallel for loop. + - It will also use the default_thread_pool(). + !*/ + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template + void parallel_for_blocked_verbose ( + thread_pool& tp, + long begin, + long end, + T& obj, + void (T::*funct)(long,long), + long chunks_per_thread = 8 + ); + /*! + requires + - begin <= end + - chunks_per_thread > 0 + ensures + - This function is identical to the parallel_for_blocked() routine defined + above except that it will print messages to cout showing the progress in + executing the parallel for loop. + !*/ + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for_blocked_verbose ( + unsigned long num_threads, + long begin, + long end, + T& obj, + void (T::*funct)(long,long), + long chunks_per_thread = 8 + ); + /*! + requires + - begin <= end + - chunks_per_thread > 0 + ensures + - This function is identical to the parallel_for_blocked() routine defined + above except that it will print messages to cout showing the progress in + executing the parallel for loop. + !*/ + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for_blocked_verbose ( + thread_pool& tp, + long begin, + long end, + const T& funct, + long chunks_per_thread = 8 + ); + /*! + requires + - begin <= end + - chunks_per_thread > 0 + ensures + - This function is identical to the parallel_for_blocked() routine defined + above except that it will print messages to cout showing the progress in + executing the parallel for loop. + !*/ + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for_blocked_verbose ( + unsigned long num_threads, + long begin, + long end, + const T& funct, + long chunks_per_thread = 8 + ); + /*! + requires + - begin <= end + - chunks_per_thread > 0 + ensures + - This function is identical to the parallel_for_blocked() routine defined + above except that it will print messages to cout showing the progress in + executing the parallel for loop. + !*/ + +// ---------------------------------------------------------------------------------------- + + template + void parallel_for_blocked_verbose ( + long begin, + long end, + const T& funct, + long chunks_per_thread = 8 + ); + /*! + requires + - begin <= end + - chunks_per_thread > 0 + ensures + - This function is identical to the parallel_for_blocked() routine defined + above except that it will print messages to cout showing the progress in + executing the parallel for loop. + - It will also use the default_thread_pool() + !*/ + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_PARALLEL_FoR_ABSTRACT_Hh_ + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/posix.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/posix.h new file mode 100644 index 0000000..7226743 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/posix.h @@ -0,0 +1,6 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_THREADS_KERNEl_1_ +#include "threads_kernel_2.h" +#endif + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/read_write_mutex_extension.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/read_write_mutex_extension.h new file mode 100644 index 0000000..20e5d5e --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/read_write_mutex_extension.h @@ -0,0 +1,177 @@ +// Copyright (C) 2010 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_READ_WRITE_MUTEX_EXTENSIOn_ +#define DLIB_READ_WRITE_MUTEX_EXTENSIOn_ + +#include "threads_kernel.h" +#include "read_write_mutex_extension_abstract.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class read_write_mutex + { + /*! + INITIAL VALUE + - max_locks == defined by constructor + - available_locks == max_locks + - write_lock_in_progress == false + - write_lock_active == false + + CONVENTION + - Each time someone gets a read only lock they take one of the "available locks" + and each write lock takes all possible locks (i.e. max_locks). The number of + available locks is recorded in available_locks. Any time you try to lock this + object and there aren't available locks you have to wait. + + - max_locks == max_readonly_locks() + + - if (some thread is on the process of obtaining a write lock) then + - write_lock_in_progress == true + - else + - write_lock_in_progress == false + + - if (some thread currently has a write lock on this mutex) then + - write_lock_active == true + - else + - write_lock_active == false + !*/ + + public: + + read_write_mutex ( + ) : s(m), + max_locks(0xFFFFFFFF), + available_locks(max_locks), + write_lock_in_progress(false), + write_lock_active(false) + {} + + explicit read_write_mutex ( + unsigned long max_locks_ + ) : s(m), + max_locks(max_locks_), + available_locks(max_locks_), + write_lock_in_progress(false), + write_lock_active(false) + { + // make sure requires clause is not broken + DLIB_ASSERT(max_locks > 0, + "\t read_write_mutex::read_write_mutex(max_locks)" + << "\n\t You must give a non-zero value for max_locks" + << "\n\t this: " << this + ); + } + + ~read_write_mutex ( + ) + {} + + void lock ( + ) const + { + m.lock(); + + // If another write lock is already in progress then wait for it to finish + // before we start trying to grab all the available locks. This way we + // don't end up fighting over the locks. + while (write_lock_in_progress) + s.wait(); + + // grab the right to perform a write lock + write_lock_in_progress = true; + + // now start grabbing all the locks + unsigned long locks_obtained = available_locks; + available_locks = 0; + while (locks_obtained != max_locks) + { + s.wait(); + locks_obtained += available_locks; + available_locks = 0; + } + + write_lock_in_progress = false; + write_lock_active = true; + + m.unlock(); + } + + void unlock ( + ) const + { + m.lock(); + + // only do something if there really was a lock in place + if (write_lock_active) + { + available_locks = max_locks; + write_lock_active = false; + s.broadcast(); + } + + m.unlock(); + } + + void lock_readonly ( + ) const + { + m.lock(); + + while (available_locks == 0) + s.wait(); + + --available_locks; + + m.unlock(); + } + + void unlock_readonly ( + ) const + { + m.lock(); + + // If this condition is false then it means there are no more readonly locks + // to free. So we don't do anything. + if (available_locks != max_locks && !write_lock_active) + { + ++available_locks; + + // only perform broadcast when there is another thread that might be listening + if (available_locks == 1 || write_lock_in_progress) + { + s.broadcast(); + } + } + + m.unlock(); + } + + unsigned long max_readonly_locks ( + ) const + { + return max_locks; + } + + private: + mutex m; + signaler s; + const unsigned long max_locks; + mutable unsigned long available_locks; + mutable bool write_lock_in_progress; + mutable bool write_lock_active; + + // restricted functions + read_write_mutex(read_write_mutex&); // copy constructor + read_write_mutex& operator=(read_write_mutex&); // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_READ_WRITE_MUTEX_EXTENSIOn_ + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/read_write_mutex_extension_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/read_write_mutex_extension_abstract.h new file mode 100644 index 0000000..18672b0 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/read_write_mutex_extension_abstract.h @@ -0,0 +1,146 @@ +// Copyright (C) 2010 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_READWRITE_MUTEX_EXTENSIOn_ABSTRACT_ +#ifdef DLIB_READWRITE_MUTEX_EXTENSIOn_ABSTRACT_ + +#include "threads_kernel_abstract.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class read_write_mutex + { + /*! + INITIAL VALUE + read_write_mutex is in the fully unlocked state + + WHAT THIS OBJECT REPRESENTS + This object represents a mutex intended to be used for synchronous + thread control of shared data. When a thread wants to access some + shared data it locks out other threads by calling lock() and calls + unlock() when it is finished. + + This mutex also has the additional ability to distinguish between + a lock for the purposes of modifying some shared data, a write lock, + and a lock for the purposes of only reading shared data, a readonly + lock. The lock() and unlock() functions are used for write locks while + the lock_readonly() and unlock_readonly() are for readonly locks. + + The difference between a readonly and write lock can be understood as + follows. The read_write_mutex will allow many threads to obtain simultaneous + readonly locks but will only allow a single thread to obtain a write lock. + Moreover, while the write lock is obtained no other threads are allowed + to have readonly locks. + !*/ + public: + + read_write_mutex ( + ); + /*! + ensures + - #*this is properly initialized + - max_readonly_locks() == 0xFFFFFFFF + (i.e. about 4 billion) + throws + - dlib::thread_error + the constructor may throw this exception if there is a problem + gathering resources to create the read_write_mutex. + !*/ + + explicit read_write_mutex ( + unsigned long max_locks + ); + /*! + requires + - max_locks > 0 + ensures + - #*this is properly initialized + - max_readonly_locks() == max_locks + throws + - dlib::thread_error + the constructor may throw this exception if there is a problem + gathering resources to create the read_write_mutex. + !*/ + + ~read_write_mutex ( + ); + /*! + requires + - *this is not locked + ensures + - all resources allocated by *this have been freed + !*/ + + void lock ( + ) const; + /*! + requires + - The thread calling this function does not have any kind of lock on this + object + ensures + - if (there is any kind of lock on *this) then + - the calling thread is put to sleep until a write lock becomes available. + Once available, a write lock is obtained on this mutex and this function + terminates. + - else + - a write lock is obtained on this mutex and the calling thread is not put to sleep + !*/ + + void unlock ( + ) const; + /*! + ensures + - if (there is a write lock on *this) then + - #*this is unlocked (i.e. other threads may now lock this object) + - else + - the call to unlock() has no effect + !*/ + + unsigned long max_readonly_locks ( + ) const; + /*! + ensures + - returns the maximum number of concurrent readonly locks this object will allow. + !*/ + + void lock_readonly ( + ) const; + /*! + requires + - The thread calling this function does not already have a write + lock on this object + ensures + - if (there is a write lock on *this or there are no free readonly locks) then + - the calling thread is put to sleep until there is no longer a write lock + and a free readonly lock is available. Once this is the case, a readonly + lock is obtained and this function terminates. + - else + - a readonly lock is obtained on *this and the calling thread is not put + to sleep. Note that multiple readonly locks can be obtained at once. + !*/ + + void unlock_readonly ( + ) const; + /*! + ensures + - if (there is a readonly lock on *this) then + - one readonly lock is removed from *this. + - else + - the call to unlock_readonly() has no effect. + !*/ + + private: + // restricted functions + read_write_mutex(read_write_mutex&); // copy constructor + read_write_mutex& operator=(read_write_mutex&); // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_READWRITE_MUTEX_EXTENSIOn_ABSTRACT_ + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/rmutex_extension.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/rmutex_extension.h new file mode 100644 index 0000000..b7bf998 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/rmutex_extension.h @@ -0,0 +1,109 @@ +// Copyright (C) 2005 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_RMUTEX_EXTENSIOn_ +#define DLIB_RMUTEX_EXTENSIOn_ + +#include "threads_kernel.h" +#include "rmutex_extension_abstract.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class rmutex + { + /*! + INITIAL VALUE + count == 0 + thread_id == 0 + + CONVENTION + - count == lock_count() + + - if (no thread currently has a lock on this mutex) then + - count == 0 + - else + - count == the number of times the thread that owns this mutex has + called lock() + - thread_id == the id of this thread. + !*/ + public: + + rmutex ( + ) : s(m), + thread_id(0), + count(0) + {} + + ~rmutex ( + ) + {} + + unsigned long lock_count ( + ) const + { + return count; + } + + void lock ( + unsigned long times = 1 + ) const + { + const thread_id_type current_thread_id = get_thread_id(); + m.lock(); + if (thread_id == current_thread_id) + { + // we already own this mutex in this case + count += times; + } + else + { + // wait for our turn to claim this rmutex + while (count != 0) + s.wait(); + + count = times; + thread_id = current_thread_id; + } + m.unlock(); + } + + void unlock ( + unsigned long times = 1 + ) const + { + const thread_id_type current_thread_id = get_thread_id(); + m.lock(); + if (thread_id == current_thread_id) + { + if (count <= times) + { + count = 0; + s.signal(); + } + else + { + count -= times; + } + } + m.unlock(); + } + + private: + mutex m; + signaler s; + mutable thread_id_type thread_id; + mutable unsigned long count; + + // restricted functions + rmutex(rmutex&); // copy constructor + rmutex& operator=(rmutex&); // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_RMUTEX_EXTENSIOn_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/rmutex_extension_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/rmutex_extension_abstract.h new file mode 100644 index 0000000..144dbf4 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/rmutex_extension_abstract.h @@ -0,0 +1,107 @@ +// Copyright (C) 2005 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_RMUTEX_EXTENSIOn_ABSTRACT_ +#ifdef DLIB_RMUTEX_EXTENSIOn_ABSTRACT_ + +#include "threads_kernel_abstract.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class rmutex + { + /*! + INITIAL VALUE + rmutex is in the unlocked state + + WHAT THIS OBJECT REPRESENTS + This object represents a recursive mutex intended to be used for synchronous + thread control of shared data. When a thread wants to access some + shared data it locks out other threads by calling lock() and calls + unlock() when it is finished. + + The difference between this and the normal mutex object is that it is safe to + call lock() from a thread that already has a lock on this mutex. Doing + so just increments a counter but otherwise has no effect on the mutex. + Note that unlock() must be called for each call to lock() to release the + mutex. + !*/ + public: + + rmutex ( + ); + /*! + ensures + - #*this is properly initialized + throws + - dlib::thread_error + the constructor may throw this exception if there is a problem + gathering resources to create the rmutex. + !*/ + + ~rmutex ( + ); + /*! + requires + - *this is not locked + ensures + - all resources allocated by *this have been freed + !*/ + + unsigned long lock_count ( + ) const; + /*! + requires + - the calling thread has a lock on this mutex + ensures + - returns the number of times the thread has called lock() + !*/ + + void lock ( + unsigned long times = 1 + ) const; + /*! + ensures + - if (*this is currently locked by another thread) then + - the thread that called lock() on *this is put to sleep until + it becomes available. + - #lock_count() == times + - if (*this is currently unlocked) then + - #*this becomes locked and the current thread is NOT put to sleep + but now "owns" #*this + - #lock_count() == times + - if (*this is locked and owned by the current thread) then + - the calling thread retains its lock on *this and isn't put to sleep. + - #lock_count() == lock_count() + times + !*/ + + void unlock ( + unsigned long times = 1 + ) const; + /*! + ensures + - if (*this is currently locked and owned by the thread calling unlock) then + - if (lock_count() <= times ) then + - #*this is unlocked (i.e. other threads may now lock this object) + - else + - #*this will remain locked + - #lock_count() == lock_count() - times + - else + - the call to unlock() has no effect + !*/ + + + private: + // restricted functions + rmutex(rmutex&); // copy constructor + rmutex& operator=(rmutex&); // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_RMUTEX_EXTENSIOn_ABSTRACT_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/rsignaler_extension.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/rsignaler_extension.h new file mode 100644 index 0000000..bfb5a7e --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/rsignaler_extension.h @@ -0,0 +1,90 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_RSIGNALER_EXTENSIOn_ +#define DLIB_RSIGNALER_EXTENSIOn_ + +#include "rsignaler_extension_abstract.h" +#include "rmutex_extension.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class rsignaler + { + public: + rsignaler ( + const rmutex& associated_mutex + ) : + assoc_mutex(associated_mutex), + s(m) + {} + + ~rsignaler ( + ) + {} + + void wait ( + ) const + { + m.lock(); + const unsigned long lock_count = assoc_mutex.lock_count(); + assoc_mutex.unlock(lock_count); + s.wait(); + m.unlock(); + assoc_mutex.lock(lock_count); + } + + bool wait_or_timeout ( + unsigned long milliseconds + ) const + { + m.lock(); + const unsigned long lock_count = assoc_mutex.lock_count(); + assoc_mutex.unlock(lock_count); + bool res = s.wait_or_timeout(milliseconds); + m.unlock(); + assoc_mutex.lock(lock_count); + return res; + } + + void signal ( + ) const + { + m.lock(); + s.signal(); + m.unlock(); + } + + void broadcast ( + ) const + { + m.lock(); + s.broadcast(); + m.unlock(); + } + + const rmutex& get_mutex ( + ) const { return assoc_mutex; } + + private: + + const rmutex& assoc_mutex; + mutex m; + signaler s; + + + // restricted functions + rsignaler(rsignaler&); // copy constructor + rsignaler& operator=(rsignaler&); // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_RSIGNALER_EXTENSIOn_ + + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/rsignaler_extension_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/rsignaler_extension_abstract.h new file mode 100644 index 0000000..ae5f450 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/rsignaler_extension_abstract.h @@ -0,0 +1,123 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_RSIGNALER_EXTENSIOn_ABSTRACT_ +#ifdef DLIB_RSIGNALER_EXTENSIOn_ABSTRACT_ + +#include "threads_kernel_abstract.h" +#include "rmutex_extension_abstract.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class rsignaler + { + /*! + WHAT THIS OBJECT REPRESENTS + This object represents an event signaling system for threads. It gives + a thread the ability to wake up other threads that are waiting for a + particular signal. + + Each rsignaler object is associated with one and only one rmutex object. + More than one rsignaler object may be associated with a single rmutex + but a signaler object may only be associated with a single rmutex. + + NOTE: + You must guard against spurious wakeups. This means that a thread + might return from a call to wait even if no other thread called + signal. This is rare but must be guarded against. + + Also note that this object is identical to the signaler object + except that it works with rmutex objects rather than mutex objects. + !*/ + + public: + + rsignaler ( + const rmutex& associated_mutex + ); + /*! + ensures + - #*this is properly initialized + - #get_mutex() == associated_mutex + throws + - dlib::thread_error + the constructor may throw this exception if there is a problem + gathering resources to create the signaler. + !*/ + + + ~rsignaler ( + ); + /*! + ensures + - all resources allocated by *this have been freed + !*/ + + void wait ( + ) const; + /*! + requires + - get_mutex() is locked and owned by the calling thread + ensures + - atomically unlocks get_mutex() and blocks the calling thread + - calling thread may wake if another thread calls signal() or broadcast() + on *this + - when wait() returns the calling thread again has a lock on get_mutex() + !*/ + + bool wait_or_timeout ( + unsigned long milliseconds + ) const; + /*! + requires + - get_mutex() is locked and owned by the calling thread + ensures + - atomically unlocks get_mutex() and blocks the calling thread + - calling thread may wake if another thread calls signal() or broadcast() + on *this + - after the specified number of milliseconds has elapsed the calling thread + will wake once get_mutex() is free + - when wait returns the calling thread again has a lock on get_mutex() + + - returns false if the call to wait_or_timeout timed out + - returns true if the call did not time out + !*/ + + void signal ( + ) const; + /*! + ensures + - if (at least one thread is waiting on *this) then + - at least one of the waiting threads will wake + !*/ + + void broadcast ( + ) const; + /*! + ensures + - any and all threads waiting on *this will wake + !*/ + + const rmutex& get_mutex ( + ) const; + /*! + ensures + - returns a const reference to the rmutex associated with *this + !*/ + + + private: + // restricted functions + rsignaler(rsignaler&); // copy constructor + rsignaler& operator=(rsignaler&); // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_RSIGNALER_EXTENSIOn_ABSTRACT_ + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/thread_function_extension.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/thread_function_extension.h new file mode 100644 index 0000000..7ecdd65 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/thread_function_extension.h @@ -0,0 +1,215 @@ +// Copyright (C) 2007 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_THREAD_FUNCTIOn_ +#define DLIB_THREAD_FUNCTIOn_ + +#include + +#include "thread_function_extension_abstract.h" +#include "threads_kernel.h" +#include "auto_mutex_extension.h" +#include "threaded_object_extension.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class thread_function : private threaded_object + { + + class base_funct + { + public: + virtual void go() = 0; + virtual ~base_funct() {} + }; + + template + class super_funct_4 : public base_funct + { + public: + super_funct_4 ( F funct, T1 arg1, T2 arg2, T3 arg3, T4 arg4) : + f(funct), + a1(arg1), + a2(arg2), + a3(arg3), + a4(arg4) + { + } + + void go() { f(a1, a2, a3, a4); } + + + F f; + T1 a1; + T2 a2; + T3 a3; + T4 a4; + }; + + template + class super_funct_3 : public base_funct + { + public: + super_funct_3 ( F funct, T1 arg1, T2 arg2, T3 arg3): + f(funct), + a1(arg1), + a2(arg2), + a3(arg3) + { + } + + void go() { f(a1, a2, a3); } + + + F f; + T1 a1; + T2 a2; + T3 a3; + }; + + template + class super_funct_2 : public base_funct + { + public: + super_funct_2 ( F funct, T1 arg1, T2 arg2) : + f(funct), + a1(arg1), + a2(arg2) + { + } + + void go() { f(a1, a2); } + + + F f; + T1 a1; + T2 a2; + }; + + template + class super_funct_1 : public base_funct + { + public: + super_funct_1 ( F funct, T arg) : f(funct), a(arg) + { + } + + void go() { f(a); } + + + F f; + T a; + }; + + template + class super_funct_0 : public base_funct + { + public: + super_funct_0 ( F funct) : f(funct) + { + } + + void go() { f(); } + + F f; + }; + + public: + + template + thread_function ( + F funct + ) + { + f.reset(new super_funct_0(funct)); + start(); + } + + template + thread_function ( + F funct, + T arg + ) + { + f.reset(new super_funct_1(funct,arg)); + start(); + } + + template + thread_function ( + F funct, + T1 arg1, + T2 arg2 + ) + { + f.reset(new super_funct_2(funct, arg1, arg2)); + start(); + } + + template + thread_function ( + F funct, + T1 arg1, + T2 arg2, + T3 arg3 + ) + { + f.reset(new super_funct_3(funct, arg1, arg2, arg3)); + start(); + } + + template + thread_function ( + F funct, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4 + ) + { + f.reset(new super_funct_4(funct, arg1, arg2, arg3, arg4)); + start(); + } + + ~thread_function ( + ) + { + threaded_object::wait(); + } + + bool is_alive ( + ) const + { + return threaded_object::is_alive(); + } + + void wait ( + ) const + { + threaded_object::wait(); + } + + private: + + void thread () + { + f->go(); + } + + std::unique_ptr f; + + // restricted functions + thread_function(thread_function&); // copy constructor + thread_function& operator=(thread_function&); // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_THREAD_FUNCTIOn_ + + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/thread_function_extension_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/thread_function_extension_abstract.h new file mode 100644 index 0000000..65ea998 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/thread_function_extension_abstract.h @@ -0,0 +1,146 @@ +// Copyright (C) 2007 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_THREAD_FUNCTIOn_ABSTRACT_ +#ifdef DLIB_THREAD_FUNCTIOn_ABSTRACT_ + +#include "threads_kernel_abstract.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class thread_function + { + /*! + WHAT THIS OBJECT REPRESENTS + This object represents a thread on a global C++ function or function + object. That is, it allows you to run a function in its own thread. + !*/ + public: + + template + thread_function ( + F funct + ); + /*! + ensures + - #*this is properly initialized + - the function funct has been started in its own thread + throws + - std::bad_alloc + - dlib::thread_error + the constructor may throw this exception if there is a problem + gathering resources to create threading objects. + !*/ + + template + thread_function ( + F funct, + T1 arg1 + ); + /*! + ensures + - #*this is properly initialized + - A thread has been created and it will call funct(arg1) + throws + - std::bad_alloc + - dlib::thread_error + the constructor may throw this exception if there is a problem + gathering resources to create threading objects. + !*/ + + template + thread_function ( + F funct, + T1 arg1, + T2 arg2 + ); + /*! + ensures + - #*this is properly initialized + - A thread has been created and it will call funct(arg1, arg2) + throws + - std::bad_alloc + - dlib::thread_error + the constructor may throw this exception if there is a problem + gathering resources to create threading objects. + !*/ + + template + thread_function ( + F funct, + T1 arg1, + T2 arg2, + T3 arg3 + ); + /*! + ensures + - #*this is properly initialized + - A thread has been created and it will call funct(arg1, arg2, arg3) + throws + - std::bad_alloc + - dlib::thread_error + the constructor may throw this exception if there is a problem + gathering resources to create threading objects. + !*/ + + template + thread_function ( + F funct, + T1 arg1, + T2 arg2, + T3 arg3, + T4 arg4 + ); + /*! + ensures + - #*this is properly initialized + - A thread has been created and it will call funct(arg1, arg2, arg3, arg4) + throws + - std::bad_alloc + - dlib::thread_error + the constructor may throw this exception if there is a problem + gathering resources to create threading objects. + !*/ + + ~thread_function ( + ); + /*! + ensures + - all resources allocated by *this have been freed. + - blocks until is_alive() == false + !*/ + + bool is_alive ( + ) const; + /*! + ensures + - if (this object's thread has yet to terminate) then + - returns true + - else + - returns false + !*/ + + void wait ( + ) const; + /*! + ensures + - if (is_alive() == true) then + - blocks until this object's thread terminates + !*/ + + private: + + // restricted functions + thread_function(thread_function&); // copy constructor + thread_function& operator=(thread_function&); // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_THREAD_FUNCTIOn_ABSTRACT_ + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/thread_pool_extension.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/thread_pool_extension.h new file mode 100644 index 0000000..bc2e178 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/thread_pool_extension.h @@ -0,0 +1,1392 @@ +// Copyright (C) 2008 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_THREAD_POOl_Hh_ +#define DLIB_THREAD_POOl_Hh_ + +#include +#include +#include + +#include "thread_pool_extension_abstract.h" +#include "multithreaded_object_extension.h" +#include "../member_function_pointer.h" +#include "../bound_function_pointer.h" +#include "threads_kernel.h" +#include "auto_mutex_extension.h" +#include "../uintn.h" +#include "../array.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class thread_pool_implementation; + + template < + typename T + > + class future + { + /*! + INITIAL VALUE + - task_id == 0 + - tp.get() == 0 + + CONVENTION + - is_ready() == (tp.get() == 0) + - get() == var + + - if (tp.get() != 0) + - tp == a pointer to the thread_pool_implementation that is using this future object + - task_id == the task id of the task in the thread pool tp that is using + this future object. + !*/ + public: + + future ( + ) : task_id(0) {} + + future ( + const T& item + ) : task_id(0), var(item) {} + + future ( + const future& item + ) :task_id(0), var(item.get()) {} + + ~future ( + ) { wait(); } + + future& operator=( + const T& item + ) { get() = item; return *this; } + + future& operator=( + const future& item + ) { get() = item.get(); return *this; } + + operator T& ( + ) { return get(); } + + operator const T& ( + ) const { return get(); } + + T& get ( + ) { wait(); return var; } + + const T& get ( + ) const { wait(); return var; } + + bool is_ready ( + ) const { return tp.get() == 0; } + + private: + + friend class thread_pool; + + inline void wait () const; + + mutable uint64 task_id; + mutable std::shared_ptr tp; + + T var; + }; + +// ---------------------------------------------------------------------------------------- + + template + inline void swap ( + future& a, + future& b + ) { dlib::exchange(a.get(), b.get()); } + // Note that dlib::exchange() just calls std::swap. I'm only using it because + // this works around some bugs in certain compilers. + +// ---------------------------------------------------------------------------------------- + + template bool operator== (const future& a, const future& b) { return a.get() == b.get(); } + template bool operator!= (const future& a, const future& b) { return a.get() != b.get(); } + template bool operator<= (const future& a, const future& b) { return a.get() <= b.get(); } + template bool operator>= (const future& a, const future& b) { return a.get() >= b.get(); } + template bool operator< (const future& a, const future& b) { return a.get() < b.get(); } + template bool operator> (const future& a, const future& b) { return a.get() > b.get(); } + + template bool operator== (const future& a, const T& b) { return a.get() == b; } + template bool operator== (const T& a, const future& b) { return a == b.get(); } + template bool operator!= (const future& a, const T& b) { return a.get() != b; } + template bool operator!= (const T& a, const future& b) { return a != b.get(); } + template bool operator<= (const future& a, const T& b) { return a.get() <= b; } + template bool operator<= (const T& a, const future& b) { return a <= b.get(); } + template bool operator>= (const future& a, const T& b) { return a.get() >= b; } + template bool operator>= (const T& a, const future& b) { return a >= b.get(); } + template bool operator< (const future& a, const T& b) { return a.get() < b; } + template bool operator< (const T& a, const future& b) { return a < b.get(); } + template bool operator> (const future& a, const T& b) { return a.get() > b; } + template bool operator> (const T& a, const future& b) { return a > b.get(); } + +// ---------------------------------------------------------------------------------------- + + class thread_pool_implementation + { + /*! + CONVENTION + - num_threads_in_pool() == tasks.size() + - if (the destructor has been called) then + - we_are_destructing == true + - else + - we_are_destructing == false + + - is_task_thread() == is_worker_thread(get_thread_id()) + + - m == the mutex used to protect everything in this object + - worker_thread_ids == an array that contains the thread ids for + all the threads in the thread pool + !*/ + typedef bound_function_pointer::kernel_1a_c bfp_type; + + friend class thread_pool; + explicit thread_pool_implementation ( + unsigned long num_threads + ); + + public: + ~thread_pool_implementation( + ); + + void wait_for_task ( + uint64 task_id + ) const; + + unsigned long num_threads_in_pool ( + ) const; + + void wait_for_all_tasks ( + ) const; + + bool is_task_thread ( + ) const; + + template + uint64 add_task ( + T& obj, + void (T::*funct)() + ) + { + auto_mutex M(m); + const thread_id_type my_thread_id = get_thread_id(); + + // find a thread that isn't doing anything + long idx = find_empty_task_slot(); + if (idx == -1 && is_worker_thread(my_thread_id)) + { + // this function is being called from within a worker thread and there + // aren't any other worker threads free so just perform the task right + // here + + M.unlock(); + (obj.*funct)(); + + // return a task id that is both non-zero and also one + // that is never normally returned. This way calls + // to wait_for_task() will never block given this id. + return 1; + } + + // wait until there is a thread that isn't doing anything + while (idx == -1) + { + task_done_signaler.wait(); + idx = find_empty_task_slot(); + } + + tasks[idx].thread_id = my_thread_id; + tasks[idx].task_id = make_next_task_id(idx); + tasks[idx].mfp0.set(obj,funct); + + task_ready_signaler.signal(); + + return tasks[idx].task_id; + } + + template + uint64 add_task ( + T& obj, + void (T::*funct)(long), + long arg1 + ) + { + auto_mutex M(m); + const thread_id_type my_thread_id = get_thread_id(); + + // find a thread that isn't doing anything + long idx = find_empty_task_slot(); + if (idx == -1 && is_worker_thread(my_thread_id)) + { + // this function is being called from within a worker thread and there + // aren't any other worker threads free so just perform the task right + // here + + M.unlock(); + (obj.*funct)(arg1); + + // return a task id that is both non-zero and also one + // that is never normally returned. This way calls + // to wait_for_task() will never block given this id. + return 1; + } + + // wait until there is a thread that isn't doing anything + while (idx == -1) + { + task_done_signaler.wait(); + idx = find_empty_task_slot(); + } + + tasks[idx].thread_id = my_thread_id; + tasks[idx].task_id = make_next_task_id(idx); + tasks[idx].mfp1.set(obj,funct); + tasks[idx].arg1 = arg1; + + task_ready_signaler.signal(); + + return tasks[idx].task_id; + } + + template + uint64 add_task ( + T& obj, + void (T::*funct)(long,long), + long arg1, + long arg2 + ) + { + auto_mutex M(m); + const thread_id_type my_thread_id = get_thread_id(); + + // find a thread that isn't doing anything + long idx = find_empty_task_slot(); + if (idx == -1 && is_worker_thread(my_thread_id)) + { + // this function is being called from within a worker thread and there + // aren't any other worker threads free so just perform the task right + // here + + M.unlock(); + (obj.*funct)(arg1, arg2); + + // return a task id that is both non-zero and also one + // that is never normally returned. This way calls + // to wait_for_task() will never block given this id. + return 1; + } + + // wait until there is a thread that isn't doing anything + while (idx == -1) + { + task_done_signaler.wait(); + idx = find_empty_task_slot(); + } + + tasks[idx].thread_id = my_thread_id; + tasks[idx].task_id = make_next_task_id(idx); + tasks[idx].mfp2.set(obj,funct); + tasks[idx].arg1 = arg1; + tasks[idx].arg2 = arg2; + + task_ready_signaler.signal(); + + return tasks[idx].task_id; + } + + struct function_object_copy + { + virtual ~function_object_copy(){} + }; + + template + struct function_object_copy_instance : function_object_copy + { + function_object_copy_instance(const T& item_) : item(item_) {} + T item; + virtual ~function_object_copy_instance(){} + }; + + uint64 add_task_internal ( + const bfp_type& bfp, + std::shared_ptr& item + ); + /*! + ensures + - adds a task to call the given bfp object. + - swaps item into the internal task object which will have a lifetime + at least as long as the running task. + - returns the task id for this new task + !*/ + + uint64 add_task_internal ( + const bfp_type& bfp + ) { std::shared_ptr temp; return add_task_internal(bfp, temp); } + /*! + ensures + - adds a task to call the given bfp object. + - returns the task id for this new task + !*/ + + void shutdown_pool ( + ); + /*! + ensures + - causes all threads to terminate and blocks the + caller until this happens. + !*/ + + private: + + bool is_worker_thread ( + const thread_id_type id + ) const; + /*! + requires + - m is locked + ensures + - if (thread with given id is one of the thread pool's worker threads or num_threads_in_pool() == 0) then + - returns true + - else + - returns false + !*/ + + void thread ( + ); + /*! + this is the function that executes the threads in the thread pool + !*/ + + long find_empty_task_slot ( + ) const; + /*! + requires + - m is locked + ensures + - if (there is currently a empty task slot) then + - returns the index of that task slot in tasks + - there is a task slot + - else + - returns -1 + !*/ + + long find_ready_task ( + ) const; + /*! + requires + - m is locked + ensures + - if (there is currently a task to do) then + - returns the index of that task in tasks + - else + - returns -1 + !*/ + + uint64 make_next_task_id ( + long idx + ); + /*! + requires + - m is locked + - 0 <= idx < tasks.size() + ensures + - returns the next index to be used for tasks that are placed in + tasks[idx] + !*/ + + unsigned long task_id_to_index ( + uint64 id + ) const; + /*! + requires + - m is locked + - num_threads_in_pool() != 0 + ensures + - returns the index in tasks corresponding to the given id + !*/ + + struct task_state_type + { + task_state_type() : is_being_processed(false), task_id(0), next_task_id(2), arg1(0), arg2(0), eptr(nullptr) {} + + bool is_ready () const + /*! + ensures + - if (is_empty() == false && no thread is currently processing this task) then + - returns true + - else + - returns false + !*/ + { + return !is_being_processed && !is_empty(); + } + + bool is_empty () const + /*! + ensures + - if (this task state is empty. i.e. it doesn't contain a task to be processed) then + - returns true + - else + - returns false + !*/ + { + return task_id == 0; + } + + bool is_being_processed; // true when a thread is working on this task + uint64 task_id; // the id of this task. 0 means this task is empty + thread_id_type thread_id; // the id of the thread that requested this task + + uint64 next_task_id; + + long arg1; + long arg2; + + member_function_pointer<> mfp0; + member_function_pointer mfp1; + member_function_pointer mfp2; + bfp_type bfp; + + std::shared_ptr function_copy; + mutable std::exception_ptr eptr; // non-null if the task threw an exception + + void propagate_exception() const + { + if (eptr) + { + auto tmp = eptr; + eptr = nullptr; + std::rethrow_exception(tmp); + } + } + + }; + + array tasks; + array worker_thread_ids; + + mutex m; + signaler task_done_signaler; + signaler task_ready_signaler; + bool we_are_destructing; + + std::vector threads; + + // restricted functions + thread_pool_implementation(thread_pool_implementation&); // copy constructor + thread_pool_implementation& operator=(thread_pool_implementation&); // assignment operator + + }; + + +// ---------------------------------------------------------------------------------------- + + class thread_pool + { + /*! + This object is just a shell that holds a std::shared_ptr + to the real thread_pool_implementation object. The reason for doing + it this way is so that we can allow any mixture of destruction orders + between thread_pool objects and futures. Whoever gets destroyed + last cleans up the thread_pool_implementation resources. + !*/ + typedef bound_function_pointer::kernel_1a_c bfp_type; + + public: + explicit thread_pool ( + unsigned long num_threads + ) + { + impl.reset(new thread_pool_implementation(num_threads)); + } + + ~thread_pool ( + ) + { + try + { + impl->shutdown_pool(); + } + catch (std::exception& e) + { + std::cerr << "An unhandled exception was inside a dlib::thread_pool when it was destructed." << std::endl; + std::cerr << "It's what string is: \n" << e.what() << std::endl; + using namespace std; + assert(false); + abort(); + } + catch (...) + { + std::cerr << "An unhandled exception was inside a dlib::thread_pool when it was destructed." << std::endl; + using namespace std; + assert(false); + abort(); + } + } + + void wait_for_task ( + uint64 task_id + ) const { impl->wait_for_task(task_id); } + + unsigned long num_threads_in_pool ( + ) const { return impl->num_threads_in_pool(); } + + void wait_for_all_tasks ( + ) const { impl->wait_for_all_tasks(); } + + bool is_task_thread ( + ) const { return impl->is_task_thread(); } + + template + uint64 add_task ( + T& obj, + void (T::*funct)() + ) + { + return impl->add_task(obj, funct); + } + + template + uint64 add_task ( + T& obj, + void (T::*funct)(long), + long arg1 + ) + { + return impl->add_task(obj, funct, arg1); + } + + template + uint64 add_task ( + T& obj, + void (T::*funct)(long,long), + long arg1, + long arg2 + ) + { + return impl->add_task(obj, funct, arg1, arg2); + } + + // -------------------- + + template + uint64 add_task ( + F& function_object + ) + { + COMPILE_TIME_ASSERT(is_function::value == false); + COMPILE_TIME_ASSERT(is_pointer_type::value == false); + + bfp_type temp; + temp.set(function_object); + uint64 id = impl->add_task_internal(temp); + + return id; + } + + template + uint64 add_task_by_value ( + const F& function_object + ) + { + thread_pool_implementation::function_object_copy_instance* ptr = 0; + ptr = new thread_pool_implementation::function_object_copy_instance(function_object); + std::shared_ptr function_copy(ptr); + + + bfp_type temp; + temp.set(ptr->item); + uint64 id = impl->add_task_internal(temp, function_copy); + + return id; + } + + template + uint64 add_task ( + const T& obj, + void (T::*funct)() const + ) + { + bfp_type temp; + temp.set(obj,funct); + uint64 id = impl->add_task_internal(temp); + + return id; + } + + template + uint64 add_task_by_value ( + const T& obj, + void (T::*funct)() const + ) + { + thread_pool_implementation::function_object_copy_instance* ptr = 0; + ptr = new thread_pool_implementation::function_object_copy_instance(obj); + std::shared_ptr function_copy(ptr); + + bfp_type temp; + temp.set(ptr->item,funct); + uint64 id = impl->add_task_internal(temp, function_copy); + + return id; + } + + template + uint64 add_task_by_value ( + const T& obj, + void (T::*funct)() + ) + { + thread_pool_implementation::function_object_copy_instance* ptr = 0; + ptr = new thread_pool_implementation::function_object_copy_instance(obj); + std::shared_ptr function_copy(ptr); + + bfp_type temp; + temp.set(ptr->item,funct); + uint64 id = impl->add_task_internal(temp, function_copy); + + return id; + } + + uint64 add_task ( + void (*funct)() + ) + { + bfp_type temp; + temp.set(funct); + uint64 id = impl->add_task_internal(temp); + + return id; + } + + // -------------------- + + template + uint64 add_task ( + F& function_object, + future& arg1 + ) + { + COMPILE_TIME_ASSERT(is_function::value == false); + COMPILE_TIME_ASSERT(is_pointer_type::value == false); + + bfp_type temp; + temp.set(function_object,arg1.get()); + uint64 id = impl->add_task_internal(temp); + + // tie the future to this task + arg1.task_id = id; + arg1.tp = impl; + return id; + } + + template + uint64 add_task_by_value ( + const F& function_object, + future& arg1 + ) + { + thread_pool_implementation::function_object_copy_instance* ptr = 0; + ptr = new thread_pool_implementation::function_object_copy_instance(function_object); + std::shared_ptr function_copy(ptr); + + bfp_type temp; + temp.set(ptr->item, arg1.get()); + uint64 id = impl->add_task_internal(temp, function_copy); + + // tie the future to this task + arg1.task_id = id; + arg1.tp = impl; + return id; + } + + template + uint64 add_task ( + T& obj, + void (T::*funct)(T1), + future& arg1 + ) + { + bfp_type temp; + temp.set(obj,funct,arg1.get()); + uint64 id = impl->add_task_internal(temp); + + // tie the future to this task + arg1.task_id = id; + arg1.tp = impl; + return id; + } + + template + uint64 add_task_by_value ( + const T& obj, + void (T::*funct)(T1), + future& arg1 + ) + { + thread_pool_implementation::function_object_copy_instance* ptr = 0; + ptr = new thread_pool_implementation::function_object_copy_instance(obj); + std::shared_ptr function_copy(ptr); + + bfp_type temp; + temp.set(ptr->item,funct,arg1.get()); + uint64 id = impl->add_task_internal(temp, function_copy); + + // tie the future to this task + arg1.task_id = id; + arg1.tp = impl; + return id; + } + + + template + uint64 add_task ( + const T& obj, + void (T::*funct)(T1) const, + future& arg1 + ) + { + bfp_type temp; + temp.set(obj,funct,arg1.get()); + uint64 id = impl->add_task_internal(temp); + + // tie the future to this task + arg1.task_id = id; + arg1.tp = impl; + return id; + } + + template + uint64 add_task_by_value ( + const T& obj, + void (T::*funct)(T1) const, + future& arg1 + ) + { + thread_pool_implementation::function_object_copy_instance* ptr = 0; + ptr = new thread_pool_implementation::function_object_copy_instance(obj); + std::shared_ptr function_copy(ptr); + + bfp_type temp; + temp.set(ptr->item,funct,arg1.get()); + uint64 id = impl->add_task_internal(temp, function_copy); + + // tie the future to this task + arg1.task_id = id; + arg1.tp = impl; + return id; + } + + template + uint64 add_task ( + void (*funct)(T1), + future& arg1 + ) + { + bfp_type temp; + temp.set(funct,arg1.get()); + uint64 id = impl->add_task_internal(temp); + + // tie the future to this task + arg1.task_id = id; + arg1.tp = impl; + return id; + } + + // -------------------- + + template + uint64 add_task ( + F& function_object, + future& arg1, + future& arg2 + ) + { + COMPILE_TIME_ASSERT(is_function::value == false); + COMPILE_TIME_ASSERT(is_pointer_type::value == false); + + bfp_type temp; + temp.set(function_object, arg1.get(), arg2.get()); + uint64 id = impl->add_task_internal(temp); + + // tie the future to this task + arg1.task_id = id; + arg1.tp = impl; + arg2.task_id = id; + arg2.tp = impl; + return id; + } + + template + uint64 add_task_by_value ( + const F& function_object, + future& arg1, + future& arg2 + ) + { + thread_pool_implementation::function_object_copy_instance* ptr = 0; + ptr = new thread_pool_implementation::function_object_copy_instance(function_object); + std::shared_ptr function_copy(ptr); + + bfp_type temp; + temp.set(ptr->item, arg1.get(), arg2.get()); + uint64 id = impl->add_task_internal(temp, function_copy); + + // tie the future to this task + arg1.task_id = id; + arg1.tp = impl; + arg2.task_id = id; + arg2.tp = impl; + return id; + } + + template + uint64 add_task ( + T& obj, + void (T::*funct)(T1,T2), + future& arg1, + future& arg2 + ) + { + bfp_type temp; + temp.set(obj, funct, arg1.get(), arg2.get()); + uint64 id = impl->add_task_internal(temp); + + // tie the futures to this task + arg1.task_id = id; + arg1.tp = impl; + arg2.task_id = id; + arg2.tp = impl; + return id; + } + + template + uint64 add_task_by_value ( + const T& obj, + void (T::*funct)(T1,T2), + future& arg1, + future& arg2 + ) + { + thread_pool_implementation::function_object_copy_instance* ptr = 0; + ptr = new thread_pool_implementation::function_object_copy_instance(obj); + std::shared_ptr function_copy(ptr); + + bfp_type temp; + temp.set(ptr->item, funct, arg1.get(), arg2.get()); + uint64 id = impl->add_task_internal(temp, function_copy); + + // tie the futures to this task + arg1.task_id = id; + arg1.tp = impl; + arg2.task_id = id; + arg2.tp = impl; + return id; + } + + template + uint64 add_task ( + const T& obj, + void (T::*funct)(T1,T2) const, + future& arg1, + future& arg2 + ) + { + bfp_type temp; + temp.set(obj, funct, arg1.get(), arg2.get()); + uint64 id = impl->add_task_internal(temp); + + // tie the futures to this task + arg1.task_id = id; + arg1.tp = impl; + arg2.task_id = id; + arg2.tp = impl; + return id; + } + + template + uint64 add_task_by_value ( + const T& obj, + void (T::*funct)(T1,T2) const, + future& arg1, + future& arg2 + ) + { + thread_pool_implementation::function_object_copy_instance* ptr = 0; + ptr = new thread_pool_implementation::function_object_copy_instance(obj); + std::shared_ptr function_copy(ptr); + + bfp_type temp; + temp.set(ptr->item, funct, arg1.get(), arg2.get()); + uint64 id = impl->add_task_internal(temp, function_copy); + + // tie the futures to this task + arg1.task_id = id; + arg1.tp = impl; + arg2.task_id = id; + arg2.tp = impl; + return id; + } + + template + uint64 add_task ( + void (*funct)(T1,T2), + future& arg1, + future& arg2 + ) + { + bfp_type temp; + temp.set(funct, arg1.get(), arg2.get()); + uint64 id = impl->add_task_internal(temp); + + // tie the futures to this task + arg1.task_id = id; + arg1.tp = impl; + arg2.task_id = id; + arg2.tp = impl; + return id; + } + + // -------------------- + + template + uint64 add_task ( + F& function_object, + future& arg1, + future& arg2, + future& arg3 + ) + { + COMPILE_TIME_ASSERT(is_function::value == false); + COMPILE_TIME_ASSERT(is_pointer_type::value == false); + + bfp_type temp; + temp.set(function_object, arg1.get(), arg2.get(), arg3.get()); + uint64 id = impl->add_task_internal(temp); + + // tie the future to this task + arg1.task_id = id; + arg1.tp = impl; + arg2.task_id = id; + arg2.tp = impl; + arg3.task_id = id; + arg3.tp = impl; + return id; + } + + template + uint64 add_task_by_value ( + const F& function_object, + future& arg1, + future& arg2, + future& arg3 + ) + { + thread_pool_implementation::function_object_copy_instance* ptr = 0; + ptr = new thread_pool_implementation::function_object_copy_instance(function_object); + std::shared_ptr function_copy(ptr); + + bfp_type temp; + temp.set(ptr->item, arg1.get(), arg2.get(), arg3.get()); + uint64 id = impl->add_task_internal(temp, function_copy); + + // tie the future to this task + arg1.task_id = id; + arg1.tp = impl; + arg2.task_id = id; + arg2.tp = impl; + arg3.task_id = id; + arg3.tp = impl; + return id; + } + + template + uint64 add_task ( + T& obj, + void (T::*funct)(T1,T2,T3), + future& arg1, + future& arg2, + future& arg3 + ) + { + bfp_type temp; + temp.set(obj, funct, arg1.get(), arg2.get(), arg3.get()); + uint64 id = impl->add_task_internal(temp); + + // tie the futures to this task + arg1.task_id = id; + arg1.tp = impl; + arg2.task_id = id; + arg2.tp = impl; + arg3.task_id = id; + arg3.tp = impl; + return id; + } + + template + uint64 add_task_by_value ( + const T& obj, + void (T::*funct)(T1,T2,T3), + future& arg1, + future& arg2, + future& arg3 + ) + { + thread_pool_implementation::function_object_copy_instance* ptr = 0; + ptr = new thread_pool_implementation::function_object_copy_instance(obj); + std::shared_ptr function_copy(ptr); + + bfp_type temp; + temp.set(ptr->item, funct, arg1.get(), arg2.get(), arg3.get()); + uint64 id = impl->add_task_internal(temp, function_copy); + + // tie the futures to this task + arg1.task_id = id; + arg1.tp = impl; + arg2.task_id = id; + arg2.tp = impl; + arg3.task_id = id; + arg3.tp = impl; + return id; + } + + template + uint64 add_task ( + const T& obj, + void (T::*funct)(T1,T2,T3) const, + future& arg1, + future& arg2, + future& arg3 + ) + { + bfp_type temp; + temp.set(obj, funct, arg1.get(), arg2.get(), arg3.get()); + uint64 id = impl->add_task_internal(temp); + + // tie the futures to this task + arg1.task_id = id; + arg1.tp = impl; + arg2.task_id = id; + arg2.tp = impl; + arg3.task_id = id; + arg3.tp = impl; + return id; + } + + template + uint64 add_task_by_value ( + const T& obj, + void (T::*funct)(T1,T2,T3) const, + future& arg1, + future& arg2, + future& arg3 + ) + { + thread_pool_implementation::function_object_copy_instance* ptr = 0; + ptr = new thread_pool_implementation::function_object_copy_instance(obj); + std::shared_ptr function_copy(ptr); + + bfp_type temp; + temp.set(ptr->item, funct, arg1.get(), arg2.get(), arg3.get()); + uint64 id = impl->add_task_internal(temp, function_copy); + + // tie the futures to this task + arg1.task_id = id; + arg1.tp = impl; + arg2.task_id = id; + arg2.tp = impl; + arg3.task_id = id; + arg3.tp = impl; + return id; + } + + template + uint64 add_task ( + void (*funct)(T1,T2,T3), + future& arg1, + future& arg2, + future& arg3 + ) + { + bfp_type temp; + temp.set(funct, arg1.get(), arg2.get(), arg3.get()); + uint64 id = impl->add_task_internal(temp); + + // tie the futures to this task + arg1.task_id = id; + arg1.tp = impl; + arg2.task_id = id; + arg2.tp = impl; + arg3.task_id = id; + arg3.tp = impl; + return id; + } + + // -------------------- + + template + uint64 add_task ( + F& function_object, + future& arg1, + future& arg2, + future& arg3, + future& arg4 + ) + { + COMPILE_TIME_ASSERT(is_function::value == false); + COMPILE_TIME_ASSERT(is_pointer_type::value == false); + + bfp_type temp; + temp.set(function_object, arg1.get(), arg2.get(), arg3.get(), arg4.get()); + uint64 id = impl->add_task_internal(temp); + + // tie the future to this task + arg1.task_id = id; + arg1.tp = impl; + arg2.task_id = id; + arg2.tp = impl; + arg3.task_id = id; + arg3.tp = impl; + arg4.task_id = id; + arg4.tp = impl; + return id; + } + + template + uint64 add_task_by_value ( + const F& function_object, + future& arg1, + future& arg2, + future& arg3, + future& arg4 + ) + { + thread_pool_implementation::function_object_copy_instance* ptr = 0; + ptr = new thread_pool_implementation::function_object_copy_instance(function_object); + std::shared_ptr function_copy(ptr); + + bfp_type temp; + temp.set(ptr->item, arg1.get(), arg2.get(), arg3.get(), arg4.get()); + uint64 id = impl->add_task_internal(temp, function_copy); + + // tie the future to this task + arg1.task_id = id; + arg1.tp = impl; + arg2.task_id = id; + arg2.tp = impl; + arg3.task_id = id; + arg3.tp = impl; + arg4.task_id = id; + arg4.tp = impl; + return id; + } + + template + uint64 add_task ( + T& obj, + void (T::*funct)(T1,T2,T3,T4), + future& arg1, + future& arg2, + future& arg3, + future& arg4 + ) + { + bfp_type temp; + temp.set(obj, funct, arg1.get(), arg2.get(), arg3.get(), arg4.get()); + uint64 id = impl->add_task_internal(temp); + + // tie the futures to this task + arg1.task_id = id; + arg1.tp = impl; + arg2.task_id = id; + arg2.tp = impl; + arg3.task_id = id; + arg3.tp = impl; + arg4.task_id = id; + arg4.tp = impl; + return id; + } + + template + uint64 add_task_by_value ( + const T& obj, + void (T::*funct)(T1,T2,T3,T4), + future& arg1, + future& arg2, + future& arg3, + future& arg4 + ) + { + thread_pool_implementation::function_object_copy_instance* ptr = 0; + ptr = new thread_pool_implementation::function_object_copy_instance(obj); + std::shared_ptr function_copy(ptr); + + bfp_type temp; + temp.set(ptr->item, funct, arg1.get(), arg2.get(), arg3.get(), arg4.get()); + uint64 id = impl->add_task_internal(temp, function_copy); + + // tie the futures to this task + arg1.task_id = id; + arg1.tp = impl; + arg2.task_id = id; + arg2.tp = impl; + arg3.task_id = id; + arg3.tp = impl; + arg4.task_id = id; + arg4.tp = impl; + return id; + } + + template + uint64 add_task ( + const T& obj, + void (T::*funct)(T1,T2,T3,T4) const, + future& arg1, + future& arg2, + future& arg3, + future& arg4 + ) + { + bfp_type temp; + temp.set(obj, funct, arg1.get(), arg2.get(), arg3.get(), arg4.get()); + uint64 id = impl->add_task_internal(temp); + + // tie the futures to this task + arg1.task_id = id; + arg1.tp = impl; + arg2.task_id = id; + arg2.tp = impl; + arg3.task_id = id; + arg3.tp = impl; + arg4.task_id = id; + arg4.tp = impl; + return id; + } + + template + uint64 add_task_by_value ( + const T& obj, + void (T::*funct)(T1,T2,T3,T4) const, + future& arg1, + future& arg2, + future& arg3, + future& arg4 + ) + { + thread_pool_implementation::function_object_copy_instance* ptr = 0; + ptr = new thread_pool_implementation::function_object_copy_instance(obj); + std::shared_ptr function_copy(ptr); + + bfp_type temp; + temp.set(ptr->item, funct, arg1.get(), arg2.get(), arg3.get(), arg4.get()); + uint64 id = impl->add_task_internal(temp, function_copy); + + // tie the futures to this task + arg1.task_id = id; + arg1.tp = impl; + arg2.task_id = id; + arg2.tp = impl; + arg3.task_id = id; + arg3.tp = impl; + arg4.task_id = id; + arg4.tp = impl; + return id; + } + + template + uint64 add_task ( + void (*funct)(T1,T2,T3,T4), + future& arg1, + future& arg2, + future& arg3, + future& arg4 + ) + { + bfp_type temp; + temp.set(funct, arg1.get(), arg2.get(), arg3.get(), arg4.get()); + uint64 id = impl->add_task_internal(temp); + + // tie the futures to this task + arg1.task_id = id; + arg1.tp = impl; + arg2.task_id = id; + arg2.tp = impl; + arg3.task_id = id; + arg3.tp = impl; + arg4.task_id = id; + arg4.tp = impl; + return id; + } + + private: + + std::shared_ptr impl; + + // restricted functions + thread_pool(thread_pool&); // copy constructor + thread_pool& operator=(thread_pool&); // assignment operator + + }; + + +// ---------------------------------------------------------------------------------------- + + template + void future:: + wait ( + ) const + { + if (tp) + { + tp->wait_for_task(task_id); + tp.reset(); + task_id = 0; + } + } + +} + +// ---------------------------------------------------------------------------------------- + +#ifdef NO_MAKEFILE +#include "thread_pool_extension.cpp" +#endif + +#endif // DLIB_THREAD_POOl_Hh_ + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/thread_pool_extension_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/thread_pool_extension_abstract.h new file mode 100644 index 0000000..ba54a75 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/thread_pool_extension_abstract.h @@ -0,0 +1,842 @@ +// Copyright (C) 2008 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_THREAD_POOl_ABSTRACT_Hh_ +#ifdef DLIB_THREAD_POOl_ABSTRACT_Hh_ + +#include "threads_kernel_abstract.h" +#include "../uintn.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + class future + { + /*! + INITIAL VALUE + - is_ready() == true + + WHAT THIS OBJECT REPRESENTS + This object represents a container that allows you to safely pass objects + into the tasks performed by the thread_pool object defined below. An + example will make it clear: + + // Suppose you have a global function defined as follows + void add (int a, int b, int& result) { result = a + b; } + + // Also suppose you have a thread_pool named tp defined somewhere. + // Then you could do the following. + future a, b, result; + a = 3; + b = 4; + // this function call causes another thread to execute a call to the add() function + // and passes in the int objects contained in a, b, and result + tp.add_task(add,a,b,result); + // This line will wait for the task in the thread pool to finish and then print the + // value in the result integer. So it will print a 7. + cout << result << endl; + !*/ + + public: + future ( + ); + /*! + ensures + - The object of type T contained in this future has + an initial value for its type. + - #is_ready() == true + !*/ + + future ( + const T& item + ); + /*! + ensures + - #get() == item + - #is_ready() == true + !*/ + + future ( + const future& item + ); + /*! + ensures + - if (item.is_ready() == false) then + - the call to this function blocks until the thread processing the task related + to the item future has finished. + - #is_ready() == true + - #item.is_ready() == true + - #get() == item.get() + !*/ + + ~future ( + ); + /*! + ensures + - if (is_ready() == false) then + - the call to this function blocks until the thread processing the task related + to this future has finished. + !*/ + + bool is_ready ( + ) const; + /*! + ensures + - if (the value of this future may not yet be ready to be accessed because it + is in use by a task in a thread_pool) then + - returns false + - else + - returns true + !*/ + + future& operator=( + const T& item + ); + /*! + ensures + - if (is_ready() == false) then + - the call to this function blocks until the thread processing the task related + to this future has finished. + - #is_ready() == true + - #get() == item + - returns *this + !*/ + + future& operator=( + const future& item + ); + /*! + ensures + - if (is_ready() == false || item.is_ready() == false) then + - the call to this function blocks until the threads processing the tasks related + to this future and the item future have finished. + - #is_ready() == true + - #item.is_ready() == true + - #get() == item.get() + - returns *this + !*/ + + operator T& ( + ); + /*! + ensures + - if (is_ready() == false) then + - the call to this function blocks until the thread processing the task related + to this future has finished. + - #is_ready() == true + - returns get() + !*/ + + operator const T& ( + ) const; + /*! + ensures + - if (is_ready() == false) then + - the call to this function blocks until the thread processing the task related + to this future has finished. + - #is_ready() == true + - returns get() + !*/ + + T& get ( + ); + /*! + ensures + - if (is_ready() == false) then + - the call to this function blocks until the thread processing the task related + to this future has finished. + - #is_ready() == true + - returns a non-const reference to the object of type T contained inside this future + !*/ + + const T& get ( + ) const; + /*! + ensures + - if (is_ready() == false) then + - the call to this function blocks until the thread processing the task related + to this future has finished. + - #is_ready() == true + - returns a const reference to the object of type T contained inside this future + !*/ + + }; + +// ---------------------------------------------------------------------------------------- + + template + inline void swap ( + future& a, + future& b + ) { std::swap(a.get(), b.get()); } + /*! + provides a global swap function + !*/ + +// ---------------------------------------------------------------------------------------- + + +// The future object comes with overloads for all the usual comparison operators. + + template bool operator== (const future& a, const future& b) { return a.get() == b.get(); } + template bool operator!= (const future& a, const future& b) { return a.get() != b.get(); } + template bool operator<= (const future& a, const future& b) { return a.get() <= b.get(); } + template bool operator>= (const future& a, const future& b) { return a.get() >= b.get(); } + template bool operator< (const future& a, const future& b) { return a.get() < b.get(); } + template bool operator> (const future& a, const future& b) { return a.get() > b.get(); } + + template bool operator== (const future& a, const T& b) { return a.get() == b; } + template bool operator== (const T& a, const future& b) { return a == b.get(); } + template bool operator!= (const future& a, const T& b) { return a.get() != b; } + template bool operator!= (const T& a, const future& b) { return a != b.get(); } + template bool operator<= (const future& a, const T& b) { return a.get() <= b; } + template bool operator<= (const T& a, const future& b) { return a <= b.get(); } + template bool operator>= (const future& a, const T& b) { return a.get() >= b; } + template bool operator>= (const T& a, const future& b) { return a >= b.get(); } + template bool operator< (const future& a, const T& b) { return a.get() < b; } + template bool operator< (const T& a, const future& b) { return a < b.get(); } + template bool operator> (const future& a, const T& b) { return a.get() > b; } + template bool operator> (const T& a, const future& b) { return a > b.get(); } + +// ---------------------------------------------------------------------------------------- + + class thread_pool + { + /*! + WHAT THIS OBJECT REPRESENTS + This object represents a fixed size group of threads which you can + submit tasks to and then wait for those tasks to be completed. + + Note that setting the number of threads to 0 is a valid way to + use this object. It causes it to not contain any threads + at all. When tasks are submitted to the object in this mode + the tasks are processed within the calling thread. So in this + mode any thread that calls add_task() is considered to be + a thread_pool thread capable of executing tasks. + + This object is also implemented such that no memory allocations occur + after the thread_pool has been constructed so long as the user doesn't + call any of the add_task_by_value() routines. The future object also + doesn't perform any memory allocations or contain any system resources + such as mutex objects. + + EXCEPTIONS + Note that if an exception is thrown inside a task thread and is not caught + then the exception will be trapped inside the thread pool and rethrown at a + later time when someone calls one of the add task or wait member functions + of the thread pool. This allows exceptions to propagate out of task threads + and into the calling code where they can be handled. + !*/ + + public: + explicit thread_pool ( + unsigned long num_threads + ); + /*! + ensures + - #num_threads_in_pool() == num_threads + throws + - std::bad_alloc + - dlib::thread_error + the constructor may throw this exception if there is a problem + gathering resources to create threading objects. + !*/ + + ~thread_pool( + ); + /*! + ensures + - blocks until all tasks in the pool have finished. + - If one of the threads has generated an exception but it hasn't yet been + rethrown to the caller (e.g. by calling wait_for_all_tasks()) then the + program will be terminated. So make sure you handle all the possible + exceptions from your tasks. + !*/ + + bool is_task_thread ( + ) const; + /*! + ensures + - if (the thread calling this function is one of the threads in this + thread pool or num_threads_in_pool() == 0) then + - returns true + - else + - returns false + !*/ + + unsigned long num_threads_in_pool ( + ) const; + /*! + ensures + - returns the number of threads contained in this thread pool. That is, returns + the maximum number of tasks that this object will process concurrently. + !*/ + + template + uint64 add_task_by_value ( + const F& function_object + ); + /*! + requires + - function_object() is a valid expression + ensures + - makes a copy of function_object, call it FCOPY. + - if (is_task_thread() == true and there aren't any free threads available) then + - calls FCOPY() within the calling thread and returns when it finishes + - else + - the call to this function blocks until there is a free thread in the pool + to process this new task. Once a free thread is available the task + is handed off to that thread which then calls FCOPY(). + - returns a task id that can be used by this->wait_for_task() to wait + for the submitted task to finish. + !*/ + + template + uint64 add_task ( + T& obj, + void (T::*funct)() + ); + /*! + requires + - funct == a valid member function pointer for class T + - obj will not go out of scope until after the task has completed (i.e. + this function passes obj to the task by reference. If you want to avoid + this restriction then use add_task_by_value()) + ensures + - if (is_task_thread() == true and there aren't any free threads available) then + - calls (obj.*funct)() within the calling thread and returns + when it finishes. + - else + - the call to this function blocks until there is a free thread in the pool + to process this new task. Once a free thread is available the task + is handed off to that thread which then calls (obj.*funct)() + - returns a task id that can be used by this->wait_for_task() to wait + for the submitted task to finish. + !*/ + + template + uint64 add_task_by_value ( + const T& obj, + void (T::*funct)() + ); + /*! + requires + - funct == a valid member function pointer for class T + ensures + - makes a copy of obj, call it OBJ_COPY. + - if (is_task_thread() == true and there aren't any free threads available) then + - calls (OBJ_COPY.*funct)() within the calling thread and returns + when it finishes. + - else + - the call to this function blocks until there is a free thread in the pool + to process this new task. Once a free thread is available the task + is handed off to that thread which then calls (OBJ_COPY.*funct)(). + - returns a task id that can be used by this->wait_for_task() to wait + for the submitted task to finish. + !*/ + + template + uint64 add_task ( + T& obj, + void (T::*funct)(long), + long arg1 + ); + /*! + requires + - funct == a valid member function pointer for class T + - obj will not go out of scope until after the task has completed (i.e. + this function passes obj to the task by reference. If you want to avoid + this restriction then use add_task_by_value()) + ensures + - if (is_task_thread() == true and there aren't any free threads available) then + - calls (obj.*funct)(arg1) within the calling thread and returns + when it finishes + - else + - the call to this function blocks until there is a free thread in the pool + to process this new task. Once a free thread is available the task + is handed off to that thread which then calls (obj.*funct)(arg1) + - returns a task id that can be used by this->wait_for_task() to wait + for the submitted task to finish. + !*/ + + template + uint64 add_task ( + T& obj, + void (T::*funct)(long,long), + long arg1, + long arg2 + ); + /*! + requires + - funct == a valid member function pointer for class T + - obj will not go out of scope until after the task has completed (i.e. + this function passes obj to the task by reference. If you want to avoid + this restriction then use add_task_by_value()) + ensures + - if (is_task_thread() == true and there aren't any free threads available) then + - calls (obj.*funct)(arg1,arg2) within the calling thread and returns + when it finishes + - else + - the call to this function blocks until there is a free thread in the pool + to process this new task. Once a free thread is available the task + is handed off to that thread which then calls (obj.*funct)(arg1,arg2) + - returns a task id that can be used by this->wait_for_task() to wait + for the submitted task to finish. + !*/ + + void wait_for_task ( + uint64 task_id + ) const; + /*! + ensures + - if (there is currently a task with the given id being executed in the thread pool) then + - the call to this function blocks until the task with the given id is complete + - else + - the call to this function returns immediately + !*/ + + void wait_for_all_tasks ( + ) const; + /*! + ensures + - the call to this function blocks until all tasks which were submitted + to the thread pool by the thread that is calling this function have + finished. + !*/ + + // -------------------- + + template + uint64 add_task ( + F& function_object, + future& arg1 + ); + /*! + requires + - function_object(arg1.get()) is a valid expression + (i.e. The A1 type stored in the future must be a type that can be passed into the given function object) + - function_object will not go out of scope until after the task has completed (i.e. + this function passes function_object to the task by reference. If you want to avoid + this restriction then use add_task_by_value()) + ensures + - if (is_task_thread() == true and there aren't any free threads available) then + - calls function_object(arg1.get()) within the calling thread and returns + when it finishes + - else + - the call to this function blocks until there is a free thread in the pool + to process this new task. Once a free thread is available the task + is handed off to that thread which then calls function_object(arg1.get()). + - #arg1.is_ready() == false + - returns a task id that can be used by this->wait_for_task() to wait + for the submitted task to finish. + !*/ + + template + uint64 add_task_by_value ( + const F& function_object, + future& arg1 + ); + /*! + requires + - function_object(arg1.get()) is a valid expression + (i.e. The A1 type stored in the future must be a type that can be passed into the given function object) + ensures + - makes a copy of function_object, call it FCOPY. + - if (is_task_thread() == true and there aren't any free threads available) then + - calls FCOPY(arg1.get()) within the calling thread and returns when it finishes + - else + - the call to this function blocks until there is a free thread in the pool + to process this new task. Once a free thread is available the task + is handed off to that thread which then calls FCOPY(arg1.get()). + - #arg1.is_ready() == false + - returns a task id that can be used by this->wait_for_task() to wait + for the submitted task to finish. + !*/ + + template + uint64 add_task ( + T& obj, + void (T::*funct)(T1), + future& arg1 + ); + /*! + requires + - funct == a valid member function pointer for class T + - (obj.*funct)(arg1.get()) must be a valid expression. + (i.e. The A1 type stored in the future must be a type that can be passed into the given function) + - obj will not go out of scope until after the task has completed (i.e. + this function passes obj to the task by reference. If you want to avoid + this restriction then use add_task_by_value()) + ensures + - if (is_task_thread() == true and there aren't any free threads available) then + - calls (obj.*funct)(arg1.get()) within the calling thread and returns + when it finishes + - else + - the call to this function blocks until there is a free thread in the pool + to process this new task. Once a free thread is available the task + is handed off to that thread which then calls (obj.*funct)(arg1.get()). + - #arg1.is_ready() == false + - returns a task id that can be used by this->wait_for_task() to wait + for the submitted task to finish. + !*/ + + template + uint64 add_task_by_value ( + const T& obj, + void (T::*funct)(T1), + future& arg1 + ); + /*! + requires + - funct == a valid member function pointer for class T + - (obj.*funct)(arg1.get()) must be a valid expression. + (i.e. The A1 type stored in the future must be a type that can be passed into the given function) + ensures + - makes a copy of obj, call it OBJ_COPY. + - if (is_task_thread() == true and there aren't any free threads available) then + - calls (OBJ_COPY.*funct)(arg1.get()) within the calling thread and returns + when it finishes. + - else + - the call to this function blocks until there is a free thread in the pool + to process this new task. Once a free thread is available the task + is handed off to that thread which then calls (OBJ_COPY.*funct)(arg1.get()). + - returns a task id that can be used by this->wait_for_task() to wait + for the submitted task to finish. + !*/ + + template + uint64 add_task ( + const T& obj, + void (T::*funct)(T1) const, + future& arg1 + ); + /*! + requires + - funct == a valid member function pointer for class T + - (obj.*funct)(arg1.get()) must be a valid expression. + (i.e. The A1 type stored in the future must be a type that can be passed into the given function) + - obj will not go out of scope until after the task has completed (i.e. + this function passes obj to the task by reference. If you want to avoid + this restriction then use add_task_by_value()) + ensures + - if (is_task_thread() == true and there aren't any free threads available) then + - calls (obj.*funct)(arg1.get()) within the calling thread and returns + when it finishes + - else + - the call to this function blocks until there is a free thread in the pool + to process this new task. Once a free thread is available the task + is handed off to that thread which then calls (obj.*funct)(arg1.get()). + - #arg1.is_ready() == false + - returns a task id that can be used by this->wait_for_task() to wait + for the submitted task to finish. + !*/ + + template + uint64 add_task_by_value ( + const T& obj, + void (T::*funct)(T1) const, + future& arg1 + ); + /*! + requires + - funct == a valid member function pointer for class T + - (obj.*funct)(arg1.get()) must be a valid expression. + (i.e. The A1 type stored in the future must be a type that can be passed into the given function) + ensures + - makes a copy of obj, call it OBJ_COPY. + - if (is_task_thread() == true and there aren't any free threads available) then + - calls (OBJ_COPY.*funct)(arg1.get()) within the calling thread and returns + when it finishes. + - else + - the call to this function blocks until there is a free thread in the pool + to process this new task. Once a free thread is available the task + is handed off to that thread which then calls (OBJ_COPY.*funct)(arg1.get()). + - returns a task id that can be used by this->wait_for_task() to wait + for the submitted task to finish. + !*/ + + template + uint64 add_task ( + void (*funct)(T1), + future& arg1 + ); + /*! + requires + - funct == a valid function pointer + - (funct)(arg1.get()) must be a valid expression. + (i.e. The A1 type stored in the future must be a type that can be passed into the given function) + ensures + - if (is_task_thread() == true and there aren't any free threads available) then + - calls funct(arg1.get()) within the calling thread and returns + when it finishes + - else + - the call to this function blocks until there is a free thread in the pool + to process this new task. Once a free thread is available the task + is handed off to that thread which then calls funct(arg1.get()). + - #arg1.is_ready() == false + - returns a task id that can be used by this->wait_for_task() to wait + for the submitted task to finish. + !*/ + + // -------------------------------------------------------------------------------- + // The remainder of this class just contains overloads for add_task() and add_task_by_value() + // that take up to 4 futures (as well as 0 futures). Their behavior is identical to the above + // add_task() and add_task_by_value() functions. + // -------------------------------------------------------------------------------- + + template + uint64 add_task ( + F& function_object, + future& arg1, + future& arg2 + ); + + template + uint64 add_task_by_value ( + const F& function_object, + future& arg1, + future& arg2 + ); + + template + uint64 add_task ( + T& obj, + void (T::*funct)(T1,T2), + future& arg1, + future& arg2 + ); + + uint64 add_task_by_value ( + const T& obj, + void (T::*funct)(T1,T2), + future& arg1, + future& arg2 + ); + + template + uint64 add_task ( + const T& obj, + void (T::*funct)(T1,T2) const, + future& arg1, + future& arg2 + ); + + template + uint64 add_task_by_value ( + const T& obj, + void (T::*funct)(T1,T2) const, + future& arg1, + future& arg2 + ); + + template + uint64 add_task ( + void (*funct)(T1,T2), + future& arg1, + future& arg2 + ); + + // -------------------- + + template + uint64 add_task ( + F& function_object, + future& arg1, + future& arg2, + future& arg3 + ); + + template + uint64 add_task_by_value ( + const F& function_object, + future& arg1, + future& arg2, + future& arg3 + ); + + template + uint64 add_task ( + T& obj, + void (T::*funct)(T1,T2,T3), + future& arg1, + future& arg2, + future& arg3 + ); + + template + uint64 add_task_by_value ( + const T& obj, + void (T::*funct)(T1,T2,T3), + future& arg1, + future& arg2, + future& arg3 + ); + + template + uint64 add_task ( + const T& obj, + void (T::*funct)(T1,T2,T3) const, + future& arg1, + future& arg2, + future& arg3 + ); + + template + uint64 add_task_by_value ( + const T& obj, + void (T::*funct)(T1,T2,T3) const, + future& arg1, + future& arg2, + future& arg3 + ); + + template + uint64 add_task ( + void (*funct)(T1,T2,T3), + future& arg1, + future& arg2, + future& arg3 + ); + + // -------------------- + + template + uint64 add_task ( + F& function_object, + future& arg1, + future& arg2, + future& arg3, + future& arg4 + ); + + template + uint64 add_task_by_value ( + const F& function_object, + future& arg1, + future& arg2, + future& arg3, + future& arg4 + ); + + template + uint64 add_task ( + T& obj, + void (T::*funct)(T1,T2,T3,T4), + future& arg1, + future& arg2, + future& arg3, + future& arg4 + ); + + template + uint64 add_task_by_value ( + const T& obj, + void (T::*funct)(T1,T2,T3,T4), + future& arg1, + future& arg2, + future& arg3, + future& arg4 + ); + + template + uint64 add_task ( + const T& obj, + void (T::*funct)(T1,T2,T3,T4) const, + future& arg1, + future& arg2, + future& arg3, + future& arg4 + ); + + template + uint64 add_task_by_value ( + const T& obj, + void (T::*funct)(T1,T2,T3,T4) const, + future& arg1, + future& arg2, + future& arg3, + future& arg4 + ); + + template + uint64 add_task ( + void (*funct)(T1,T2,T3,T4), + future& arg1, + future& arg2, + future& arg3, + future& arg4 + ); + + // -------------------- + + template + uint64 add_task ( + F& function_object + ); + + template + uint64 add_task ( + const T& obj, + void (T::*funct)() const, + ); + + template + uint64 add_task_by_value ( + const T& obj, + void (T::*funct)() const + ); + + uint64 add_task ( + void (*funct)() + ); + + // -------------------- + + private: + + // restricted functions + thread_pool(thread_pool&); // copy constructor + thread_pool& operator=(thread_pool&); // assignment operator + }; + +} + +// ---------------------------------------------------------------------------------------- + +#endif // DLIB_THREAD_POOl_ABSTRACT_Hh_ + + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/thread_specific_data_extension.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/thread_specific_data_extension.h new file mode 100644 index 0000000..0b53392 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/thread_specific_data_extension.h @@ -0,0 +1,141 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_THREAD_SPECIFIC_DATA_EXTENSIOn_ +#define DLIB_THREAD_SPECIFIC_DATA_EXTENSIOn_ + +#include "thread_specific_data_extension_abstract.h" +#include "threads_kernel_abstract.h" +#include "../binary_search_tree.h" +#include "auto_mutex_extension.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + class thread_specific_data + { + /*! + CONVENTION + - for all valid ID: + (*items[ID]) == pointer to the data for thread with id ID + !*/ + public: + + thread_specific_data ( + ) + { + thread_end_handler_calls_left = 0; + } + + ~thread_specific_data ( + ) + { + // We should only call the unregister_thread_end_handler function if there are + // some outstanding callbacks we expect to get. Otherwise lets avoid calling it + // since the dlib state that maintains the registered thread end handlers may have + // been destructed already (since the program might be in the process of terminating). + bool call_unregister = false; + m.lock(); + if (thread_end_handler_calls_left > 0) + call_unregister = true; + m.unlock(); + + if (call_unregister) + unregister_thread_end_handler(const_cast(*this),&thread_specific_data::thread_end_handler); + + auto_mutex M(m); + items.reset(); + while (items.move_next()) + { + delete items.element().value(); + } + } + + inline T& data ( + ) { return get_data(); } + + inline const T& data ( + ) const { return get_data(); } + + private: + + T& get_data ( + ) const + { + thread_id_type id = get_thread_id(); + auto_mutex M(m); + + T** item = items[id]; + if (item) + { + return **item; + } + else + { + // register an end handler for this thread so long as it is a dlib created thread. + T* new_item = new T; + + bool in_tree = false; + try + { + T* temp_item = new_item; + thread_id_type temp_id = id; + items.add(temp_id,temp_item); + in_tree = true; + + if (is_dlib_thread(id)) + { + register_thread_end_handler(const_cast(*this),&thread_specific_data::thread_end_handler); + ++thread_end_handler_calls_left; + } + } + catch (...) + { + if (in_tree) + { + items.destroy(id); + } + delete new_item; + throw; + } + + return *new_item; + } + } + + void thread_end_handler ( + ) + { + const thread_id_type id = get_thread_id(); + thread_id_type junk = 0; + T* item = 0; + auto_mutex M(m); + --thread_end_handler_calls_left; + if (items[id]) + { + items.remove(id,junk,item); + delete item; + } + } + + mutable typename binary_search_tree::kernel_2a items; + mutex m; + mutable long thread_end_handler_calls_left; + + // restricted functions + thread_specific_data(thread_specific_data&); // copy constructor + thread_specific_data& operator=(thread_specific_data&); // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_THREAD_SPECIFIC_DATA_EXTENSIOn_ + + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/thread_specific_data_extension_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/thread_specific_data_extension_abstract.h new file mode 100644 index 0000000..03fb9dd --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/thread_specific_data_extension_abstract.h @@ -0,0 +1,87 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_THREAD_SPECIFIC_DATA_EXTENSIOn_ABSTRACT_ +#ifdef DLIB_THREAD_SPECIFIC_DATA_EXTENSIOn_ABSTRACT_ + +#include "threads_kernel_abstract.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + class thread_specific_data + { + /*! + WHAT THIS OBJECT REPRESENTS + This object represents a container of thread specific data. When + a thread calls the data() member function it gets a reference to a T object + that is specific to its own thread. Each subsequent call to data() from that + thread returns the same instance. Also note that when a thread ends + the instance of its data() object gets destroyed and freed (if the thread + was created by the dlib library). So any pointers or references to the object + will be invalid after the thread has ended. + !*/ + public: + + thread_specific_data ( + ); + /*! + ensures + - #*this is properly initialized + !*/ + + ~thread_specific_data ( + ); + /*! + ensures + - all resources allocated by *this have been freed. This includes + all the thread specific data returned by the data() functions. + !*/ + + T& data ( + ); + /*! + ensures + - if (the calling thread has NOT called this->data() before) then + - constructs an instance of T that is specific to the calling + thread. + - returns a reference to the T instance that was constructed for + the calling thread. + throws + - std::bad_alloc or any exception thrown by T's constructor + If an exception is thrown then the call to data() will have + no effect on *this. + !*/ + + const T& data ( + ) const; + /*! + ensures + - if (the calling thread has NOT called this->data() before) then + - constructs an instance of T that is specific to the calling + thread. + - returns a const reference to the T instance that was constructed for + the calling thread. + throws + - std::bad_alloc or any exception thrown by T's constructor + If an exception is thrown then the call to data() will have + no effect on *this. + !*/ + + private: + // restricted functions + thread_specific_data(thread_specific_data&); // copy constructor + thread_specific_data& operator=(thread_specific_data&); // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_THREAD_SPECIFIC_DATA_EXTENSIOn_ABSTRACT_ + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/threaded_object_extension.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/threaded_object_extension.h new file mode 100644 index 0000000..dcf00da --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/threaded_object_extension.h @@ -0,0 +1,123 @@ +// Copyright (C) 2007 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_THREADED_OBJECT_EXTENSIOn_ +#define DLIB_THREADED_OBJECT_EXTENSIOn_ + +#include "threaded_object_extension_abstract.h" +#include "threads_kernel.h" +#include "auto_mutex_extension.h" +#include "../algs.h" +#include "../assert.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class threaded_object + { + /*! + INITIAL VALUE + - is_running_ == false + - is_alive_ == false + - should_stop_ == false + - should_respawn_ == false + +#ifdef ENABLE_ASSERTS + - id_valid == false + - id1 == get_main_thread_id() +#endif + + CONVENTION + - is_running() == is_running_ + - is_alive() == is_alive_ + - should_stop() == should_stop_ + - should_respawn() == should_respawn_ + + +#ifdef ENABLE_ASSERTS + - if (when thread() is executing) then + - id1 == the id of the running thread + - id_valid == true + - else + - id1 == an undefined value + - id_valid == false +#endif + + - m_ == the mutex used to protect all our variables + - s == the signaler for m_ + !*/ + + public: + + threaded_object ( + ); + + virtual ~threaded_object ( + ); + + bool is_running ( + ) const; + + bool is_alive ( + ) const; + + void wait ( + ) const; + + void start ( + ); + + void restart ( + ); + + void set_respawn ( + ); + + bool should_respawn ( + ) const; + + void pause ( + ); + + void stop ( + ); + + protected: + + bool should_stop ( + ) const; + + private: + + void thread_helper( + ); + + virtual void thread ( + ) = 0; + + mutex m_; + signaler s; + thread_id_type id1; + bool is_running_; + bool is_alive_; + bool should_stop_; + bool should_respawn_; + bool id_valid; + + // restricted functions + threaded_object(threaded_object&); // copy constructor + threaded_object& operator=(threaded_object&); // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + +} + +#ifdef NO_MAKEFILE +#include "threaded_object_extension.cpp" +#endif + +#endif // DLIB_THREADED_OBJECT_EXTENSIOn_ + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/threaded_object_extension_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/threaded_object_extension_abstract.h new file mode 100644 index 0000000..32a8fbc --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/threaded_object_extension_abstract.h @@ -0,0 +1,199 @@ +// Copyright (C) 2007 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_THREADED_OBJECT_EXTENSIOn_ABSTRACT_ +#ifdef DLIB_THREADED_OBJECT_EXTENSIOn_ABSTRACT_ + +#include "threads_kernel_abstract.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class threaded_object + { + /*! + INITIAL VALUE + - is_running() == false + - is_alive() == false + - should_respawn() == false + + WHAT THIS OBJECT REPRESENTS + This object represents a simple threaded object. To use it you inherit + from it and define the thread() function. Then when you call start() + it will spawn a thread that calls this->thread(). + !*/ + public: + + threaded_object ( + ); + /*! + ensures + - #*this is properly initialized + throws + - std::bad_alloc + - dlib::thread_error + the constructor may throw this exception if there is a problem + gathering resources to create threading objects. + !*/ + + virtual ~threaded_object ( + ); + /*! + requires + - is_alive() == false + (i.e. in the destructor for the object you derive from this one you + must wait for this->thread() to end.) + ensures + - all resources allocated by *this have been freed. + !*/ + + bool is_running ( + ) const; + /*! + requires + - is not called from this->thread() + ensures + - if (is_alive() && this->thread() is currently supposed to be executing) then + - returns true + - else + - returns false + !*/ + + bool is_alive ( + ) const; + /*! + requires + - is not called from this->thread() + ensures + - if (this->thread() has been called by some thread and has yet to terminate) then + - returns true + - else + - returns false + !*/ + + void wait ( + ) const; + /*! + requires + - is not called from this->thread() + ensures + - if (is_alive() == true) then + - blocks until this->thread() terminates + !*/ + + void start ( + ); + /*! + requires + - is not called from this->thread() + ensures + - #is_alive() == true + - #is_running() == true + - #should_stop() == false + throws + - std::bad_alloc or dlib::thread_error + If either of these exceptions are thrown then + #is_alive() == false and #is_running() == false + !*/ + + void set_respawn ( + ); + /*! + requires + - is not called from this->thread() + ensures + - #should_respawn() == true + !*/ + + bool should_respawn ( + ) const; + /*! + requires + - is not called from this->thread() + ensures + - returns true if the thread will automatically restart upon termination and + false otherwise. Note that every time a thread starts it sets should_respawn() + back to false. Therefore, a single call to set_respawn() can cause at most + one respawn to occur. + !*/ + + void restart ( + ); + /*! + requires + - is not called from this->thread() + ensures + - This function atomically executes set_respawn() and start(). The precise meaning of this + is defined below. + - if (is_alive()) then + - #should_respawn() == true + - else + - #should_respawn() == false + - #is_alive() == true + - #is_running() == true + - #should_stop() == false + throws + - std::bad_alloc or dlib::thread_error + If either of these exceptions are thrown then + #is_alive() == false and #is_running() == false + !*/ + + void pause ( + ); + /*! + requires + - is not called from this->thread() + ensures + - #is_running() == false + !*/ + + void stop ( + ); + /*! + requires + - is not called from this->thread() + ensures + - #should_stop() == true + - #is_running() == false + - #should_respawn() == false + !*/ + + protected: + + bool should_stop ( + ) const; + /*! + requires + - is only called from the thread that executes this->thread() + ensures + - calls to this function block until (#is_running() == true || #should_stop() == true) + - if (this thread is supposed to terminate) then + - returns true + - else + - returns false + !*/ + + private: + + virtual void thread ( + ) = 0; + /*! + requires + - is executed in its own thread + - is only executed in one thread at a time + throws + - does not throw any exceptions + !*/ + + // restricted functions + threaded_object(threaded_object&); // copy constructor + threaded_object& operator=(threaded_object&); // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_THREADED_OBJECT_EXTENSIOn_ABSTRACT_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/threads_kernel.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/threads_kernel.h new file mode 100644 index 0000000..77cb16d --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/threads_kernel.h @@ -0,0 +1,18 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_THREADs_KERNEL_ +#define DLIB_THREADs_KERNEL_ + +#include "../platform.h" + +#ifdef WIN32 +#include "windows.h" +#endif + +#ifndef WIN32 +#include "posix.h" +#endif + +#endif // DLIB_THREADs_KERNEL_ + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/threads_kernel_1.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/threads_kernel_1.h new file mode 100644 index 0000000..586a21b --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/threads_kernel_1.h @@ -0,0 +1,158 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_THREADS_KERNEl_1_ +#define DLIB_THREADS_KERNEl_1_ + +#ifdef DLIB_ISO_CPP_ONLY +#error "DLIB_ISO_CPP_ONLY is defined so you can't use this OS dependent code. Turn DLIB_ISO_CPP_ONLY off if you want to use it." +#endif + +#include "threads_kernel_abstract.h" + +#include "../windows_magic.h" +#include +#include "../algs.h" +#include +#include +#include + + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + typedef DWORD thread_id_type; + + inline thread_id_type get_thread_id ( + ) + { + return GetCurrentThreadId(); + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // mutex object +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + // forward declaration of signaler + class signaler; + + class mutex + { + public: + + mutex ( + ) + { + } + + ~mutex ( + ) { } + + void lock ( + ) const { cs.lock(); } + + void unlock ( + ) const { cs.unlock(); } + + private: + + friend class signaler; + + mutable std::mutex cs; + + // restricted functions + mutex(mutex&); // copy constructor + mutex& operator=(mutex&); // assignment operator + }; + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // signaler object +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + class signaler + { + + public: + signaler ( + const mutex& associated_mutex + ) : + m(associated_mutex) + { + + } + + ~signaler ( + ) { } + + void wait ( + ) const + { + std::unique_lock cs(m.cs, std::defer_lock); + cv.wait(cs); + } + + bool wait_or_timeout ( + unsigned long milliseconds + ) const + { + std::unique_lock cs(m.cs, std::defer_lock); + auto status = cv.wait_until(cs, std::chrono::system_clock::now() + std::chrono::milliseconds(milliseconds)); + return status == std::cv_status::no_timeout; + } + + void signal ( + ) const + { + cv.notify_one(); + } + + void broadcast ( + ) const + { + cv.notify_all(); + } + + const mutex& get_mutex ( + ) const { return m; } + + private: + + mutable std::condition_variable cv; + + const mutex& m; + + // restricted functions + signaler(signaler&); // copy constructor + signaler& operator=(signaler&); // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + + namespace threads_kernel_shared_helpers + { + bool spawn_thread ( + void (*funct)(void*), + void* param + ); + /*! + is identical to create_new_thread() but just doesn't use any thread pooling. + !*/ + } + +// ---------------------------------------------------------------------------------------- + +} + +#include "threads_kernel_shared.h" + +#ifdef NO_MAKEFILE +#include "threads_kernel_1.cpp" +#endif + +#endif // DLIB_THREADS_KERNEl_1_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/threads_kernel_2.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/threads_kernel_2.h new file mode 100644 index 0000000..2091421 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/threads_kernel_2.h @@ -0,0 +1,180 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_THREADS_KERNEl_2_ +#define DLIB_THREADS_KERNEl_2_ + +#ifdef DLIB_ISO_CPP_ONLY +#error "DLIB_ISO_CPP_ONLY is defined so you can't use this OS dependent code. Turn DLIB_ISO_CPP_ONLY off if you want to use it." +#endif + +#include "threads_kernel_abstract.h" +#include +#include +#include +#include "../algs.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + typedef pthread_t thread_id_type; + + inline thread_id_type get_thread_id ( + ) + { + return pthread_self(); + } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // mutex object +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + // forward declaration of signaler + class signaler; + + class mutex + { + // give signaler access to hMutex + friend class signaler; + public: + + mutex ( + ) + { + if (pthread_mutex_init(&myMutex,0)) + { + throw dlib::thread_error(ECREATE_MUTEX, + "in function mutex::mutex() an error occurred making the mutex" + ); + } + } + + ~mutex ( + ) { pthread_mutex_destroy(&myMutex); } + + void lock ( + ) const { pthread_mutex_lock(&myMutex); } + + void unlock ( + ) const { pthread_mutex_unlock(&myMutex); } + + private: + + mutable pthread_mutex_t myMutex; + + // restricted functions + mutex(mutex&); // copy constructor + mutex& operator=(mutex&); // assignement opertor + }; + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // signaler object +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + class signaler + { + + public: + + + signaler ( + const mutex& assoc_mutex + ) : + associated_mutex(&assoc_mutex.myMutex), + m(assoc_mutex) + { + if (pthread_cond_init(&cond,0)) + { + throw dlib::thread_error(ECREATE_SIGNALER, + "in function signaler::signaler() an error occurred making the signaler" + ); + } + } + + ~signaler ( + ) { pthread_cond_destroy(&cond); } + + void wait ( + ) const + { + pthread_cond_wait(&cond,associated_mutex); + } + + bool wait_or_timeout ( + unsigned long milliseconds + ) const + { + timespec time_to_wait; + + timeval curtime; + gettimeofday(&curtime,0); + + // get the time and adjust the timespec object by the appropriate amount + time_to_wait.tv_sec = milliseconds/1000 + curtime.tv_sec; + time_to_wait.tv_nsec = curtime.tv_usec; + time_to_wait.tv_nsec *= 1000; + time_to_wait.tv_nsec += (milliseconds%1000)*1000000; + + time_to_wait.tv_sec += time_to_wait.tv_nsec/1000000000; + time_to_wait.tv_nsec = time_to_wait.tv_nsec%1000000000; + + if ( pthread_cond_timedwait(&cond,associated_mutex,&time_to_wait) == ETIMEDOUT) + { + return false; + } + else + { + return true; + } + } + + void signal ( + ) const { pthread_cond_signal(&cond); } + + void broadcast ( + ) const { pthread_cond_broadcast(&cond); } + + const mutex& get_mutex ( + ) const { return m; } + + private: + + pthread_mutex_t* const associated_mutex; + mutable pthread_cond_t cond; + const mutex& m; + + // restricted functions + signaler(signaler&); // copy constructor + signaler& operator=(signaler&); // assignement opertor + }; + +// ---------------------------------------------------------------------------------------- + + namespace threads_kernel_shared_helpers + { + bool spawn_thread ( + void (*funct)(void*), + void* param + ); + /*! + is identical to create_new_thread() but just doesn't use any thread pooling. + !*/ + } + +// ---------------------------------------------------------------------------------------- + +} + +#include "threads_kernel_shared.h" + +#ifdef NO_MAKEFILE +#include "threads_kernel_2.cpp" +#endif + +#endif // DLIB_THREADS_KERNEl_2_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/threads_kernel_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/threads_kernel_abstract.h new file mode 100644 index 0000000..d88d37d --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/threads_kernel_abstract.h @@ -0,0 +1,302 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_THREADS_KERNEl_ABSTRACT_ +#ifdef DLIB_THREADS_KERNEl_ABSTRACT_ + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + /*! + THREAD POOLING + When threads end they go into a global thread pool and each waits there + for 30 seconds before timing out and having its resources returned to the + operating system. When create_new_thread() is called it first looks in the + thread pool to see if there are any threads it can snatch from the pool, if + not then it makes a new one. + + Note that whenever I say something happens when a thread "terminates" or "ends" + I mean "when it returns to the thread pool." From the client programmer point + of view a thread terminates/ends when it returns to the dlib thread pool and you + shouldn't and indeed don't need to know when it actually gets its resources + reclaimed by the operating system. + + If you want to change the timeout to a different value you can #define + DLIB_THREAD_POOL_TIMEOUT to whatever value (in milliseconds) that you like. + + EXCEPTIONS + Unless specified otherwise, nothing in this file throws exceptions. + !*/ + +// ---------------------------------------------------------------------------------------- + + thread_id_type get_thread_id ( + ); + /*! + ensures + - returns a unique id for the calling thread. Note that while the id is unique + among all currently existing threads it may have been used by a previous + thread that has terminated. + !*/ + +// ---------------------------------------------------------------------------------------- + + bool is_dlib_thread ( + thread_id_type id = get_thread_id() + ); + /*! + ensures + - if (the thread with the given id was spawned by a call to + dlib::create_new_thread) then + - returns true + - else + - returns false + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void register_thread_end_handler ( + T& obj, + void (T::*handler)() + ); + /*! + requires + - handler == a valid member function pointer for class T + - handler does not throw + - handler does not call register_thread_end_handler() + - handler does not block + - is_dlib_thread() == true (i.e. the calling thread was spawned by dlib::create_new_thread()) + ensures + - let ID == the thread id for the thread calling register_thread_end_handler() + - (obj.*handler)() will be called when the thread with thread id ID is + terminating and it will be called from within that terminating thread. + (i.e. inside the handler function get_thread_id() == ID == the id of the + thread that is terminating. ) + - each call to this function adds another handler that will be called when + the given thread terminates. This means that if you call it a bunch of + times then you will end up registering multiple handlers (or single + handlers multiple times) that will be called when the thread ends. + throws + - std::bad_alloc + If this exception is thrown then the call to this function had no effect. + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void unregister_thread_end_handler ( + T& obj, + void (T::*handler)() + ); + /*! + requires + - handler == a valid member function pointer for class T + ensures + - Undoes all previous calls to register_thread_end_handler(obj,handler). + So the given handler won't be called when any threads end. + throws + - std::bad_alloc + If this exception is thrown then the call to this function had no effect. + !*/ + +// ---------------------------------------------------------------------------------------- + + bool create_new_thread ( + void (*funct)(void*), + void* param + ); + /*! + ensures + - creates a new thread for the function pointed to by funct + - passes it param as its parameter. (i.e. calls funct(param) from the new thread) + - returns true upon success and false upon failure to create the new thread + !*/ + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // mutex object +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + class mutex + { + /*! + INITIAL VALUE + mutex is in the unlocked state + + WHAT THIS OBJECT REPRESENTS + This object represents a mutex intended to be used for synchronous + thread control of shared data. When a thread wants to access some + shared data it locks out other threads by calling lock() and calls + unlock() when it is finished. + !*/ + public: + + mutex ( + ); + /*! + ensures + - #*this is properly initialized + throws + - dlib::thread_error + the constructor may throw this exception if there is a problem + gathering resources to create the mutex. + !*/ + + ~mutex ( + ); + /*! + requires + - *this is not locked + ensures + - all resources allocated by *this have been freed + !*/ + + void lock ( + ) const; + /*! + requires + - the thread calling lock() does not already have a lock on *this + ensures + - if (*this is currently locked by another thread) then + - the thread that called lock() on *this is put to sleep until + it becomes available + - if (*this is currently unlocked) then + - #*this becomes locked and the current thread is NOT put to sleep + but now "owns" #*this + !*/ + + void unlock ( + ) const; + /*! + requires + - the thread calling unlock() already has a lock on *this + ensures + - #*this is unlocked (i.e. other threads may now lock this object) + !*/ + + + private: + // restricted functions + mutex(mutex&); // copy constructor + mutex& operator=(mutex&); // assignment operator + }; + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // signaler object +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + class signaler + { + /*! + + WHAT THIS OBJECT REPRESENTS + This object represents an event signaling system for threads. It gives + a thread the ability to wake up other threads that are waiting for a + particular signal. + + Each signaler object is associated with one and only one mutex object. + More than one signaler object may be associated with a single mutex + but a signaler object may only be associated with a single mutex. + + NOTE: + You must guard against spurious wakeups. This means that a thread + might return from a call to wait even if no other thread called + signal. This is rare but must be guarded against. + !*/ + public: + + signaler ( + const mutex& associated_mutex + ); + /*! + ensures + - #*this is properly initialized + - #get_mutex() == associated_mutex + throws + - dlib::thread_error + the constructor may throw this exception if there is a problem + gathering resources to create the signaler. + !*/ + + + ~signaler ( + ); + /*! + ensures + - all resources allocated by *this have been freed + !*/ + + void wait ( + ) const; + /*! + requires + - get_mutex() is locked and owned by the calling thread + ensures + - atomically unlocks get_mutex() and blocks the calling thread + - calling thread may wake if another thread calls signal() or broadcast() + on *this + - when wait() returns the calling thread again has a lock on get_mutex() + !*/ + + bool wait_or_timeout ( + unsigned long milliseconds + ) const; + /*! + requires + - get_mutex() is locked and owned by the calling thread + ensures + - atomically unlocks get_mutex() and blocks the calling thread + - calling thread may wake if another thread calls signal() or broadcast() + on *this + - after the specified number of milliseconds has elapsed the calling thread + will wake once get_mutex() is free + - when wait returns the calling thread again has a lock on get_mutex() + + - returns false if the call to wait_or_timeout timed out + - returns true if the call did not time out + !*/ + + + void signal ( + ) const; + /*! + ensures + - if (at least one thread is waiting on *this) then + - at least one of the waiting threads will wake + !*/ + + void broadcast ( + ) const; + /*! + ensures + - any and all threads waiting on *this will wake + !*/ + + const mutex& get_mutex ( + ) const; + /*! + ensures + - returns a const reference to the mutex associated with *this + !*/ + + private: + // restricted functions + signaler(signaler&); // copy constructor + signaler& operator=(signaler&); // assignment operator + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_THREADS_KERNEl_ABSTRACT_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/threads_kernel_shared.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/threads_kernel_shared.h new file mode 100644 index 0000000..b4526e8 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/threads_kernel_shared.h @@ -0,0 +1,274 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_THREADS_KERNEl_SHARED_ +#define DLIB_THREADS_KERNEl_SHARED_ + +// this file should be included at the bottom of one of the thread kernel headers for a +// specific platform. +//#include "../threads.h" +#include "auto_mutex_extension.h" +#include "../binary_search_tree.h" +#include "../member_function_pointer.h" +#include "../memory_manager.h" +#include "../queue.h" +#include "../set.h" +#include "../test_for_odr_violations.h" + + + + + +namespace dlib +{ + + +// ---------------------------------------------------------------------------------------- + + namespace threads_kernel_shared + { + void thread_starter ( + void* + ); + + class threader + { + /*! + INITIAL VALUE + - pool_count == 0 and + - data_ready is associated with the mutex data_mutex + - data_empty is associated with the mutex data_mutex + - destructed is associated with the mutex data_mutex + - destruct == false + - total_count == 0 + - function_pointer == 0 + - do_not_ever_destruct == false + + CONVENTION + - data_ready is associated with the mutex data_mutex + - data_empty is associated with the mutex data_mutex + - data_ready == a signaler used signal when there is new data waiting + to start a thread with. + - data_empty == a signaler used to signal when the data is now empty + - pool_count == the number of suspended threads in the thread pool + - total_count == the number of threads that are executing anywhere. i.e. + pool_count + the ones that are currently running some user function. + - if (function_pointer != 0) then + - parameter == a void pointer pointing to the parameter which + should be used to start the next thread + - function_pointer == a pointer to the next function to make a + new thread with + + - if (the destructor is running) then + - destruct == true + - else + - destruct == false + + - thread_ids is locked by the data_mutex + - thread_ids == a set that contains the thread id for each thread spawned by this + object. + !*/ + + + public: + threader ( + ); + + ~threader ( + ); + + void destruct_if_ready ( + ); + /*! + ensures + - if (there are no threads currently running and we haven't set do_not_ever_destruct) then + - calls delete this + - else + - does nothing + !*/ + + bool create_new_thread ( + void (*funct)(void*), + void* param + ); + + template < + typename T + > + void unregister_thread_end_handler ( + T& obj, + void (T::*handler)() + ) + { + member_function_pointer<> mfp, junk_mfp; + mfp.set(obj,handler); + + thread_id_type junk_id; + + // find any member function pointers in the registry that point to the same + // thing as mfp and remove them + auto_mutex M(reg.m); + reg.reg.reset(); + while (reg.reg.move_next()) + { + while (reg.reg.current_element_valid() && reg.reg.element().value() == mfp) + { + reg.reg.remove_current_element(junk_id, junk_mfp); + } + } + } + + template < + typename T + > + void register_thread_end_handler ( + T& obj, + void (T::*handler)() + ) + { + thread_id_type id = get_thread_id(); + member_function_pointer<> mfp; + mfp.set(obj,handler); + + auto_mutex M(reg.m); + reg.reg.add(id,mfp); + } + + bool is_dlib_thread ( + thread_id_type id + ); + + private: + + friend void thread_starter ( + void* + ); + + void call_end_handlers ( + ); + /*! + ensures + - calls the registered end handlers for the calling thread and + then removes them from reg.reg + !*/ + + + // private data + set::kernel_2b>::kernel_1b_c thread_ids; + unsigned long total_count; + void* parameter; + void (*function_pointer)(void*); + unsigned long pool_count; + mutex data_mutex; // mutex to protect the above data + signaler data_ready; // signaler to signal when there is new data + signaler data_empty; // signaler to signal when the data is empty + bool destruct; + signaler destructed; // signaler to signal when a thread has ended + bool do_not_ever_destruct; + + struct registry_type + { + mutex m; + binary_search_tree< + thread_id_type, + member_function_pointer<>, + memory_manager::kernel_2a + >::kernel_2a_c reg; + }; + + // stuff for the register_thread_end_handler + registry_type reg; + + + // restricted functions + threader(threader&); // copy constructor + threader& operator=(threader&); // assignement opertor + + }; + + // ------------------------------------------------------------------------------------ + + threader& thread_pool ( + ); + /*! + ensures + - returns a reference to the global threader object + !*/ + + // ------------------------------------------------------------------------------------ + + extern bool thread_pool_has_been_destroyed; + } + + bool is_dlib_thread ( + thread_id_type id + ); + + bool is_dlib_thread ( + ); + +// ---------------------------------------------------------------------------------------- + + inline bool create_new_thread ( + void (*funct)(void*), + void* param + ) + { + try + { + // now make this thread + return threads_kernel_shared::thread_pool().create_new_thread(funct,param); + } + catch (std::bad_alloc&) + { + return false; + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + inline void register_thread_end_handler ( + T& obj, + void (T::*handler)() + ) + { + DLIB_ASSERT(is_dlib_thread(), + "\tvoid register_thread_end_handler" + << "\n\tYou can't register a thread end handler for a thread dlib didn't spawn." + ); + + threads_kernel_shared::thread_pool().register_thread_end_handler(obj,handler); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + inline void unregister_thread_end_handler ( + T& obj, + void (T::*handler)() + ) + { + // Check if the thread pool has been destroyed and if it has then don't do anything. + // This bool here is always true except when the program has started to terminate and + // the thread pool object has been destroyed. This if is here to catch other global + // objects that have destructors that try to call unregister_thread_end_handler(). + // Without this check we get into trouble if the thread pool is destroyed before these + // objects. + if (threads_kernel_shared::thread_pool_has_been_destroyed == false) + threads_kernel_shared::thread_pool().unregister_thread_end_handler(obj,handler); + } + +// ---------------------------------------------------------------------------------------- + +} + +#ifdef NO_MAKEFILE +#include "threads_kernel_shared.cpp" +#endif + +#endif // DLIB_THREADS_KERNEl_SHARED_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/windows.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/windows.h new file mode 100644 index 0000000..f7c7759 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/threads/windows.h @@ -0,0 +1,6 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_THREADS_KERNEl_2_ +#include "threads_kernel_1.h" +#endif + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/time_this.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/time_this.h new file mode 100644 index 0000000..aec0d2d --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/time_this.h @@ -0,0 +1,36 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_TIME_THIs_ +#define DLIB_TIME_THIs_ + + +#include + +// ---------------------------------------------------------------------------------------- + +#define TIME_THIS_TO(_tt_op,_tt_out) \ + { \ + auto _tt_start = std::chrono::high_resolution_clock::now(); \ + {_tt_op;} \ + auto _tt_stop = std::chrono::high_resolution_clock::now(); \ + auto _tt_thetime = _tt_stop-_tt_start; \ + using std::chrono::duration_cast; \ + using std::chrono::duration; \ + if (_tt_thetime >= std::chrono::minutes(1)) \ + _tt_out << "\ntime: " << duration_cast>>(_tt_thetime).count() << "min\n"; \ + else if (_tt_thetime >= std::chrono::seconds(1)) \ + _tt_out << "\ntime: " << duration_cast>(_tt_thetime).count() << "sec\n"; \ + else if (_tt_thetime >= std::chrono::milliseconds(1)) \ + _tt_out << "\ntime: " << duration_cast>(_tt_thetime).count() << "ms\n"; \ + else if (_tt_thetime >= std::chrono::microseconds(1)) \ + _tt_out << "\ntime: " << duration_cast>(_tt_thetime).count() << "us\n"; \ + else \ + _tt_out << "\ntime: " << duration_cast>(_tt_thetime).count() << "ns\n"; \ + } + +#define TIME_THIS(_tt_op) TIME_THIS_TO(_tt_op,std::cout) + +// ---------------------------------------------------------------------------------------- + +#endif // DLIB_TIME_THIs_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timeout.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timeout.h new file mode 100644 index 0000000..2c3590e --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timeout.h @@ -0,0 +1,10 @@ +// Copyright (C) 2007 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_TIMEOUt_ +#define DLIB_TIMEOUt_ + +#include "timeout/timeout.h" + +#endif // DLIB_TIMEOUt_ + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timeout/timeout.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timeout/timeout.h new file mode 100644 index 0000000..663e0ca --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timeout/timeout.h @@ -0,0 +1,200 @@ +// Copyright (C) 2007 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_TIMEOUT_KERNEl_1_ +#define DLIB_TIMEOUT_KERNEl_1_ + +#include "../threads.h" +#include "../algs.h" +#include "../misc_api.h" +#include "timeout_abstract.h" +#include "../uintn.h" +#include "../timer.h" + +#ifdef _MSC_VER +// this is to disable the "'this' : used in base member initializer list" +// warning you get from some of the GUI objects since all the objects +// require that their parent class be passed into their constructor. +// In this case though it is totally safe so it is ok to disable this warning. +#pragma warning(disable : 4355) +#endif // _MSC_VER + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + class timeout + { + /*! + INITIAL VALUE + - b == a pointer to some kind of bind object + + CONVENTION + - b == a pointer to some kind of bind object + !*/ + + class bind + { + public: + virtual void go() = 0; + virtual ~bind() {} + }; + + template + class functor : public bind + { + public: + functor(const T& f) : function(f) {} + T function; + void go() { function(); } + }; + + template + class zero : public bind + { + public: + T* object; + R (T::*callback_function)(); + void go() { (object->*callback_function)(); } + + }; + + template + class one : public bind + { + public: + T* object; + R (T::*callback_function)(U); + U val; + void go() { (object->*callback_function)(val); } + }; + + public: + + // This typedef is here for backwards compatibility with previous versions of dlib. + typedef timeout kernel_1a; + + template < + typename T + > + timeout ( + T callback_function, + unsigned long ms_to_timeout + ) : + t(*this,&timeout::trigger_timeout) + { + b = new functor(callback_function); + t.set_delay_time(ms_to_timeout); + t.start(); + } + + template < + typename T + > + timeout ( + T& object, + void (T::*callback_function)(), + unsigned long ms_to_timeout + ): + t(*this,&timeout::trigger_timeout) + { + zero* B = new zero; + b = B; + B->object = &object; + B->callback_function = callback_function; + t.set_delay_time(ms_to_timeout); + t.start(); + } + + template < + typename T, + typename U + > + timeout ( + T& object, + void (T::*callback_function)(U callback_function_argument), + unsigned long ms_to_timeout, + U callback_function_argument + ): + t(*this,&timeout::trigger_timeout) + { + one* B = new one; + b = B; + B->object = &object; + B->callback_function = callback_function; + B->val = callback_function_argument; + t.set_delay_time(ms_to_timeout); + t.start(); + } + + template < + typename T + > + timeout ( + T& object, + int (T::*callback_function)(), + unsigned long ms_to_timeout + ): + t(*this,&timeout::trigger_timeout) + { + zero* B = new zero; + b = B; + B->object = &object; + B->callback_function = callback_function; + t.set_delay_time(ms_to_timeout); + t.start(); + } + + template < + typename T, + typename U + > + timeout ( + T& object, + int (T::*callback_function)(U callback_function_argument), + unsigned long ms_to_timeout, + U callback_function_argument + ): + t(*this,&timeout::trigger_timeout) + { + one* B = new one; + b = B; + B->object = &object; + B->callback_function = callback_function; + B->val = callback_function_argument; + t.set_delay_time(ms_to_timeout); + t.start(); + } + + virtual ~timeout ( + ) + { + t.stop_and_wait(); + delete b; + } + + private: + + void trigger_timeout () + { + b->go(); + t.stop(); + } + + dlib::timer t; + bind* b; + + // restricted functions + timeout(const timeout&); // copy constructor + timeout& operator=(const timeout&); // assignment operator + + }; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_TIMEOUT_KERNEl_1_ + + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timeout/timeout_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timeout/timeout_abstract.h new file mode 100644 index 0000000..c2401bb --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timeout/timeout_abstract.h @@ -0,0 +1,188 @@ +// Copyright (C) 2007 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_TIMEOUT_KERNEl_ABSTRACT_ +#ifdef DLIB_TIMEOUT_KERNEl_ABSTRACT_ + +#include "../threads.h" + +namespace dlib +{ + + class timeout + { + /*! + WHAT THIS OBJECT REPRESENTS + This object provides a simple way to implement a timeout. An example will + make its use clear. Suppose we want to read from a socket but we want to + terminate the connection if the read takes longer than 10 seconds. This + could be accomplished as follows: + + connection* con = a connection from somewhere; + { + // setup a timer that will call con->shutdown() in 10 seconds + timeout t(*con,&connection::shutdown,10000); + // Now call read on the connection. If this call to read() takes more + // than 10 seconds then the t timeout will trigger and shutdown the + // connection. If read completes in less than 10 seconds then the t + // object will be destructed on the next line due to the } and then the + // timeout won't trigger. + con->read(buf,100); + } + + + Alternatively, if you have a compiler capable of using C++11 lambda + functions, you can use a syntax like this: + { + timeout t([con](){ con->shutdown(); }, 10000); + con->read(buf,100); + } + + More generally, you can use this with things other than sockets. For + example, the following statement will print "Hello world!" after 1000ms: + timeout t([](){ cout << "Hello world!" << endl; }, 1000); + + + + THREAD SAFETY + All methods of this class are thread safe. + !*/ + + public: + + template < + typename T + > + timeout ( + T callback_function, + unsigned long ms_to_timeout + ); + /*! + requires + - callback_function does not throw + ensures + - does not block. + - #*this is properly initialized + - if (this object isn't destructed in ms_to_timeout milliseconds) then + - callback_function() will be called in ms_to_timeout milliseconds. + throws + - std::bad_alloc + - dlib::thread_error + !*/ + + template < + typename T + > + timeout ( + T& object, + void (T::*callback_function)(), + unsigned long ms_to_timeout + ); + /*! + requires + - callback_function does not throw + ensures + - does not block. + - #*this is properly initialized + - if (this object isn't destructed in ms_to_timeout milliseconds) then + - (object.*callback_function)() will be called in ms_to_timeout + milliseconds. + throws + - std::bad_alloc + - dlib::thread_error + !*/ + + template < + typename T, + typename U + > + timeout ( + T& object, + void (T::*callback_function)(U callback_function_argument), + unsigned long ms_to_timeout, + U callback_function_argument + ); + /*! + requires + - callback_function does not throw + ensures + - does not block. + - #*this is properly initialized + - if (this object isn't destructed in ms_to_timeout milliseconds) then + - (object.*callback_function)(callback_function_argument) will be + called in ms_to_timeout milliseconds. + throws + - std::bad_alloc + - dlib::thread_error + !*/ + + template < + typename T + > + timeout ( + T& object, + int (T::*callback_function)(), + unsigned long ms_to_timeout + ); + /*! + requires + - callback_function does not throw + ensures + - does not block. + - #*this is properly initialized + - if (this object isn't destructed in ms_to_timeout milliseconds) then + - (object.*callback_function)() will be called in ms_to_timeout + milliseconds. + throws + - std::bad_alloc + - dlib::thread_error + !*/ + + template < + typename T, + typename U + > + timeout ( + T& object, + int (T::*callback_function)(U callback_function_argument), + unsigned long ms_to_timeout, + U callback_function_argument + ); + /*! + requires + - callback_function does not throw + ensures + - does not block. + - #*this is properly initialized + - if (this object isn't destructed in ms_to_timeout milliseconds) then + - (object.*callback_function)(callback_function_argument) will be + called in ms_to_timeout milliseconds. + throws + - std::bad_alloc + - dlib::thread_error + !*/ + + virtual ~timeout ( + ); + /*! + requires + - is not called from inside the callback_function given to the + constructor. + ensures + - any resources associated with *this have been released + - if (the callback_function hasn't been called yet) then + - the callback_function specified in the constructor will not be called + !*/ + + private: + + // restricted functions + timeout(const timeout&); // copy constructor + timeout& operator=(const timeout&); // assignment operator + + }; + +} + +#endif // DLIB_TIMEOUT_KERNEl_ABSTRACT_ + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timer.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timer.h new file mode 100644 index 0000000..918078e --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timer.h @@ -0,0 +1,10 @@ +// Copyright (C) 2005 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_TIMEr_ +#define DLIB_TIMEr_ + +#include "timer/timer.h" +#include "timer/timer_heavy.h" + +#endif // DLIB_TIMEr_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timer/timer.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timer/timer.h new file mode 100644 index 0000000..c8b6c0a --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timer/timer.h @@ -0,0 +1,427 @@ +// Copyright (C) 2007 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_TIMEr_Hh_ +#define DLIB_TIMEr_Hh_ + +#include + +#include "../threads.h" +#include "../algs.h" +#include "../misc_api.h" +#include "timer_abstract.h" +#include "../uintn.h" +#include "../binary_search_tree.h" +#include "timer_heavy.h" + +namespace dlib +{ + + struct timer_base : public threaded_object + { + /*! + WHAT THIS OBJECT REPRESENTS + This object contains the base members of the timer object. + It exists so that we can access them from outside any templated functions. + !*/ + + unsigned long delay; + // these are only modified by the global_clock + uint64 next_time_to_run; + timestamper ts; + bool running; + bool in_global_clock; + }; + +// ---------------------------------------------------------------------------------------- + + class timer_global_clock : private threaded_object + { + /*! + This object sets up a timer that triggers the action function + for timer objects that are tracked inside this object. + INITIAL VALUE + - shutdown == false + - running == false + + CONVENTION + - if (shutdown) then + - thread() should terminate + - else (running) then + - thread() is running + + - tm[time] == pointer to a timer_base object + !*/ + typedef binary_search_tree::kernel_2b>::kernel_2a_c time_map; + public: + + ~timer_global_clock(); + + void add ( + timer_base* r + ); + /*! + requires + - m is locked + ensures + - starts the thread if it isn't already started + - adds r to tm + - #r->in_global_clock == true + - updates r->next_time_to_run appropriately according to + r->delay + !*/ + + void remove ( + timer_base* r + ); + /*! + requires + - m is locked + ensures + - if (r is in tm) then + - removes r from tm + - #r->in_global_clock == false + !*/ + + void adjust_delay ( + timer_base* r, + unsigned long new_delay + ); + /*! + requires + - m is locked + ensures + - #r->delay == new_delay + - if (r->in_global_clock) then + - the time to the next event will have been appropriately adjusted + !*/ + + mutex m; + + friend std::shared_ptr get_global_clock(); + + private: + timer_global_clock(); + + time_map tm; + signaler s; + bool shutdown; + bool running; + timestamper ts; + + void thread(); + /*! + ensures + - spawns timer tasks as is appropriate + !*/ + }; + std::shared_ptr get_global_clock(); + /*! + ensures + - returns the global instance of the timer_global_clock object + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + class timer : private timer_base + { + /*! + INITIAL VALUE + - running == false + - delay == 1000 + - ao == a pointer to the action_object() + - af == a pointer to the action_function() + - in_global_clock == false + - next_time_to_run == 0 + - gc == get_global_clock() + + CONVENTION + - the mutex used to lock everything is gc->m + - running == is_running() + - delay == delay_time() + - *ao == action_object() + - af == action_function() + - if (!running) then + - in_global_clock == false + - else + - next_time_to_run == the next time this timer should run according + to the timestamper in the global_clock + !*/ + + public: + + // These typedefs are here for backwards compatibility with previous versions of + // dlib. + typedef timer_heavy kernel_1a; + typedef timer kernel_2a; + + typedef void (T::*af_type)(); + + timer( + T& ao_, + af_type af_ + ); + + virtual ~timer( + ); + + void clear( + ); + + af_type action_function ( + ) const; + + const T& action_object ( + ) const; + + T& action_object ( + ); + + bool is_running ( + ) const; + + unsigned long delay_time ( + ) const; + + void set_delay_time ( + unsigned long milliseconds + ); + + void start ( + ); + + void stop ( + ); + + void stop_and_wait ( + ); + + private: + + void thread ( + ); + /*! + ensures + - calls the action function + !*/ + + // data members + T& ao; + const af_type af; + std::shared_ptr gc; + + // restricted functions + timer(const timer&); // copy constructor + timer& operator=(const timer&); // assignment operator + + }; + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + timer:: + timer( + T& ao_, + af_type af_ + ) : + ao(ao_), + af(af_), + gc(get_global_clock()) + { + delay = 1000; + next_time_to_run = 0; + running = false; + in_global_clock = false; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + timer:: + ~timer( + ) + { + clear(); + wait(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void timer:: + clear( + ) + { + auto_mutex M(gc->m); + running = false; + gc->remove(this); + delay = 1000; + next_time_to_run = 0; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + typename timer::af_type timer:: + action_function ( + ) const + { + return af; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + const T& timer:: + action_object ( + ) const + { + return ao; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + T& timer:: + action_object ( + ) + { + return ao; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + bool timer:: + is_running ( + ) const + { + auto_mutex M(gc->m); + return running; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + unsigned long timer:: + delay_time ( + ) const + { + auto_mutex M(gc->m); + return delay; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void timer:: + set_delay_time ( + unsigned long milliseconds + ) + { + auto_mutex M(gc->m); + gc->adjust_delay(this,milliseconds); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void timer:: + start ( + ) + { + auto_mutex M(gc->m); + if (!running) + { + gc->add(this); + running = true; + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void timer:: + stop ( + ) + { + gc->m.lock(); + running = false; + gc->remove(this); + gc->m.unlock(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void timer:: + thread ( + ) + { + // call the action function + (ao.*af)(); + auto_mutex M(gc->m); + if (running) + { + gc->remove(this); + gc->add(this); + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void timer:: + stop_and_wait ( + ) + { + gc->m.lock(); + running = false; + gc->remove(this); + gc->m.unlock(); + wait(); + } + +// ---------------------------------------------------------------------------------------- + +} + +#ifdef NO_MAKEFILE +#include "timer.cpp" +#endif + +#endif // DLIB_TIMEr_Hh_ + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timer/timer_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timer/timer_abstract.h new file mode 100644 index 0000000..180cd49 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timer/timer_abstract.h @@ -0,0 +1,190 @@ +// Copyright (C) 2005 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_TIMER_KERNEl_ABSTRACT_ +#ifdef DLIB_TIMER_KERNEl_ABSTRACT_ + +#include "../threads.h" + +namespace dlib +{ + + template < + typename T + > + class timer + { + /*! + INITIAL VALUE + is_running() == false + delay_time() == 1000 + action_object() == The object that is passed into the constructor + action_function() == The member function pointer that is passed to + the constructor. + + WHAT THIS OBJECT REPRESENTS + This object represents a timer that will call a given member function + (the action function) repeatedly at regular intervals and in its own + thread. + + Note that the delay_time() is measured in milliseconds but you are not + guaranteed to have that level of resolution. The actual resolution + is implementation dependent. + + THREAD SAFETY + All methods of this class are thread safe. + !*/ + + public: + + typedef void (T::*af_type)(); + + timer ( + T& ao, + af_type af + ); + /*! + requires + - af does not throw + ensures + - does not block. + - #*this is properly initialized + - #action_object() == ao + - #action_function() == af + (af is a member function pointer to a member in the class T) + throws + - std::bad_alloc + - dlib::thread_error + !*/ + + virtual ~timer ( + ); + /*! + requires + - is not called from inside the action_function() + ensures + - any resources associated with *this have been released + - will not call the action_function() anymore. + - if (the action function is currently executing) then + - blocks until it finishes + !*/ + + void clear( + ); + /*! + ensures + - #*this has its initial value + - does not block + throws + - std::bad_alloc or dlib::thread_error + If either of these exceptions are thrown then #*this is unusable + until clear() is called and succeeds. + !*/ + + af_type action_function ( + ) const; + /*! + ensures + - does not block. + - returns a pointer to the member function of action_object() that is + called by *this. + !*/ + + const T& action_object ( + ) const; + /*! + ensures + - does not block. + - returns a const reference to the object used to call the member + function pointer action_function() + !*/ + + T& action_object ( + ); + /*! + ensures + - does not block. + - returns a non-const reference to the object used to call the member + function pointer action_function() + !*/ + + bool is_running ( + ) const; + /*! + ensures + - does not block. + - if (*this is currently scheduled to call the action_function()) then + - returns true + - else + - returns false + !*/ + + unsigned long delay_time ( + ) const; + /*! + ensures + - does not block. + - returns the amount of time, in milliseconds, that *this will wait between + the return of one call to the action_function() and the beginning of the + next call to the action_function(). + !*/ + + void set_delay_time ( + unsigned long milliseconds + ); + /*! + ensures + - does not block. + - #delay_time() == milliseconds + throws + - std::bad_alloc or dlib::thread_error + If either of these exceptions are thrown then #is_running() == false + but otherwise this function succeeds + !*/ + + void start ( + ); + /*! + ensures + - does not block. + - if (is_running() == false) then + - #is_running() == true + - The action_function() will run in another thread. + - The first call to the action_function() will occur in roughly + delay_time() milliseconds. + - else + - this call to start() has no effect + throws + - dlib::thread_error or std::bad_alloc + If this exception is thrown then #is_running() == false but + otherwise this call to start() has no effect. + !*/ + + void stop ( + ); + /*! + ensures + - #is_running() == false + - does not block. + !*/ + + void stop_and_wait ( + ); + /*! + ensures + - #is_running() == false + - if (the action function is currently executing) then + - blocks until it finishes + !*/ + + private: + + // restricted functions + timer(const timer&); // copy constructor + timer& operator=(const timer&); // assignment operator + + }; + +} + +#endif // DLIB_TIMER_KERNEl_ABSTRACT_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timer/timer_heavy.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timer/timer_heavy.h new file mode 100644 index 0000000..693b91a --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timer/timer_heavy.h @@ -0,0 +1,392 @@ +// Copyright (C) 2005 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_TIMER_KERNEl_1_ +#define DLIB_TIMER_KERNEl_1_ + +#include "../threads.h" +#include "../algs.h" +#include "../misc_api.h" +#include "timer_abstract.h" + +namespace dlib +{ + + template < + typename T + > + class timer_heavy + { + /*! + WHAT THIS OBJECT REPRESENTS + This is an implementation of the timer_abstract.h interface. It is very + simple and uses only one thread which is always alive in a timer_heavy. + The reason this object exists is for historical reasons. Originally, the + dlib::timer was a multi-implementation component and the timer_heavy was + its first implementation. It was superseded later by the more efficient + dlib::timer. However, timer_heavy is still around so that + dlib::timer::kernel_1a has something to refer to. This way, old client + code which somehow depends on the same thread always calling a timer action + function isn't going to be disrupted. + + + INITIAL VALUE + - running == false + - delay == 1000 + - ao == a pointer to the action_object() + - af == a pointer to the action_function() + - m == a mutex that locks everything in this class + - s == a signaler for mutex m + - stop_running == false + + CONVENTION + - running && !stop_running == is_running() + - delay == delay_time() + - *ao == action_object() + - af == action_function() + + - if (running) then + - there is a thread running + - if (is_running()) then + - next_time_to_run == the time when the next execution of the action + function should occur. (the time is given by ts.get_timestamp()) + + - stop_running is used to tell the thread to quit. If it is + set to true then the thread should end. + !*/ + + public: + + typedef void (T::*af_type)(); + + timer_heavy( + T& ao_, + af_type af_ + ); + + virtual ~timer_heavy( + ); + + void clear( + ); + + af_type action_function ( + ) const; + + const T& action_object ( + ) const; + + T& action_object ( + ); + + bool is_running ( + ) const; + + unsigned long delay_time ( + ) const; + + void set_delay_time ( + unsigned long milliseconds + ); + + void start ( + ); + + void stop ( + ); + + void stop_and_wait ( + ); + + private: + + void thread ( + ); + /*! + requires + - is run in its own thread + ensures + - calls the action function for the given timer object in the manner + specified by timer_kernel_abstract.h + !*/ + + // data members + T& ao; + const af_type af; + unsigned long delay; + mutex m; + signaler s; + + bool running; + bool stop_running; + timestamper ts; + uint64 next_time_to_run; + + // restricted functions + timer_heavy(const timer_heavy&); // copy constructor + timer_heavy& operator=(const timer_heavy&); // assignment operator + + }; + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + timer_heavy:: + timer_heavy( + T& ao_, + af_type af_ + ) : + ao(ao_), + af(af_), + delay(1000), + s(m), + running(false), + stop_running(false) + { + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + timer_heavy:: + ~timer_heavy( + ) + { + stop_and_wait(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void timer_heavy:: + clear( + ) + { + m.lock(); + stop_running = true; + delay = 1000; + s.broadcast(); + m.unlock(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + typename timer_heavy::af_type timer_heavy:: + action_function ( + ) const + { + return af; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + const T& timer_heavy:: + action_object ( + ) const + { + return ao; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + T& timer_heavy:: + action_object ( + ) + { + return ao; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + bool timer_heavy:: + is_running ( + ) const + { + auto_mutex M(m); + return running && !stop_running; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + unsigned long timer_heavy:: + delay_time ( + ) const + { + auto_mutex M(m); + return delay; + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void timer_heavy:: + set_delay_time ( + unsigned long milliseconds + ) + { + m.lock(); + + // if (is_running()) then we should adjust next_time_to_run + if (running && !stop_running) + { + next_time_to_run -= delay*1000; + next_time_to_run += milliseconds*1000; + } + + delay = milliseconds; + s.broadcast(); + m.unlock(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void timer_heavy:: + start ( + ) + { + auto_mutex M(m); + + // if (is_running() == false) then reset the countdown to the next call + // to the action_function() + if ( (running && !stop_running) == false) + next_time_to_run = ts.get_timestamp() + delay*1000; + + stop_running = false; + if (running == false) + { + running = true; + + // start the thread + if (create_new_thread(*this) == false) + { + running = false; + throw dlib::thread_error("error creating new thread in timer_heavy::start"); + } + } + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void timer_heavy:: + stop ( + ) + { + m.lock(); + stop_running = true; + s.broadcast(); + m.unlock(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void timer_heavy:: + thread ( + ) + { + auto_mutex M(m); + unsigned long delay_remaining; + uint64 current_time = ts.get_timestamp(); + + if (current_time < next_time_to_run) + delay_remaining = static_cast((next_time_to_run-current_time)/1000); + else + delay_remaining = 0; + + while (stop_running == false) + { + if (delay_remaining > 0) + s.wait_or_timeout(delay_remaining); + + if (stop_running) + break; + + current_time = ts.get_timestamp(); + if (current_time < next_time_to_run) + { + // then we woke up too early so we should keep waiting + delay_remaining = static_cast((next_time_to_run-current_time)/1000); + + // rounding might make this be zero anyway. So if it is + // then we will say we have hit the next time to run. + if (delay_remaining > 0) + continue; + } + + // call the action function + m.unlock(); + (ao.*af)(); + m.lock(); + + current_time = ts.get_timestamp(); + next_time_to_run = current_time + delay*1000; + delay_remaining = delay; + } + running = false; + stop_running = false; + s.broadcast(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + void timer_heavy:: + stop_and_wait ( + ) + { + m.lock(); + if (running) + { + // make the running thread terminate + stop_running = true; + + s.broadcast(); + // wait for the thread to quit + while (running) + s.wait(); + } + m.unlock(); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_TIMER_KERNEl_1_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timing.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timing.h new file mode 100644 index 0000000..2d5116a --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/timing.h @@ -0,0 +1,196 @@ +// Copyright (C) 2011 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_TImING_Hh_ +#define DLIB_TImING_Hh_ + +#include +#include +#include +#include "string.h" + +#include + +// ---------------------------------------------------------------------------------------- + +/*!A timing + + This set of functions is useful for determining how much time is spent + executing blocks of code. Consider the following example: + + int main() + { + using namespace dlib::timing; + for (int i = 0; i < 10; ++i) + { + // timing block #1 + start(1,"block #1"); + dlib::sleep(500); + stop(1); + + // timing block #2 + start(2,"block #2"); + dlib::sleep(1000); + stop(2); + } + + print(); + } + + This program would output: + Timing report: + block #1: 5.0 seconds + block #2: 10.0 seconds + + So we spent 5 seconds in block #1 and 10 seconds in block #2 + + + + Additionally, note that you can use an RAII style timing block object. For + example, if we wanted to find out how much time we spent in a loop a convenient + way to do this would be as follows: + + int main() + { + using namespace dlib::timing; + for (int i = 0; i < 10; ++i) + { + block tb(1, "main loop"); + + dlib::sleep(1500); + } + + print(); + } + + This program would output: + Timing report: + block main loop: 15.0 seconds + +!*/ + +// ---------------------------------------------------------------------------------------- + +namespace dlib +{ + namespace timing + { + const int TIME_SLOTS = 500; + const int NAME_LENGTH = 40; + + inline std::atomic* time_buf() + { + static std::atomic buf[TIME_SLOTS]; + return buf; + } + + inline char* name_buf(int i, const char* name) + { + static char buf[TIME_SLOTS][NAME_LENGTH] = {{0}}; + // if this name buffer is empty then copy name into it + if (buf[i][0] == '\0') + { + using namespace std; + strncpy(buf[i], name, NAME_LENGTH-1); + buf[i][NAME_LENGTH-1] = '\0'; + } + // return the name buffer + return buf[i]; + } + + inline uint64_t ts() + { + using namespace std::chrono; + return duration_cast>(high_resolution_clock::now().time_since_epoch()).count(); + } + + inline void start(int i) + { + time_buf()[i] -= ts(); + } + + inline void start(int i, const char* name) + { + time_buf()[i] -= ts(); + name_buf(i,name); + } + + inline void stop(int i) + { + time_buf()[i] += ts(); + } + + inline void print() + { + using namespace std; + cout << "Timing report: " << endl; + + // figure out how long the longest name is going to be. + unsigned long max_name_length = 0; + for (int i = 0; i < TIME_SLOTS; ++i) + { + string name; + // Check if the name buffer is empty. Use the name it contains if it isn't. + if (name_buf(i,"")[0] != '\0') + name = cast_to_string(i) + ": " + name_buf(i,""); + else + name = cast_to_string(i); + max_name_length = std::max(max_name_length, name.size()); + } + + for (int i = 0; i < TIME_SLOTS; ++i) + { + if (time_buf()[i] != 0) + { + double time = time_buf()[i]/1000.0/1000.0; + string name; + // Check if the name buffer is empty. Use the name it contains if it isn't. + if (name_buf(i,"")[0] != '\0') + name = cast_to_string(i) + ": " + name_buf(i,""); + else + name = cast_to_string(i); + + // make sure the name is always the same length. Do so by padding with spaces + if (name.size() < max_name_length) + name += string(max_name_length-name.size(),' '); + + if (time < 1000) + cout << " " << name << ": " << time << " milliseconds" << endl; + else if (time < 1000*60) + cout << " " << name << ": " << time/1000.0 << " seconds" << endl; + else if (time < 1000*60*60) + cout << " " << name << ": " << time/1000.0/60.0 << " minutes" << endl; + else + cout << " " << name << ": " << time/1000.0/60.0/60.0 << " hours" << endl; + } + } + } + + inline void clear() + { + for (int i = 0; i < TIME_SLOTS; ++i) + { + // clear timing buffer + time_buf()[i] = 0; + // clear name buffer + name_buf(i,"")[0] = '\0'; + } + } + + struct block + { + /*! + WHAT THIS OBJECT REPRESENTS + This is an RAII tool for calling start() and stop() + !*/ + + block(int i):idx(i) {start(idx);} + block(int i, const char* str):idx(i) {start(idx,str);} + ~block() { stop(idx); } + const int idx; + }; + } +} + + +#endif // DLIB_TImING_Hh_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/tokenizer.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/tokenizer.h new file mode 100644 index 0000000..01b6fcf --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/tokenizer.h @@ -0,0 +1,33 @@ +// Copyright (C) 2005 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_TOKENIZEr_ +#define DLIB_TOKENIZEr_ + +#include "tokenizer/tokenizer_kernel_1.h" +#include "tokenizer/tokenizer_kernel_c.h" + + +namespace dlib +{ + + class tokenizer + { + tokenizer() {} + + + public: + + //----------- kernels --------------- + + // kernel_1a + typedef tokenizer_kernel_1 + kernel_1a; + typedef tokenizer_kernel_c + kernel_1a_c; + + + }; +} + +#endif // DLIB_TOKENIZEr_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/tokenizer/tokenizer_kernel_1.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/tokenizer/tokenizer_kernel_1.h new file mode 100644 index 0000000..d67ae27 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/tokenizer/tokenizer_kernel_1.h @@ -0,0 +1,155 @@ +// Copyright (C) 2005 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_TOKENIZER_KERNEl_1_ +#define DLIB_TOKENIZER_KERNEl_1_ + +#include +#include +#include +#include "../algs.h" +#include "tokenizer_kernel_abstract.h" + +namespace dlib +{ + + class tokenizer_kernel_1 + { + /*! + INITIAL VALUE + - in == 0 + - streambuf == 0 + - have_peeked == false + - head == "_" + lowercase_letters() + uppercase_letters() + - body == "_" + lowercase_letters() + uppercase_letters() + numbers() + - headset == pointer to an array of UCHAR_MAX bools and set according + to the CONVENTION. + - bodyset == pointer to an array of UCHAR_MAX bools and set according + to the CONVENTION. + + CONVENTION + - if (stream_is_set()) then + - get_stream() == *in + - streambuf == in->rdbuf() + - else + - in == 0 + - streambuf == 0 + + - body == get_identifier_body() + - head == get_identifier_head() + + - if (the char x appears in head) then + - headset[static_cast(x)] == true + - else + - headset[static_cast(x)] == false + + - if (the char x appears in body) then + - bodyset[static_cast(x)] == true + - else + - bodyset[static_cast(x)] == false + + - if (have_peeked) then + - next_token == the next token to be returned from get_token() + - next_type == the type of token in peek_token + !*/ + + public: + + // The name of this enum is irrelevant but on some compilers (gcc on MAC OS X) not having it named + // causes an error for whatever reason + enum some_random_name + { + END_OF_LINE, + END_OF_FILE, + IDENTIFIER, + CHAR, + NUMBER, + WHITE_SPACE + }; + + tokenizer_kernel_1 ( + ); + + virtual ~tokenizer_kernel_1 ( + ); + + void clear( + ); + + void set_stream ( + std::istream& in + ); + + bool stream_is_set ( + ) const; + + std::istream& get_stream ( + ) const; + + void get_token ( + int& type, + std::string& token + ); + + void swap ( + tokenizer_kernel_1& item + ); + + void set_identifier_token ( + const std::string& head, + const std::string& body + ); + + int peek_type ( + ) const; + + const std::string& peek_token ( + ) const; + + const std::string get_identifier_head ( + ) const; + + const std::string get_identifier_body ( + ) const; + + const std::string lowercase_letters ( + ) const; + + const std::string uppercase_letters ( + ) const; + + const std::string numbers ( + ) const; + + private: + + // restricted functions + tokenizer_kernel_1(const tokenizer_kernel_1&); // copy constructor + tokenizer_kernel_1& operator=(const tokenizer_kernel_1&); // assignment operator + + + // data members + std::istream* in; + std::streambuf* streambuf; + std::string head; + std::string body; + bool* headset; + bool* bodyset; + + mutable std::string next_token; + mutable int next_type; + mutable bool have_peeked; + }; + + inline void swap ( + tokenizer_kernel_1& a, + tokenizer_kernel_1& b + ) { a.swap(b); } + +} + +#ifdef NO_MAKEFILE +#include "tokenizer_kernel_1.cpp" +#endif + +#endif // DLIB_TOKENIZER_KERNEl_1 + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/tokenizer/tokenizer_kernel_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/tokenizer/tokenizer_kernel_abstract.h new file mode 100644 index 0000000..f534b8f --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/tokenizer/tokenizer_kernel_abstract.h @@ -0,0 +1,289 @@ +// Copyright (C) 2005 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_TOKENIZER_KERNEl_ABSTRACT_ +#ifdef DLIB_TOKENIZER_KERNEl_ABSTRACT_ + +#include +#include + +namespace dlib +{ + + class tokenizer + { + /*! + INITIAL VALUE + stream_is_set() == false + get_identifier_head() == "_" + lowercase_letters() + uppercase_letters() + get_identifier_body() == "_" + lowercase_letters() + uppercase_letters() + + numbers() + + WHAT THIS OBJECT REPRESENTS + This object represents a simple tokenizer for textual data. + + BUFFERING + This object is allowed to buffer data from the input stream. + Thus if you clear it or switch streams (via calling set_stream()) + any buffered data will be lost. + + TOKENS + When picking out tokens the tokenizer will always extract the + longest token it can. For example, if faced with the string + "555" it will consider the three 5s to be a single NUMBER + token not three smaller NUMBER tokens. + + Also note that no characters in the input stream are discarded. + They will all be returned in the text of some token. + Additionally, each character will never be returned more than once. + This means that if you concatenated all returned tokens it would exactly + reproduce the contents of the input stream. + + The tokens are defined as follows: + + END_OF_LINE + This is a single character token and is always the '\n' + character. + + END_OF_FILE + This token represents the end of file. It doesn't have any + actual characters associated with it. + + IDENTIFIER + This is a multi-character token. It is defined as a string that + begins with a character from get_identifier_head() and is + followed by any number of characters from get_identifier_body(). + + NUMBER + This is a multi-character token. It is defined as a sequence of + numbers. + + WHITE_SPACE + This is a multi character token. It is defined as a sequence of + one or more spaces, carrage returns, and tabs. I.e. It is + composed of characters from the following string " \r\t". + + CHAR + This is a single character token. It matches anything that isn't + part of one of the above tokens. + !*/ + + public: + + enum + { + END_OF_LINE, + END_OF_FILE, + IDENTIFIER, + CHAR, + NUMBER, + WHITE_SPACE + }; + + tokenizer ( + ); + /*! + ensures + - #*this is properly initialized + throws + - std::bad_alloc + !*/ + + virtual ~tokenizer ( + ); + /*! + ensures + - any resources associated with *this have been released + !*/ + + void clear( + ); + /*! + ensures + - #*this has its initial value + throws + - std::bad_alloc + If this exception is thrown then #*this is unusable + until clear() is called and succeeds. + !*/ + + void set_stream ( + std::istream& in + ); + /*! + ensures + - #*this will read data from in and tokenize it + - #stream_is_set() == true + - #get_stream() == in + !*/ + + bool stream_is_set ( + ) const; + /*! + ensures + - returns true if a stream has been associated with *this by calling + set_stream() + !*/ + + std::istream& get_stream ( + ) const; + /*! + requires + - stream_is_set() == true + ensures + - returns a reference to the istream object that *this is reading + from. + !*/ + + void get_token ( + int& type, + std::string& token + ); + /*! + requires + - stream_is_set() == true + ensures + - #token == the next token from the input stream get_stream() + - #type == the type of the token in #token + throws + - bad_alloc + If this exception is thrown then the call to this function will + have no effect on *this but the values of #type and #token will be + undefined. Additionally, some characters may have been read + from the stream get_stream() and lost. + !*/ + + int peek_type ( + ) const; + /*! + requires + - stream_is_set() == true + ensures + - returns the type of the token that will be returned from + the next call to get_token() + throws + - bad_alloc + If this exception is thrown then the call to this function will + have no effect on *this. However, some characters may have been + read from the stream get_stream() and lost. + !*/ + + const std::string& peek_token ( + ) const; + /*! + requires + - stream_is_set() == true + ensures + - returns the text of the token that will be returned from + the next call to get_token() + throws + - bad_alloc + If this exception is thrown then the call to this function will + have no effect on *this. However, some characters may have been + read from the stream get_stream() and lost. + !*/ + + void set_identifier_token ( + const std::string& head, + const std::string& body + ); + /*! + requires + - head.find_first_of(" \r\t\n0123456789") == std::string::npos + (i.e. head doesn't contain any characters from the string + " \r\t\n0123456789"). + - body.find_frst_of(" \r\t\n") == std::string::npos + (i.e. body doesn't contain any characters from the string " \r\t\n"). + ensures + - #get_identifier_head() == head + - #get_identifier_body() == body + throws + - std::bad_alloc + If this exception is thrown then #*this is unusable + until clear() is called and succeeds. + !*/ + + const std::string get_identifier_head ( + ) const; + /*! + ensures + - returns a string containing the characters that can be the start + of an IDENTIFIER token. + throws + - std::bad_alloc + If this exception is thrown then the call to this function + has no effect. + !*/ + + const std::string get_identifier_body ( + ) const; + /*! + ensures + - returns a string containing the characters that can appear in the + body of an IDENTIFIER token. + throws + - std::bad_alloc + If this exception is thrown then the call to this function + has no effect. + !*/ + + const std::string lowercase_letters ( + ) const; + /*! + ensures + - returns "abcdefghijklmnopqrstuvwxyz" + throws + - std::bad_alloc + If this exception is thrown then the call to this function + has no effect. + !*/ + + const std::string uppercase_letters ( + ) const; + /*! + ensures + - returns "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + throws + - std::bad_alloc + If this exception is thrown then the call to this function + has no effect. + !*/ + + const std::string numbers ( + ) const; + /*! + ensures + - returns "0123456789" + throws + - std::bad_alloc + If this exception is thrown then the call to this function + has no effect. + !*/ + + void swap ( + tokenizer& item + ); + /*! + ensures + - swaps *this and item + !*/ + + private: + + // restricted functions + tokenizer(const tokenizer&); // copy constructor + tokenizer& operator=(const tokenizer&); // assignment operator + + }; + + inline void swap ( + tokenizer& a, + tokenizer& b + ) { a.swap(b); } + /*! + provides a global swap function + !*/ + +} + +#endif // DLIB_TOKENIZER_KERNEl_ABSTRACT_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/tokenizer/tokenizer_kernel_c.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/tokenizer/tokenizer_kernel_c.h new file mode 100644 index 0000000..f960480 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/tokenizer/tokenizer_kernel_c.h @@ -0,0 +1,167 @@ +// Copyright (C) 2003 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_TOKENIZER_KERNEl_C_ +#define DLIB_TOKENIZER_KERNEl_C_ + +#include "tokenizer_kernel_abstract.h" +#include "../assert.h" +#include +#include + +namespace dlib +{ + + template < + typename tokenizer + > + class tokenizer_kernel_c : public tokenizer + { + + public: + std::istream& get_stream ( + ) const; + + void get_token ( + int& type, + std::string& token + ); + + void set_identifier_token ( + const std::string& head, + const std::string& body + ); + + int peek_type ( + ) const; + + const std::string& peek_token ( + ) const; + }; + + template < + typename tokenizer + > + inline void swap ( + tokenizer_kernel_c& a, + tokenizer_kernel_c& b + ) { a.swap(b); } + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + // member function definitions +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename tokenizer + > + void tokenizer_kernel_c:: + set_identifier_token ( + const std::string& head, + const std::string& body + ) + { + using namespace std; + // make sure requires clause is not broken + DLIB_CASSERT( head.find_first_of(" \r\t\n0123456789") == string::npos && + body.find_first_of(" \r\t\n") == string::npos , + "\tvoid tokenizer::set_identifier_token()" + << "\n\tyou can't define the IDENTIFIER token this way." + << "\n\thead: " << head + << "\n\tbody: " << body + << "\n\tthis: " << this + ); + + // call the real function + tokenizer::set_identifier_token(head,body); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename tokenizer + > + std::istream& tokenizer_kernel_c:: + get_stream ( + ) const + { + // make sure requires clause is not broken + DLIB_CASSERT( this->stream_is_set() == true, + "\tstd::istream& tokenizer::get_stream()" + << "\n\tyou must set a stream for this object before you can get it" + << "\n\tthis: " << this + ); + + // call the real function + return tokenizer::get_stream(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename tokenizer + > + int tokenizer_kernel_c:: + peek_type ( + ) const + { + // make sure requires clause is not broken + DLIB_CASSERT( this->stream_is_set() == true, + "\tint tokenizer::peek_type()" + << "\n\tyou must set a stream for this object before you peek at what it contains" + << "\n\tthis: " << this + ); + + // call the real function + return tokenizer::peek_type(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename tokenizer + > + const std::string& tokenizer_kernel_c:: + peek_token ( + ) const + { + // make sure requires clause is not broken + DLIB_CASSERT( this->stream_is_set() == true, + "\tint tokenizer::peek_token()" + << "\n\tyou must set a stream for this object before you peek at what it contains" + << "\n\tthis: " << this + ); + + // call the real function + return tokenizer::peek_token(); + } + +// ---------------------------------------------------------------------------------------- + + template < + typename tokenizer + > + void tokenizer_kernel_c:: + get_token ( + int& type, + std::string& token + ) + { + // make sure requires clause is not broken + DLIB_CASSERT( this->stream_is_set() == true, + "\tvoid tokenizer::get_token()" + << "\n\tyou must set a stream for this object before you can get tokens from it." + << "\n\tthis: " << this + ); + + // call the real function + tokenizer::get_token(type,token); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_TOKENIZER_KERNEl_C_ + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/uintn.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/uintn.h new file mode 100644 index 0000000..8e27265 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/uintn.h @@ -0,0 +1,96 @@ +// Copyright (C) 2005 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. + +#ifndef DLIB_UINtn_ +#define DLIB_UINtn_ + +#include "assert.h" + +namespace dlib +{ + + /*! + uint64 is a typedef for an unsigned integer that is exactly 64 bits wide. + uint32 is a typedef for an unsigned integer that is exactly 32 bits wide. + uint16 is a typedef for an unsigned integer that is exactly 16 bits wide. + uint8 is a typedef for an unsigned integer that is exactly 8 bits wide. + + int64 is a typedef for an integer that is exactly 64 bits wide. + int32 is a typedef for an integer that is exactly 32 bits wide. + int16 is a typedef for an integer that is exactly 16 bits wide. + int8 is a typedef for an integer that is exactly 8 bits wide. + !*/ + + +#ifdef __GNUC__ + typedef unsigned long long uint64; + typedef long long int64; +#elif defined(__BORLANDC__) + typedef unsigned __int64 uint64; + typedef __int64 int64; +#elif defined(_MSC_VER) + typedef unsigned __int64 uint64; + typedef __int64 int64; +#else + typedef unsigned long long uint64; + typedef long long int64; +#endif + + typedef unsigned short uint16; + typedef unsigned int uint32; + typedef unsigned char uint8; + + typedef short int16; + typedef int int32; + typedef char int8; + + + // make sure these types have the right sizes on this platform + COMPILE_TIME_ASSERT(sizeof(uint8) == 1); + COMPILE_TIME_ASSERT(sizeof(uint16) == 2); + COMPILE_TIME_ASSERT(sizeof(uint32) == 4); + COMPILE_TIME_ASSERT(sizeof(uint64) == 8); + + COMPILE_TIME_ASSERT(sizeof(int8) == 1); + COMPILE_TIME_ASSERT(sizeof(int16) == 2); + COMPILE_TIME_ASSERT(sizeof(int32) == 4); + COMPILE_TIME_ASSERT(sizeof(int64) == 8); + + + + template + struct unsigned_type; + template + struct unsigned_type { typedef uint8 type; }; + template + struct unsigned_type { typedef uint16 type; }; + template + struct unsigned_type { typedef uint32 type; }; + template + struct unsigned_type { typedef uint64 type; }; + /*! + ensures + - sizeof(unsigned_type::type) == sizeof(T) + - unsigned_type::type is an unsigned integral type + !*/ + + template + T zero_extend_cast( + const U val + ) + /*! + requires + - U and T are integral types + ensures + - let ut be a typedef for unsigned_type::type + - return static_cast(static_cast(val)); + !*/ + { + typedef typename unsigned_type::type ut; + return static_cast(static_cast(val)); + } + +} + +#endif // DLIB_UINtn_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/unicode.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/unicode.h new file mode 100644 index 0000000..3c15988 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/unicode.h @@ -0,0 +1,9 @@ +// Copyright (C) 2007 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_UNICODe_TOP_ +#define DLIB_UNICODe_TOP_ + +#include "unicode/unicode.h" + +#endif // DLIB_UNICODe_TOP_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/unicode/unicode.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/unicode/unicode.h new file mode 100644 index 0000000..d7510e3 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/unicode/unicode.h @@ -0,0 +1,622 @@ +// Copyright (C) 2007 Davis E. King (davis@dlib.net), and Nils Labugt +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_UNICODe_H_ +#define DLIB_UNICODe_H_ + +#include "../uintn.h" +#include "../algs.h" +#include "unicode_abstract.h" +#include +#include + +#include + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + typedef uint32 unichar; + +#if defined(__GNUC__) && __GNUC__ < 4 && __GNUC_MINOR__ < 4 + struct unichar_traits + { + typedef dlib::unichar char_type; + typedef dlib::unichar int_type; + typedef std::streamoff off_type; + typedef std::streampos pos_type; + typedef std::mbstate_t state_type; + + static void assign(char_type& c1, const char_type& c2) { c1 = c2; } + static bool eq(const char_type& c1, const char_type& c2) { return c1 == c2; } + static bool lt(const char_type& c1, const char_type& c2) { return c1 < c2; } + static int compare(const char_type* s1, const char_type* s2, size_t n) + { + for (size_t i = 0; i < n; ++i) + { + if (s1[i] < s2[i]) + return -1; + else if (s1[i] > s2[i]) + return 1; + } + return 0; + } + + static size_t length(const char_type* s) + { + size_t i = 0; + while (s[i] != 0) + ++i; + return i; + } + + static const char_type* find(const char_type* s, size_t n, + const char_type& a) + { + for (size_t i = 0; i < n; ++i) + { + if (s[i] == a) + { + return s+i; + } + } + return 0; + } + + static char_type* move(char_type* s1, const char_type* s2, size_t n) + { + return static_cast(std::memmove(s1, s2, sizeof(char_type)*n)); + } + + static char_type* copy(char_type* s1, const char_type* s2, size_t n) + { + for (size_t i = 0; i < n; ++i) + s1[i] = s2[i]; + + return s1; + } + + static char_type* assign(char_type* s, size_t n, char_type a) + { + for (size_t i = 0; i < n; ++i) + s[i] = a; + + return s; + } + + + static int_type not_eof(const int_type& c) + { + if (!eq_int_type(c,eof())) + return to_int_type(c); + else + return 0; + } + + static char_type to_char_type(const int_type& c) { return static_cast(c); } + static int_type to_int_type(const char_type& c) { return zero_extend_cast(c); } + + static bool eq_int_type(const int_type& c1, const int_type& c2) { return c1 == c2; } + + static int_type eof() { return static_cast(EOF); } + }; + + typedef std::basic_string ustring; +#else + typedef std::basic_string ustring; +#endif + +// ---------------------------------------------------------------------------------------- + + namespace unicode_helpers + { + + template < + typename charT + > + int u8_to_u32( + charT& result, + std::istream& in + ) + /*! + ensures + - if (there just wasn't any more data and we hit EOF) then + - returns 0 + - else if (we decoded another character without error) then + - #result == the decoded character + - returns the number of bytes consumed to make this character + - else + - some error occurred + - returns -1 + !*/ + { + int val = in.get(); + if (val == EOF) + return 0; + + unichar ch[4]; + ch[0] = zero_extend_cast(val); + if ( ch[0] < 0x80 ) + { + result = static_cast(ch[0]); + return 1; + } + if ( ( ch[0] & ~0x3F ) == 0x80 ) + { + // invalid leading byte + return -1; + } + if ( ( ch[0] & ~0x1F ) == 0xC0 ) + { + val = in.get(); + if ( val == EOF ) + return -1; + + ch[1] = zero_extend_cast(val); + if ( ( ch[1] & ~0x3F ) != 0x80 ) + return -1; // invalid tail + if ( ( ch[0] & ~0x01 ) == 0xC0 ) + return -1; // overlong form + ch[0] &= 0x1F; + ch[1] &= 0x3F; + result = static_cast(( ch[0] << 6 ) | ch[1]); + return 2; + } + if ( ( ch[0] & ~0x0F ) == 0xE0 ) + { + for ( unsigned n = 1;n < 3;n++ ) + { + val = in.get(); + if ( val == EOF ) + return -1; + ch[n] = zero_extend_cast(val); + if ( ( ch[n] & ~0x3F ) != 0x80 ) + return -1; // invalid tail + ch[n] &= 0x3F; + } + ch[0] &= 0x0F; + result = static_cast(( ch[0] << 12 ) | ( ch[1] << 6 ) | ch[2]); + if ( result < 0x0800 ) + return -1; // overlong form + if ( result >= 0xD800 && result < 0xE000 ) + return -1; // invalid character (UTF-16 surrogate pairs) + if ( result >= 0xFDD0 && result <= 0xFDEF ) + return -1; // noncharacter + if ( result >= 0xFFFE ) + return -1; // noncharacter + return 3; + } + if ( ( ch[0] & ~0x07 ) == 0xF0 ) + { + for ( unsigned n = 1;n < 4;n++ ) + { + val = in.get(); + if ( val == EOF ) + return -1; + ch[n] = zero_extend_cast(val); + if ( ( ch[n] & ~0x3F ) != 0x80 ) + return -1; // invalid tail + ch[n] &= 0x3F; + } + if ( ( ch[0] ^ 0xF6 ) < 4 ) + return -1; + ch[0] &= 0x07; + result = static_cast(( ch[0] << 18 ) | ( ch[1] << 12 ) | ( ch[2] << 6 ) | ch[3]); + if ( result < 0x10000 ) + return -1; // overlong form + if ( (result & 0xFFFF) >= 0xFFFE ) + return -1; // noncharacter + return 4; + } + return -1; + } + + // ------------------------------------------------------------------------------------ + + template + class basic_utf8_streambuf : public std::basic_streambuf + { + public: + basic_utf8_streambuf ( + std::ifstream& fin_ + ) : + fin(fin_) + { + this->setg(in_buffer+max_putback, + in_buffer+max_putback, + in_buffer+max_putback); + } + + protected: + + typedef typename std::basic_streambuf::int_type int_type; + + // input functions + int_type underflow( + ) + { + if (this->gptr() < this->egptr()) + { + return zero_extend_cast(*this->gptr()); + } + + int num_put_back = static_cast(this->gptr() - this->eback()); + if (num_put_back > max_putback) + { + num_put_back = max_putback; + } + + // copy the putback characters into the putback end of the in_buffer + std::memmove(in_buffer+(max_putback-num_put_back), this->gptr()-num_put_back, num_put_back); + + + // fill the buffer with characters + int n = in_buffer_size-max_putback; + int i; + for (i = 0; i < n; ++i) + { + charT ch; + if (unicode_helpers::u8_to_u32(ch,fin) > 0) + { + (in_buffer+max_putback)[i] = ch; + } + else + { + break; + } + } + + if (i == 0) + { + // an error occurred or we hit EOF + return EOF; + } + + // reset in_buffer pointers + this->setg (in_buffer+(max_putback-num_put_back), + in_buffer+max_putback, + in_buffer+max_putback+i); + + return zero_extend_cast(*this->gptr()); + } + + private: + std::ifstream& fin; + static const int max_putback = 4; + static const int in_buffer_size = 10; + charT in_buffer[in_buffer_size]; + }; + } + +// ---------------------------------------------------------------------------------------- +#if defined(__GNUC__) && __GNUC__ >= 6 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmisleading-indentation" +#endif + template + bool is_combining_char( + const T ch_ + ) + { + const unichar ch = zero_extend_cast(ch_); + if ( ch < 0x300 ) return false; + if ( ch < 0x370 ) return true; + + if ( ch < 0x800 ) + { + if ( ch < 0x483 )return false;if ( ch < 0x48A )return true; + + if ( ch < 0x591 )return false;if ( ch < 0x5D0 ) + { + if ( ch == 0x5C0 )return false; + if ( ch == 0x5C3 )return false; + if ( ch == 0x5C6 )return false; + return true; + } + if ( ch < 0x610 )return false;if ( ch < 0x616 )return true; + if ( ch < 0x64B )return false;if ( ch < 0x660 )return true; + + if ( ch == 0x670 )return true; + + if ( ch < 0x6D6 )return false;if ( ch < 0x6EE ) + { + if ( ch == 0x6DD )return false; + if ( ch == 0x6E5 )return false; + if ( ch == 0x6E6 )return false; + if ( ch == 0x6E9 )return false; + return true; + } + if ( ch == 0x711 )return true; + + if ( ch < 0x730 )return false;if ( ch < 0x74B )return true; + if ( ch < 0x7A6 )return false;if ( ch < 0x7B1 )return true; + if ( ch < 0x7EB )return false;if ( ch < 0x7F4 )return true; + return false; + } + if ( ch < 0xA00 ) + { + if ( ch < 0x901 )return false;if ( ch < 0x904 )return true; + if ( ch < 0x93C )return false;if ( ch < 0x955 ) + { + if ( ch == 0x93D )return false; + if ( ch == 0x950 )return false; + return true; + } + if ( ch < 0x962 )return false;if ( ch < 0x964 )return true; + if ( ch < 0x981 )return false;if ( ch < 0x984 )return true; + if ( ch < 0x9BC )return false;if ( ch < 0x9D8 ) + { + if ( ch == 0x9BD )return false; + if ( ch == 0x9CE )return false; + return true; + } + if ( ch < 0x9E2 )return false;if ( ch < 0x9E4 )return true; + return false; + } + if ( ch < 0xC00 ) + { + if ( ch < 0xA01 )return false;if ( ch < 0xA04 )return true; + if ( ch < 0xA3C )return false;if ( ch < 0xA4E )return true; + if ( ch < 0xA70 )return false;if ( ch < 0xA72 )return true; + if ( ch < 0xA81 )return false;if ( ch < 0xA84 )return true; + if ( ch < 0xABC )return false;if ( ch < 0xACE ) + { + if ( ch == 0xABD )return false; + return true; + } + if ( ch < 0xAE2 )return false;if ( ch < 0xAE4 )return true; + if ( ch < 0xB01 )return false;if ( ch < 0xB04 )return true; + if ( ch < 0xB3C )return false;if ( ch < 0xB58 ) + { + if ( ch == 0xB3D )return false; + return true; + } + if ( ch == 0xB82 )return true; + + if ( ch < 0xBBE )return false;if ( ch < 0xBD8 )return true; + + if ( ch == 0xBF4 )return true; + if ( ch == 0xBF8 )return true; + return false; + } + if(ch < 0xE00) + { + if ( ch < 0xC01 )return false;if ( ch < 0xC04 )return true; + if ( ch < 0xC3E )return false;if ( ch < 0xC57 )return true; + if ( ch < 0xC82 )return false;if ( ch < 0xC84 )return true; + if ( ch < 0xCBC )return false;if ( ch < 0xCD7 ) + { + if ( ch == 0xCBD )return false; + return true; + } + if ( ch < 0xCE2 )return false;if ( ch < 0xCE4 )return true; + if ( ch < 0xD02 )return false;if ( ch < 0xD04 )return true; + if ( ch < 0xD3E )return false;if ( ch < 0xD58 )return true; + if ( ch < 0xD82 )return false;if ( ch < 0xD84 )return true; + if ( ch < 0xDCA )return false;if ( ch < 0xDF4 )return true; + return false; + } + if(ch < 0x1000) + { + if ( ch == 0xE31 )return true; + + if ( ch < 0xE34 )return false;if ( ch < 0xE3B )return true; + if ( ch < 0xE47 )return false;if ( ch < 0xE4F )return true; + + if ( ch == 0xEB1 )return true; + + if ( ch < 0xEB4 )return false;if ( ch < 0xEBD )return true; + if ( ch < 0xEC8 )return false;if ( ch < 0xECE )return true; + if ( ch < 0xF18 )return false;if ( ch < 0xF1A )return true; + + if ( ch == 0xF35 )return true; + if ( ch == 0xF37 )return true; + if ( ch == 0xF39 )return true; + + if ( ch < 0xF3E )return false;if ( ch < 0xF40 )return true; + if ( ch < 0xF71 )return false;if ( ch < 0xF88 ) + { + if ( ch == 0xF85 )return false; + return true; + } + if ( ch < 0xF90 )return false;if ( ch < 0xFBD )return true; + + if ( ch == 0xFC6 )return true; + return false; + } + if ( ch < 0x1800 ) + { + if ( ch < 0x102C )return false;if ( ch < 0x1040 )return true; + if ( ch < 0x1056 )return false;if ( ch < 0x105A )return true; + + if ( ch == 0x135F )return true; + + if ( ch < 0x1712 )return false;if ( ch < 0x1715 )return true; + if ( ch < 0x1732 )return false;if ( ch < 0x1735 )return true; + if ( ch < 0x1752 )return false;if ( ch < 0x1754 )return true; + if ( ch < 0x1772 )return false;if ( ch < 0x1774 )return true; + if ( ch < 0x17B6 )return false;if ( ch < 0x17D4 )return true; + + if ( ch == 0x17DD )return true; + return false; + } + if(ch < 0x2000) + { + if ( ch < 0x180B )return false;if ( ch < 0x180E )return true; + + if ( ch == 0x18A9 )return true; + + if ( ch < 0x1920 )return false;if ( ch < 0x193C )return true; + if ( ch < 0x19B0 )return false;if ( ch < 0x19C1 )return true; + if ( ch < 0x19C8 )return false;if ( ch < 0x19CA )return true; + if ( ch < 0x1A17 )return false;if ( ch < 0x1A1C )return true; + if ( ch < 0x1B00 )return false;if ( ch < 0x1B05 )return true; + if ( ch < 0x1B34 )return false;if ( ch < 0x1B45 )return true; + if ( ch < 0x1B6B )return false;if ( ch < 0x1B74 )return true; + if ( ch < 0x1DC0 )return false;if ( ch < 0x1E00 )return true; + return false; + } + if ( ch < 0x20D0 )return false;if ( ch < 0x2100 )return true; + if ( ch < 0x302A )return false;if ( ch < 0x3030 )return true; + if ( ch < 0x3099 )return false;if ( ch < 0x309B )return true; + + if ( ch == 0xA802 )return true; + if ( ch == 0xA806 )return true; + if ( ch == 0xA80B )return true; + + if ( ch < 0xA823 )return false;if ( ch < 0xA828 )return true; + + if ( ch == 0xFB1E )return true; + + if ( ch < 0xFE00 )return false;if ( ch < 0xFE10 )return true; + if ( ch < 0xFE20 )return false;if ( ch < 0xFE30 )return true; + if ( ch < 0x10A01 )return false;if ( ch < 0x10A10 )return true; + if ( ch < 0x10A38 )return false;if ( ch < 0x10A40 )return true; + if ( ch < 0x1D165 )return false;if ( ch < 0x1D16A )return true; + if ( ch < 0x1D16D )return false;if ( ch < 0x1D173 )return true; + if ( ch < 0x1D17B )return false;if ( ch < 0x1D183 )return true; + if ( ch < 0x1D185 )return false;if ( ch < 0x1D18C )return true; + if ( ch < 0x1D1AA )return false;if ( ch < 0x1D1AE )return true; + if ( ch < 0x1D242 )return false;if ( ch < 0x1D245 )return true; + if ( ch < 0xE0100 )return false;if ( ch < 0xE01F0 )return true; + return false; + } +#if defined(__GNUC__) && __GNUC__ >= 6 +#pragma GCC diagnostic pop +#endif + +// ---------------------------------------------------------------------------------------- + + class invalid_utf8_error : public error + { + public: + invalid_utf8_error():error(EUTF8_TO_UTF32) {} + }; + + inline const ustring convert_utf8_to_utf32 ( + const std::string& str + ) + { + using namespace unicode_helpers; + ustring temp; + std::istringstream sin(str); + + temp.reserve(str.size()); + + int status; + unichar ch; + while ( (status = u8_to_u32(ch,sin)) > 0) + temp.push_back(ch); + + if (status < 0) + throw invalid_utf8_error(); + + return temp; + } + +// ---------------------------------------------------------------------------------------- + + bool is_surrogate(unichar ch); + + unichar surrogate_pair_to_unichar(unichar first, unichar second); + + void unichar_to_surrogate_pair(unichar unicode, unichar &first, unichar &second); + + + const ustring convert_wstring_to_utf32 ( + const std::wstring &wstr + ); + + const std::wstring convert_utf32_to_wstring ( + const ustring &src + ); + + const std::wstring convert_mbstring_to_wstring ( + const std::string &src + ); + + const std::string convert_wstring_to_mbstring( + const std::wstring &src + ); + +// ---------------------------------------------------------------------------------------- + + template + class basic_utf8_ifstream : public std::basic_istream + { + public: + + basic_utf8_ifstream ( + ) : std::basic_istream(&buf), buf(fin) {} + + basic_utf8_ifstream ( + const char* file_name, + std::ios_base::openmode mode = std::ios::in + ) : + std::basic_istream(&buf), + buf(fin) + { + fin.open(file_name,mode); + // make this have the same error state as fin + this->clear(fin.rdstate()); + } + + basic_utf8_ifstream ( + const std::string& file_name, + std::ios_base::openmode mode = std::ios::in + ) : + std::basic_istream(&buf), + buf(fin) + { + fin.open(file_name.c_str(),mode); + // make this have the same error state as fin + this->clear(fin.rdstate()); + } + + void open( + const std::string& file_name, + std::ios_base::openmode mode = std::ios::in + ) + { + open(file_name.c_str(),mode); + } + + void open ( + const char* file_name, + std::ios_base::openmode mode = std::ios::in + ) + { + fin.close(); + fin.clear(); + fin.open(file_name,mode); + // make this have the same error state as fin + this->clear(fin.rdstate()); + } + + void close ( + ) + { + fin.close(); + // make this have the same error state as fin + this->clear(fin.rdstate()); + } + + private: + + std::ifstream fin; + unicode_helpers::basic_utf8_streambuf buf; + }; + + typedef basic_utf8_ifstream utf8_uifstream; + typedef basic_utf8_ifstream utf8_wifstream; + +// ---------------------------------------------------------------------------------------- + +} + +#ifdef NO_MAKEFILE +#include "unicode.cpp" +#endif + +#endif // DLIB_UNICODe_H_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/unicode/unicode_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/unicode/unicode_abstract.h new file mode 100644 index 0000000..ed5b9ab --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/unicode/unicode_abstract.h @@ -0,0 +1,233 @@ +// Copyright (C) 2007 Davis E. King (davis@dlib.net), and Nils Labugt +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_UNICODe_ABSTRACT_H_ +#ifdef DLIB_UNICODe_ABSTRACT_H_ + +#include "../uintn.h" +#include "../error.h" +#include +#include + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + // a typedef for an unsigned 32bit integer to hold our UNICODE characters + typedef uint32 unichar; + + // a typedef for a string object to hold our UNICODE strings + typedef std::basic_string ustring; + +// ---------------------------------------------------------------------------------------- + + template + bool is_combining_char( + const T ch_ + ); + /*! + ensures + - if (ch_ is a unicode combining character) then + - returns true + - else + - returns false + !*/ + + bool is_surrogate( + unichar ch + ); + /*! + ensures + - if (ch is a unicode surrogate character) then + - returns true + - else + - returns false + !*/ + + unichar surrogate_pair_to_unichar( + unichar first, + unichar second + ); + /*! + requires + - 0xD800 <= first < 0xDC00 + - 0xDC00 <= second < 0xE000 + - is_surrogate(first) == true + - is_surrogate(second) == true + ensures + - converts two surrogates into one unicode character + !*/ + + void unichar_to_surrogate_pair( + unichar ch, + unichar& first, + unichar& second + ); + /*! + requires + - ch >= 0x10000 (i.e. is not in Basic Multilingual Plane) + ensures + - surrogate_pair_to_unichar(#first,#second) == ch + (i.e. converts ch into two surrogate characters) + !*/ + +// ---------------------------------------------------------------------------------------- + + class invalid_utf8_error : public error + { + public: + invalid_utf8_error():error(EUTF8_TO_UTF32) {} + }; + + const ustring convert_utf8_to_utf32 ( + const std::string& str + ); + /*! + ensures + - if (str is a valid UTF-8 encoded string) then + - returns a copy of str that has been converted into a + unichar string + - else + - throws invalid_utf8_error + !*/ + +// ---------------------------------------------------------------------------------------- + + const ustring convert_wstring_to_utf32 ( + const std::wstring &wstr + ); + /*! + requires + - wstr is a valid UTF-16 string when sizeof(wchar_t) == 2 + - wstr is a valid UTF-32 string when sizeof(wchar_t) == 4 + ensures + - converts wstr into UTF-32 string + !*/ + +// ---------------------------------------------------------------------------------------- + + const std::wstring convert_utf32_to_wstring ( + const ustring &str + ); + /*! + requires + - str is a valid UTF-32 encoded string + ensures + - converts str into wstring whose encoding is UTF-16 when sizeof(wchar_t) == 2 + - converts str into wstring whose encoding is UTF-32 when sizeof(wchar_t) == 4 + !*/ + +// ---------------------------------------------------------------------------------------- + + const std::wstring convert_mbstring_to_wstring ( + const std::string &str + ); + /*! + requires + - str is a valid multibyte string whose encoding is same as current locale setting + ensures + - converts str into wstring whose encoding is UTF-16 when sizeof(wchar_t) == 2 + - converts str into wstring whose encoding is UTF-32 when sizeof(wchar_t) == 4 + !*/ + +// ---------------------------------------------------------------------------------------- + + const std::string convert_wstring_to_mbstring ( + const std::wstring &src + ); + /*! + requires + - str is a valid wide character string string whose encoding is same as current + locale setting + ensures + - returns a multibyte encoded version of the given string + !*/ + +// ---------------------------------------------------------------------------------------- + + template < + typename charT + > + class basic_utf8_ifstream : public std::basic_istream + { + /*! + WHAT THIS OBJECT REPRESENTS + This object represents an input file stream much like the + normal std::ifstream except that it knows how to read UTF-8 + data. So when you read characters out of this stream it will + automatically convert them from the UTF-8 multibyte encoding + into a fixed width wide character encoding. + !*/ + + public: + + basic_utf8_ifstream ( + ); + /*! + ensures + - constructs an input stream that isn't yet associated with + a file. + !*/ + + basic_utf8_ifstream ( + const char* file_name, + std::ios_base::openmode mode = std::ios::in + ); + /*! + ensures + - tries to open the given file for reading by this stream + - mode is interpreted exactly the same was as the open mode + argument used by std::ifstream. + !*/ + + basic_utf8_ifstream ( + const std::string& file_name, + std::ios_base::openmode mode = std::ios::in + ); + /*! + ensures + - tries to open the given file for reading by this stream + - mode is interpreted exactly the same was as the open mode + argument used by std::ifstream. + !*/ + + void open( + const std::string& file_name, + std::ios_base::openmode mode = std::ios::in + ); + /*! + ensures + - tries to open the given file for reading by this stream + - mode is interpreted exactly the same was as the open mode + argument used by std::ifstream. + !*/ + + void open ( + const char* file_name, + std::ios_base::openmode mode = std::ios::in + ); + /*! + ensures + - tries to open the given file for reading by this stream + - mode is interpreted exactly the same was as the open mode + argument used by std::ifstream. + !*/ + + void close ( + ); + /*! + ensures + - any file opened by this stream has been closed + !*/ + }; + + typedef basic_utf8_ifstream utf8_uifstream; + typedef basic_utf8_ifstream utf8_wifstream; + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_UNICODe_ABSTRACT_H_ + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/unordered_pair.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/unordered_pair.h new file mode 100644 index 0000000..9ea75b9 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/unordered_pair.h @@ -0,0 +1,176 @@ +// Copyright (C) 2010 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_UNORDERED_PAiR_Hh_ +#define DLIB_UNORDERED_PAiR_Hh_ + +#include "serialize.h" + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + template < + typename T + > + struct unordered_pair + { + /*! + REQUIREMENTS ON T + T must be default constructable, copyable, and comparable using + operator < and == + + WHAT THIS OBJECT REPRESENTS + This object is very similar to the std::pair struct except unordered_pair + is only capable of representing an unordered set of two items rather than + an ordered list of two items like std::pair. + + This is best illustrated by example. Suppose we have the following + five variables: + std::pair p1(1, 5), p2(5,1); + unordered_pair up1(1,5), up2(5,1), up3(6,7); + + Then it is the case that: + up1 == up2 + up1 != up3 + p1 != p2 + + So the unordered_pair doesn't care about the order of the arguments. + In this case, up1 and up2 are both equivalent. + + !*/ + + typedef T type; + typedef T first_type; + typedef T second_type; + + const T first; + const T second; + + unordered_pair() : first(), second() + /*! + ensures + - #first and #second are default initialized + !*/ {} + + unordered_pair( + const T& a, + const T& b + ) : + first( a < b ? a : b), + second(a < b ? b : a) + /*! + ensures + - #first <= #second + - #first and #second contain copies of the items a and b. + !*/ {} + + template + unordered_pair ( + const unordered_pair & p + ) : + first(p.first), + second(p.second) + /*! + ensures + - #*this is a copy of p + !*/ {} + + unordered_pair& operator= ( + const unordered_pair& item + ) + /*! + ensures + - #*this == item + !*/ + { + const_cast(first) = item.first; + const_cast(second) = item.second; + return *this; + } + }; + +// ---------------------------------------------------------------------------------------- + + template + bool operator==(const unordered_pair& a, const unordered_pair & b) + { + return a.first == b.first && a.second == b.second; + } + + template + bool operator!=(const unordered_pair& a, const unordered_pair & b) + { + return !(a == b); + } + + template + bool operator<(const unordered_pair& a, const unordered_pair& b) + { + return (a.first < b.first || (!(b.first < a.first) && a.second < b.second)); + } + + template + bool operator>(const unordered_pair& a, const unordered_pair & b) + { + return b < a; + } + + template + bool operator<=(const unordered_pair& a, const unordered_pair & b) + { + return !(b < a); + } + + template + bool operator>=(const unordered_pair& a, const unordered_pair & b) + { + return !(a < b); + } + + template + unordered_pair make_unordered_pair (const T& a, const T& b) + { + return unordered_pair(a,b); + } + +// ---------------------------------------------------------------------------------------- + + template + void serialize ( + const unordered_pair& item, + std::ostream& out + ) + { + try + { + serialize(item.first,out); + serialize(item.second,out); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing object of type unordered_pair"); } + } + + template + void deserialize ( + unordered_pair& item, + std::istream& in + ) + { + try + { + T a, b; + deserialize(a,in); + deserialize(b,in); + item = make_unordered_pair(a,b); + } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing object of type unordered_pair"); } + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_UNORDERED_PAiR_Hh_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/vectorstream.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/vectorstream.h new file mode 100644 index 0000000..afeb247 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/vectorstream.h @@ -0,0 +1,11 @@ +// Copyright (C) 2012 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_VECTORSTReAMh_ +#define DLIB_VECTORSTReAMh_ + +#include "vectorstream/vectorstream.h" +#include "vectorstream/unserialize.h" + + +#endif // DLIB_VECTORSTReAMh_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/vectorstream/unserialize.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/vectorstream/unserialize.h new file mode 100644 index 0000000..dbfe558 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/vectorstream/unserialize.h @@ -0,0 +1,98 @@ +// Copyright (C) 2016 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_uNSERIALIZE_Hh_ +#define DLIB_uNSERIALIZE_Hh_ + +#include "unserialize_abstract.h" + +#include "../serialize.h" +#include "../algs.h" +#include "vectorstream.h" + + + +namespace dlib +{ + class unserialize : public std::istream + { + class mystreambuf : public std::streambuf + { + typedef std::vector::size_type size_type; + size_type read_pos; // buffer[read_pos] == next byte to read from buffer + public: + std::vector buffer; + std::istream& str; + + template + mystreambuf( + const T& item, + std::istream& str_ + ) : + read_pos(0), + str(str_) + { + // put the item into our buffer. + vectorstream vstr(buffer); + serialize(item, vstr); + } + + + // ------------------------ INPUT FUNCTIONS ------------------------ + + int_type underflow( + ) + { + if (read_pos < buffer.size()) + return static_cast(buffer[read_pos]); + else + return str.peek(); + } + + int_type uflow( + ) + { + if (read_pos < buffer.size()) + return static_cast(buffer[read_pos++]); + else + return str.get(); + } + + std::streamsize xsgetn ( + char* s, + std::streamsize n + ) + { + if (read_pos < buffer.size()) + { + const size_type num = std::min(n, buffer.size()-read_pos); + std::memcpy(s, &buffer[read_pos], num); + read_pos += num; + return num; + } + else + { + return str.rdbuf()->sgetn(s,n); + } + return 0; + } + + }; + + public: + + template + unserialize ( + const T& item, + std::istream& str + ) : + std::istream(&buf), + buf(item, str) + {} + + private: + mystreambuf buf; + }; +} + +#endif // DLIB_uNSERIALIZE_Hh_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/vectorstream/unserialize_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/vectorstream/unserialize_abstract.h new file mode 100644 index 0000000..b7d6783 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/vectorstream/unserialize_abstract.h @@ -0,0 +1,58 @@ +// Copyright (C) 2016 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_uNSERIALIZE_ABSTRACT_Hh_ +#ifdef DLIB_uNSERIALIZE_ABSTRACT_Hh_ + +#include "../serialize.h" +#include + +namespace dlib +{ + class unserialize : public std::istream + { + /*! + WHAT THIS OBJECT REPRESENTS + This is a tool that allows you to effectively put an object you just + deserialized from a stream back into the stream. Its use is best + illustrated via an example. + + void example(std::istream& in) + { + // Suppose that in contains serialized copies of three "some_type" + // objects. You could read them as follows: + some_type obj1, obj2, obj3; + + deserialize(obj1, in); // reads obj1 from stream. + deserialize(obj2, in); // reads obj2 from stream. + + unserialize in2(obj2, in); // make the in2 stream that has obj2 at its front. + deserialize(obj2, in2); // reads obj2 from stream again. + deserialize(obj3, in2); // reads obj3 from stream. + } + + The reason unserialize is useful is because it allows you to peek at the + next object in a stream and potentially do something different based on + what object is coming next, but still allowing subsequent deserialize() + statements to be undisturbed by the fact that you peeked at the data. + !*/ + + public: + + template + unserialize ( + const T& item, + std::istream& in + ); + /*! + requires + - T must be serializable + ensures + - The bytes in this stream begin with a serialized copy of item followed + immediately by the bytes in the given istream. + !*/ + }; +} + +#endif // DLIB_uNSERIALIZE_ABSTRACT_Hh_ + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/vectorstream/vectorstream.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/vectorstream/vectorstream.h new file mode 100644 index 0000000..2b6e2e0 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/vectorstream/vectorstream.h @@ -0,0 +1,159 @@ +// Copyright (C) 2012 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_VECTORStREAM_Hh_ +#define DLIB_VECTORStREAM_Hh_ + +#include "vectorstream_abstract.h" + +#include +#include +#include +#include +#include +#include "../algs.h" +#include "../assert.h" + +#ifdef _MSC_VER +// Disable the warning about inheriting from std::iostream 'via dominance' since this warning is a warning about +// visual studio conforming to the standard and is ignorable. See http://connect.microsoft.com/VisualStudio/feedback/details/733720/inheriting-from-std-fstream-produces-c4250-warning +// for further details if interested. +#pragma warning(disable : 4250) +#endif // _MSC_VER + +namespace dlib +{ + class vectorstream : public std::iostream + { + class vector_streambuf : public std::streambuf + { + typedef std::vector::size_type size_type; + size_type read_pos; // buffer[read_pos] == next byte to read from buffer + public: + std::vector& buffer; + + vector_streambuf( + std::vector& buffer_ + ) : + read_pos(0), + buffer(buffer_) + {} + + + void seekg(size_type pos) + { + read_pos = pos; + } + + pos_type seekpos(pos_type pos, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) + { + return seekoff(pos - pos_type(off_type(0)), std::ios_base::beg, mode); + } + + pos_type seekoff(off_type off, std::ios_base::seekdir dir, + std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out ) + { + DLIB_CASSERT(mode == std::ios_base::in, "vectorstream does not support std::ios_base::out"); + switch (dir) + { + case std::ios_base::beg: + read_pos = off; + break; + case std::ios_base::cur: + read_pos += off; + break; + case std::ios_base::end: + read_pos = buffer.size() + off; + break; + default: + break; + } + return pos_type(read_pos); + } + + // ------------------------ OUTPUT FUNCTIONS ------------------------ + + int_type overflow ( int_type c) + { + if (c != EOF) buffer.push_back(static_cast(c)); + return c; + } + + std::streamsize xsputn ( const char* s, std::streamsize num) + { + buffer.insert(buffer.end(), s, s+num); + return num; + } + + // ------------------------ INPUT FUNCTIONS ------------------------ + + int_type underflow( + ) + { + if (read_pos < buffer.size()) + return static_cast(buffer[read_pos]); + else + return EOF; + } + + int_type uflow( + ) + { + if (read_pos < buffer.size()) + return static_cast(buffer[read_pos++]); + else + return EOF; + } + + int_type pbackfail( + int_type c + ) + { + // if they are trying to push back a character that they didn't read last + // that is an error + const unsigned long prev = read_pos-1; + if (c != EOF && prev < buffer.size() && + c != static_cast(buffer[prev])) + { + return EOF; + } + + read_pos = prev; + return 1; + } + + std::streamsize xsgetn ( + char* s, + std::streamsize n + ) + { + if (read_pos < buffer.size()) + { + const size_type num = std::min(n, buffer.size()-read_pos); + std::memcpy(s, &buffer[read_pos], num); + read_pos += num; + return num; + } + return 0; + } + + }; + + public: + + vectorstream ( + std::vector& buffer + ) : + std::iostream(&buf), + buf(buffer) + {} + + vectorstream(const vectorstream& ori) = delete; + vectorstream(vectorstream&& item) = delete; + + private: + vector_streambuf buf; + }; +} + +#endif // DLIB_VECTORStREAM_Hh_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/vectorstream/vectorstream_abstract.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/vectorstream/vectorstream_abstract.h new file mode 100644 index 0000000..f5fe100 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/vectorstream/vectorstream_abstract.h @@ -0,0 +1,62 @@ +// Copyright (C) 2012 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#undef DLIB_VECTORStREAM_ABSTRACT_Hh_ +#ifdef DLIB_VECTORStREAM_ABSTRACT_Hh_ + +#include +#include + +namespace dlib +{ + class vectorstream : public std::iostream + { + /*! + WHAT THIS OBJECT REPRESENTS + This is an iostream object that reads and writes from an in-memory buffer. + It functions very much the same way as the std::stringstream object. + However, while the std::stringstream holds its buffer internally and it can + only be accessed by copying it out, the vectorstream uses an external + std::vector as its buffer. That is, it holds a reference to an + external vector and does not contain any internal buffers of its own. + + This object is useful as a slightly more efficient alternative to the + std::stringstream since you can avoid the overhead of copying buffer + contents to and from the stream. This is particularly useful when used as + a source or target for serialization routines. + !*/ + + public: + + vectorstream ( + std::vector& buffer + ); + /*! + ensures + - This object will use the given vector as its read/write buffer. That is: + - Any data written to this stream will be appended to the given buffer + - Any data read from this stream is read from the given buffer, + starting with buffer[0], then buffer[1], and so on. Just like + std::stringstream, writes to the stream do not move the position of + the next byte that will be read from the buffer. + - This constructor does not copy the buffer. Only a reference to it will + be used. Therefore, any time data is written to this stream it will + immediately show up in the buffer. + !*/ + + std::istream& seekg ( + std::streampos pos + ); + /*! + ensures + - The next read from this object will read from the position buffer[pos], + where buffer is the std::vector given to this object's constructor. Note + that if pos >= buffer.size() then the next read will simply return EOF. + - returns *this + !*/ + + }; +} + +#endif // DLIB_VECTORStREAM_ABSTRACT_Hh_ + + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/windows_magic.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/windows_magic.h new file mode 100644 index 0000000..cfb7f22 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlib/windows_magic.h @@ -0,0 +1,50 @@ +// Copyright (C) 2006 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_WINDOWS_MAGIc_ +#define DLIB_WINDOWS_MAGIc_ + +#include "platform.h" + +#ifdef WIN32 + +// This file contains all the magical #defines you have to setup before you +// include the windows header files. + +#ifndef NOMINMAX +#define NOMINMAX // prevent windows from messing with std::min and std::max +#endif + +// Prevent windows from #defining IN or OUT +#ifndef _NO_W32_PSEUDO_MODIFIERS +#define _NO_W32_PSEUDO_MODIFIERS +#endif + +// now just for good measure undefine min and max if they are defined +#ifdef min +#undef min +#endif + +#ifdef max +#undef max +#endif + +#ifdef NO_MAKEFILE +// only define this if all the cpp files are going to be sucked into the headers +// because otherwise we don't need it since everything is isolated in the sockets +// cpp file and this declaration for _WINSOCKAPI_ appears there also. +#ifndef _WINSOCKAPI_ +#define _WINSOCKAPI_ /* Prevent inclusion of winsock.h in windows.h */ +#endif +#endif + +// This is something stupid you have to do to make visual studio include the right +// stuff. I don't really know what the deal is with this. +#if _WIN32_WINNT < 0x0500 +#undef _WIN32_WINNT +#define _WIN32_WINNT 0x0500 +#endif + +#endif // WIN32 + +#endif // DLIB_WINDOWS_MAGIc_ + diff --git a/include/icsneo/third-party/concurrentqueue/benchmarks/dlibqueue.h b/include/icsneo/third-party/concurrentqueue/benchmarks/dlibqueue.h new file mode 100644 index 0000000..ba58aa8 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/benchmarks/dlibqueue.h @@ -0,0 +1,39 @@ +#pragma once + +#include +#include "dlib/pipe.h" +#include "wrappers.h" + +template +struct DlibQueueWrapper +{ +public: + typedef DummyToken producer_token_t; + typedef DummyToken consumer_token_t; + +public: + DlibQueueWrapper() : q(1024*1024*1024) { } + + template + inline bool enqueue(U&& item) + { + return q.enqueue(std::forward(item)); + } + + inline bool try_dequeue(T& item) + { + return q.dequeue_or_timeout(item, 0); + } + + // Dummy token methods (not used) + bool enqueue(producer_token_t const&, T const&) { return false; } + bool try_enqueue(producer_token_t, T const&) { return false; } + bool try_dequeue(consumer_token_t, T& item) { return false; } + template bool enqueue_bulk(It, size_t) { return false; } + template bool enqueue_bulk(producer_token_t const&, It, size_t) { return false; } + template size_t try_dequeue_bulk(It, size_t) { return 0; } + template size_t try_dequeue_bulk(consumer_token_t, It, size_t) { return 0; } + +private: + dlib::pipe q; +}; diff --git a/include/icsneo/third-party/concurrentqueue/blockingconcurrentqueue.h b/include/icsneo/third-party/concurrentqueue/blockingconcurrentqueue.h index 9b71339..205a4db 100644 --- a/include/icsneo/third-party/concurrentqueue/blockingconcurrentqueue.h +++ b/include/icsneo/third-party/concurrentqueue/blockingconcurrentqueue.h @@ -56,7 +56,7 @@ public: // includes making the memory effects of construction visible, possibly with a // memory barrier). explicit BlockingConcurrentQueue(size_t capacity = 6 * BLOCK_SIZE) - : inner(capacity), sema(create(0, (int)Traits::MAX_SEMA_SPINS), &BlockingConcurrentQueue::template destroy) + : inner(capacity), sema(create(0, (int)Traits::MAX_SEMA_SPINS), &BlockingConcurrentQueue::template destroy) { assert(reinterpret_cast((BlockingConcurrentQueue*)1) == &((BlockingConcurrentQueue*)1)->inner && "BlockingConcurrentQueue must have ConcurrentQueue as its first member"); if (!sema) { @@ -65,7 +65,7 @@ public: } BlockingConcurrentQueue(size_t minCapacity, size_t maxExplicitProducers, size_t maxImplicitProducers) - : inner(minCapacity, maxExplicitProducers, maxImplicitProducers), sema(create(0, (int)Traits::MAX_SEMA_SPINS), &BlockingConcurrentQueue::template destroy) + : inner(minCapacity, maxExplicitProducers, maxImplicitProducers), sema(create(0, (int)Traits::MAX_SEMA_SPINS), &BlockingConcurrentQueue::template destroy) { assert(reinterpret_cast((BlockingConcurrentQueue*)1) == &((BlockingConcurrentQueue*)1)->inner && "BlockingConcurrentQueue must have ConcurrentQueue as its first member"); if (!sema) { @@ -544,7 +544,7 @@ public: // Returns true if the underlying atomic variables used by // the queue are lock-free (they should be on most platforms). // Thread-safe. - static bool is_lock_free() + static constexpr bool is_lock_free() { return ConcurrentQueue::is_lock_free(); } diff --git a/include/icsneo/third-party/concurrentqueue/c_api/blockingconcurrentqueue.cpp b/include/icsneo/third-party/concurrentqueue/c_api/blockingconcurrentqueue.cpp new file mode 100644 index 0000000..a27e60e --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/c_api/blockingconcurrentqueue.cpp @@ -0,0 +1,40 @@ +#include "concurrentqueue.h" +#include "../blockingconcurrentqueue.h" + +typedef moodycamel::BlockingConcurrentQueue MoodycamelBCQType, *MoodycamelBCQPtr; + +extern "C" { + +int moodycamel_bcq_create(MoodycamelBCQHandle* handle) +{ + MoodycamelBCQPtr retval = new MoodycamelBCQType; + if (retval == nullptr) { + return 0; + } + *handle = retval; + return 1; +} + +int moodycamel_bcq_destroy(MoodycamelBCQHandle handle) +{ + delete reinterpret_cast(handle); + return 1; +} + +int moodycamel_bcq_enqueue(MoodycamelBCQHandle handle, MoodycamelValue value) +{ + return reinterpret_cast(handle)->enqueue(value) ? 1 : 0; +} + +int moodycamel_bcq_wait_dequeue(MoodycamelBCQHandle handle, MoodycamelValue* value) +{ + reinterpret_cast(handle)->wait_dequeue(*value); + return 1; +} + +int moodycamel_bcq_try_dequeue(MoodycamelBCQHandle handle, MoodycamelValue* value) +{ + return reinterpret_cast(handle)->try_dequeue(*value) ? 1 : 0; +} + +} \ No newline at end of file diff --git a/include/icsneo/third-party/concurrentqueue/c_api/concurrentqueue.cpp b/include/icsneo/third-party/concurrentqueue/c_api/concurrentqueue.cpp new file mode 100644 index 0000000..4947344 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/c_api/concurrentqueue.cpp @@ -0,0 +1,39 @@ +#include "concurrentqueue.h" +#include "../concurrentqueue.h" + +typedef moodycamel::ConcurrentQueue MoodycamelCQType, *MoodycamelCQPtr; + +extern "C" { + +int moodycamel_cq_create(MoodycamelCQHandle* handle) +{ + MoodycamelCQPtr retval = new MoodycamelCQType; + if (retval == nullptr) { + return 0; + } + *handle = retval; + return 1; +} + +int moodycamel_cq_destroy(MoodycamelCQHandle handle) +{ + delete reinterpret_cast(handle); + return 1; +} + +int moodycamel_cq_enqueue(MoodycamelCQHandle handle, MoodycamelValue value) +{ + return reinterpret_cast(handle)->enqueue(value) ? 1 : 0; +} + +int moodycamel_cq_try_dequeue(MoodycamelCQHandle handle, MoodycamelValue* value) +{ + return reinterpret_cast(handle)->try_dequeue(*value) ? 1 : 0; +} + +size_t moodycamel_cq_size_approx(MoodycamelCQHandle handle) +{ + return reinterpret_cast(handle)->size_approx(); +} + +} diff --git a/include/icsneo/third-party/concurrentqueue/c_api/concurrentqueue.h b/include/icsneo/third-party/concurrentqueue/c_api/concurrentqueue.h new file mode 100644 index 0000000..27822d0 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/c_api/concurrentqueue.h @@ -0,0 +1,41 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef MOODYCAMEL_EXPORT +#ifdef _WIN32 +#if defined(MOODYCAMEL_STATIC) //preferred way +#define MOODYCAMEL_EXPORT +#elif defined(DLL_EXPORT) +#define MOODYCAMEL_EXPORT __declspec(dllexport) +#else +#define MOODYCAMEL_EXPORT __declspec(dllimport) +#endif +#else +#define MOODYCAMEL_EXPORT +#endif +#endif + +typedef void* MoodycamelCQHandle; +typedef void* MoodycamelBCQHandle; +typedef void* MoodycamelValue; + +MOODYCAMEL_EXPORT int moodycamel_cq_create(MoodycamelCQHandle* handle); +MOODYCAMEL_EXPORT int moodycamel_cq_destroy(MoodycamelCQHandle handle); +MOODYCAMEL_EXPORT int moodycamel_cq_enqueue(MoodycamelCQHandle handle, MoodycamelValue value); +MOODYCAMEL_EXPORT int moodycamel_cq_try_dequeue(MoodycamelCQHandle handle, MoodycamelValue* value); +MOODYCAMEL_EXPORT size_t moodycamel_cq_size_approx(MoodycamelCQHandle handle); + +MOODYCAMEL_EXPORT int moodycamel_bcq_create(MoodycamelBCQHandle* handle); +MOODYCAMEL_EXPORT int moodycamel_bcq_destroy(MoodycamelBCQHandle handle); +MOODYCAMEL_EXPORT int moodycamel_bcq_enqueue(MoodycamelBCQHandle handle, MoodycamelValue value); +MOODYCAMEL_EXPORT int moodycamel_bcq_wait_dequeue(MoodycamelBCQHandle handle, MoodycamelValue* value); +MOODYCAMEL_EXPORT int moodycamel_bcq_try_dequeue(MoodycamelBCQHandle handle, MoodycamelValue* value); + +#ifdef __cplusplus +} +#endif diff --git a/include/icsneo/third-party/concurrentqueue/concurrentqueue.h b/include/icsneo/third-party/concurrentqueue/concurrentqueue.h index 830b819..4b2ad79 100644 --- a/include/icsneo/third-party/concurrentqueue/concurrentqueue.h +++ b/include/icsneo/third-party/concurrentqueue/concurrentqueue.h @@ -31,7 +31,7 @@ #pragma once -#if defined(__GNUC__) +#if defined(__GNUC__) && !defined(__INTEL_COMPILER) // Disable -Wconversion warnings (spuriously triggered when Traits::size_t and // Traits::index_t are set to < 32 bits, causing integer promotion, causing warnings // upon assigning any computed values) @@ -77,6 +77,7 @@ #include // for CHAR_BIT #include #include // partly for __WINPTHREADS_VERSION if on MinGW-w64 w/ POSIX threading +#include // used for thread exit synchronization // Platform-specific definitions of a numeric thread ID type and an invalid value namespace moodycamel { namespace details { @@ -104,7 +105,7 @@ namespace moodycamel { namespace details { static const thread_id_t invalid_thread_id2 = 0xFFFFFFFFU; // Not technically guaranteed to be invalid, but is never used in practice. Note that all Win32 thread IDs are presently multiples of 4. static inline thread_id_t thread_id() { return static_cast(::GetCurrentThreadId()); } } } -#elif defined(__arm__) || defined(_M_ARM) || defined(__aarch64__) || (defined(__APPLE__) && TARGET_OS_IPHONE) +#elif defined(__arm__) || defined(_M_ARM) || defined(__aarch64__) || (defined(__APPLE__) && TARGET_OS_IPHONE) || defined(MOODYCAMEL_NO_THREAD_LOCAL) namespace moodycamel { namespace details { static_assert(sizeof(std::thread::id) == 4 || sizeof(std::thread::id) == 8, "std::thread::id is expected to be either 4 or 8 bytes"); @@ -218,7 +219,7 @@ namespace moodycamel { namespace details { // Finally, iOS/ARM doesn't have support for it either, and g++/ARM allows it to compile but it's unconfirmed to actually work #if (!defined(_MSC_VER) || _MSC_VER >= 1900) && (!defined(__MINGW32__) && !defined(__MINGW64__) || !defined(__WINPTHREADS_VERSION)) && (!defined(__GNUC__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) && (!defined(__APPLE__) || !TARGET_OS_IPHONE) && !defined(__arm__) && !defined(_M_ARM) && !defined(__aarch64__) // Assume `thread_local` is fully supported in all other C++11 compilers/platforms -//#define MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED // always disabled for now since several users report having problems with it on +#define MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED // tentatively enabled for now; years ago several users report having problems with it on #endif #endif #endif @@ -378,7 +379,14 @@ struct ConcurrentQueueDefaultTraits // consumer threads exceeds the number of idle cores (in which case try 0-100). // Only affects instances of the BlockingConcurrentQueue. static const int MAX_SEMA_SPINS = 10000; - + + // Whether to recycle dynamically-allocated blocks into an internal free list or + // not. If false, only pre-allocated blocks (controlled by the constructor + // arguments) will be recycled, and all others will be `free`d back to the heap. + // Note that blocks consumed by explicit producers are only freed on destruction + // of the queue (not following destruction of the token) regardless of this trait. + static const bool RECYCLE_ALLOCATED_BLOCKS = false; + #ifndef MCDBGQ_USE_RELACY // Memory allocation can be customized if needed. @@ -468,15 +476,10 @@ namespace details template static inline bool circular_less_than(T a, T b) { -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable: 4554) -#endif static_assert(std::is_integral::value && !std::numeric_limits::is_signed, "circular_less_than is intended to be used only with unsigned integer types"); - return static_cast(a - b) > static_cast(static_cast(1) << static_cast(sizeof(T) * CHAR_BIT - 1)); -#ifdef _MSC_VER -#pragma warning(pop) -#endif + return static_cast(a - b) > static_cast(static_cast(1) << (static_cast(sizeof(T) * CHAR_BIT - 1))); + // Note: extra parens around rhs of operator<< is MSVC bug: https://developercommunity2.visualstudio.com/t/C4554-triggers-when-both-lhs-and-rhs-is/10034931 + // silencing the bug requires #pragma warning(disable: 4554) around the calling code and has no effect when done here. } template @@ -555,6 +558,8 @@ namespace details typedef RelacyThreadExitListener ThreadExitListener; typedef RelacyThreadExitNotifier ThreadExitNotifier; #else + class ThreadExitNotifier; + struct ThreadExitListener { typedef void (*callback_t)(void*); @@ -562,22 +567,29 @@ namespace details void* userData; ThreadExitListener* next; // reserved for use by the ThreadExitNotifier + ThreadExitNotifier* chain; // reserved for use by the ThreadExitNotifier }; - - + class ThreadExitNotifier { public: static void subscribe(ThreadExitListener* listener) { auto& tlsInst = instance(); + std::lock_guard guard(mutex()); listener->next = tlsInst.tail; + listener->chain = &tlsInst; tlsInst.tail = listener; } static void unsubscribe(ThreadExitListener* listener) { - auto& tlsInst = instance(); + std::lock_guard guard(mutex()); + if (!listener->chain) { + return; // race with ~ThreadExitNotifier + } + auto& tlsInst = *listener->chain; + listener->chain = nullptr; ThreadExitListener** prev = &tlsInst.tail; for (auto ptr = tlsInst.tail; ptr != nullptr; ptr = ptr->next) { if (ptr == listener) { @@ -597,7 +609,9 @@ namespace details { // This thread is about to exit, let everyone know! assert(this == &instance() && "If this assert fails, you likely have a buggy compiler! Change the preprocessor conditions such that MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED is no longer defined."); + std::lock_guard guard(mutex()); for (auto ptr = tail; ptr != nullptr; ptr = ptr->next) { + ptr->chain = nullptr; ptr->callback(ptr->userData); } } @@ -608,6 +622,13 @@ namespace details static thread_local ThreadExitNotifier notifier; return notifier; } + + static inline std::mutex& mutex() + { + // Must be static because the ThreadExitNotifier could be destroyed while unsubscribe is called + static std::mutex mutex; + return mutex; + } private: ThreadExitListener* tail; @@ -789,7 +810,7 @@ public: // queue is fully constructed before it starts being used by other threads (this // includes making the memory effects of construction visible, possibly with a // memory barrier). - explicit ConcurrentQueue(size_t capacity = 6 * BLOCK_SIZE) + explicit ConcurrentQueue(size_t capacity = 32 * BLOCK_SIZE) : producerListTail(nullptr), producerCount(0), initialBlockPoolIndex(0), @@ -1314,7 +1335,7 @@ public: // Returns true if the underlying atomic variables used by // the queue are lock-free (they should be on most platforms). // Thread-safe. - static bool is_lock_free() + static constexpr bool is_lock_free() { return details::static_is_lock_free::value == 2 && @@ -1538,7 +1559,7 @@ private: struct Block { Block() - : next(nullptr), elementsCompletelyDequeued(0), freeListRefs(0), freeListNext(nullptr), shouldBeOnFreeList(false), dynamicallyAllocated(true) + : next(nullptr), elementsCompletelyDequeued(0), freeListRefs(0), freeListNext(nullptr), dynamicallyAllocated(true) { #ifdef MCDBGQ_TRACKMEM owner = nullptr; @@ -1655,7 +1676,6 @@ private: public: std::atomic freeListRefs; std::atomic freeListNext; - std::atomic shouldBeOnFreeList; bool dynamicallyAllocated; // Perhaps a better name for this would be 'isNotPartOfInitialBlockPool' #ifdef MCDBGQ_TRACKMEM @@ -1688,7 +1708,7 @@ private: { } - virtual ~ProducerBase() { }; + virtual ~ProducerBase() { } template inline bool dequeue(U& element) @@ -1810,12 +1830,7 @@ private: auto block = this->tailBlock; do { auto nextBlock = block->next; - if (block->dynamicallyAllocated) { - destroy(block); - } - else { - this->parent->add_block_to_free_list(block); - } + this->parent->add_block_to_free_list(block); block = nextBlock; } while (block != this->tailBlock); } @@ -1897,7 +1912,7 @@ private: ++pr_blockIndexSlotsUsed; } - MOODYCAMEL_CONSTEXPR_IF (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new ((T*)nullptr) T(std::forward(element)))) { + MOODYCAMEL_CONSTEXPR_IF (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new (static_cast(nullptr)) T(std::forward(element)))) { // The constructor may throw. We want the element not to appear in the queue in // that case (without corrupting the queue): MOODYCAMEL_TRY { @@ -1923,7 +1938,7 @@ private: blockIndex.load(std::memory_order_relaxed)->front.store(pr_blockIndexFront, std::memory_order_release); pr_blockIndexFront = (pr_blockIndexFront + 1) & (pr_blockIndexSize - 1); - MOODYCAMEL_CONSTEXPR_IF (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new ((T*)nullptr) T(std::forward(element)))) { + MOODYCAMEL_CONSTEXPR_IF (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new (static_cast(nullptr)) T(std::forward(element)))) { this->tailIndex.store(newTailIndex, std::memory_order_release); return true; } @@ -1998,7 +2013,7 @@ private: // block size (in order to get a correct signed block count offset in all cases): auto headBase = localBlockIndex->entries[localBlockIndexHead].base; auto blockBaseIndex = index & ~static_cast(BLOCK_SIZE - 1); - auto offset = static_cast(static_cast::type>(blockBaseIndex - headBase) / BLOCK_SIZE); + auto offset = static_cast(static_cast::type>(blockBaseIndex - headBase) / static_cast::type>(BLOCK_SIZE)); auto block = localBlockIndex->entries[(localBlockIndexHead + offset) & (localBlockIndex->size - 1)].block; // Dequeue @@ -2139,7 +2154,7 @@ private: block = block->next; } - MOODYCAMEL_CONSTEXPR_IF (MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new ((T*)nullptr) T(details::deref_noexcept(itemFirst)))) { + MOODYCAMEL_CONSTEXPR_IF (MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new (static_cast(nullptr)) T(details::deref_noexcept(itemFirst)))) { blockIndex.load(std::memory_order_relaxed)->front.store((pr_blockIndexFront - 1) & (pr_blockIndexSize - 1), std::memory_order_release); } } @@ -2158,7 +2173,7 @@ private: if (details::circular_less_than(newTailIndex, stopIndex)) { stopIndex = newTailIndex; } - MOODYCAMEL_CONSTEXPR_IF (MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new ((T*)nullptr) T(details::deref_noexcept(itemFirst)))) { + MOODYCAMEL_CONSTEXPR_IF (MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new (static_cast(nullptr)) T(details::deref_noexcept(itemFirst)))) { while (currentTailIndex != stopIndex) { new ((*this->tailBlock)[currentTailIndex++]) T(*itemFirst++); } @@ -2173,7 +2188,7 @@ private: // may only define a (noexcept) move constructor, and so calls to the // cctor will not compile, even if they are in an if branch that will never // be executed - new ((*this->tailBlock)[currentTailIndex]) T(details::nomove_if<(bool)!MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new ((T*)nullptr) T(details::deref_noexcept(itemFirst)))>::eval(*itemFirst)); + new ((*this->tailBlock)[currentTailIndex]) T(details::nomove_if(nullptr)) T(details::deref_noexcept(itemFirst)))>::eval(*itemFirst)); ++currentTailIndex; ++itemFirst; } @@ -2220,7 +2235,7 @@ private: this->tailBlock = this->tailBlock->next; } - MOODYCAMEL_CONSTEXPR_IF (!MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new ((T*)nullptr) T(details::deref_noexcept(itemFirst)))) { + MOODYCAMEL_CONSTEXPR_IF (!MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new (static_cast(nullptr)) T(details::deref_noexcept(itemFirst)))) { if (firstAllocatedBlock != nullptr) blockIndex.load(std::memory_order_relaxed)->front.store((pr_blockIndexFront - 1) & (pr_blockIndexSize - 1), std::memory_order_release); } @@ -2239,7 +2254,7 @@ private: desiredCount = desiredCount < max ? desiredCount : max; std::atomic_thread_fence(std::memory_order_acquire); - auto myDequeueCount = this->dequeueOptimisticCount.fetch_add(desiredCount, std::memory_order_relaxed);; + auto myDequeueCount = this->dequeueOptimisticCount.fetch_add(desiredCount, std::memory_order_relaxed); tail = this->tailIndex.load(std::memory_order_acquire); auto actualCount = static_cast(tail - (myDequeueCount - overcommit)); @@ -2259,7 +2274,7 @@ private: auto headBase = localBlockIndex->entries[localBlockIndexHead].base; auto firstBlockBaseIndex = firstIndex & ~static_cast(BLOCK_SIZE - 1); - auto offset = static_cast(static_cast::type>(firstBlockBaseIndex - headBase) / BLOCK_SIZE); + auto offset = static_cast(static_cast::type>(firstBlockBaseIndex - headBase) / static_cast::type>(BLOCK_SIZE)); auto indexIndex = (localBlockIndexHead + offset) & (localBlockIndex->size - 1); // Iterate the blocks and dequeue @@ -2501,7 +2516,7 @@ private: #endif newBlock->ConcurrentQueue::Block::template reset_empty(); - MOODYCAMEL_CONSTEXPR_IF (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new ((T*)nullptr) T(std::forward(element)))) { + MOODYCAMEL_CONSTEXPR_IF (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new (static_cast(nullptr)) T(std::forward(element)))) { // May throw, try to insert now before we publish the fact that we have this new block MOODYCAMEL_TRY { new ((*newBlock)[currentTailIndex]) T(std::forward(element)); @@ -2519,7 +2534,7 @@ private: this->tailBlock = newBlock; - MOODYCAMEL_CONSTEXPR_IF (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new ((T*)nullptr) T(std::forward(element)))) { + MOODYCAMEL_CONSTEXPR_IF (!MOODYCAMEL_NOEXCEPT_CTOR(T, U, new (static_cast(nullptr)) T(std::forward(element)))) { this->tailIndex.store(newTailIndex, std::memory_order_release); return true; } @@ -2697,7 +2712,7 @@ private: if (details::circular_less_than(newTailIndex, stopIndex)) { stopIndex = newTailIndex; } - MOODYCAMEL_CONSTEXPR_IF (MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new ((T*)nullptr) T(details::deref_noexcept(itemFirst)))) { + MOODYCAMEL_CONSTEXPR_IF (MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new (static_cast(nullptr)) T(details::deref_noexcept(itemFirst)))) { while (currentTailIndex != stopIndex) { new ((*this->tailBlock)[currentTailIndex++]) T(*itemFirst++); } @@ -2705,7 +2720,7 @@ private: else { MOODYCAMEL_TRY { while (currentTailIndex != stopIndex) { - new ((*this->tailBlock)[currentTailIndex]) T(details::nomove_if<(bool)!MOODYCAMEL_NOEXCEPT_CTOR(T, decltype(*itemFirst), new ((T*)nullptr) T(details::deref_noexcept(itemFirst)))>::eval(*itemFirst)); + new ((*this->tailBlock)[currentTailIndex]) T(details::nomove_if(nullptr)) T(details::deref_noexcept(itemFirst)))>::eval(*itemFirst)); ++currentTailIndex; ++itemFirst; } @@ -2906,13 +2921,15 @@ private: else if (!new_block_index()) { return false; } - localBlockIndex = blockIndex.load(std::memory_order_relaxed); - newTail = (localBlockIndex->tail.load(std::memory_order_relaxed) + 1) & (localBlockIndex->capacity - 1); - idxEntry = localBlockIndex->index[newTail]; - assert(idxEntry->key.load(std::memory_order_relaxed) == INVALID_BLOCK_BASE); - idxEntry->key.store(blockStartIndex, std::memory_order_relaxed); - localBlockIndex->tail.store(newTail, std::memory_order_release); - return true; + else { + localBlockIndex = blockIndex.load(std::memory_order_relaxed); + newTail = (localBlockIndex->tail.load(std::memory_order_relaxed) + 1) & (localBlockIndex->capacity - 1); + idxEntry = localBlockIndex->index[newTail]; + assert(idxEntry->key.load(std::memory_order_relaxed) == INVALID_BLOCK_BASE); + idxEntry->key.store(blockStartIndex, std::memory_order_relaxed); + localBlockIndex->tail.store(newTail, std::memory_order_release); + return true; + } } inline void rewind_block_index_tail() @@ -2940,7 +2957,7 @@ private: assert(tailBase != INVALID_BLOCK_BASE); // Note: Must use division instead of shift because the index may wrap around, causing a negative // offset, whose negativity we want to preserve - auto offset = static_cast(static_cast::type>(index - tailBase) / BLOCK_SIZE); + auto offset = static_cast(static_cast::type>(index - tailBase) / static_cast::type>(BLOCK_SIZE)); size_t idx = (tail + offset) & (localBlockIndex->capacity - 1); assert(localBlockIndex->index[idx]->key.load(std::memory_order_relaxed) == index && localBlockIndex->index[idx]->value.load(std::memory_order_relaxed) != nullptr); return idx; @@ -3052,7 +3069,12 @@ private: #ifdef MCDBGQ_TRACKMEM block->owner = nullptr; #endif - freeList.add(block); + if (!Traits::RECYCLE_ALLOCATED_BLOCKS && block->dynamicallyAllocated) { + destroy(block); + } + else { + freeList.add(block); + } } inline void add_blocks_to_free_list(Block* block) @@ -3203,12 +3225,6 @@ private: ////////////////////////////////// ProducerBase* recycle_or_create_producer(bool isExplicit) - { - bool recycled; - return recycle_or_create_producer(isExplicit, recycled); - } - - ProducerBase* recycle_or_create_producer(bool isExplicit, bool& recycled) { #ifdef MCDBGQ_NOLOCKFREE_IMPLICITPRODHASH debug::DebugLock lock(implicitProdMutex); @@ -3219,13 +3235,11 @@ private: bool expected = true; if (ptr->inactive.compare_exchange_strong(expected, /* desired */ false, std::memory_order_acquire, std::memory_order_relaxed)) { // We caught one! It's been marked as activated, the caller can have it - recycled = true; return ptr; } } } - - recycled = false; + return add_producer(isExplicit ? static_cast(create(this)) : create(this)); } @@ -3396,7 +3410,7 @@ private: // Look for the id in this hash auto index = hashedId; while (true) { // Not an infinite loop because at least one slot is free in the hash table - index &= hash->capacity - 1; + index &= hash->capacity - 1u; auto probedKey = hash->entries[index].key.load(std::memory_order_relaxed); if (probedKey == id) { @@ -3409,15 +3423,14 @@ private: if (hash != mainHash) { index = hashedId; while (true) { - index &= mainHash->capacity - 1; - probedKey = mainHash->entries[index].key.load(std::memory_order_relaxed); + index &= mainHash->capacity - 1u; auto empty = details::invalid_thread_id; #ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED auto reusable = details::invalid_thread_id2; - if ((probedKey == empty && mainHash->entries[index].key.compare_exchange_strong(empty, id, std::memory_order_relaxed, std::memory_order_relaxed)) || - (probedKey == reusable && mainHash->entries[index].key.compare_exchange_strong(reusable, id, std::memory_order_acquire, std::memory_order_acquire))) { + if (mainHash->entries[index].key.compare_exchange_strong(empty, id, std::memory_order_seq_cst, std::memory_order_relaxed) || + mainHash->entries[index].key.compare_exchange_strong(reusable, id, std::memory_order_seq_cst, std::memory_order_relaxed)) { #else - if ((probedKey == empty && mainHash->entries[index].key.compare_exchange_strong(empty, id, std::memory_order_relaxed, std::memory_order_relaxed))) { + if (mainHash->entries[index].key.compare_exchange_strong(empty, id, std::memory_order_seq_cst, std::memory_order_relaxed)) { #endif mainHash->entries[index].value = value; break; @@ -3446,7 +3459,7 @@ private: // locked block). mainHash = implicitProducerHash.load(std::memory_order_acquire); if (newCount >= (mainHash->capacity >> 1)) { - auto newCapacity = mainHash->capacity << 1; + size_t newCapacity = mainHash->capacity << 1; while (newCount >= (newCapacity >> 1)) { newCapacity <<= 1; } @@ -3459,7 +3472,7 @@ private: } auto newHash = new (raw) ImplicitProducerHash; - newHash->capacity = (size_t)newCapacity; + newHash->capacity = static_cast(newCapacity); newHash->entries = reinterpret_cast(details::align_for(raw + sizeof(ImplicitProducerHash))); for (size_t i = 0; i != newCapacity; ++i) { new (newHash->entries + i) ImplicitProducerKVP; @@ -3479,15 +3492,11 @@ private: // to finish being allocated by another thread (and if we just finished allocating above, the condition will // always be true) if (newCount < (mainHash->capacity >> 1) + (mainHash->capacity >> 2)) { - bool recycled; - auto producer = static_cast(recycle_or_create_producer(false, recycled)); + auto producer = static_cast(recycle_or_create_producer(false)); if (producer == nullptr) { implicitProducerHashCount.fetch_sub(1, std::memory_order_relaxed); return nullptr; } - if (recycled) { - implicitProducerHashCount.fetch_sub(1, std::memory_order_relaxed); - } #ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED producer->threadExitListener.callback = &ConcurrentQueue::implicit_producer_thread_exited_callback; @@ -3497,17 +3506,17 @@ private: auto index = hashedId; while (true) { - index &= mainHash->capacity - 1; - auto probedKey = mainHash->entries[index].key.load(std::memory_order_relaxed); - + index &= mainHash->capacity - 1u; auto empty = details::invalid_thread_id; #ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED auto reusable = details::invalid_thread_id2; - if ((probedKey == empty && mainHash->entries[index].key.compare_exchange_strong(empty, id, std::memory_order_relaxed, std::memory_order_relaxed)) || - (probedKey == reusable && mainHash->entries[index].key.compare_exchange_strong(reusable, id, std::memory_order_acquire, std::memory_order_acquire))) { -#else - if ((probedKey == empty && mainHash->entries[index].key.compare_exchange_strong(empty, id, std::memory_order_relaxed, std::memory_order_relaxed))) { + if (mainHash->entries[index].key.compare_exchange_strong(reusable, id, std::memory_order_seq_cst, std::memory_order_relaxed)) { + implicitProducerHashCount.fetch_sub(1, std::memory_order_relaxed); // already counted as a used slot + mainHash->entries[index].value = producer; + break; + } #endif + if (mainHash->entries[index].key.compare_exchange_strong(empty, id, std::memory_order_seq_cst, std::memory_order_relaxed)) { mainHash->entries[index].value = producer; break; } @@ -3526,9 +3535,6 @@ private: #ifdef MOODYCAMEL_CPP11_THREAD_LOCAL_SUPPORTED void implicit_producer_thread_exited(ImplicitProducer* producer) { - // Remove from thread exit listeners - details::ThreadExitNotifier::unsubscribe(&producer->threadExitListener); - // Remove from hash #ifdef MCDBGQ_NOLOCKFREE_IMPLICITPRODHASH debug::DebugLock lock(implicitProdMutex); @@ -3544,10 +3550,9 @@ private: for (; hash != nullptr; hash = hash->prev) { auto index = hashedId; do { - index &= hash->capacity - 1; - probedKey = hash->entries[index].key.load(std::memory_order_relaxed); - if (probedKey == id) { - hash->entries[index].key.store(details::invalid_thread_id2, std::memory_order_release); + index &= hash->capacity - 1u; + probedKey = id; + if (hash->entries[index].key.compare_exchange_strong(probedKey, details::invalid_thread_id2, std::memory_order_seq_cst, std::memory_order_relaxed)) { break; } ++index; @@ -3698,7 +3703,7 @@ ConsumerToken::ConsumerToken(ConcurrentQueue& queue) : itemsConsumedFromCurrent(0), currentProducer(nullptr), desiredProducer(nullptr) { initialOffset = queue.nextExplicitConsumerId.fetch_add(1, std::memory_order_release); - lastKnownGlobalOffset = (std::uint32_t)-1; + lastKnownGlobalOffset = static_cast(-1); } template @@ -3706,7 +3711,7 @@ ConsumerToken::ConsumerToken(BlockingConcurrentQueue& queue) : itemsConsumedFromCurrent(0), currentProducer(nullptr), desiredProducer(nullptr) { initialOffset = reinterpret_cast*>(&queue)->nextExplicitConsumerId.fetch_add(1, std::memory_order_release); - lastKnownGlobalOffset = (std::uint32_t)-1; + lastKnownGlobalOffset = static_cast(-1); } template @@ -3737,6 +3742,6 @@ inline void swap(typename ConcurrentQueue::ImplicitProducerKVP& a, ty #pragma warning(pop) #endif -#if defined(__GNUC__) +#if defined(__GNUC__) && !defined(__INTEL_COMPILER) #pragma GCC diagnostic pop #endif diff --git a/include/icsneo/third-party/concurrentqueue/concurrentqueueConfig.cmake.in b/include/icsneo/third-party/concurrentqueue/concurrentqueueConfig.cmake.in new file mode 100644 index 0000000..b8fad19 --- /dev/null +++ b/include/icsneo/third-party/concurrentqueue/concurrentqueueConfig.cmake.in @@ -0,0 +1,3 @@ +@PACKAGE_INIT@ + +include(${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake) diff --git a/include/icsneo/third-party/concurrentqueue/lightweightsemaphore.h b/include/icsneo/third-party/concurrentqueue/lightweightsemaphore.h index 7372f4c..41ba094 100644 --- a/include/icsneo/third-party/concurrentqueue/lightweightsemaphore.h +++ b/include/icsneo/third-party/concurrentqueue/lightweightsemaphore.h @@ -26,6 +26,12 @@ extern "C" { #include #elif defined(__unix__) #include + +#if defined(__GLIBC_PREREQ) && defined(_GNU_SOURCE) +#if __GLIBC_PREREQ(2,30) +#define MOODYCAMEL_LIGHTWEIGHTSEMAPHORE_MONOTONIC +#endif +#endif #endif namespace moodycamel @@ -139,7 +145,7 @@ public: { mach_timespec_t ts; ts.tv_sec = static_cast(timeout_usecs / 1000000); - ts.tv_nsec = (timeout_usecs % 1000000) * 1000; + ts.tv_nsec = static_cast((timeout_usecs % 1000000) * 1000); // added in OSX 10.10: https://developer.apple.com/library/prerelease/mac/documentation/General/Reference/APIDiffsMacOSX10_10SeedDiff/modules/Darwin.html kern_return_t rc = semaphore_timedwait(m_sema, ts); @@ -175,7 +181,7 @@ public: Semaphore(int initialCount = 0) { assert(initialCount >= 0); - int rc = sem_init(&m_sema, 0, initialCount); + int rc = sem_init(&m_sema, 0, static_cast(initialCount)); assert(rc == 0); (void)rc; } @@ -209,7 +215,11 @@ public: struct timespec ts; const int usecs_in_1_sec = 1000000; const int nsecs_in_1_sec = 1000000000; +#ifdef MOODYCAMEL_LIGHTWEIGHTSEMAPHORE_MONOTONIC + clock_gettime(CLOCK_MONOTONIC, &ts); +#else clock_gettime(CLOCK_REALTIME, &ts); +#endif ts.tv_sec += (time_t)(usecs / usecs_in_1_sec); ts.tv_nsec += (long)(usecs % usecs_in_1_sec) * 1000; // sem_timedwait bombs if you have more than 1e9 in tv_nsec @@ -221,7 +231,11 @@ public: int rc; do { +#ifdef MOODYCAMEL_LIGHTWEIGHTSEMAPHORE_MONOTONIC + rc = sem_clockwait(&m_sema, CLOCK_MONOTONIC, &ts); +#else rc = sem_timedwait(&m_sema, &ts); +#endif } while (rc == -1 && errno == EINTR); return rc == 0; } @@ -401,10 +415,10 @@ public: } } - ssize_t availableApprox() const + std::size_t availableApprox() const { ssize_t count = m_count.load(std::memory_order_relaxed); - return count > 0 ? count : 0; + return count > 0 ? static_cast(count) : 0; } }; diff --git a/include/icsneo/third-party/concurrentqueue/samples.md b/include/icsneo/third-party/concurrentqueue/samples.md index cd73c3b..52cf9b7 100644 --- a/include/icsneo/third-party/concurrentqueue/samples.md +++ b/include/icsneo/third-party/concurrentqueue/samples.md @@ -186,7 +186,7 @@ for (int i = 0; i != ProducerCount; ++i) { for (int i = 0; i != ConsumerCount; ++i) { consumers[i] = std::thread([&]() { Item item; - while (promisedElementsRemaining.fetch_sub(1, std::memory_order_relaxed)) { + while (promisedElementsRemaining.fetch_sub(1, std::memory_order_relaxed) > 0) { q.wait_dequeue(item); consumeItem(item); } diff --git a/include/icsneo/third-party/concurrentqueue/tests/unittests/unittests.cpp b/include/icsneo/third-party/concurrentqueue/tests/unittests/unittests.cpp index a83604f..b4c4d9c 100644 --- a/include/icsneo/third-party/concurrentqueue/tests/unittests/unittests.cpp +++ b/include/icsneo/third-party/concurrentqueue/tests/unittests/unittests.cpp @@ -13,6 +13,7 @@ #include #include #include +#include struct MakeSureCustomNewCanPeacefullyCoexist; void* operator new(size_t size, MakeSureCustomNewCanPeacefullyCoexist* x); @@ -30,6 +31,7 @@ void operator delete(void* ptr, MakeSureCustomNewCanPeacefullyCoexist* x); #include "../common/systemtime.h" #include "../../concurrentqueue.h" #include "../../blockingconcurrentqueue.h" +#include "../../c_api/concurrentqueue.h" namespace { struct tracking_allocator @@ -94,7 +96,7 @@ struct MallocTrackingTraits : public ConcurrentQueueDefaultTraits static inline void free(void* ptr) { tracking_allocator::free(ptr); } }; -template +template struct TestTraits : public MallocTrackingTraits { typedef std::size_t size_t; @@ -103,6 +105,7 @@ struct TestTraits : public MallocTrackingTraits static const size_t BLOCK_SIZE = BlockSize; static const size_t EXPLICIT_INITIAL_INDEX_SIZE = InitialIndexSize; static const size_t IMPLICIT_INITIAL_INDEX_SIZE = InitialIndexSize * 2; + static const bool RECYCLE_ALLOCATED_BLOCKS = RecycleBlocks; static inline void reset() { _malloc_count() = 0; _free_count() = 0; } static inline std::atomic& _malloc_count() { static std::atomic c; return c; } @@ -346,6 +349,7 @@ public: REGISTER_TEST(index_wrapping); REGISTER_TEST(subqueue_size_limit); REGISTER_TEST(exceptions); + REGISTER_TEST(implicit_producer_churn); REGISTER_TEST(test_threaded); REGISTER_TEST(test_threaded_bulk); REGISTER_TEST(full_api); @@ -353,6 +357,12 @@ public: REGISTER_TEST(blocking_wrappers); REGISTER_TEST(timed_blocking_wrappers); + //c_api/concurrentqueue + REGISTER_TEST(c_api_create); + REGISTER_TEST(c_api_enqueue); + REGISTER_TEST(c_api_try_dequeue); + REGISTER_TEST(c_api_destroy); + // Semaphore REGISTER_TEST(acquire_and_signal); REGISTER_TEST(try_acquire_and_signal); @@ -984,8 +994,10 @@ public: bool block_alloc() { typedef TestTraits<2> Traits; + typedef TestTraits<2, 32, true> RecycleTraits; Traits::reset(); + // Explicit { ConcurrentQueue q(7); ASSERT_OR_FAIL(q.initialBlockPoolSize == 4); @@ -993,37 +1005,41 @@ public: ASSERT_OR_FAIL(Traits::malloc_count() == 1); ASSERT_OR_FAIL(Traits::free_count() == 0); - ProducerToken tok(q); - ASSERT_OR_FAIL(Traits::malloc_count() == 3); // one for producer, one for its block index - ASSERT_OR_FAIL(Traits::free_count() == 0); - - // Enqueue one item too many (force extra block allocation) - for (int i = 0; i != 9; ++i) { - ASSERT_OR_FAIL(q.enqueue(tok, i)); + { + ProducerToken tok(q); + ASSERT_OR_FAIL(Traits::malloc_count() == 3); // one for producer, one for its block index + ASSERT_OR_FAIL(Traits::free_count() == 0); + + // Enqueue one item too many (force extra block allocation) + for (int i = 0; i != 9; ++i) { + ASSERT_OR_FAIL(q.enqueue(tok, i)); + } + + ASSERT_OR_FAIL(Traits::malloc_count() == 4); + ASSERT_OR_FAIL(Traits::free_count() == 0); + + // Still room for one more... + ASSERT_OR_FAIL(q.enqueue(tok, 9)); + ASSERT_OR_FAIL(Traits::malloc_count() == 4); + ASSERT_OR_FAIL(Traits::free_count() == 0); + + // No more room without further allocations + ASSERT_OR_FAIL(!q.try_enqueue(tok, 10)); + ASSERT_OR_FAIL(Traits::malloc_count() == 4); + ASSERT_OR_FAIL(Traits::free_count() == 0); + + // Check items were enqueued properly + int item; + for (int i = 0; i != 10; ++i) { + ASSERT_OR_FAIL(q.try_dequeue_from_producer(tok, item)); + ASSERT_OR_FAIL(item == i); + } + + // Queue should be empty, but not freed + ASSERT_OR_FAIL(!q.try_dequeue_from_producer(tok, item)); + ASSERT_OR_FAIL(Traits::free_count() == 0); } - - ASSERT_OR_FAIL(Traits::malloc_count() == 4); - ASSERT_OR_FAIL(Traits::free_count() == 0); - - // Still room for one more... - ASSERT_OR_FAIL(q.enqueue(tok, 9)); - ASSERT_OR_FAIL(Traits::malloc_count() == 4); - ASSERT_OR_FAIL(Traits::free_count() == 0); - - // No more room without further allocations - ASSERT_OR_FAIL(!q.try_enqueue(tok, 10)); - ASSERT_OR_FAIL(Traits::malloc_count() == 4); - ASSERT_OR_FAIL(Traits::free_count() == 0); - - // Check items were enqueued properly - int item; - for (int i = 0; i != 10; ++i) { - ASSERT_OR_FAIL(q.try_dequeue_from_producer(tok, item)); - ASSERT_OR_FAIL(item == i); - } - - // Queue should be empty, but not freed - ASSERT_OR_FAIL(!q.try_dequeue_from_producer(tok, item)); + // Explicit producers are recycled, so block should still be allocated ASSERT_OR_FAIL(Traits::free_count() == 0); } @@ -1068,13 +1084,58 @@ public: ASSERT_OR_FAIL(item == i); } - // Queue should be empty, but not freed + // Queue should be empty, and extra block freed ASSERT_OR_FAIL(!q.try_dequeue(item)); - ASSERT_OR_FAIL(Traits::free_count() == 0); + ASSERT_OR_FAIL(Traits::free_count() == 1); } ASSERT_OR_FAIL(Traits::malloc_count() == 4); ASSERT_OR_FAIL(Traits::free_count() == 4); + + // Implicit + RecycleTraits::reset(); + { + ConcurrentQueue q(7); + ASSERT_OR_FAIL(q.initialBlockPoolSize == 4); + + ASSERT_OR_FAIL(q.enqueue(39)); + + ASSERT_OR_FAIL(RecycleTraits::malloc_count() == 3); // one for producer, one for its block index + ASSERT_OR_FAIL(RecycleTraits::free_count() == 0); + + // Enqueue one item too many (force extra block allocation) + for (int i = 0; i != 8; ++i) { + ASSERT_OR_FAIL(q.enqueue(i)); + } + + ASSERT_OR_FAIL(RecycleTraits::malloc_count() == 4); + ASSERT_OR_FAIL(RecycleTraits::free_count() == 0); + + // Still room for one more... + ASSERT_OR_FAIL(q.enqueue(8)); + ASSERT_OR_FAIL(RecycleTraits::malloc_count() == 4); + ASSERT_OR_FAIL(RecycleTraits::free_count() == 0); + + // No more room without further allocations + ASSERT_OR_FAIL(!q.try_enqueue(9)); + ASSERT_OR_FAIL(RecycleTraits::malloc_count() == 4); + ASSERT_OR_FAIL(RecycleTraits::free_count() == 0); + + // Check items were enqueued properly + int item; + ASSERT_OR_FAIL(q.try_dequeue(item)); + ASSERT_OR_FAIL(item == 39); + for (int i = 0; i != 9; ++i) { + ASSERT_OR_FAIL(q.try_dequeue(item)); + ASSERT_OR_FAIL(item == i); + } + + // Queue should be empty, but extra block not freed + ASSERT_OR_FAIL(!q.try_dequeue(item)); + ASSERT_OR_FAIL(RecycleTraits::free_count() == 0); + } + ASSERT_OR_FAIL(RecycleTraits::malloc_count() == 4); + ASSERT_OR_FAIL(RecycleTraits::free_count() == 4); // Super-aligned Traits::reset(); @@ -1118,9 +1179,9 @@ public: ASSERT_OR_FAIL(VeryAligned::errors == 0); } - // Queue should be empty, but not freed + // Queue should be empty, and extra block freed ASSERT_OR_FAIL(!q.try_dequeue(item)); - ASSERT_OR_FAIL(Traits::free_count() == 0); + ASSERT_OR_FAIL(Traits::free_count() == 1); ASSERT_OR_FAIL(VeryAligned::errors == 0); } @@ -3019,6 +3080,29 @@ public: return true; } + + bool implicit_producer_churn() + { + typedef TestTraits<4> Traits; + + for (int i = 0; i != 256; ++i) { + std::vector threads(32); + ConcurrentQueue q; + for (auto& thread : threads) { + thread = SimpleThread([&] { + int x; + for (int j = 0; j != 16; ++j) { + q.enqueue(0); + q.try_dequeue(x); + } + }); + } + for (auto& thread : threads) { + thread.join(); + } + } + return true; + } bool test_threaded() { @@ -3636,9 +3720,9 @@ public: // is_lock_free() { - bool lockFree = ConcurrentQueue::is_lock_free(); + constexpr bool lockFree = ConcurrentQueue::is_lock_free(); #if defined(__amd64__) || defined(_M_X64) || defined(__x86_64__) || defined(_M_IX86) || defined(__i386__) || defined(_M_PPC) || defined(__powerpc__) - ASSERT_OR_FAIL(lockFree); + static_assert(lockFree, "is_lock_free should be true"); #else (void)lockFree; #endif @@ -4389,6 +4473,58 @@ public: return true; } + + bool c_api_create() + { + MoodycamelCQHandle handle; + int rc = moodycamel_cq_create(&handle); + ASSERT_OR_FAIL(rc == 1); + ASSERT_OR_FAIL(handle != nullptr); + moodycamel_cq_destroy(handle); + return true; + } + + bool c_api_enqueue() + { + MoodycamelCQHandle handle; + int rc = moodycamel_cq_create(&handle); + int i = 10; + rc = moodycamel_cq_enqueue(handle, &i); + ASSERT_OR_FAIL(rc == 1); + moodycamel_cq_destroy(handle); + return true; + } + + bool c_api_try_dequeue() + { + MoodycamelCQHandle handle; + int rc = moodycamel_cq_create(&handle); + { + MoodycamelValue n; + rc = moodycamel_cq_try_dequeue(handle, &n); + ASSERT_OR_FAIL(rc == 0); + } + int i = 10; + rc = moodycamel_cq_enqueue(handle, &i); + { + MoodycamelValue value; + rc = moodycamel_cq_try_dequeue(handle, &value); + int n = *reinterpret_cast(value); + ASSERT_OR_FAIL(rc == 1); + ASSERT_OR_FAIL(n == 10); + } + moodycamel_cq_destroy(handle); + return true; + } + + bool c_api_destroy() + { + MoodycamelCQHandle handle; + moodycamel_cq_create(&handle); + moodycamel_cq_destroy(handle); + return true; + } + bool acquire_and_signal() { const unsigned TIMEOUT_US = 10 * 1000 * 1000; // 10s