compose.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. //
  2. // compose.cpp
  3. // ~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. // Disable autolinking for unit tests.
  11. #if !defined(BOOST_ALL_NO_LIB)
  12. #define BOOST_ALL_NO_LIB 1
  13. #endif // !defined(BOOST_ALL_NO_LIB)
  14. // Test that header file is self-contained.
  15. #include <boost/asio/compose.hpp>
  16. #include "unit_test.hpp"
  17. #include <boost/asio/io_context.hpp>
  18. #include <boost/asio/post.hpp>
  19. #if defined(BOOST_ASIO_HAS_BOOST_BIND)
  20. # include <boost/bind.hpp>
  21. #else // defined(BOOST_ASIO_HAS_BOOST_BIND)
  22. # include <functional>
  23. #endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
  24. //------------------------------------------------------------------------------
  25. class impl_0_completion_args
  26. {
  27. public:
  28. explicit impl_0_completion_args(boost::asio::io_context& ioc)
  29. : ioc_(ioc),
  30. state_(starting)
  31. {
  32. }
  33. template <typename Self>
  34. void operator()(Self& self)
  35. {
  36. switch (state_)
  37. {
  38. case starting:
  39. state_ = posting;
  40. boost::asio::post(ioc_, BOOST_ASIO_MOVE_CAST(Self)(self));
  41. break;
  42. case posting:
  43. self.complete();
  44. break;
  45. default:
  46. break;
  47. }
  48. }
  49. private:
  50. boost::asio::io_context& ioc_;
  51. enum { starting, posting } state_;
  52. };
  53. template <typename CompletionToken>
  54. BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void())
  55. async_0_completion_args(boost::asio::io_context& ioc,
  56. BOOST_ASIO_MOVE_ARG(CompletionToken) token)
  57. {
  58. return boost::asio::async_compose<CompletionToken, void()>(
  59. impl_0_completion_args(ioc), token);
  60. }
  61. void compose_0_args_handler(int* count)
  62. {
  63. ++(*count);
  64. }
  65. void compose_0_completion_args_test()
  66. {
  67. #if defined(BOOST_ASIO_HAS_BOOST_BIND)
  68. namespace bindns = boost;
  69. #else // defined(BOOST_ASIO_HAS_BOOST_BIND)
  70. namespace bindns = std;
  71. #endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
  72. boost::asio::io_context ioc;
  73. int count = 0;
  74. async_0_completion_args(ioc, bindns::bind(&compose_0_args_handler, &count));
  75. // No handlers can be called until run() is called.
  76. BOOST_ASIO_CHECK(!ioc.stopped());
  77. BOOST_ASIO_CHECK(count == 0);
  78. ioc.run();
  79. // The run() call will not return until all work has finished.
  80. BOOST_ASIO_CHECK(ioc.stopped());
  81. BOOST_ASIO_CHECK(count == 1);
  82. }
  83. //------------------------------------------------------------------------------
  84. class impl_1_completion_arg
  85. {
  86. public:
  87. explicit impl_1_completion_arg(boost::asio::io_context& ioc)
  88. : ioc_(ioc),
  89. state_(starting)
  90. {
  91. }
  92. template <typename Self>
  93. void operator()(Self& self)
  94. {
  95. switch (state_)
  96. {
  97. case starting:
  98. state_ = posting;
  99. boost::asio::post(ioc_, BOOST_ASIO_MOVE_CAST(Self)(self));
  100. break;
  101. case posting:
  102. self.complete(42);
  103. break;
  104. default:
  105. break;
  106. }
  107. }
  108. private:
  109. boost::asio::io_context& ioc_;
  110. enum { starting, posting } state_;
  111. };
  112. template <typename CompletionToken>
  113. BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(int))
  114. async_1_completion_arg(boost::asio::io_context& ioc,
  115. BOOST_ASIO_MOVE_ARG(CompletionToken) token)
  116. {
  117. return boost::asio::async_compose<CompletionToken, void(int)>(
  118. impl_1_completion_arg(ioc), token);
  119. }
  120. void compose_1_args_handler(int* count, int* result_out, int result)
  121. {
  122. ++(*count);
  123. *result_out = result;
  124. }
  125. void compose_1_completion_arg_test()
  126. {
  127. #if defined(BOOST_ASIO_HAS_BOOST_BIND)
  128. namespace bindns = boost;
  129. #else // defined(BOOST_ASIO_HAS_BOOST_BIND)
  130. namespace bindns = std;
  131. using std::placeholders::_1;
  132. #endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
  133. boost::asio::io_context ioc;
  134. int count = 0;
  135. int result = 0;
  136. async_1_completion_arg(ioc,
  137. bindns::bind(&compose_1_args_handler, &count, &result, _1));
  138. // No handlers can be called until run() is called.
  139. BOOST_ASIO_CHECK(!ioc.stopped());
  140. BOOST_ASIO_CHECK(count == 0);
  141. BOOST_ASIO_CHECK(result == 0);
  142. ioc.run();
  143. // The run() call will not return until all work has finished.
  144. BOOST_ASIO_CHECK(ioc.stopped());
  145. BOOST_ASIO_CHECK(count == 1);
  146. BOOST_ASIO_CHECK(result == 42);
  147. }
  148. //------------------------------------------------------------------------------
  149. BOOST_ASIO_TEST_SUITE
  150. (
  151. "compose",
  152. BOOST_ASIO_TEST_CASE(compose_0_completion_args_test)
  153. BOOST_ASIO_TEST_CASE(compose_1_completion_arg_test)
  154. )