243 lines
5.4 KiB
C++
243 lines
5.4 KiB
C++
//
|
|
// compose.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 <boost/asio/compose.hpp>
|
|
|
|
#include "unit_test.hpp"
|
|
|
|
#include <boost/asio/io_context.hpp>
|
|
#include <boost/asio/post.hpp>
|
|
|
|
#if defined(BOOST_ASIO_HAS_BOOST_BIND)
|
|
# include <boost/bind/bind.hpp>
|
|
#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
|
|
# include <functional>
|
|
#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
class impl_0_completion_args
|
|
{
|
|
public:
|
|
explicit impl_0_completion_args(boost::asio::io_context& ioc)
|
|
: ioc_(ioc),
|
|
state_(starting)
|
|
{
|
|
}
|
|
|
|
template <typename Self>
|
|
void operator()(Self& self)
|
|
{
|
|
switch (state_)
|
|
{
|
|
case starting:
|
|
state_ = posting;
|
|
boost::asio::post(ioc_, BOOST_ASIO_MOVE_CAST(Self)(self));
|
|
break;
|
|
case posting:
|
|
self.complete();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
private:
|
|
boost::asio::io_context& ioc_;
|
|
enum { starting, posting } state_;
|
|
};
|
|
|
|
template <typename CompletionToken>
|
|
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void())
|
|
async_0_completion_args(boost::asio::io_context& ioc,
|
|
BOOST_ASIO_MOVE_ARG(CompletionToken) token)
|
|
{
|
|
return boost::asio::async_compose<CompletionToken, void()>(
|
|
impl_0_completion_args(ioc), token);
|
|
}
|
|
|
|
void compose_0_args_handler(int* count)
|
|
{
|
|
++(*count);
|
|
}
|
|
|
|
struct compose_0_args_lvalue_handler
|
|
{
|
|
int* count_;
|
|
|
|
void operator()()
|
|
{
|
|
++(*count_);
|
|
}
|
|
};
|
|
|
|
void compose_0_completion_args_test()
|
|
{
|
|
#if defined(BOOST_ASIO_HAS_BOOST_BIND)
|
|
namespace bindns = boost;
|
|
#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
|
|
namespace bindns = std;
|
|
#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
|
|
|
|
boost::asio::io_context ioc;
|
|
int count = 0;
|
|
|
|
async_0_completion_args(ioc, bindns::bind(&compose_0_args_handler, &count));
|
|
|
|
// No handlers can be called until run() is called.
|
|
BOOST_ASIO_CHECK(!ioc.stopped());
|
|
BOOST_ASIO_CHECK(count == 0);
|
|
|
|
ioc.run();
|
|
|
|
// The run() call will not return until all work has finished.
|
|
BOOST_ASIO_CHECK(ioc.stopped());
|
|
BOOST_ASIO_CHECK(count == 1);
|
|
|
|
ioc.restart();
|
|
count = 0;
|
|
|
|
compose_0_args_lvalue_handler lvalue_handler = { &count };
|
|
async_0_completion_args(ioc, lvalue_handler);
|
|
|
|
// No handlers can be called until run() is called.
|
|
BOOST_ASIO_CHECK(!ioc.stopped());
|
|
BOOST_ASIO_CHECK(count == 0);
|
|
|
|
ioc.run();
|
|
|
|
// The run() call will not return until all work has finished.
|
|
BOOST_ASIO_CHECK(ioc.stopped());
|
|
BOOST_ASIO_CHECK(count == 1);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
class impl_1_completion_arg
|
|
{
|
|
public:
|
|
explicit impl_1_completion_arg(boost::asio::io_context& ioc)
|
|
: ioc_(ioc),
|
|
state_(starting)
|
|
{
|
|
}
|
|
|
|
template <typename Self>
|
|
void operator()(Self& self)
|
|
{
|
|
switch (state_)
|
|
{
|
|
case starting:
|
|
state_ = posting;
|
|
boost::asio::post(ioc_, BOOST_ASIO_MOVE_CAST(Self)(self));
|
|
break;
|
|
case posting:
|
|
self.complete(42);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
private:
|
|
boost::asio::io_context& ioc_;
|
|
enum { starting, posting } state_;
|
|
};
|
|
|
|
template <typename CompletionToken>
|
|
BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void(int))
|
|
async_1_completion_arg(boost::asio::io_context& ioc,
|
|
BOOST_ASIO_MOVE_ARG(CompletionToken) token)
|
|
{
|
|
return boost::asio::async_compose<CompletionToken, void(int)>(
|
|
impl_1_completion_arg(ioc), token);
|
|
}
|
|
|
|
void compose_1_arg_handler(int* count, int* result_out, int result)
|
|
{
|
|
++(*count);
|
|
*result_out = result;
|
|
}
|
|
|
|
struct compose_1_arg_lvalue_handler
|
|
{
|
|
int* count_;
|
|
int* result_out_;
|
|
|
|
void operator()(int result)
|
|
{
|
|
++(*count_);
|
|
*result_out_ = result;
|
|
}
|
|
};
|
|
|
|
void compose_1_completion_arg_test()
|
|
{
|
|
#if defined(BOOST_ASIO_HAS_BOOST_BIND)
|
|
namespace bindns = boost;
|
|
#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
|
|
namespace bindns = std;
|
|
#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
|
|
using bindns::placeholders::_1;
|
|
|
|
boost::asio::io_context ioc;
|
|
int count = 0;
|
|
int result = 0;
|
|
|
|
async_1_completion_arg(ioc,
|
|
bindns::bind(&compose_1_arg_handler, &count, &result, _1));
|
|
|
|
// No handlers can be called until run() is called.
|
|
BOOST_ASIO_CHECK(!ioc.stopped());
|
|
BOOST_ASIO_CHECK(count == 0);
|
|
BOOST_ASIO_CHECK(result == 0);
|
|
|
|
ioc.run();
|
|
|
|
// The run() call will not return until all work has finished.
|
|
BOOST_ASIO_CHECK(ioc.stopped());
|
|
BOOST_ASIO_CHECK(count == 1);
|
|
BOOST_ASIO_CHECK(result == 42);
|
|
|
|
ioc.restart();
|
|
count = 0;
|
|
result = 0;
|
|
|
|
compose_1_arg_lvalue_handler lvalue_handler = { &count, &result };
|
|
async_1_completion_arg(ioc, lvalue_handler);
|
|
|
|
// No handlers can be called until run() is called.
|
|
BOOST_ASIO_CHECK(!ioc.stopped());
|
|
BOOST_ASIO_CHECK(count == 0);
|
|
BOOST_ASIO_CHECK(result == 0);
|
|
|
|
ioc.run();
|
|
|
|
// The run() call will not return until all work has finished.
|
|
BOOST_ASIO_CHECK(ioc.stopped());
|
|
BOOST_ASIO_CHECK(count == 1);
|
|
BOOST_ASIO_CHECK(result == 42);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
|
|
BOOST_ASIO_TEST_SUITE
|
|
(
|
|
"compose",
|
|
BOOST_ASIO_TEST_CASE(compose_0_completion_args_test)
|
|
BOOST_ASIO_TEST_CASE(compose_1_completion_arg_test)
|
|
)
|