blob: 947fd923abcb80622ea1fa22956906b3363848fa [file] [log] [blame]
//
// 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 "asio/compose.hpp"
#include "unit_test.hpp"
#include "asio/io_context.hpp"
#include "asio/post.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)
//------------------------------------------------------------------------------
class impl_0_completion_args
{
public:
explicit impl_0_completion_args(asio::io_context& ioc)
: ioc_(ioc),
state_(starting)
{
}
template <typename Self>
void operator()(Self& self)
{
switch (state_)
{
case starting:
state_ = posting;
asio::post(ioc_, ASIO_MOVE_CAST(Self)(self));
break;
case posting:
self.complete();
break;
default:
break;
}
}
private:
asio::io_context& ioc_;
enum { starting, posting } state_;
};
template <typename CompletionToken>
ASIO_INITFN_RESULT_TYPE(CompletionToken, void())
async_0_completion_args(asio::io_context& ioc,
ASIO_MOVE_ARG(CompletionToken) token)
{
return 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(ASIO_HAS_BOOST_BIND)
namespace bindns = boost;
#else // defined(ASIO_HAS_BOOST_BIND)
namespace bindns = std;
#endif // defined(ASIO_HAS_BOOST_BIND)
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.
ASIO_CHECK(!ioc.stopped());
ASIO_CHECK(count == 0);
ioc.run();
// The run() call will not return until all work has finished.
ASIO_CHECK(ioc.stopped());
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.
ASIO_CHECK(!ioc.stopped());
ASIO_CHECK(count == 0);
ioc.run();
// The run() call will not return until all work has finished.
ASIO_CHECK(ioc.stopped());
ASIO_CHECK(count == 1);
}
//------------------------------------------------------------------------------
class impl_1_completion_arg
{
public:
explicit impl_1_completion_arg(asio::io_context& ioc)
: ioc_(ioc),
state_(starting)
{
}
template <typename Self>
void operator()(Self& self)
{
switch (state_)
{
case starting:
state_ = posting;
asio::post(ioc_, ASIO_MOVE_CAST(Self)(self));
break;
case posting:
self.complete(42);
break;
default:
break;
}
}
private:
asio::io_context& ioc_;
enum { starting, posting } state_;
};
template <typename CompletionToken>
ASIO_INITFN_RESULT_TYPE(CompletionToken, void(int))
async_1_completion_arg(asio::io_context& ioc,
ASIO_MOVE_ARG(CompletionToken) token)
{
return 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(ASIO_HAS_BOOST_BIND)
namespace bindns = boost;
#else // defined(ASIO_HAS_BOOST_BIND)
namespace bindns = std;
#endif // defined(ASIO_HAS_BOOST_BIND)
using bindns::placeholders::_1;
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.
ASIO_CHECK(!ioc.stopped());
ASIO_CHECK(count == 0);
ASIO_CHECK(result == 0);
ioc.run();
// The run() call will not return until all work has finished.
ASIO_CHECK(ioc.stopped());
ASIO_CHECK(count == 1);
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.
ASIO_CHECK(!ioc.stopped());
ASIO_CHECK(count == 0);
ASIO_CHECK(result == 0);
ioc.run();
// The run() call will not return until all work has finished.
ASIO_CHECK(ioc.stopped());
ASIO_CHECK(count == 1);
ASIO_CHECK(result == 42);
}
//------------------------------------------------------------------------------
ASIO_TEST_SUITE
(
"compose",
ASIO_TEST_CASE(compose_0_completion_args_test)
ASIO_TEST_CASE(compose_1_completion_arg_test)
)