summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/asio/src/tests/unit/thread_pool.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/asio/src/tests/unit/thread_pool.cpp')
-rw-r--r--3rdparty/asio/src/tests/unit/thread_pool.cpp526
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)
+)