diff options
Diffstat (limited to '3rdparty/asio/src/tests/unit/thread_pool.cpp')
-rw-r--r-- | 3rdparty/asio/src/tests/unit/thread_pool.cpp | 526 |
1 files changed, 526 insertions, 0 deletions
diff --git a/3rdparty/asio/src/tests/unit/thread_pool.cpp b/3rdparty/asio/src/tests/unit/thread_pool.cpp new file mode 100644 index 00000000000..aec68023367 --- /dev/null +++ b/3rdparty/asio/src/tests/unit/thread_pool.cpp @@ -0,0 +1,526 @@ +// +// thread_pool.cpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// 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) +// + +// Disable autolinking for unit tests. +#if !defined(BOOST_ALL_NO_LIB) +#define BOOST_ALL_NO_LIB 1 +#endif // !defined(BOOST_ALL_NO_LIB) + +// Test that header file is self-contained. +#include "asio/thread_pool.hpp" + +#include "asio/dispatch.hpp" +#include "asio/post.hpp" +#include "unit_test.hpp" + +#if defined(ASIO_HAS_BOOST_BIND) +# include <boost/bind/bind.hpp> +#else // defined(ASIO_HAS_BOOST_BIND) +# include <functional> +#endif // defined(ASIO_HAS_BOOST_BIND) + +using namespace asio; + +#if defined(ASIO_HAS_BOOST_BIND) +namespace bindns = boost; +#else // defined(ASIO_HAS_BOOST_BIND) +namespace bindns = std; +#endif + +void increment(int* count) +{ + ++(*count); +} + +void decrement_to_zero(thread_pool* pool, int* count) +{ + if (*count > 0) + { + --(*count); + + int before_value = *count; + asio::post(*pool, bindns::bind(decrement_to_zero, pool, count)); + + // Handler execution cannot nest, so count value should remain unchanged. + ASIO_CHECK(*count == before_value); + } +} + +void nested_decrement_to_zero(thread_pool* pool, int* count) +{ + if (*count > 0) + { + --(*count); + + asio::dispatch(*pool, + bindns::bind(nested_decrement_to_zero, pool, count)); + + // Handler execution is nested, so count value should now be zero. + ASIO_CHECK(*count == 0); + } +} + +void thread_pool_test() +{ + thread_pool pool(1); + + int count1 = 0; + asio::post(pool, bindns::bind(increment, &count1)); + + int count2 = 10; + asio::post(pool, bindns::bind(decrement_to_zero, &pool, &count2)); + + int count3 = 10; + asio::post(pool, bindns::bind(nested_decrement_to_zero, &pool, &count3)); + + pool.wait(); + + ASIO_CHECK(count1 == 1); + ASIO_CHECK(count2 == 0); + ASIO_CHECK(count3 == 0); +} + +class test_service : public asio::execution_context::service +{ +public: +#if defined(ASIO_NO_TYPEID) + static asio::execution_context::id id; +#endif // defined(ASIO_NO_TYPEID) + + typedef test_service key_type; + + test_service(asio::execution_context& ctx) + : asio::execution_context::service(ctx) + { + } + +private: + virtual void shutdown() {} +}; + +#if defined(ASIO_NO_TYPEID) +asio::execution_context::id test_service::id; +#endif // defined(ASIO_NO_TYPEID) + +void thread_pool_service_test() +{ + asio::thread_pool pool1(1); + asio::thread_pool pool2(1); + asio::thread_pool pool3(1); + + // Implicit service registration. + + asio::use_service<test_service>(pool1); + + ASIO_CHECK(asio::has_service<test_service>(pool1)); + + test_service* svc1 = new test_service(pool1); + try + { + asio::add_service(pool1, svc1); + ASIO_ERROR("add_service did not throw"); + } + catch (asio::service_already_exists&) + { + } + delete svc1; + + // Explicit service registration. + + test_service& svc2 = asio::make_service<test_service>(pool2); + + ASIO_CHECK(asio::has_service<test_service>(pool2)); + ASIO_CHECK(&asio::use_service<test_service>(pool2) == &svc2); + + test_service* svc3 = new test_service(pool2); + try + { + asio::add_service(pool2, svc3); + ASIO_ERROR("add_service did not throw"); + } + catch (asio::service_already_exists&) + { + } + delete svc3; + + // Explicit registration with invalid owner. + + test_service* svc4 = new test_service(pool2); + try + { + asio::add_service(pool3, svc4); + ASIO_ERROR("add_service did not throw"); + } + catch (asio::invalid_service_owner&) + { + } + delete svc4; + + ASIO_CHECK(!asio::has_service<test_service>(pool3)); +} + +void thread_pool_executor_query_test() +{ + thread_pool pool(1); + + ASIO_CHECK( + &asio::query(pool.executor(), + asio::execution::context) + == &pool); + + ASIO_CHECK( + asio::query(pool.executor(), + asio::execution::blocking) + == asio::execution::blocking.possibly); + + ASIO_CHECK( + asio::query(pool.executor(), + asio::execution::blocking.possibly) + == asio::execution::blocking.possibly); + + ASIO_CHECK( + asio::query(pool.executor(), + asio::execution::outstanding_work) + == asio::execution::outstanding_work.untracked); + + ASIO_CHECK( + asio::query(pool.executor(), + asio::execution::outstanding_work.untracked) + == asio::execution::outstanding_work.untracked); + + ASIO_CHECK( + asio::query(pool.executor(), + asio::execution::relationship) + == asio::execution::relationship.fork); + + ASIO_CHECK( + asio::query(pool.executor(), + asio::execution::relationship.fork) + == asio::execution::relationship.fork); + + ASIO_CHECK( + asio::query(pool.executor(), + asio::execution::bulk_guarantee) + == asio::execution::bulk_guarantee.parallel); + + ASIO_CHECK( + asio::query(pool.executor(), + asio::execution::mapping) + == asio::execution::mapping.thread); + + ASIO_CHECK( + asio::query(pool.executor(), + asio::execution::allocator) + == std::allocator<void>()); + + ASIO_CHECK( + asio::query(pool.executor(), + asio::execution::occupancy) + == 1); +} + +void thread_pool_executor_execute_test() +{ + int count = 0; + thread_pool pool(1); + + asio::execution::execute(pool.executor(), + bindns::bind(increment, &count)); + + asio::execution::execute( + asio::require(pool.executor(), + asio::execution::blocking.possibly), + bindns::bind(increment, &count)); + + asio::execution::execute( + asio::require(pool.executor(), + asio::execution::blocking.always), + bindns::bind(increment, &count)); + + asio::execution::execute( + asio::require(pool.executor(), + asio::execution::blocking.never), + bindns::bind(increment, &count)); + + asio::execution::execute( + asio::require(pool.executor(), + asio::execution::blocking.never, + asio::execution::outstanding_work.tracked), + bindns::bind(increment, &count)); + + asio::execution::execute( + asio::require(pool.executor(), + asio::execution::blocking.never, + asio::execution::outstanding_work.untracked), + bindns::bind(increment, &count)); + + asio::execution::execute( + asio::require(pool.executor(), + asio::execution::blocking.never, + asio::execution::outstanding_work.untracked, + asio::execution::relationship.fork), + bindns::bind(increment, &count)); + + asio::execution::execute( + asio::require(pool.executor(), + asio::execution::blocking.never, + asio::execution::outstanding_work.untracked, + asio::execution::relationship.continuation), + bindns::bind(increment, &count)); + + asio::execution::execute( + asio::prefer( + asio::require(pool.executor(), + asio::execution::blocking.never, + asio::execution::outstanding_work.untracked, + asio::execution::relationship.continuation), + asio::execution::allocator(std::allocator<void>())), + bindns::bind(increment, &count)); + + asio::execution::execute( + asio::prefer( + asio::require(pool.executor(), + asio::execution::blocking.never, + asio::execution::outstanding_work.untracked, + asio::execution::relationship.continuation), + asio::execution::allocator), + bindns::bind(increment, &count)); + + pool.wait(); + + ASIO_CHECK(count == 10); +} + +struct receiver +{ + int* count_; + + receiver(int* count) + : count_(count) + { + } + + receiver(const receiver& other) ASIO_NOEXCEPT + : count_(other.count_) + { + } + +#if defined(ASIO_HAS_MOVE) + receiver(receiver&& other) ASIO_NOEXCEPT + : count_(other.count_) + { + other.count_ = 0; + } +#endif // defined(ASIO_HAS_MOVE) + + void set_value() ASIO_NOEXCEPT + { + ++(*count_); + } + + template <typename E> + void set_error(ASIO_MOVE_ARG(E) e) ASIO_NOEXCEPT + { + (void)e; + } + + void set_done() ASIO_NOEXCEPT + { + } +}; + +namespace asio { +namespace traits { + +#if !defined(ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT) + +template <> +struct set_value_member<receiver, void()> +{ + ASIO_STATIC_CONSTEXPR(bool, is_valid = true); + ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + typedef void result_type; +}; + +#endif // !defined(ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT) + +#if !defined(ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT) + +template <typename E> +struct set_error_member<receiver, E> +{ + ASIO_STATIC_CONSTEXPR(bool, is_valid = true); + ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + typedef void result_type; +}; + +#endif // !defined(ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT) + +#if !defined(ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT) + +template <> +struct set_done_member<receiver> +{ + ASIO_STATIC_CONSTEXPR(bool, is_valid = true); + ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + typedef void result_type; +}; + +#endif // !defined(ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT) + +} // namespace traits +} // namespace asio + +void thread_pool_scheduler_test() +{ + int count = 0; + receiver r(&count); + thread_pool pool(1); + + asio::execution::submit( + asio::execution::schedule(pool.scheduler()), r); + + asio::execution::submit( + asio::require( + asio::execution::schedule(pool.executor()), + asio::execution::blocking.possibly), r); + + asio::execution::submit( + asio::require( + asio::execution::schedule(pool.executor()), + asio::execution::blocking.always), r); + + asio::execution::submit( + asio::require( + asio::execution::schedule(pool.executor()), + asio::execution::blocking.never), r); + + asio::execution::submit( + asio::require( + asio::execution::schedule(pool.executor()), + asio::execution::blocking.never, + asio::execution::outstanding_work.tracked), r); + + asio::execution::submit( + asio::require( + asio::execution::schedule(pool.executor()), + asio::execution::blocking.never, + asio::execution::outstanding_work.untracked), r); + + asio::execution::submit( + asio::require( + asio::execution::schedule(pool.executor()), + asio::execution::blocking.never, + asio::execution::outstanding_work.untracked, + asio::execution::relationship.fork), r); + + asio::execution::submit( + asio::require( + asio::execution::schedule(pool.executor()), + asio::execution::blocking.never, + asio::execution::outstanding_work.untracked, + asio::execution::relationship.continuation), r); + + asio::execution::submit( + asio::prefer( + asio::require( + asio::execution::schedule(pool.executor()), + asio::execution::blocking.never, + asio::execution::outstanding_work.untracked, + asio::execution::relationship.continuation), + asio::execution::allocator(std::allocator<void>())), r); + + asio::execution::submit( + asio::prefer( + asio::require( + asio::execution::schedule(pool.executor()), + asio::execution::blocking.never, + asio::execution::outstanding_work.untracked, + asio::execution::relationship.continuation), + asio::execution::allocator), r); + + pool.wait(); + + ASIO_CHECK(count == 10); +} + +void thread_pool_executor_bulk_execute_test() +{ + int count = 0; + thread_pool pool(1); + + pool.executor().bulk_execute( + bindns::bind(increment, &count), 2); + + asio::require(pool.executor(), + asio::execution::blocking.possibly).bulk_execute( + bindns::bind(increment, &count), 2); + + asio::require(pool.executor(), + asio::execution::blocking.always).bulk_execute( + bindns::bind(increment, &count), 2); + + asio::require(pool.executor(), + asio::execution::blocking.never).bulk_execute( + bindns::bind(increment, &count), 2); + + asio::require(pool.executor(), + asio::execution::blocking.never, + asio::execution::outstanding_work.tracked).bulk_execute( + bindns::bind(increment, &count), 2); + + asio::require(pool.executor(), + asio::execution::blocking.never, + asio::execution::outstanding_work.untracked).bulk_execute( + bindns::bind(increment, &count), 2); + + asio::require(pool.executor(), + asio::execution::blocking.never, + asio::execution::outstanding_work.untracked, + asio::execution::relationship.fork).bulk_execute( + bindns::bind(increment, &count), 2); + + asio::require(pool.executor(), + asio::execution::blocking.never, + asio::execution::outstanding_work.untracked, + asio::execution::relationship.continuation).bulk_execute( + bindns::bind(increment, &count), 2); + + asio::prefer( + asio::require(pool.executor(), + asio::execution::blocking.never, + asio::execution::outstanding_work.untracked, + asio::execution::relationship.continuation), + asio::execution::allocator(std::allocator<void>())).bulk_execute( + bindns::bind(increment, &count), 2); + + asio::prefer( + asio::require(pool.executor(), + asio::execution::blocking.never, + asio::execution::outstanding_work.untracked, + asio::execution::relationship.continuation), + asio::execution::allocator).bulk_execute( + bindns::bind(increment, &count), 2); + + pool.wait(); + + ASIO_CHECK(count == 20); +} + +ASIO_TEST_SUITE +( + "thread_pool", + ASIO_TEST_CASE(thread_pool_test) + ASIO_TEST_CASE(thread_pool_service_test) + ASIO_TEST_CASE(thread_pool_executor_query_test) + ASIO_TEST_CASE(thread_pool_executor_execute_test) + ASIO_TEST_CASE(thread_pool_executor_bulk_execute_test) + ASIO_TEST_CASE(thread_pool_scheduler_test) +) |