• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // compose.cpp
3 // ~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2020 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 
11 // Disable autolinking for unit tests.
12 #if !defined(BOOST_ALL_NO_LIB)
13 #define BOOST_ALL_NO_LIB 1
14 #endif // !defined(BOOST_ALL_NO_LIB)
15 
16 // Test that header file is self-contained.
17 #include <boost/asio/compose.hpp>
18 
19 #include "unit_test.hpp"
20 
21 #include <boost/asio/io_context.hpp>
22 #include <boost/asio/post.hpp>
23 
24 #if defined(BOOST_ASIO_HAS_BOOST_BIND)
25 # include <boost/bind/bind.hpp>
26 #else // defined(BOOST_ASIO_HAS_BOOST_BIND)
27 # include <functional>
28 #endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
29 
30 //------------------------------------------------------------------------------
31 
32 class impl_0_completion_args
33 {
34 public:
impl_0_completion_args(boost::asio::io_context & ioc)35   explicit impl_0_completion_args(boost::asio::io_context& ioc)
36     : ioc_(ioc),
37       state_(starting)
38   {
39   }
40 
41   template <typename Self>
operator ()(Self & self)42   void operator()(Self& self)
43   {
44     switch (state_)
45     {
46     case starting:
47       state_ = posting;
48       boost::asio::post(ioc_, BOOST_ASIO_MOVE_CAST(Self)(self));
49       break;
50     case posting:
51       self.complete();
52       break;
53     default:
54       break;
55     }
56   }
57 
58 private:
59   boost::asio::io_context& ioc_;
60   enum { starting, posting } state_;
61 };
62 
63 template <typename CompletionToken>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken,void ())64 BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void())
65 async_0_completion_args(boost::asio::io_context& ioc,
66     BOOST_ASIO_MOVE_ARG(CompletionToken) token)
67 {
68   return boost::asio::async_compose<CompletionToken, void()>(
69       impl_0_completion_args(ioc), token);
70 }
71 
compose_0_args_handler(int * count)72 void compose_0_args_handler(int* count)
73 {
74   ++(*count);
75 }
76 
77 struct compose_0_args_lvalue_handler
78 {
79   int* count_;
80 
operator ()compose_0_args_lvalue_handler81   void operator()()
82   {
83     ++(*count_);
84   }
85 };
86 
compose_0_completion_args_test()87 void compose_0_completion_args_test()
88 {
89 #if defined(BOOST_ASIO_HAS_BOOST_BIND)
90   namespace bindns = boost;
91 #else // defined(BOOST_ASIO_HAS_BOOST_BIND)
92   namespace bindns = std;
93 #endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
94 
95   boost::asio::io_context ioc;
96   int count = 0;
97 
98   async_0_completion_args(ioc, bindns::bind(&compose_0_args_handler, &count));
99 
100   // No handlers can be called until run() is called.
101   BOOST_ASIO_CHECK(!ioc.stopped());
102   BOOST_ASIO_CHECK(count == 0);
103 
104   ioc.run();
105 
106   // The run() call will not return until all work has finished.
107   BOOST_ASIO_CHECK(ioc.stopped());
108   BOOST_ASIO_CHECK(count == 1);
109 
110   ioc.restart();
111   count = 0;
112 
113   compose_0_args_lvalue_handler lvalue_handler = { &count };
114   async_0_completion_args(ioc, lvalue_handler);
115 
116   // No handlers can be called until run() is called.
117   BOOST_ASIO_CHECK(!ioc.stopped());
118   BOOST_ASIO_CHECK(count == 0);
119 
120   ioc.run();
121 
122   // The run() call will not return until all work has finished.
123   BOOST_ASIO_CHECK(ioc.stopped());
124   BOOST_ASIO_CHECK(count == 1);
125 }
126 
127 //------------------------------------------------------------------------------
128 
129 class impl_1_completion_arg
130 {
131 public:
impl_1_completion_arg(boost::asio::io_context & ioc)132   explicit impl_1_completion_arg(boost::asio::io_context& ioc)
133     : ioc_(ioc),
134       state_(starting)
135   {
136   }
137 
138   template <typename Self>
operator ()(Self & self)139   void operator()(Self& self)
140   {
141     switch (state_)
142     {
143     case starting:
144       state_ = posting;
145       boost::asio::post(ioc_, BOOST_ASIO_MOVE_CAST(Self)(self));
146       break;
147     case posting:
148       self.complete(42);
149       break;
150     default:
151       break;
152     }
153   }
154 
155 private:
156   boost::asio::io_context& ioc_;
157   enum { starting, posting } state_;
158 };
159 
160 template <typename CompletionToken>
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken,void (int))161 BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(int))
162 async_1_completion_arg(boost::asio::io_context& ioc,
163     BOOST_ASIO_MOVE_ARG(CompletionToken) token)
164 {
165   return boost::asio::async_compose<CompletionToken, void(int)>(
166       impl_1_completion_arg(ioc), token);
167 }
168 
compose_1_arg_handler(int * count,int * result_out,int result)169 void compose_1_arg_handler(int* count, int* result_out, int result)
170 {
171   ++(*count);
172   *result_out = result;
173 }
174 
175 struct compose_1_arg_lvalue_handler
176 {
177   int* count_;
178   int* result_out_;
179 
operator ()compose_1_arg_lvalue_handler180   void operator()(int result)
181   {
182     ++(*count_);
183     *result_out_ = result;
184   }
185 };
186 
compose_1_completion_arg_test()187 void compose_1_completion_arg_test()
188 {
189 #if defined(BOOST_ASIO_HAS_BOOST_BIND)
190   namespace bindns = boost;
191 #else // defined(BOOST_ASIO_HAS_BOOST_BIND)
192   namespace bindns = std;
193 #endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
194   using bindns::placeholders::_1;
195 
196   boost::asio::io_context ioc;
197   int count = 0;
198   int result = 0;
199 
200   async_1_completion_arg(ioc,
201       bindns::bind(&compose_1_arg_handler, &count, &result, _1));
202 
203   // No handlers can be called until run() is called.
204   BOOST_ASIO_CHECK(!ioc.stopped());
205   BOOST_ASIO_CHECK(count == 0);
206   BOOST_ASIO_CHECK(result == 0);
207 
208   ioc.run();
209 
210   // The run() call will not return until all work has finished.
211   BOOST_ASIO_CHECK(ioc.stopped());
212   BOOST_ASIO_CHECK(count == 1);
213   BOOST_ASIO_CHECK(result == 42);
214 
215   ioc.restart();
216   count = 0;
217   result = 0;
218 
219   compose_1_arg_lvalue_handler lvalue_handler = { &count, &result };
220   async_1_completion_arg(ioc, lvalue_handler);
221 
222   // No handlers can be called until run() is called.
223   BOOST_ASIO_CHECK(!ioc.stopped());
224   BOOST_ASIO_CHECK(count == 0);
225   BOOST_ASIO_CHECK(result == 0);
226 
227   ioc.run();
228 
229   // The run() call will not return until all work has finished.
230   BOOST_ASIO_CHECK(ioc.stopped());
231   BOOST_ASIO_CHECK(count == 1);
232   BOOST_ASIO_CHECK(result == 42);
233 }
234 
235 //------------------------------------------------------------------------------
236 
237 BOOST_ASIO_TEST_SUITE
238 (
239   "compose",
240   BOOST_ASIO_TEST_CASE(compose_0_completion_args_test)
241   BOOST_ASIO_TEST_CASE(compose_1_completion_arg_test)
242 )
243