mirror of
https://github.com/boostorg/beast.git
synced 2025-07-30 21:07:26 +02:00
New stream_socket:
This I/O object wraps an ordinary socket and provides a built-in timeout and optional bandwidth rate-limiting facility. Added class template basic_stream_socket * Meets the requirements of AsyncReadStream and AsyncWriteStream * Partially supports P1322R0: "Networking TS enhancement to enable custom I/O executors" http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1322r0.html A strand or other io_context-compatible executor may be chosen to use for all asynchronous stream operations. * Supports independent timeouts on logical operations: connect, read, write, or both read and write. * Provides an option for a configurable rate limit limit on the maximum rates of reading or writing. * The previous experimental implementation, `timeout_socket` and related types, is removed. * stream_socket is an alias for basic_stream_socket which uses `net::ip::tcp` as its protocol.
This commit is contained in:
@ -4,6 +4,7 @@ Version 201
|
|||||||
* Add bind_back_handler
|
* Add bind_back_handler
|
||||||
* Tidy up default-constructed iterators
|
* Tidy up default-constructed iterators
|
||||||
* Add core errors and conditions
|
* Add core errors and conditions
|
||||||
|
* New basic_stream_socket
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
|
|
||||||
[*Experimental]
|
[*Experimental]
|
||||||
|
|
||||||
* Add [link beast.ref.boost__beast__timeout_socket `timeout_socket`]
|
* Add `timeout_socket`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -179,6 +179,7 @@
|
|||||||
<simplelist type="vert" columns="1">
|
<simplelist type="vert" columns="1">
|
||||||
<member><link linkend="beast.ref.boost__beast__basic_flat_buffer">basic_flat_buffer</link></member>
|
<member><link linkend="beast.ref.boost__beast__basic_flat_buffer">basic_flat_buffer</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__basic_multi_buffer">basic_multi_buffer</link></member>
|
<member><link linkend="beast.ref.boost__beast__basic_multi_buffer">basic_multi_buffer</link></member>
|
||||||
|
<member><link linkend="beast.ref.boost__beast__basic_stream_socket">basic_stream_socket</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__buffered_read_stream">buffered_read_stream</link></member>
|
<member><link linkend="beast.ref.boost__beast__buffered_read_stream">buffered_read_stream</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__buffers_adaptor">buffers_adaptor</link></member>
|
<member><link linkend="beast.ref.boost__beast__buffers_adaptor">buffers_adaptor</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__buffers_cat_view">buffers_cat_view</link></member>
|
<member><link linkend="beast.ref.boost__beast__buffers_cat_view">buffers_cat_view</link></member>
|
||||||
@ -189,14 +190,14 @@
|
|||||||
<member><link linkend="beast.ref.boost__beast__file_posix">file_posix</link></member>
|
<member><link linkend="beast.ref.boost__beast__file_posix">file_posix</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__file_stdio">file_stdio</link></member>
|
<member><link linkend="beast.ref.boost__beast__file_stdio">file_stdio</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__file_win32">file_win32</link></member>
|
<member><link linkend="beast.ref.boost__beast__file_win32">file_win32</link></member>
|
||||||
|
<member><link linkend="beast.ref.boost__beast__flat_buffer">flat_buffer</link></member>
|
||||||
|
<member><link linkend="beast.ref.boost__beast__flat_static_buffer">flat_static_buffer</link></member>
|
||||||
|
<member><link linkend="beast.ref.boost__beast__flat_static_buffer_base">flat_static_buffer_base</link></member>
|
||||||
</simplelist>
|
</simplelist>
|
||||||
</entry>
|
</entry>
|
||||||
<entry valign="top">
|
<entry valign="top">
|
||||||
<bridgehead renderas="sect3"> </bridgehead>
|
<bridgehead renderas="sect3"> </bridgehead>
|
||||||
<simplelist type="vert" columns="1">
|
<simplelist type="vert" columns="1">
|
||||||
<member><link linkend="beast.ref.boost__beast__flat_buffer">flat_buffer</link></member>
|
|
||||||
<member><link linkend="beast.ref.boost__beast__flat_static_buffer">flat_static_buffer</link></member>
|
|
||||||
<member><link linkend="beast.ref.boost__beast__flat_static_buffer_base">flat_static_buffer_base</link></member>
|
|
||||||
<member><link linkend="beast.ref.boost__beast__handler_ptr">handler_ptr</link></member>
|
<member><link linkend="beast.ref.boost__beast__handler_ptr">handler_ptr</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__iequal">iequal</link></member>
|
<member><link linkend="beast.ref.boost__beast__iequal">iequal</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__iless">iless</link></member>
|
<member><link linkend="beast.ref.boost__beast__iless">iless</link></member>
|
||||||
@ -205,17 +206,24 @@
|
|||||||
<member><link linkend="beast.ref.boost__beast__static_buffer">static_buffer</link></member>
|
<member><link linkend="beast.ref.boost__beast__static_buffer">static_buffer</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__static_buffer_base">static_buffer_base</link></member>
|
<member><link linkend="beast.ref.boost__beast__static_buffer_base">static_buffer_base</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__static_string">static_string</link></member>
|
<member><link linkend="beast.ref.boost__beast__static_string">static_string</link></member>
|
||||||
|
<member><link linkend="beast.ref.boost__beast__stream_socket">stream_socket</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__string_param">string_param</link></member>
|
<member><link linkend="beast.ref.boost__beast__string_param">string_param</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__string_view">string_view</link></member>
|
<member><link linkend="beast.ref.boost__beast__string_view">string_view</link></member>
|
||||||
</simplelist>
|
</simplelist>
|
||||||
|
<bridgehead renderas="sect3">Constants</bridgehead>
|
||||||
|
<simplelist type="vert" columns="1">
|
||||||
|
<member><link linkend="beast.ref.boost__beast__condition">condition</link></member>
|
||||||
|
<member><link linkend="beast.ref.boost__beast__error">error</link></member>
|
||||||
|
<member><link linkend="beast.ref.boost__beast__file_mode">file_mode</link></member>
|
||||||
|
</simplelist>
|
||||||
</entry>
|
</entry>
|
||||||
<entry valign="top">
|
<entry valign="top">
|
||||||
<bridgehead renderas="sect3">Functions</bridgehead>
|
<bridgehead renderas="sect3">Functions</bridgehead>
|
||||||
<simplelist type="vert" columns="1">
|
<simplelist type="vert" columns="1">
|
||||||
|
<member><link linkend="beast.ref.boost__beast__async_connect">async_connect</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__bind_back_handler">bind_back_handler</link></member>
|
<member><link linkend="beast.ref.boost__beast__bind_back_handler">bind_back_handler</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__bind_front_handler">bind_front_handler</link></member>
|
<member><link linkend="beast.ref.boost__beast__bind_front_handler">bind_front_handler</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__bind_handler">bind_handler</link></member>
|
<member><link linkend="beast.ref.boost__beast__bind_handler">bind_handler</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__make_printable">make_printable</link></member>
|
|
||||||
<member><link linkend="beast.ref.boost__beast__buffers_cat">buffers_cat</link></member>
|
<member><link linkend="beast.ref.boost__beast__buffers_cat">buffers_cat</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__buffers_front">buffers_front</link></member>
|
<member><link linkend="beast.ref.boost__beast__buffers_front">buffers_front</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__buffers_prefix">buffers_prefix</link></member>
|
<member><link linkend="beast.ref.boost__beast__buffers_prefix">buffers_prefix</link></member>
|
||||||
@ -224,17 +232,12 @@
|
|||||||
<member><link linkend="beast.ref.boost__beast__buffers_to_string">buffers_to_string</link></member>
|
<member><link linkend="beast.ref.boost__beast__buffers_to_string">buffers_to_string</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__generic_category">generic_category</link></member>
|
<member><link linkend="beast.ref.boost__beast__generic_category">generic_category</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__iequals">iequals</link></member>
|
<member><link linkend="beast.ref.boost__beast__iequals">iequals</link></member>
|
||||||
|
<member><link linkend="beast.ref.boost__beast__make_printable">make_printable</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__ostream">ostream</link></member>
|
<member><link linkend="beast.ref.boost__beast__ostream">ostream</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__read_size">read_size</link></member>
|
<member><link linkend="beast.ref.boost__beast__read_size">read_size</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__read_size_or_throw">read_size_or_throw</link></member>
|
<member><link linkend="beast.ref.boost__beast__read_size_or_throw">read_size_or_throw</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__to_static_string">to_static_string</link></member>
|
<member><link linkend="beast.ref.boost__beast__to_static_string">to_static_string</link></member>
|
||||||
</simplelist>
|
</simplelist>
|
||||||
<bridgehead renderas="sect3">Constants</bridgehead>
|
|
||||||
<simplelist type="vert" columns="1">
|
|
||||||
<member><link linkend="beast.ref.boost__beast__condition">condition</link></member>
|
|
||||||
<member><link linkend="beast.ref.boost__beast__error">error</link></member>
|
|
||||||
<member><link linkend="beast.ref.boost__beast__file_mode">file_mode</link></member>
|
|
||||||
</simplelist>
|
|
||||||
</entry>
|
</entry>
|
||||||
<entry valign="top">
|
<entry valign="top">
|
||||||
<bridgehead renderas="sect3">Type Traits</bridgehead>
|
<bridgehead renderas="sect3">Type Traits</bridgehead>
|
||||||
@ -312,22 +315,16 @@
|
|||||||
<entry valign="top">
|
<entry valign="top">
|
||||||
<bridgehead renderas="sect3">Classes</bridgehead>
|
<bridgehead renderas="sect3">Classes</bridgehead>
|
||||||
<simplelist type="vert" columns="1">
|
<simplelist type="vert" columns="1">
|
||||||
<member><link linkend="beast.ref.boost__beast__basic_timeout_socket">basic_timeout_socket</link></member>
|
|
||||||
<member><link linkend="beast.ref.boost__beast__flat_stream">flat_stream</link></member>
|
<member><link linkend="beast.ref.boost__beast__flat_stream">flat_stream</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__ssl_stream">ssl_stream</link></member>
|
<member><link linkend="beast.ref.boost__beast__ssl_stream">ssl_stream</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__http__icy_stream">http::icy_stream</link></member>
|
<member><link linkend="beast.ref.boost__beast__http__icy_stream">http::icy_stream</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__test__fail_count">test::fail_count</link></member>
|
<member><link linkend="beast.ref.boost__beast__test__fail_count">test::fail_count</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__test__stream">test::stream</link></member>
|
<member><link linkend="beast.ref.boost__beast__test__stream">test::stream</link></member>
|
||||||
<member><link linkend="beast.ref.boost__beast__timeout_handle">timeout_handle</link></member>
|
|
||||||
<member><link linkend="beast.ref.boost__beast__timeout_socket">timeout_socket</link></member>
|
|
||||||
<member><link linkend="beast.ref.boost__beast__timeout_work_guard">timeout_work_guard</link></member>
|
|
||||||
</simplelist>
|
</simplelist>
|
||||||
</entry>
|
</entry>
|
||||||
<entry valign="top">
|
<entry valign="top">
|
||||||
<bridgehead renderas="sect3">Functions</bridgehead>
|
<bridgehead renderas="sect3">Functions</bridgehead>
|
||||||
<simplelist type="vert" columns="1">
|
<simplelist type="vert" columns="1">
|
||||||
<member><link linkend="beast.ref.boost__beast__async_connect">async_connect</link></member>
|
|
||||||
<member><link linkend="beast.ref.boost__beast__set_timeout_service_options">set_timeout_service_options</link></member>
|
|
||||||
<member><link linkend="beast.ref.boost__beast__test__connect">test::connect</link></member>
|
<member><link linkend="beast.ref.boost__beast__test__connect">test::connect</link></member>
|
||||||
</simplelist>
|
</simplelist>
|
||||||
</entry>
|
</entry>
|
||||||
|
@ -1,326 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2018 Vinnie Falco (vinnie dot falco at gmail 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)
|
|
||||||
//
|
|
||||||
// Official repository: https://github.com/boostorg/beast
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef BOOST_BEAST_CORE_DETAIL_IMPL_TIMEOUT_SERVICE_HPP
|
|
||||||
#define BOOST_BEAST_CORE_DETAIL_IMPL_TIMEOUT_SERVICE_HPP
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace beast {
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
timeout_service::
|
|
||||||
timeout_service(net::io_context& ctx)
|
|
||||||
: service_base(ctx)
|
|
||||||
, thunks_(1) // element [0] reserved for "null"
|
|
||||||
, timer_(ctx)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
timeout_handle
|
|
||||||
timeout_service::
|
|
||||||
make_handle()
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(m_);
|
|
||||||
if(free_thunk_ != 0)
|
|
||||||
{
|
|
||||||
auto const n = free_thunk_;
|
|
||||||
auto& t = thunks_[n];
|
|
||||||
free_thunk_ = t.pos; // next in free list
|
|
||||||
t = {};
|
|
||||||
return timeout_handle(n, *this);
|
|
||||||
}
|
|
||||||
auto const n = thunks_.size();
|
|
||||||
thunks_.emplace_back();
|
|
||||||
return timeout_handle(n, *this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
timeout_service::
|
|
||||||
set_option(std::chrono::seconds n)
|
|
||||||
{
|
|
||||||
interval_ = n;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Executor, class CancelHandler>
|
|
||||||
void
|
|
||||||
timeout_service::
|
|
||||||
set_callback(
|
|
||||||
timeout_handle h,
|
|
||||||
Executor const& ex,
|
|
||||||
CancelHandler&& handler)
|
|
||||||
{
|
|
||||||
thunks_[h.id_].callback.emplace(
|
|
||||||
callback<
|
|
||||||
Executor,
|
|
||||||
typename std::decay<CancelHandler>::type>{
|
|
||||||
h, ex,
|
|
||||||
std::forward<CancelHandler>(handler)});
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
timeout_service::
|
|
||||||
on_work_started(timeout_handle h)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(h.id_ != 0);
|
|
||||||
if( [this, h]
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(m_);
|
|
||||||
auto& t = thunks_[h.id_];
|
|
||||||
insert(t, *fresh_);
|
|
||||||
return ++pending_ == 1;
|
|
||||||
}())
|
|
||||||
{
|
|
||||||
do_async_wait();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
timeout_service::
|
|
||||||
on_work_stopped(timeout_handle h)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(h.id_ != 0);
|
|
||||||
std::lock_guard<std::mutex> lock(m_);
|
|
||||||
auto& t = thunks_[h.id_];
|
|
||||||
if(t.list != nullptr)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(! t.expired);
|
|
||||||
remove(t);
|
|
||||||
}
|
|
||||||
if(--pending_ == 0)
|
|
||||||
timer_.cancel();
|
|
||||||
BOOST_ASSERT(pending_ >= 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Synchronization points
|
|
||||||
|
|
||||||
(A) async_op invoke
|
|
||||||
(B) timeout handler invoke expired=true
|
|
||||||
(C) posted handler invoked canceled=true
|
|
||||||
|
|
||||||
----------------------------------------------
|
|
||||||
|
|
||||||
Linearized paths (for async_read)
|
|
||||||
|
|
||||||
----------------------------------------------
|
|
||||||
|
|
||||||
1. async_read
|
|
||||||
2. async_read complete, async_op posted
|
|
||||||
(A) 3. async_op invoked
|
|
||||||
- work_.try_complete() returns true
|
|
||||||
+ expired==false
|
|
||||||
+ thunk is removed from list
|
|
||||||
|
|
||||||
----------------------------------------------
|
|
||||||
|
|
||||||
1. async_read
|
|
||||||
2. async_read complete, async_op posted
|
|
||||||
(B) 3. timeout, cancel posted
|
|
||||||
- expired=true
|
|
||||||
- thunk is removed from list
|
|
||||||
(A) 4. async_op invoked
|
|
||||||
- work_.try_complete() returns false
|
|
||||||
+ completed=true
|
|
||||||
- handler is saved
|
|
||||||
(C) 5. cancel invoked
|
|
||||||
- saved handler is invoked
|
|
||||||
+ expired==true, canceled==false, completed==true
|
|
||||||
+ work_.try_complete() returns true
|
|
||||||
|
|
||||||
----------------------------------------------
|
|
||||||
|
|
||||||
The following two paths are not distinguishable:
|
|
||||||
|
|
||||||
1. async_read
|
|
||||||
(B) 2. timeout, cancel posted
|
|
||||||
- expired=true
|
|
||||||
- thunk is removed from list
|
|
||||||
3. async_read complete, async_op posted
|
|
||||||
(C) 4. cancel invoked
|
|
||||||
- socket::cancel called (what does this do?)
|
|
||||||
- canceled=true
|
|
||||||
(A) 5. async_op invoked
|
|
||||||
- expired==true, canceled==true, completed==false
|
|
||||||
- work_.try_complete() returns `true`
|
|
||||||
|
|
||||||
1. async_read
|
|
||||||
(B) 2. timeout, `cancel` posted
|
|
||||||
- expired=true
|
|
||||||
- thunk is removed from list
|
|
||||||
(C) 3. cancel invoked, async_read canceled
|
|
||||||
- socket::cancel called
|
|
||||||
- canceled=true
|
|
||||||
(A) 4. async_op invoked, ec==operation_aborted
|
|
||||||
- expired==true, canceled==true, completed=false
|
|
||||||
- work_.try_complete()` returns true
|
|
||||||
*/
|
|
||||||
bool
|
|
||||||
timeout_service::
|
|
||||||
on_try_work_complete(timeout_handle h)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(h.id_ != 0);
|
|
||||||
std::lock_guard<std::mutex> lock(m_);
|
|
||||||
auto& t = thunks_[h.id_];
|
|
||||||
if(! t.expired)
|
|
||||||
{
|
|
||||||
// hot path: operation complete
|
|
||||||
BOOST_ASSERT(t.list != nullptr);
|
|
||||||
BOOST_ASSERT(! t.canceled);
|
|
||||||
BOOST_ASSERT(! t.completed);
|
|
||||||
remove(t);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
BOOST_ASSERT(t.list == nullptr);
|
|
||||||
if(! t.canceled)
|
|
||||||
{
|
|
||||||
// happens when operation completes before
|
|
||||||
// posted cancel handler is invoked.
|
|
||||||
t.completed = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(t.completed)
|
|
||||||
{
|
|
||||||
// happens when the saved handler is
|
|
||||||
// invoked from the posted callback
|
|
||||||
t.expired = false;
|
|
||||||
t.canceled = false;
|
|
||||||
t.completed = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// happens when operation_aborted is delivered
|
|
||||||
t.expired = false;
|
|
||||||
t.canceled = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
timeout_service::
|
|
||||||
on_cancel(timeout_handle h)
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(m_);
|
|
||||||
auto& t = thunks_[h.id_];
|
|
||||||
BOOST_ASSERT(t.expired);
|
|
||||||
t.canceled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void
|
|
||||||
timeout_service::
|
|
||||||
destroy(timeout_handle h)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(h.id_ != 0);
|
|
||||||
std::lock_guard<std::mutex> lock(m_);
|
|
||||||
thunks_[h.id_].pos = free_thunk_;
|
|
||||||
free_thunk_ = h.id_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Precondition: caller holds the mutex
|
|
||||||
void
|
|
||||||
timeout_service::
|
|
||||||
insert(
|
|
||||||
thunk& t,
|
|
||||||
thunk::list_type& list)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(t.list == nullptr);
|
|
||||||
list.emplace_back(&t); // can throw
|
|
||||||
t.list = &list;
|
|
||||||
t.pos = list.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Precondition: caller holds the mutex
|
|
||||||
void
|
|
||||||
timeout_service::
|
|
||||||
remove(thunk& t)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(t.list != nullptr);
|
|
||||||
BOOST_ASSERT(
|
|
||||||
t.list == stale_ ||
|
|
||||||
t.list == fresh_);
|
|
||||||
BOOST_ASSERT(t.list->size() > 0);
|
|
||||||
auto& list = *t.list;
|
|
||||||
auto const n = list.size() - 1;
|
|
||||||
if(t.pos != n)
|
|
||||||
{
|
|
||||||
// move back element to t.pos
|
|
||||||
list[t.pos] = list[n];
|
|
||||||
list[t.pos]->pos = t.pos;
|
|
||||||
}
|
|
||||||
t.list = nullptr;
|
|
||||||
list.resize(n);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
timeout_service::
|
|
||||||
do_async_wait()
|
|
||||||
{
|
|
||||||
timer_.expires_after(interval_);
|
|
||||||
timer_.async_wait(
|
|
||||||
[this](error_code ec)
|
|
||||||
{
|
|
||||||
this->on_timer(ec);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
timeout_service::
|
|
||||||
on_timer(error_code ec)
|
|
||||||
{
|
|
||||||
if(ec == net::error::operation_aborted)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(fresh_->empty());
|
|
||||||
BOOST_ASSERT(stale_->empty());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
std::vector<thunk*> expired;
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(m_);
|
|
||||||
if(! stale_->empty())
|
|
||||||
{
|
|
||||||
for(auto t : *stale_)
|
|
||||||
{
|
|
||||||
// remove from list
|
|
||||||
t->list = nullptr;
|
|
||||||
t->expired = true;
|
|
||||||
}
|
|
||||||
std::swap(expired, *stale_);
|
|
||||||
stale_->reserve(expired.size() / 2);
|
|
||||||
}
|
|
||||||
std::swap(fresh_, stale_);
|
|
||||||
}
|
|
||||||
for(auto p : expired)
|
|
||||||
p->callback();
|
|
||||||
if( [this]
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(m_);
|
|
||||||
BOOST_ASSERT(pending_);
|
|
||||||
pending_ =
|
|
||||||
! stale_->empty() ||
|
|
||||||
! fresh_->empty();
|
|
||||||
return pending_;
|
|
||||||
}())
|
|
||||||
{
|
|
||||||
do_async_wait();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
timeout_service::
|
|
||||||
shutdown() noexcept
|
|
||||||
{
|
|
||||||
// The ExecutionContext is already in a stopped
|
|
||||||
// state, so no synchronization is required.
|
|
||||||
timer_.cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // detail
|
|
||||||
} // beast
|
|
||||||
} // boost
|
|
||||||
|
|
||||||
#endif
|
|
@ -59,11 +59,10 @@ public:
|
|||||||
std::forward<Handler>(h)));
|
std::forward<Handler>(h)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Handler,
|
template<
|
||||||
class T0, class... TN>
|
class Handler, class T0, class... TN>
|
||||||
void
|
void
|
||||||
emplace(Handler&& h,
|
emplace(Handler&& h, T0&& t0, TN&&... tn)
|
||||||
T0&& t0, TN&... tn)
|
|
||||||
{
|
{
|
||||||
using type = decltype(
|
using type = decltype(
|
||||||
beast::bind_front_handler(
|
beast::bind_front_handler(
|
||||||
|
@ -1,133 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2018 Vinnie Falco (vinnie dot falco at gmail 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)
|
|
||||||
//
|
|
||||||
// Official repository: https://github.com/boostorg/beast
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef BOOST_BEAST_CORE_DETAIL_TIMEOUT_SERVICE_HPP
|
|
||||||
#define BOOST_BEAST_CORE_DETAIL_TIMEOUT_SERVICE_HPP
|
|
||||||
|
|
||||||
#include <boost/beast/_experimental/core/detail/service_base.hpp>
|
|
||||||
#include <boost/beast/_experimental/core/detail/timeout_service_base.hpp>
|
|
||||||
#include <boost/beast/core/bind_handler.hpp>
|
|
||||||
#include <boost/beast/core/error.hpp>
|
|
||||||
#include <boost/asio/executor.hpp>
|
|
||||||
#include <boost/asio/io_context.hpp> // #include <boost/asio/execution_context.hpp>
|
|
||||||
#include <boost/asio/post.hpp>
|
|
||||||
#include <boost/asio/steady_timer.hpp>
|
|
||||||
#include <chrono>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <deque>
|
|
||||||
#include <mutex>
|
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
class timeout_handle;
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
class timeout_service
|
|
||||||
: public service_base<timeout_service>
|
|
||||||
{
|
|
||||||
template<class Executor, class Handler>
|
|
||||||
struct callback
|
|
||||||
{
|
|
||||||
timeout_handle th;
|
|
||||||
Executor ex;
|
|
||||||
Handler h;
|
|
||||||
|
|
||||||
void
|
|
||||||
operator()()
|
|
||||||
{
|
|
||||||
net::post(ex,
|
|
||||||
beast::bind_front_handler(
|
|
||||||
std::move(*this), 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
operator()(int)
|
|
||||||
{
|
|
||||||
th.service().on_cancel(th);
|
|
||||||
h();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
using key_type = timeout_service;
|
|
||||||
|
|
||||||
// VFALCO Should be execution_context
|
|
||||||
BOOST_BEAST_DECL
|
|
||||||
explicit
|
|
||||||
timeout_service(net::io_context& ctx);
|
|
||||||
|
|
||||||
BOOST_BEAST_DECL
|
|
||||||
timeout_handle
|
|
||||||
make_handle();
|
|
||||||
|
|
||||||
BOOST_BEAST_DECL
|
|
||||||
void set_option(std::chrono::seconds n);
|
|
||||||
|
|
||||||
// Undefined if work is active
|
|
||||||
template<class Executor, class CancelHandler>
|
|
||||||
void set_callback(
|
|
||||||
timeout_handle h,
|
|
||||||
Executor const& ex,
|
|
||||||
CancelHandler&& handler);
|
|
||||||
|
|
||||||
BOOST_BEAST_DECL
|
|
||||||
void on_work_started(timeout_handle h);
|
|
||||||
|
|
||||||
BOOST_BEAST_DECL
|
|
||||||
void on_work_stopped(timeout_handle h);
|
|
||||||
|
|
||||||
BOOST_BEAST_DECL
|
|
||||||
bool on_try_work_complete(timeout_handle h);
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class beast::timeout_handle;
|
|
||||||
|
|
||||||
BOOST_BEAST_DECL
|
|
||||||
void destroy(timeout_handle h);
|
|
||||||
|
|
||||||
BOOST_BEAST_DECL
|
|
||||||
void insert(thunk& t, thunk::list_type& list);
|
|
||||||
|
|
||||||
BOOST_BEAST_DECL
|
|
||||||
void remove(thunk& t);
|
|
||||||
|
|
||||||
BOOST_BEAST_DECL
|
|
||||||
void do_async_wait();
|
|
||||||
|
|
||||||
BOOST_BEAST_DECL
|
|
||||||
void on_cancel(timeout_handle h);
|
|
||||||
|
|
||||||
BOOST_BEAST_DECL
|
|
||||||
void on_timer(error_code ec);
|
|
||||||
|
|
||||||
BOOST_BEAST_DECL
|
|
||||||
virtual void shutdown() noexcept override;
|
|
||||||
|
|
||||||
std::mutex m_;
|
|
||||||
thunk::list_type list_[2];
|
|
||||||
thunk::list_type* fresh_ = &list_[0];
|
|
||||||
thunk::list_type* stale_ = &list_[1];
|
|
||||||
std::deque<thunk> thunks_;
|
|
||||||
std::size_t free_thunk_ = 0;
|
|
||||||
net::steady_timer timer_;
|
|
||||||
std::chrono::seconds interval_{30ul};
|
|
||||||
long pending_ = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // detail
|
|
||||||
} // beast
|
|
||||||
} // boost
|
|
||||||
|
|
||||||
#include <boost/beast/_experimental/core/detail/impl/timeout_service.hpp>
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,38 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2018 Vinnie Falco (vinnie dot falco at gmail 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)
|
|
||||||
//
|
|
||||||
// Official repository: https://github.com/boostorg/beast
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef BOOST_BEAST_CORE_DETAIL_TIMEOUT_SERVICE_BASE_HPP
|
|
||||||
#define BOOST_BEAST_CORE_DETAIL_TIMEOUT_SERVICE_BASE_HPP
|
|
||||||
|
|
||||||
#include <boost/beast/_experimental/core/detail/saved_handler.hpp>
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace beast {
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
struct thunk
|
|
||||||
{
|
|
||||||
using list_type =
|
|
||||||
std::vector<thunk*>;
|
|
||||||
|
|
||||||
saved_handler callback;
|
|
||||||
list_type* list = nullptr;
|
|
||||||
std::size_t pos = 0; // also: next in free list
|
|
||||||
bool expired = false;
|
|
||||||
bool canceled = false;
|
|
||||||
bool completed = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // detail
|
|
||||||
} // beast
|
|
||||||
} // boost
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,64 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2018 Vinnie Falco (vinnie dot falco at gmail 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)
|
|
||||||
//
|
|
||||||
// Official repository: https://github.com/boostorg/beast
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef BOOST_BEAST_CORE_IMPL_TIMEOUT_SERVICE_HPP
|
|
||||||
#define BOOST_BEAST_CORE_IMPL_TIMEOUT_SERVICE_HPP
|
|
||||||
|
|
||||||
#include <boost/beast/_experimental/core/detail/timeout_service.hpp>
|
|
||||||
#include <boost/asio/execution_context.hpp>
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
timeout_handle::
|
|
||||||
timeout_handle(net::io_context& ioc)
|
|
||||||
: timeout_handle(
|
|
||||||
net::use_service<
|
|
||||||
detail::timeout_service>(
|
|
||||||
ioc).make_handle())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
timeout_handle::
|
|
||||||
destroy()
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(svc_ != nullptr);
|
|
||||||
svc_->destroy(*this);
|
|
||||||
id_ = 0;
|
|
||||||
svc_ = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Executor, class CancelHandler>
|
|
||||||
void
|
|
||||||
timeout_handle::
|
|
||||||
set_callback(
|
|
||||||
Executor const& ex, CancelHandler&& handler)
|
|
||||||
{
|
|
||||||
svc_->set_callback(*this, ex,
|
|
||||||
std::forward<CancelHandler>(handler));
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void
|
|
||||||
set_timeout_service_options(
|
|
||||||
net::io_context& ioc,
|
|
||||||
std::chrono::seconds interval)
|
|
||||||
{
|
|
||||||
net::use_service<
|
|
||||||
detail::timeout_service>(
|
|
||||||
ioc).set_option(interval);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // beast
|
|
||||||
} // boost
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,478 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2018 Vinnie Falco (vinnie dot falco at gmail 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)
|
|
||||||
//
|
|
||||||
// Official repository: https://github.com/boostorg/beast
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef BOOST_BEAST_CORE_IMPL_TIMEOUT_SOCKET_HPP
|
|
||||||
#define BOOST_BEAST_CORE_IMPL_TIMEOUT_SOCKET_HPP
|
|
||||||
|
|
||||||
#include <boost/beast/core/detail/stream_algorithm.hpp>
|
|
||||||
#include <boost/beast/_experimental/core/timeout_work_guard.hpp>
|
|
||||||
#include <boost/asio/executor_work_guard.hpp>
|
|
||||||
#include <memory>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
template<class Protocol, class Executor>
|
|
||||||
template<class Handler>
|
|
||||||
class basic_timeout_socket<Protocol, Executor>::async_op
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
async_op(async_op&&) = default;
|
|
||||||
async_op(async_op const&) = delete;
|
|
||||||
|
|
||||||
template<class Buffers, class DeducedHandler>
|
|
||||||
async_op(
|
|
||||||
Buffers const& b,
|
|
||||||
DeducedHandler&& h,
|
|
||||||
basic_timeout_socket& s,
|
|
||||||
std::true_type)
|
|
||||||
: h_(std::forward<DeducedHandler>(h))
|
|
||||||
, s_(s)
|
|
||||||
, work_(s.rd_timer_)
|
|
||||||
, wg0_(s_.get_executor())
|
|
||||||
, wg1_(get_executor())
|
|
||||||
, saved_(s_.rd_op_)
|
|
||||||
|
|
||||||
{
|
|
||||||
s_.sock_.async_read_some(b, std::move(*this));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Buffers, class DeducedHandler>
|
|
||||||
async_op(
|
|
||||||
Buffers const& b,
|
|
||||||
DeducedHandler&& h,
|
|
||||||
basic_timeout_socket& s,
|
|
||||||
std::false_type)
|
|
||||||
: h_(std::forward<DeducedHandler>(h))
|
|
||||||
, s_(s)
|
|
||||||
, work_(s.wr_timer_)
|
|
||||||
, wg0_(s_.get_executor())
|
|
||||||
, wg1_(get_executor())
|
|
||||||
, saved_(s_.wr_op_)
|
|
||||||
{
|
|
||||||
s_.sock_.async_write_some(b, std::move(*this));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
operator()(error_code ec, std::size_t bytes_transferred)
|
|
||||||
{
|
|
||||||
if(! work_.try_complete())
|
|
||||||
{
|
|
||||||
saved_.emplace(
|
|
||||||
std::move(*this),
|
|
||||||
ec,
|
|
||||||
bytes_transferred);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
h_(ec, bytes_transferred);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
using allocator_type =
|
|
||||||
net::associated_allocator_t<Handler>;
|
|
||||||
|
|
||||||
using executor_type =
|
|
||||||
net::associated_executor_t<Handler,
|
|
||||||
decltype(std::declval<basic_timeout_socket<
|
|
||||||
Protocol, Executor>&>().get_executor())>;
|
|
||||||
|
|
||||||
allocator_type
|
|
||||||
get_allocator() const noexcept
|
|
||||||
{
|
|
||||||
return net::get_associated_allocator(h_);
|
|
||||||
}
|
|
||||||
|
|
||||||
executor_type
|
|
||||||
get_executor() const noexcept
|
|
||||||
{
|
|
||||||
return net::get_associated_executor(
|
|
||||||
h_, s_.get_executor());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Function>
|
|
||||||
friend
|
|
||||||
void asio_handler_invoke(Function&& f, async_op* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_invoke;
|
|
||||||
asio_handler_invoke(f, std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
void* asio_handler_allocate(
|
|
||||||
std::size_t size, async_op* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_allocate;
|
|
||||||
return asio_handler_allocate(
|
|
||||||
size, std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
void asio_handler_deallocate(
|
|
||||||
void* p, std::size_t size, async_op* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_deallocate;
|
|
||||||
asio_handler_deallocate(
|
|
||||||
p, size, std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
bool asio_handler_is_continuation(async_op* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_is_continuation;
|
|
||||||
return asio_handler_is_continuation(
|
|
||||||
std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Handler h_;
|
|
||||||
basic_timeout_socket& s_;
|
|
||||||
timeout_work_guard work_;
|
|
||||||
net::executor_work_guard<Executor> wg0_;
|
|
||||||
net::executor_work_guard<executor_type> wg1_;
|
|
||||||
detail::saved_handler& saved_;
|
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<class Protocol, class Executor>
|
|
||||||
template<class ExecutionContext, class>
|
|
||||||
basic_timeout_socket<Protocol, Executor>::
|
|
||||||
basic_timeout_socket(ExecutionContext& ctx)
|
|
||||||
: ex_(ctx.get_executor())
|
|
||||||
, rd_timer_(ctx)
|
|
||||||
, wr_timer_(ctx)
|
|
||||||
, cn_timer_(ctx)
|
|
||||||
, sock_(ctx)
|
|
||||||
{
|
|
||||||
rd_timer_.set_callback(ex_,
|
|
||||||
[this]
|
|
||||||
{
|
|
||||||
if(rd_op_.empty())
|
|
||||||
sock_.cancel();
|
|
||||||
else
|
|
||||||
rd_op_();
|
|
||||||
});
|
|
||||||
|
|
||||||
wr_timer_.set_callback(ex_,
|
|
||||||
[this]
|
|
||||||
{
|
|
||||||
if(wr_op_.empty())
|
|
||||||
sock_.cancel();
|
|
||||||
else
|
|
||||||
wr_op_();
|
|
||||||
});
|
|
||||||
|
|
||||||
cn_timer_.set_callback(ex_,
|
|
||||||
[this]
|
|
||||||
{
|
|
||||||
if(cn_op_.empty())
|
|
||||||
sock_.cancel();
|
|
||||||
else
|
|
||||||
cn_op_();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Protocol, class Executor>
|
|
||||||
basic_timeout_socket<Protocol, Executor>::
|
|
||||||
~basic_timeout_socket()
|
|
||||||
{
|
|
||||||
rd_timer_.destroy();
|
|
||||||
wr_timer_.destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Protocol, class Executor>
|
|
||||||
template<class MutableBufferSequence, class ReadHandler>
|
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
|
|
||||||
void(error_code, std::size_t))
|
|
||||||
basic_timeout_socket<Protocol, Executor>::
|
|
||||||
async_read_some(
|
|
||||||
MutableBufferSequence const& buffers,
|
|
||||||
ReadHandler&& handler)
|
|
||||||
{
|
|
||||||
static_assert(net::is_mutable_buffer_sequence<
|
|
||||||
MutableBufferSequence>::value,
|
|
||||||
"MutableBufferSequence requirements not met");
|
|
||||||
BOOST_BEAST_HANDLER_INIT(
|
|
||||||
ReadHandler, void(error_code, std::size_t));
|
|
||||||
async_op<BOOST_ASIO_HANDLER_TYPE(ReadHandler,
|
|
||||||
void(error_code, std::size_t))>(buffers,
|
|
||||||
std::forward<ReadHandler>(handler), *this,
|
|
||||||
std::true_type{});
|
|
||||||
return init.result.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Protocol, class Executor>
|
|
||||||
template<class ConstBufferSequence, class WriteHandler>
|
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
|
|
||||||
void(error_code, std::size_t))
|
|
||||||
basic_timeout_socket<Protocol, Executor>::
|
|
||||||
async_write_some(
|
|
||||||
ConstBufferSequence const& buffers,
|
|
||||||
WriteHandler&& handler)
|
|
||||||
{
|
|
||||||
static_assert(net::is_const_buffer_sequence<
|
|
||||||
ConstBufferSequence>::value,
|
|
||||||
"ConstBufferSequence requirements not met");
|
|
||||||
BOOST_BEAST_HANDLER_INIT(
|
|
||||||
WriteHandler, void(error_code, std::size_t));
|
|
||||||
async_op<BOOST_ASIO_HANDLER_TYPE(WriteHandler,
|
|
||||||
void(error_code, std::size_t))>(buffers,
|
|
||||||
std::forward<WriteHandler>(handler), *this,
|
|
||||||
std::false_type{});
|
|
||||||
return init.result.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template<
|
|
||||||
class Protocol, class Executor,
|
|
||||||
class Handler>
|
|
||||||
class connect_op
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
template<
|
|
||||||
class Endpoints,
|
|
||||||
class Condition,
|
|
||||||
class DeducedHandler>
|
|
||||||
connect_op(
|
|
||||||
basic_timeout_socket<Protocol, Executor>& s,
|
|
||||||
Endpoints const& eps,
|
|
||||||
Condition cond,
|
|
||||||
DeducedHandler&& h)
|
|
||||||
: h_(std::forward<DeducedHandler>(h))
|
|
||||||
, work_(s.cnd_timer_)
|
|
||||||
, s_(s)
|
|
||||||
, wg0_(s_.get_executor())
|
|
||||||
, wg1_(get_executor())
|
|
||||||
{
|
|
||||||
net::async_connect(
|
|
||||||
s_.next_layer(), eps, cond,
|
|
||||||
std::move(*this));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Arg>
|
|
||||||
void
|
|
||||||
operator()(error_code ec, Arg&& arg)
|
|
||||||
{
|
|
||||||
if(! work_.try_complete())
|
|
||||||
{
|
|
||||||
s_.cn_op_.emplace(
|
|
||||||
std::move(*this),
|
|
||||||
ec,
|
|
||||||
std::forward<Arg>(arg));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
h_(ec, std::forward<Arg>(arg));
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
using allocator_type =
|
|
||||||
net::associated_allocator_t<Handler>;
|
|
||||||
|
|
||||||
using executor_type =
|
|
||||||
net::associated_executor_t<Handler,
|
|
||||||
decltype(std::declval<basic_timeout_socket<
|
|
||||||
Protocol, Executor>&>().get_executor())>;
|
|
||||||
|
|
||||||
allocator_type
|
|
||||||
get_allocator() const noexcept
|
|
||||||
{
|
|
||||||
return net::get_associated_allocator(h_);
|
|
||||||
}
|
|
||||||
|
|
||||||
executor_type
|
|
||||||
get_executor() const noexcept
|
|
||||||
{
|
|
||||||
return net::get_associated_executor(
|
|
||||||
h_, s_.get_executor());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Function>
|
|
||||||
friend
|
|
||||||
void asio_handler_invoke(
|
|
||||||
Function&& f, connect_op* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_invoke;
|
|
||||||
asio_handler_invoke(
|
|
||||||
f, std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
void* asio_handler_allocate(
|
|
||||||
std::size_t size, connect_op* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_allocate;
|
|
||||||
return asio_handler_allocate(
|
|
||||||
size, std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
void asio_handler_deallocate(
|
|
||||||
void* p, std::size_t size, connect_op* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_deallocate;
|
|
||||||
asio_handler_deallocate(
|
|
||||||
p, size, std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend
|
|
||||||
bool asio_handler_is_continuation(connect_op* op)
|
|
||||||
{
|
|
||||||
using net::asio_handler_is_continuation;
|
|
||||||
return asio_handler_is_continuation(
|
|
||||||
std::addressof(op->h_));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Handler h_;
|
|
||||||
timeout_work_guard work_;
|
|
||||||
basic_timeout_socket<Protocol, Executor>& s_;
|
|
||||||
net::executor_work_guard<Executor> wg0_;
|
|
||||||
net::executor_work_guard<executor_type> wg1_;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct any_endpoint
|
|
||||||
{
|
|
||||||
template<class Error, class Endpoint>
|
|
||||||
bool
|
|
||||||
operator()(
|
|
||||||
Error const&, Endpoint const&) const noexcept
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class Iterator>
|
|
||||||
struct endpoint_range_type
|
|
||||||
{
|
|
||||||
using const_iterator = Iterator;
|
|
||||||
|
|
||||||
Iterator begin_;
|
|
||||||
Iterator end_;
|
|
||||||
|
|
||||||
Iterator begin() const noexcept
|
|
||||||
{
|
|
||||||
return begin_;
|
|
||||||
}
|
|
||||||
|
|
||||||
Iterator end() const noexcept
|
|
||||||
{
|
|
||||||
return end_;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class Iterator>
|
|
||||||
endpoint_range_type<Iterator>
|
|
||||||
endpoint_range(Iterator first, Iterator last)
|
|
||||||
{
|
|
||||||
return endpoint_range_type<
|
|
||||||
Iterator>(first, last);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // detail
|
|
||||||
|
|
||||||
template<
|
|
||||||
class Protocol, class Executor,
|
|
||||||
class EndpointSequence,
|
|
||||||
class RangeConnectHandler, class>
|
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,
|
|
||||||
void(error_code, typename Protocol::endpoint))
|
|
||||||
async_connect(
|
|
||||||
basic_timeout_socket<Protocol, Executor>& s,
|
|
||||||
EndpointSequence const& endpoints,
|
|
||||||
RangeConnectHandler&& handler)
|
|
||||||
{
|
|
||||||
BOOST_BEAST_HANDLER_INIT(RangeConnectHandler,
|
|
||||||
void(error_code, typename Protocol::endpoint));
|
|
||||||
detail::connect_op<Protocol, Executor,
|
|
||||||
BOOST_ASIO_HANDLER_TYPE(RangeConnectHandler,
|
|
||||||
void(error_code,
|
|
||||||
typename Protocol::endpoint))>(
|
|
||||||
s, endpoints, detail::any_endpoint{},
|
|
||||||
std::forward<RangeConnectHandler>(handler));
|
|
||||||
return init.result.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<
|
|
||||||
class Protocol, class Executor,
|
|
||||||
class EndpointSequence,
|
|
||||||
class ConnectCondition,
|
|
||||||
class RangeConnectHandler, class>
|
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,
|
|
||||||
void (error_code, typename Protocol::endpoint))
|
|
||||||
async_connect(
|
|
||||||
basic_timeout_socket<Protocol, Executor>& s,
|
|
||||||
EndpointSequence const& endpoints,
|
|
||||||
ConnectCondition connect_condition,
|
|
||||||
RangeConnectHandler&& handler)
|
|
||||||
{
|
|
||||||
BOOST_BEAST_HANDLER_INIT(RangeConnectHandler,
|
|
||||||
void(error_code, typename Protocol::endpoint));
|
|
||||||
detail::connect_op<Protocol, Executor,
|
|
||||||
BOOST_ASIO_HANDLER_TYPE(RangeConnectHandler,
|
|
||||||
void(error_code,
|
|
||||||
typename Protocol::endpoint))>(
|
|
||||||
s, endpoints, connect_condition,
|
|
||||||
std::forward<RangeConnectHandler>(handler));
|
|
||||||
return init.result.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<
|
|
||||||
class Protocol, class Executor,
|
|
||||||
class Iterator,
|
|
||||||
class IteratorConnectHandler, class>
|
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
|
|
||||||
void (error_code, Iterator))
|
|
||||||
async_connect(
|
|
||||||
basic_timeout_socket<Protocol, Executor>& s,
|
|
||||||
Iterator begin, Iterator end,
|
|
||||||
IteratorConnectHandler&& handler)
|
|
||||||
{
|
|
||||||
BOOST_BEAST_HANDLER_INIT(IteratorConnectHandler,
|
|
||||||
void(error_code, Iterator));
|
|
||||||
detail::connect_op<Protocol, Executor,
|
|
||||||
BOOST_ASIO_HANDLER_TYPE(IteratorConnectHandler,
|
|
||||||
void(error_code, Iterator))>(
|
|
||||||
s, detail::endpoint_range(begin, end), detail::any_endpoint{},
|
|
||||||
std::forward<IteratorConnectHandler>(handler));
|
|
||||||
return init.result.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<
|
|
||||||
class Protocol, class Executor,
|
|
||||||
class Iterator,
|
|
||||||
class ConnectCondition,
|
|
||||||
class IteratorConnectHandler, class>
|
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
|
|
||||||
void (error_code, Iterator))
|
|
||||||
async_connect(
|
|
||||||
basic_timeout_socket<Protocol, Executor>& s,
|
|
||||||
Iterator begin, Iterator end,
|
|
||||||
ConnectCondition connect_condition,
|
|
||||||
IteratorConnectHandler&& handler)
|
|
||||||
{
|
|
||||||
BOOST_BEAST_HANDLER_INIT(IteratorConnectHandler,
|
|
||||||
void(error_code, Iterator));
|
|
||||||
detail::connect_op<Protocol, Executor,
|
|
||||||
BOOST_ASIO_HANDLER_TYPE(IteratorConnectHandler,
|
|
||||||
void(error_code, Iterator))>(
|
|
||||||
s, detail::endpoint_range(begin, end), connect_condition,
|
|
||||||
std::forward<IteratorConnectHandler>(handler));
|
|
||||||
return init.result.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // beast
|
|
||||||
} // boost
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,135 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2018 Vinnie Falco (vinnie dot falco at gmail 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)
|
|
||||||
//
|
|
||||||
// Official repository: https://github.com/boostorg/beast
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef BOOST_BEAST_CORE_TIMEOUT_SERVICE_HPP
|
|
||||||
#define BOOST_BEAST_CORE_TIMEOUT_SERVICE_HPP
|
|
||||||
|
|
||||||
#include <boost/beast/core/detail/config.hpp>
|
|
||||||
#include <boost/asio/io_context.hpp> // #include <boost/asio/execution_context.hpp>
|
|
||||||
#include <cstddef>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
class timeout_service;
|
|
||||||
} // detail
|
|
||||||
|
|
||||||
class timeout_work_guard;
|
|
||||||
|
|
||||||
class timeout_handle
|
|
||||||
{
|
|
||||||
std::size_t id_ = 0;
|
|
||||||
detail::timeout_service* svc_ = nullptr;
|
|
||||||
|
|
||||||
timeout_handle(
|
|
||||||
std::size_t id,
|
|
||||||
detail::timeout_service& svc)
|
|
||||||
: id_(id)
|
|
||||||
, svc_(&svc)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
detail::timeout_service&
|
|
||||||
service() const
|
|
||||||
{
|
|
||||||
return *svc_;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend class detail::timeout_service;
|
|
||||||
friend class timeout_work_guard;
|
|
||||||
|
|
||||||
public:
|
|
||||||
timeout_handle() = default;
|
|
||||||
timeout_handle(timeout_handle const&) = default;
|
|
||||||
timeout_handle& operator=(timeout_handle const&) = default;
|
|
||||||
|
|
||||||
timeout_handle(std::nullptr_t)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
timeout_handle&
|
|
||||||
operator=(std::nullptr_t)
|
|
||||||
{
|
|
||||||
id_ = 0;
|
|
||||||
svc_ = nullptr;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// VFALCO should be execution_context
|
|
||||||
BOOST_BEAST_DECL
|
|
||||||
explicit
|
|
||||||
timeout_handle(net::io_context& ioc);
|
|
||||||
|
|
||||||
BOOST_BEAST_DECL
|
|
||||||
void
|
|
||||||
destroy();
|
|
||||||
|
|
||||||
template<class Executor, class CancelHandler>
|
|
||||||
void
|
|
||||||
set_callback(
|
|
||||||
Executor const& ex, CancelHandler&& handler);
|
|
||||||
|
|
||||||
explicit
|
|
||||||
operator bool() const noexcept
|
|
||||||
{
|
|
||||||
return svc_ != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend bool operator==(
|
|
||||||
timeout_handle const& lhs,
|
|
||||||
std::nullptr_t) noexcept
|
|
||||||
{
|
|
||||||
return lhs.svc_ == nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend bool operator==(
|
|
||||||
std::nullptr_t,
|
|
||||||
timeout_handle const& rhs) noexcept
|
|
||||||
{
|
|
||||||
return rhs.svc_ == nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend bool operator!=(
|
|
||||||
timeout_handle const& lhs,
|
|
||||||
std::nullptr_t) noexcept
|
|
||||||
{
|
|
||||||
return lhs.svc_ != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend bool operator!=(
|
|
||||||
std::nullptr_t,
|
|
||||||
timeout_handle const& rhs) noexcept
|
|
||||||
{
|
|
||||||
return rhs.svc_ != nullptr;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Set timeout service options in an execution context.
|
|
||||||
|
|
||||||
This changes the time interval for all timeouts associated
|
|
||||||
with the execution context. The option must be set before any
|
|
||||||
timeout objects are constructed.
|
|
||||||
|
|
||||||
@param ctx The execution context.
|
|
||||||
|
|
||||||
@param interval The approximate amount of time until a timeout occurs.
|
|
||||||
*/
|
|
||||||
BOOST_BEAST_DECL
|
|
||||||
void
|
|
||||||
set_timeout_service_options(
|
|
||||||
net::io_context& ctx, // VFALCO should be execution_context
|
|
||||||
std::chrono::seconds interval);
|
|
||||||
|
|
||||||
} // beast
|
|
||||||
} // boost
|
|
||||||
|
|
||||||
#include <boost/beast/_experimental/core/impl/timeout_service.hpp>
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,632 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2018 Vinnie Falco (vinnie dot falco at gmail 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)
|
|
||||||
//
|
|
||||||
// Official repository: https://github.com/boostorg/beast
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef BOOST_BEAST_CORE_TIMEOUT_SOCKET_HPP
|
|
||||||
#define BOOST_BEAST_CORE_TIMEOUT_SOCKET_HPP
|
|
||||||
|
|
||||||
#include <boost/beast/core/detail/config.hpp>
|
|
||||||
#include <boost/beast/core/error.hpp>
|
|
||||||
#include <boost/beast/core/type_traits.hpp>
|
|
||||||
#include <boost/beast/_experimental/core/timeout_service.hpp>
|
|
||||||
#include <boost/beast/_experimental/core/detail/saved_handler.hpp>
|
|
||||||
#include <boost/asio/async_result.hpp>
|
|
||||||
#include <boost/asio/basic_stream_socket.hpp>
|
|
||||||
#include <boost/asio/connect.hpp>
|
|
||||||
#include <boost/asio/executor.hpp>
|
|
||||||
#include <chrono>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace asio {
|
|
||||||
namespace ip {
|
|
||||||
class tcp;
|
|
||||||
} // ip
|
|
||||||
} // asio
|
|
||||||
} // boost
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
template<class, class, class>
|
|
||||||
class connect_op;
|
|
||||||
} // detail
|
|
||||||
|
|
||||||
/** A socket wrapper which automatically times out on asynchronous reads.
|
|
||||||
|
|
||||||
This wraps a normal stream socket and implements a simple and efficient
|
|
||||||
timeout for asynchronous read operations.
|
|
||||||
|
|
||||||
@note Meets the requirements of @b AsyncReadStream and @b AsyncWriteStream
|
|
||||||
*/
|
|
||||||
template<
|
|
||||||
class Protocol,
|
|
||||||
class Executor = net::executor
|
|
||||||
>
|
|
||||||
class basic_timeout_socket
|
|
||||||
{
|
|
||||||
template<class> class async_op;
|
|
||||||
template<class, class, class>
|
|
||||||
friend class detail::connect_op;
|
|
||||||
|
|
||||||
Executor ex_; // must come first
|
|
||||||
timeout_handle rd_timer_;
|
|
||||||
timeout_handle wr_timer_;
|
|
||||||
timeout_handle cn_timer_;
|
|
||||||
detail::saved_handler rd_op_;
|
|
||||||
detail::saved_handler wr_op_;
|
|
||||||
detail::saved_handler cn_op_;
|
|
||||||
net::basic_stream_socket<Protocol> sock_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// The type of the next layer.
|
|
||||||
using next_layer_type = net::basic_stream_socket<Protocol>;
|
|
||||||
|
|
||||||
/// The type of the lowest layer.
|
|
||||||
using lowest_layer_type = get_lowest_layer<next_layer_type>;
|
|
||||||
|
|
||||||
/// The protocol used by the stream.
|
|
||||||
using protocol_type = Protocol;
|
|
||||||
|
|
||||||
/// The type of the executor associated with the object.
|
|
||||||
using executor_type = Executor;
|
|
||||||
|
|
||||||
/** Destructor
|
|
||||||
|
|
||||||
The behavior of destruction while asynchronous operations
|
|
||||||
are pending is undefined.
|
|
||||||
*/
|
|
||||||
~basic_timeout_socket();
|
|
||||||
|
|
||||||
// VFALCO we only support default-construction
|
|
||||||
// of the contained socket for now.
|
|
||||||
// This constructor needs a protocol parameter.
|
|
||||||
//
|
|
||||||
/** Constructor
|
|
||||||
*/
|
|
||||||
template<class ExecutionContext
|
|
||||||
#if ! BOOST_BEAST_DOXYGEN
|
|
||||||
, class = typename std::enable_if<
|
|
||||||
std::is_convertible<
|
|
||||||
ExecutionContext&,
|
|
||||||
net::execution_context&>::value &&
|
|
||||||
std::is_constructible<
|
|
||||||
executor_type,
|
|
||||||
typename ExecutionContext::executor_type>::value
|
|
||||||
>::type
|
|
||||||
#endif
|
|
||||||
>
|
|
||||||
explicit
|
|
||||||
basic_timeout_socket(ExecutionContext& ctx);
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/** Get the executor associated with the object.
|
|
||||||
|
|
||||||
This function may be used to obtain the executor object that the
|
|
||||||
stream uses to dispatch handlers for asynchronous operations.
|
|
||||||
|
|
||||||
@return A copy of the executor that stream will use to dispatch handlers.
|
|
||||||
*/
|
|
||||||
executor_type
|
|
||||||
get_executor() const noexcept
|
|
||||||
{
|
|
||||||
return ex_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a reference to the next layer
|
|
||||||
|
|
||||||
This function returns a reference to the next layer
|
|
||||||
in a stack of stream layers.
|
|
||||||
|
|
||||||
@return A reference to the next layer in the stack of
|
|
||||||
stream layers.
|
|
||||||
*/
|
|
||||||
next_layer_type&
|
|
||||||
next_layer() noexcept
|
|
||||||
{
|
|
||||||
return sock_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a reference to the next layer
|
|
||||||
|
|
||||||
This function returns a reference to the next layer in a
|
|
||||||
stack of stream layers.
|
|
||||||
|
|
||||||
@return A reference to the next layer in the stack of
|
|
||||||
stream layers.
|
|
||||||
*/
|
|
||||||
next_layer_type const&
|
|
||||||
next_layer() const noexcept
|
|
||||||
{
|
|
||||||
return sock_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a reference to the lowest layer
|
|
||||||
|
|
||||||
This function returns a reference to the lowest layer
|
|
||||||
in a stack of stream layers.
|
|
||||||
|
|
||||||
@return A reference to the lowest layer in the stack of
|
|
||||||
stream layers.
|
|
||||||
*/
|
|
||||||
lowest_layer_type&
|
|
||||||
lowest_layer() noexcept
|
|
||||||
{
|
|
||||||
return sock_.lowest_layer();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a reference to the lowest layer
|
|
||||||
|
|
||||||
This function returns a reference to the lowest layer
|
|
||||||
in a stack of stream layers.
|
|
||||||
|
|
||||||
@return A reference to the lowest layer in the stack of
|
|
||||||
stream layers. Ownership is not transferred to the caller.
|
|
||||||
*/
|
|
||||||
lowest_layer_type const&
|
|
||||||
lowest_layer() const noexcept
|
|
||||||
{
|
|
||||||
return sock_.lowest_layer();
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/** Start an asynchronous read.
|
|
||||||
|
|
||||||
This function is used to asynchronously read data from the stream socket.
|
|
||||||
The function call always returns immediately.
|
|
||||||
|
|
||||||
@param buffers One or more buffers into which the data will be read.
|
|
||||||
Although the buffers object may be copied as necessary, ownership of the
|
|
||||||
underlying memory blocks is retained by the caller, which must guarantee
|
|
||||||
that they remain valid until the handler is called.
|
|
||||||
|
|
||||||
@param handler The handler to be called when the read operation completes.
|
|
||||||
Copies will be made of the handler as required. The function signature of
|
|
||||||
the handler must be:
|
|
||||||
@code void handler(
|
|
||||||
const boost::system::error_code& error, // Result of operation.
|
|
||||||
std::size_t bytes_transferred // Number of bytes read.
|
|
||||||
); @endcode
|
|
||||||
Regardless of whether the asynchronous operation completes immediately or
|
|
||||||
not, the handler will not be invoked from within this function. Invocation
|
|
||||||
of the handler will be performed in a manner equivalent to using
|
|
||||||
net::io_context::post().
|
|
||||||
*/
|
|
||||||
template<class MutableBufferSequence, class ReadHandler>
|
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
|
|
||||||
void(boost::system::error_code, std::size_t))
|
|
||||||
async_read_some(
|
|
||||||
MutableBufferSequence const& buffers,
|
|
||||||
ReadHandler&& handler);
|
|
||||||
|
|
||||||
/** Start an asynchronous write.
|
|
||||||
|
|
||||||
This function is used to asynchronously write data to the stream socket.
|
|
||||||
The function call always returns immediately.
|
|
||||||
|
|
||||||
@param buffers One or more data buffers to be written to the socket.
|
|
||||||
Although the buffers object may be copied as necessary, ownership of the
|
|
||||||
underlying memory blocks is retained by the caller, which must guarantee
|
|
||||||
that they remain valid until the handler is called.
|
|
||||||
|
|
||||||
@param handler The handler to be called when the write operation completes.
|
|
||||||
Copies will be made of the handler as required. The function signature of
|
|
||||||
the handler must be:
|
|
||||||
@code void handler(
|
|
||||||
const boost::system::error_code& error, // Result of operation.
|
|
||||||
std::size_t bytes_transferred // Number of bytes written.
|
|
||||||
); @endcode
|
|
||||||
Regardless of whether the asynchronous operation completes immediately or
|
|
||||||
not, the handler will not be invoked from within this function. Invocation
|
|
||||||
of the handler will be performed in a manner equivalent to using
|
|
||||||
net::io_context::post().
|
|
||||||
*/
|
|
||||||
template<class ConstBufferSequence, class WriteHandler>
|
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
|
|
||||||
void(boost::system::error_code, std::size_t))
|
|
||||||
async_write_some(
|
|
||||||
ConstBufferSequence const& buffers,
|
|
||||||
WriteHandler&& handler);
|
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/// A TCP/IP socket wrapper which has a built-in asynchronous timeout
|
|
||||||
using timeout_socket = basic_timeout_socket<
|
|
||||||
net::ip::tcp,
|
|
||||||
net::io_context::executor_type>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
@defgroup async_connect boost::beast::async_connect
|
|
||||||
|
|
||||||
@brief Asynchronously establishes a socket connection by trying each
|
|
||||||
endpoint in a sequence, and terminating if a timeout occurs.
|
|
||||||
*/
|
|
||||||
/* @{ */
|
|
||||||
/** Asynchronously establishes a socket connection by trying each endpoint in a sequence.
|
|
||||||
|
|
||||||
This function attempts to connect a socket to one of a sequence of
|
|
||||||
endpoints. It does this by repeated calls to the underlying socket's
|
|
||||||
@c async_connect member function, once for each endpoint in the sequence,
|
|
||||||
until a connection is successfully established or a timeout occurs.
|
|
||||||
|
|
||||||
@param s The @ref basic_timeout_socket to be connected. If the socket
|
|
||||||
is already open, it will be closed.
|
|
||||||
|
|
||||||
@param endpoints A sequence of endpoints.
|
|
||||||
|
|
||||||
@param handler The handler to be called when the connect operation
|
|
||||||
completes. Ownership of the handler may be transferred. The function
|
|
||||||
signature of the handler must be:
|
|
||||||
@code
|
|
||||||
void handler(
|
|
||||||
// Result of operation. if the sequence is empty, set to
|
|
||||||
// net::error::not_found. Otherwise, contains the
|
|
||||||
// error from the last connection attempt.
|
|
||||||
error_code const& error,
|
|
||||||
|
|
||||||
// On success, the successfully connected endpoint.
|
|
||||||
// Otherwise, a default-constructed endpoint.
|
|
||||||
typename Protocol::endpoint const& endpoint
|
|
||||||
);
|
|
||||||
@endcode
|
|
||||||
|
|
||||||
Regardless of whether the asynchronous operation completes immediately or
|
|
||||||
not, the handler will not be invoked from within this function. Invocation
|
|
||||||
of the handler will be performed in a manner equivalent to using
|
|
||||||
`net::io_context::post()`.
|
|
||||||
|
|
||||||
@par Example
|
|
||||||
|
|
||||||
@code
|
|
||||||
net::tcp::resolver r(ioc);
|
|
||||||
net::tcp::resolver::query q("host", "service");
|
|
||||||
timeout_socket s(ioc.get_executor());
|
|
||||||
|
|
||||||
// ...
|
|
||||||
|
|
||||||
r.async_resolve(q, resolve_handler);
|
|
||||||
|
|
||||||
// ...
|
|
||||||
|
|
||||||
void resolve_handler(
|
|
||||||
boost::system::error_code const& ec,
|
|
||||||
tcp::resolver::results_type results)
|
|
||||||
{
|
|
||||||
if (!ec)
|
|
||||||
{
|
|
||||||
async_connect(s, results, connect_handler);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ...
|
|
||||||
|
|
||||||
void connect_handler(
|
|
||||||
boost::system::error_code const& ec,
|
|
||||||
tcp::endpoint const& endpoint)
|
|
||||||
{
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
@endcode
|
|
||||||
*/
|
|
||||||
template<
|
|
||||||
class Protocol, class Executor,
|
|
||||||
class EndpointSequence,
|
|
||||||
class RangeConnectHandler
|
|
||||||
#if ! BOOST_BEAST_DOXYGEN
|
|
||||||
,class = typename std::enable_if<
|
|
||||||
net::is_endpoint_sequence<
|
|
||||||
EndpointSequence>::value>::type
|
|
||||||
#endif
|
|
||||||
>
|
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,
|
|
||||||
void (boost::system::error_code, class Protocol::endpoint))
|
|
||||||
async_connect(
|
|
||||||
basic_timeout_socket<Protocol, Executor>& s,
|
|
||||||
EndpointSequence const& endpoints,
|
|
||||||
RangeConnectHandler&& handler);
|
|
||||||
|
|
||||||
/** Asynchronously establishes a socket connection by trying each endpoint in a sequence.
|
|
||||||
|
|
||||||
This function attempts to connect a socket to one of a sequence of
|
|
||||||
endpoints. It does this by repeated calls to the underlying socket's
|
|
||||||
@c async_connect member function, once for each endpoint in the sequence,
|
|
||||||
until a connection is successfully established or a timeout occurs.
|
|
||||||
|
|
||||||
@param s The @ref basic_timeout_socket to be connected. If the socket
|
|
||||||
is already open, it will be closed.
|
|
||||||
|
|
||||||
@param endpoints A sequence of endpoints.
|
|
||||||
|
|
||||||
@param connect_condition A function object that is called prior to each
|
|
||||||
connection attempt. The signature of the function object must be:
|
|
||||||
|
|
||||||
@code
|
|
||||||
bool connect_condition(
|
|
||||||
boost::system::error_code const& ec,
|
|
||||||
typename Protocol::endpoint const& next);
|
|
||||||
@endcode
|
|
||||||
|
|
||||||
The @c ec parameter contains the result from the most recent connect
|
|
||||||
operation. Before the first connection attempt, @c ec is always set to
|
|
||||||
indicate success. The @c next parameter is the next endpoint to be tried.
|
|
||||||
The function object should return true if the next endpoint should be tried,
|
|
||||||
and false if it should be skipped.
|
|
||||||
|
|
||||||
@param handler The handler to be called when the connect operation
|
|
||||||
completes. Ownership of the handler may be transferred. The function
|
|
||||||
signature of the handler must be:
|
|
||||||
@code
|
|
||||||
void handler(
|
|
||||||
// Result of operation. if the sequence is empty, set to
|
|
||||||
// net::error::not_found. Otherwise, contains the
|
|
||||||
// error from the last connection attempt.
|
|
||||||
error_code const& error,
|
|
||||||
|
|
||||||
// On success, the successfully connected endpoint.
|
|
||||||
// Otherwise, a default-constructed endpoint.
|
|
||||||
typename Protocol::endpoint const& endpoint
|
|
||||||
);
|
|
||||||
@endcode
|
|
||||||
|
|
||||||
Regardless of whether the asynchronous operation completes immediately or
|
|
||||||
not, the handler will not be invoked from within this function. Invocation
|
|
||||||
of the handler will be performed in a manner equivalent to using
|
|
||||||
`net::io_context::post()`.
|
|
||||||
|
|
||||||
@par Example
|
|
||||||
|
|
||||||
The following connect condition function object can be used to output
|
|
||||||
information about the individual connection attempts:
|
|
||||||
|
|
||||||
@code
|
|
||||||
struct my_connect_condition
|
|
||||||
{
|
|
||||||
bool operator()(
|
|
||||||
boost::system::error_code const& ec,
|
|
||||||
net::ip::tcp::endpoint const& next)
|
|
||||||
{
|
|
||||||
if (ec) std::cout << "Error: " << ec.message() << std::endl;
|
|
||||||
std::cout << "Trying: " << next << std::endl;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@endcode
|
|
||||||
|
|
||||||
It would be used with the @ref boost::beast::async_connect
|
|
||||||
function as follows:
|
|
||||||
|
|
||||||
@code
|
|
||||||
net::tcp::resolver r(ioc);
|
|
||||||
net::tcp::resolver::query q("host", "service");
|
|
||||||
timeout_socket s(ioc.get_executor());
|
|
||||||
|
|
||||||
// ...
|
|
||||||
|
|
||||||
r.async_resolve(q, resolve_handler);
|
|
||||||
|
|
||||||
// ...
|
|
||||||
|
|
||||||
void resolve_handler(
|
|
||||||
boost::system::error_code const& ec,
|
|
||||||
tcp::resolver::results_type results)
|
|
||||||
{
|
|
||||||
if (!ec)
|
|
||||||
{
|
|
||||||
async_connect(s, results, my_connect_condition{}, connect_handler);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ...
|
|
||||||
|
|
||||||
void connect_handler(
|
|
||||||
boost::system::error_code const& ec,
|
|
||||||
tcp::endpoint const& endpoint)
|
|
||||||
{
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
@endcode
|
|
||||||
*/
|
|
||||||
template<
|
|
||||||
class Protocol, class Executor,
|
|
||||||
class EndpointSequence,
|
|
||||||
class ConnectCondition,
|
|
||||||
class RangeConnectHandler
|
|
||||||
#if ! BOOST_BEAST_DOXYGEN
|
|
||||||
,class = typename std::enable_if<
|
|
||||||
net::is_endpoint_sequence<
|
|
||||||
EndpointSequence>::value>::type
|
|
||||||
#endif
|
|
||||||
>
|
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,
|
|
||||||
void (boost::system::error_code, class Protocol::endpoint))
|
|
||||||
async_connect(
|
|
||||||
basic_timeout_socket<Protocol, Executor>& s,
|
|
||||||
EndpointSequence const& endpoints,
|
|
||||||
ConnectCondition connect_condition,
|
|
||||||
RangeConnectHandler&& handler);
|
|
||||||
|
|
||||||
/** Asynchronously establishes a socket connection by trying each endpoint in a sequence.
|
|
||||||
|
|
||||||
This function attempts to connect a socket to one of a sequence of
|
|
||||||
endpoints. It does this by repeated calls to the underlying socket's
|
|
||||||
@c async_connect member function, once for each endpoint in the sequence,
|
|
||||||
until a connection is successfully established or a timeout occurs.
|
|
||||||
|
|
||||||
@param s The @ref timeout_socket to be connected. If the socket
|
|
||||||
is already open, it will be closed.
|
|
||||||
|
|
||||||
@param begin An iterator pointing to the start of a sequence of endpoints.
|
|
||||||
|
|
||||||
@param end An iterator pointing to the end of a sequence of endpoints.
|
|
||||||
|
|
||||||
@param handler The handler to be called when the connect operation
|
|
||||||
completes. Ownership of the handler may be transferred. The function
|
|
||||||
signature of the handler must be:
|
|
||||||
@code
|
|
||||||
void handler(
|
|
||||||
// Result of operation. if the sequence is empty, set to
|
|
||||||
// net::error::not_found. Otherwise, contains the
|
|
||||||
// error from the last connection attempt.
|
|
||||||
error_code const& error,
|
|
||||||
|
|
||||||
// On success, an iterator denoting the successfully
|
|
||||||
// connected endpoint. Otherwise, the end iterator.
|
|
||||||
Iterator iterator
|
|
||||||
);
|
|
||||||
@endcode
|
|
||||||
|
|
||||||
Regardless of whether the asynchronous operation completes immediately or
|
|
||||||
not, the handler will not be invoked from within this function. Invocation
|
|
||||||
of the handler will be performed in a manner equivalent to using
|
|
||||||
`net::io_context::post()`.
|
|
||||||
|
|
||||||
@par Example
|
|
||||||
|
|
||||||
@code
|
|
||||||
std::vector<tcp::endpoint> endpoints = ...;
|
|
||||||
timeout_socket s(ioc.get_executor());
|
|
||||||
|
|
||||||
async_connect(s,
|
|
||||||
endpoints.begin(), endpoints.end(),
|
|
||||||
connect_handler);
|
|
||||||
|
|
||||||
void connect_handler(
|
|
||||||
boost::system::error_code const& ec,
|
|
||||||
std::vector<tcp::endpoint>::iterator)
|
|
||||||
{
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
@endcode
|
|
||||||
*/
|
|
||||||
template<
|
|
||||||
class Protocol, class Executor,
|
|
||||||
class Iterator,
|
|
||||||
class IteratorConnectHandler
|
|
||||||
#if ! BOOST_BEAST_DOXYGEN
|
|
||||||
,class = typename std::enable_if<
|
|
||||||
! net::is_endpoint_sequence<
|
|
||||||
Iterator>::value>::type
|
|
||||||
#endif
|
|
||||||
>
|
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
|
|
||||||
void (boost::system::error_code, Iterator))
|
|
||||||
async_connect(
|
|
||||||
basic_timeout_socket<Protocol, Executor>& s,
|
|
||||||
Iterator begin, Iterator end,
|
|
||||||
IteratorConnectHandler&& handler);
|
|
||||||
|
|
||||||
/** Asynchronously establishes a socket connection by trying each endpoint in a sequence.
|
|
||||||
|
|
||||||
This function attempts to connect a socket to one of a sequence of
|
|
||||||
endpoints. It does this by repeated calls to the underlying socket's
|
|
||||||
@c async_connect member function, once for each endpoint in the sequence,
|
|
||||||
until a connection is successfully established or a timeout occurs.
|
|
||||||
|
|
||||||
@param s The @ref basic_timeout_socket to be connected. If the socket
|
|
||||||
is already open, it will be closed.
|
|
||||||
|
|
||||||
@param begin An iterator pointing to the start of a sequence of endpoints.
|
|
||||||
|
|
||||||
@param end An iterator pointing to the end of a sequence of endpoints.
|
|
||||||
|
|
||||||
@param connect_condition A function object that is called prior to each
|
|
||||||
connection attempt. The signature of the function object must be:
|
|
||||||
|
|
||||||
@code
|
|
||||||
bool connect_condition(
|
|
||||||
boost::system::error_code const& ec,
|
|
||||||
Iterator next);
|
|
||||||
@endcode
|
|
||||||
|
|
||||||
@param handler The handler to be called when the connect operation
|
|
||||||
completes. Ownership of the handler may be transferred. The function
|
|
||||||
signature of the handler must be:
|
|
||||||
@code
|
|
||||||
void handler(
|
|
||||||
// Result of operation. if the sequence is empty, set to
|
|
||||||
// net::error::not_found. Otherwise, contains the
|
|
||||||
// error from the last connection attempt.
|
|
||||||
error_code const& error,
|
|
||||||
|
|
||||||
// On success, an iterator denoting the successfully
|
|
||||||
// connected endpoint. Otherwise, the end iterator.
|
|
||||||
Iterator iterator
|
|
||||||
);
|
|
||||||
@endcode
|
|
||||||
|
|
||||||
Regardless of whether the asynchronous operation completes immediately or
|
|
||||||
not, the handler will not be invoked from within this function. Invocation
|
|
||||||
of the handler will be performed in a manner equivalent to using
|
|
||||||
`net::io_context::post()`.
|
|
||||||
|
|
||||||
@par Example
|
|
||||||
|
|
||||||
The following connect condition function object can be used to output
|
|
||||||
information about the individual connection attempts:
|
|
||||||
|
|
||||||
@code
|
|
||||||
struct my_connect_condition
|
|
||||||
{
|
|
||||||
bool operator()(
|
|
||||||
boost::system::error_code const& ec,
|
|
||||||
net::ip::tcp::endpoint const& next)
|
|
||||||
{
|
|
||||||
if (ec) std::cout << "Error: " << ec.message() << std::endl;
|
|
||||||
std::cout << "Trying: " << next << std::endl;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@endcode
|
|
||||||
|
|
||||||
It would be used with the @ref boost::beast::async_connect
|
|
||||||
function as follows:
|
|
||||||
|
|
||||||
@code
|
|
||||||
std::vector<tcp::endpoint> endpoints = ...;
|
|
||||||
timeout_socket s(ioc.get_executor());
|
|
||||||
|
|
||||||
async_connect(s, endpoints.begin(), endpoints.end(),
|
|
||||||
my_connect_condition{}, connect_handler);
|
|
||||||
|
|
||||||
void connect_handler(
|
|
||||||
boost::system::error_code const& ec,
|
|
||||||
std::vector<tcp::endpoint>::iterator)
|
|
||||||
{
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
@endcode
|
|
||||||
*/
|
|
||||||
template<
|
|
||||||
class Protocol, class Executor,
|
|
||||||
class Iterator,
|
|
||||||
class ConnectCondition,
|
|
||||||
class IteratorConnectHandler
|
|
||||||
#if ! BOOST_BEAST_DOXYGEN
|
|
||||||
,class = typename std::enable_if<
|
|
||||||
! net::is_endpoint_sequence<
|
|
||||||
Iterator>::value>::type
|
|
||||||
#endif
|
|
||||||
>
|
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
|
|
||||||
void (boost::system::error_code, Iterator))
|
|
||||||
async_connect(
|
|
||||||
basic_timeout_socket<Protocol, Executor>& s,
|
|
||||||
Iterator begin, Iterator end,
|
|
||||||
ConnectCondition connect_condition,
|
|
||||||
IteratorConnectHandler&& handler);
|
|
||||||
/* @} */
|
|
||||||
|
|
||||||
} // beast
|
|
||||||
} // boost
|
|
||||||
|
|
||||||
#include <boost/beast/_experimental/core/impl/timeout_socket.hpp>
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,73 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2018 Vinnie Falco (vinnie dot falco at gmail 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)
|
|
||||||
//
|
|
||||||
// Official repository: https://github.com/boostorg/beast
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef BOOST_BEAST_CORE_TIMEOUT_WORK_GUARD_HPP
|
|
||||||
#define BOOST_BEAST_CORE_TIMEOUT_WORK_GUARD_HPP
|
|
||||||
|
|
||||||
#include <boost/beast/core/detail/config.hpp>
|
|
||||||
#include <boost/beast/_experimental/core/timeout_service.hpp>
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
class timeout_work_guard
|
|
||||||
{
|
|
||||||
timeout_handle h_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
timeout_work_guard(timeout_work_guard const&) = delete;
|
|
||||||
timeout_work_guard& operator=(timeout_work_guard const&) = delete;
|
|
||||||
|
|
||||||
~timeout_work_guard()
|
|
||||||
{
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
timeout_work_guard(timeout_work_guard&& other)
|
|
||||||
: h_(other.h_)
|
|
||||||
{
|
|
||||||
other.h_ = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit
|
|
||||||
timeout_work_guard(timeout_handle h)
|
|
||||||
: h_(h)
|
|
||||||
{
|
|
||||||
h_.service().on_work_started(h_);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
owns_work() const
|
|
||||||
{
|
|
||||||
return h_ != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
reset()
|
|
||||||
{
|
|
||||||
if(h_)
|
|
||||||
h_.service().on_work_stopped(h_);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
try_complete()
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(h_ != nullptr);
|
|
||||||
auto result =
|
|
||||||
h_.service().on_try_work_complete(h_);
|
|
||||||
h_ = nullptr;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // beast
|
|
||||||
} // boost
|
|
||||||
|
|
||||||
#endif
|
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include <boost/beast/core/detail/config.hpp>
|
#include <boost/beast/core/detail/config.hpp>
|
||||||
|
|
||||||
|
#include <boost/beast/core/basic_stream_socket.hpp>
|
||||||
#include <boost/beast/core/bind_handler.hpp>
|
#include <boost/beast/core/bind_handler.hpp>
|
||||||
#include <boost/beast/core/buffer_traits.hpp>
|
#include <boost/beast/core/buffer_traits.hpp>
|
||||||
#include <boost/beast/core/buffered_read_stream.hpp>
|
#include <boost/beast/core/buffered_read_stream.hpp>
|
||||||
@ -37,6 +38,7 @@
|
|||||||
#include <boost/beast/core/span.hpp>
|
#include <boost/beast/core/span.hpp>
|
||||||
#include <boost/beast/core/static_buffer.hpp>
|
#include <boost/beast/core/static_buffer.hpp>
|
||||||
#include <boost/beast/core/static_string.hpp>
|
#include <boost/beast/core/static_string.hpp>
|
||||||
|
#include <boost/beast/core/stream_socket.hpp>
|
||||||
#include <boost/beast/core/string.hpp>
|
#include <boost/beast/core/string.hpp>
|
||||||
#include <boost/beast/core/string_param.hpp>
|
#include <boost/beast/core/string_param.hpp>
|
||||||
#include <boost/beast/core/type_traits.hpp>
|
#include <boost/beast/core/type_traits.hpp>
|
||||||
|
1131
include/boost/beast/core/basic_stream_socket.hpp
Normal file
1131
include/boost/beast/core/basic_stream_socket.hpp
Normal file
File diff suppressed because it is too large
Load Diff
241
include/boost/beast/core/detail/operation_base.hpp
Normal file
241
include/boost/beast/core/detail/operation_base.hpp
Normal file
@ -0,0 +1,241 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2018 Vinnie Falco (vinnie dot falco at gmail 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)
|
||||||
|
//
|
||||||
|
// Official repository: https://github.com/boostorg/beast
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef BOOST_BEAST_CORE_DETAIL_OPERATION_BASE_HPP
|
||||||
|
#define BOOST_BEAST_CORE_DETAIL_OPERATION_BASE_HPP
|
||||||
|
|
||||||
|
#include <boost/beast/core/detail/config.hpp>
|
||||||
|
#include <boost/asio/associated_allocator.hpp>
|
||||||
|
#include <boost/asio/associated_executor.hpp>
|
||||||
|
#include <boost/asio/handler_alloc_hook.hpp>
|
||||||
|
#include <boost/asio/handler_continuation_hook.hpp>
|
||||||
|
#include <boost/asio/handler_invoke_hook.hpp>
|
||||||
|
#include <boost/asio/system_executor.hpp>
|
||||||
|
#include <boost/core/empty_value.hpp>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace beast {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
/** Base class which stores a handler and forwards handler associations.
|
||||||
|
|
||||||
|
This mix-in assists bind wrappers, intermediate handlers, composed
|
||||||
|
operations, and similar types which store a handler, by acting as
|
||||||
|
a base class which holds the handler. Any networking customizations
|
||||||
|
on the handler will be propagated to the derived class. Specifically:
|
||||||
|
|
||||||
|
@li Any allocator associated with the handler will be propagated to
|
||||||
|
this object. Otherwise, the allocator associated with this
|
||||||
|
object will be a default allocator which the caller may specify
|
||||||
|
through a template parameter and constructor parameter.
|
||||||
|
|
||||||
|
@li Any executor associated with the handler will be propagated to
|
||||||
|
this object. Otherwise, the executor associated with this
|
||||||
|
object will be a default executor which the caller may specify
|
||||||
|
through a template parameter and constructor parameter.
|
||||||
|
|
||||||
|
@li The legacy customization points
|
||||||
|
`asio_handler_invoke`,
|
||||||
|
`asio_handler_allocate`,
|
||||||
|
`asio_handler_deallocate`, and
|
||||||
|
`asio_handler_is_continuation`,
|
||||||
|
which use argument-dependent lookup, will be forwarded to the
|
||||||
|
legacy customization points associated with the handler.
|
||||||
|
|
||||||
|
@par Example
|
||||||
|
|
||||||
|
The following declaration produces a class which wraps a
|
||||||
|
handler and inherits all of the networking customizations
|
||||||
|
associated with that handler:
|
||||||
|
|
||||||
|
@code
|
||||||
|
template <class Handler>
|
||||||
|
struct wrapped_handler : operation_base<
|
||||||
|
Handler, net::associated_executor_t<Handler>>
|
||||||
|
{
|
||||||
|
template <class Handler_>
|
||||||
|
explicit wrapped_handler (Handler_&& handler)
|
||||||
|
: operation_base<Handler, net::associated_executor_t <Handler>>(
|
||||||
|
std::forward<Handler_>(handler), net::get_associated_executor(handler))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Args>
|
||||||
|
void operator()(Args&&... args)
|
||||||
|
{
|
||||||
|
this->handler_(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
@tparam Handler The type of the completion handler to store.
|
||||||
|
This type must meet the requirements of <em>CompletionHandler</em>.
|
||||||
|
|
||||||
|
@tparam Executor The executor type to use if the handler does not
|
||||||
|
have an associated executor.
|
||||||
|
|
||||||
|
@tparam Allocator The allocator type to use if the handler does not
|
||||||
|
have an associated allocator. If this parameter is omitted, then
|
||||||
|
`std::allocator<void>` will be used.
|
||||||
|
*/
|
||||||
|
template<
|
||||||
|
class Handler,
|
||||||
|
class Executor,
|
||||||
|
class Allocator = std::allocator<void>
|
||||||
|
>
|
||||||
|
class operation_base
|
||||||
|
#if ! BOOST_BEAST_DOXYGEN
|
||||||
|
: private boost::empty_value<
|
||||||
|
net::associated_allocator_t<
|
||||||
|
Handler, Allocator>, 0>
|
||||||
|
, private boost::empty_value<
|
||||||
|
net::associated_executor_t<
|
||||||
|
Handler, Executor>, 1>
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/** The type of allocator associated with this object.
|
||||||
|
|
||||||
|
If a class derived from @ref operation_base is a completion
|
||||||
|
handler, then the associated allocator of the derived class will
|
||||||
|
be this type.
|
||||||
|
*/
|
||||||
|
using allocator_type =
|
||||||
|
net::associated_allocator_t<
|
||||||
|
Handler, Allocator>;
|
||||||
|
|
||||||
|
/** The type of executor associated with this object.
|
||||||
|
|
||||||
|
If a class derived from @ref operation_base is a completion
|
||||||
|
handler, then the associated executor of the derived class will
|
||||||
|
be this type.
|
||||||
|
*/
|
||||||
|
using executor_type =
|
||||||
|
net::associated_executor_t<
|
||||||
|
Handler, Executor>;
|
||||||
|
|
||||||
|
/** Returns the allocator associated with this object.
|
||||||
|
|
||||||
|
If a class derived from @ref operation_base is a completion
|
||||||
|
handler, then the object returned from this function will be used
|
||||||
|
as the associated allocator of the derived class.
|
||||||
|
*/
|
||||||
|
allocator_type
|
||||||
|
get_allocator() const noexcept
|
||||||
|
{
|
||||||
|
return boost::empty_value<
|
||||||
|
allocator_type, 0>::get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the allocator associated with this object.
|
||||||
|
|
||||||
|
If a class derived from @ref operation_base is a completion
|
||||||
|
handler, then the object returned from this function will be used
|
||||||
|
as the associated allocator of the derived class.
|
||||||
|
*/
|
||||||
|
executor_type
|
||||||
|
get_executor() const noexcept
|
||||||
|
{
|
||||||
|
return boost::empty_value<
|
||||||
|
executor_type, 1>::get();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Handler handler_;
|
||||||
|
|
||||||
|
template<
|
||||||
|
class DeducedHandler
|
||||||
|
#if BOOST_BEAST_DOXYGEN
|
||||||
|
,class = typename std::enable_if<
|
||||||
|
! std::is_same<typename
|
||||||
|
std::decay<Handler_>::type,
|
||||||
|
operation_base
|
||||||
|
>::value>::type
|
||||||
|
#endif
|
||||||
|
>
|
||||||
|
operation_base(
|
||||||
|
DeducedHandler&& handler,
|
||||||
|
executor_type ex = executor_type{},
|
||||||
|
allocator_type alloc = allocator_type{})
|
||||||
|
: boost::empty_value<allocator_type, 0>(
|
||||||
|
boost::empty_init_t{}, alloc)
|
||||||
|
, boost::empty_value<executor_type, 1>(
|
||||||
|
boost::empty_init_t{}, ex)
|
||||||
|
, handler_(std::forward<DeducedHandler>(handler))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
#if ! BOOST_BEAST_DOXYGEN
|
||||||
|
template<
|
||||||
|
class Handler_,
|
||||||
|
class Executor_,
|
||||||
|
class Allocator_,
|
||||||
|
class Function>
|
||||||
|
friend
|
||||||
|
void asio_handler_invoke(
|
||||||
|
Function&& f,
|
||||||
|
operation_base<
|
||||||
|
Handler_, Executor_, Allocator_>* p);
|
||||||
|
|
||||||
|
friend
|
||||||
|
void* asio_handler_allocate(
|
||||||
|
std::size_t size, operation_base* p)
|
||||||
|
{
|
||||||
|
using net::asio_handler_allocate;
|
||||||
|
return asio_handler_allocate(
|
||||||
|
size, std::addressof(p->handler_));
|
||||||
|
}
|
||||||
|
|
||||||
|
friend
|
||||||
|
void asio_handler_deallocate(
|
||||||
|
void* mem, std::size_t size,
|
||||||
|
operation_base* p)
|
||||||
|
{
|
||||||
|
using net::asio_handler_deallocate;
|
||||||
|
asio_handler_deallocate(mem, size,
|
||||||
|
std::addressof(p->handler_));
|
||||||
|
}
|
||||||
|
|
||||||
|
friend
|
||||||
|
bool asio_handler_is_continuation(
|
||||||
|
operation_base* p)
|
||||||
|
{
|
||||||
|
using net::asio_handler_is_continuation;
|
||||||
|
return asio_handler_is_continuation(
|
||||||
|
std::addressof(p->handler_));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#if ! BOOST_BEAST_DOXYGEN
|
||||||
|
|
||||||
|
template<
|
||||||
|
class Handler,
|
||||||
|
class Executor,
|
||||||
|
class Allocator,
|
||||||
|
class Function>
|
||||||
|
void asio_handler_invoke(
|
||||||
|
Function&& f,
|
||||||
|
operation_base<
|
||||||
|
Handler, Executor, Allocator>* p)
|
||||||
|
{
|
||||||
|
using net::asio_handler_invoke;
|
||||||
|
asio_handler_invoke(
|
||||||
|
f, std::addressof(p->handler_));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
} // beast
|
||||||
|
} // boost
|
||||||
|
|
||||||
|
#endif
|
66
include/boost/beast/core/detail/stream_socket_base.hpp
Normal file
66
include/boost/beast/core/detail/stream_socket_base.hpp
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2018 Vinnie Falco (vinnie dot falco at gmail 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)
|
||||||
|
//
|
||||||
|
// Official repository: https://github.com/boostorg/beast
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef BOOST_BEAST_CORE_DETAIL_STREAM_SOCKET_BASE_HPP
|
||||||
|
#define BOOST_BEAST_CORE_DETAIL_STREAM_SOCKET_BASE_HPP
|
||||||
|
|
||||||
|
#include <boost/assert.hpp>
|
||||||
|
#include <boost/core/exchange.hpp>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace beast {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template<class, class, class>
|
||||||
|
class stream_socket_connect_op;
|
||||||
|
|
||||||
|
class stream_socket_base
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
class pending_guard
|
||||||
|
{
|
||||||
|
bool& b_;
|
||||||
|
bool clear_ = true;
|
||||||
|
|
||||||
|
public:
|
||||||
|
~pending_guard()
|
||||||
|
{
|
||||||
|
if(clear_)
|
||||||
|
b_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit
|
||||||
|
pending_guard(bool& b)
|
||||||
|
: b_(b)
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(! b_);
|
||||||
|
b_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pending_guard(pending_guard&& other) noexcept
|
||||||
|
: b_(other.b_)
|
||||||
|
, clear_(boost::exchange(other.clear_, false))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
reset()
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(clear_);
|
||||||
|
b_ = false;
|
||||||
|
clear_ = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
} // beast
|
||||||
|
} // boost
|
||||||
|
|
||||||
|
#endif
|
1073
include/boost/beast/core/impl/basic_stream_socket.hpp
Normal file
1073
include/boost/beast/core/impl/basic_stream_socket.hpp
Normal file
File diff suppressed because it is too large
Load Diff
30
include/boost/beast/core/stream_socket.hpp
Normal file
30
include/boost/beast/core/stream_socket.hpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2018 Vinnie Falco (vinnie dot falco at gmail 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)
|
||||||
|
//
|
||||||
|
// Official repository: https://github.com/boostorg/beast
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef BOOST_BEAST_CORE_STREAM_SOCKET_HPP
|
||||||
|
#define BOOST_BEAST_CORE_STREAM_SOCKET_HPP
|
||||||
|
|
||||||
|
#include <boost/beast/core/detail/config.hpp>
|
||||||
|
#include <boost/beast/core/basic_stream_socket.hpp>
|
||||||
|
#include <boost/beast/core/error.hpp>
|
||||||
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace beast {
|
||||||
|
|
||||||
|
/** A TCP/IP stream socket which supports timeouts and rate limits
|
||||||
|
*/
|
||||||
|
using stream_socket = basic_stream_socket<
|
||||||
|
net::ip::tcp,
|
||||||
|
net::io_context::executor_type>;
|
||||||
|
|
||||||
|
} // beast
|
||||||
|
} // boost
|
||||||
|
|
||||||
|
#endif
|
@ -42,7 +42,7 @@ class saved_handler
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<class Handler>
|
template<class Handler>
|
||||||
class impl : public base
|
class impl final : public base
|
||||||
{
|
{
|
||||||
Handler h_;
|
Handler h_;
|
||||||
net::executor_work_guard<
|
net::executor_work_guard<
|
||||||
|
@ -16,16 +16,18 @@ add_executable (tests-beast-core
|
|||||||
${EXTRAS_FILES}
|
${EXTRAS_FILES}
|
||||||
${TEST_MAIN}
|
${TEST_MAIN}
|
||||||
Jamfile
|
Jamfile
|
||||||
buffer_test.hpp
|
|
||||||
file_test.hpp
|
|
||||||
_detail_base64.cpp
|
_detail_base64.cpp
|
||||||
_detail_buffer.cpp
|
_detail_buffer.cpp
|
||||||
_detail_clamp.cpp
|
_detail_clamp.cpp
|
||||||
|
_detail_operation_base.cpp
|
||||||
_detail_read.cpp
|
_detail_read.cpp
|
||||||
_detail_sha1.cpp
|
_detail_sha1.cpp
|
||||||
_detail_tuple.cpp
|
_detail_tuple.cpp
|
||||||
_detail_variant.cpp
|
_detail_variant.cpp
|
||||||
_detail_varint.cpp
|
_detail_varint.cpp
|
||||||
|
buffer_test.hpp
|
||||||
|
file_test.hpp
|
||||||
|
basic_stream_socket.cpp
|
||||||
bind_handler.cpp
|
bind_handler.cpp
|
||||||
buffer_traits.cpp
|
buffer_traits.cpp
|
||||||
buffered_read_stream.cpp
|
buffered_read_stream.cpp
|
||||||
@ -51,6 +53,7 @@ add_executable (tests-beast-core
|
|||||||
span.cpp
|
span.cpp
|
||||||
static_buffer.cpp
|
static_buffer.cpp
|
||||||
static_string.cpp
|
static_string.cpp
|
||||||
|
stream_socket.cpp
|
||||||
string.cpp
|
string.cpp
|
||||||
string_param.cpp
|
string_param.cpp
|
||||||
type_traits.cpp
|
type_traits.cpp
|
||||||
|
@ -11,11 +11,13 @@ local SOURCES =
|
|||||||
_detail_base64.cpp
|
_detail_base64.cpp
|
||||||
_detail_buffer.cpp
|
_detail_buffer.cpp
|
||||||
_detail_clamp.cpp
|
_detail_clamp.cpp
|
||||||
|
_detail_operation_base.cpp
|
||||||
_detail_read.cpp
|
_detail_read.cpp
|
||||||
_detail_sha1.cpp
|
_detail_sha1.cpp
|
||||||
_detail_tuple.cpp
|
_detail_tuple.cpp
|
||||||
_detail_variant.cpp
|
_detail_variant.cpp
|
||||||
_detail_varint.cpp
|
_detail_varint.cpp
|
||||||
|
basic_stream_socket.cpp
|
||||||
bind_handler.cpp
|
bind_handler.cpp
|
||||||
buffer_traits.cpp
|
buffer_traits.cpp
|
||||||
buffered_read_stream.cpp
|
buffered_read_stream.cpp
|
||||||
@ -41,6 +43,7 @@ local SOURCES =
|
|||||||
span.cpp
|
span.cpp
|
||||||
static_buffer.cpp
|
static_buffer.cpp
|
||||||
static_string.cpp
|
static_string.cpp
|
||||||
|
stream_socket.cpp
|
||||||
string.cpp
|
string.cpp
|
||||||
string_param.cpp
|
string_param.cpp
|
||||||
type_traits.cpp
|
type_traits.cpp
|
||||||
|
500
test/beast/core/_detail_operation_base.cpp
Normal file
500
test/beast/core/_detail_operation_base.cpp
Normal file
@ -0,0 +1,500 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail 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)
|
||||||
|
//
|
||||||
|
// Official repository: https://github.com/boostorg/beast
|
||||||
|
//
|
||||||
|
|
||||||
|
// Test that header file is self-contained.
|
||||||
|
#include <boost/beast/core/detail/operation_base.hpp>
|
||||||
|
|
||||||
|
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||||
|
#include <boost/core/ignore_unused.hpp>
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace beast {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct specialized_handler
|
||||||
|
{
|
||||||
|
bool invoked = false;
|
||||||
|
struct executor
|
||||||
|
{
|
||||||
|
void* context() { return nullptr; }
|
||||||
|
void on_work_started() {}
|
||||||
|
void on_work_finished() {}
|
||||||
|
template<class F> void dispatch(F&&) {}
|
||||||
|
template<class F> void post(F&&) {}
|
||||||
|
template<class F> void defer(F&&) {}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class Function>
|
||||||
|
static
|
||||||
|
void
|
||||||
|
asio_handler_invoke(
|
||||||
|
Function&& f,
|
||||||
|
specialized_handler* p)
|
||||||
|
{
|
||||||
|
p->invoked = true;
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void*
|
||||||
|
asio_handler_allocate(
|
||||||
|
std::size_t,
|
||||||
|
specialized_handler* p)
|
||||||
|
{
|
||||||
|
p->invoked = true;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void
|
||||||
|
asio_handler_deallocate(
|
||||||
|
void*, std::size_t,
|
||||||
|
specialized_handler* p)
|
||||||
|
{
|
||||||
|
p->invoked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
asio_handler_is_continuation(
|
||||||
|
specialized_handler* p)
|
||||||
|
{
|
||||||
|
p->invoked = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // <anonymous>
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
} // beast
|
||||||
|
} // boost
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace asio {
|
||||||
|
|
||||||
|
template<class Allocator>
|
||||||
|
struct associated_allocator<
|
||||||
|
boost::beast::detail::specialized_handler, Allocator>
|
||||||
|
{
|
||||||
|
using type = std::allocator<int>;
|
||||||
|
|
||||||
|
static type get(
|
||||||
|
boost::beast::detail::specialized_handler const& h,
|
||||||
|
Allocator const& a = Allocator()) noexcept
|
||||||
|
{
|
||||||
|
return type{};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class Executor>
|
||||||
|
struct associated_executor<
|
||||||
|
boost::beast::detail::specialized_handler, Executor>
|
||||||
|
{
|
||||||
|
using type = typename
|
||||||
|
boost::beast::detail::specialized_handler::executor;
|
||||||
|
|
||||||
|
static type get(
|
||||||
|
boost::beast::detail::specialized_handler const& h,
|
||||||
|
Executor const& ex = Executor()) noexcept
|
||||||
|
{
|
||||||
|
return type{};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // asio
|
||||||
|
} // boost
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace beast {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
class operation_base_test : public beast::unit_test::suite
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using default_alloc = std::allocator<void>;
|
||||||
|
using default_exec = net::system_executor;
|
||||||
|
|
||||||
|
struct U {};
|
||||||
|
struct V {};
|
||||||
|
|
||||||
|
template<class E>
|
||||||
|
struct executor
|
||||||
|
{
|
||||||
|
void* context() { return nullptr; }
|
||||||
|
void on_work_started() {}
|
||||||
|
void on_work_finished() {}
|
||||||
|
template<class F> void dispatch(F&&) {}
|
||||||
|
template<class F> void post(F&&) {}
|
||||||
|
template<class F> void defer(F&&) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct none
|
||||||
|
{
|
||||||
|
void operator()() const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct with_alloc
|
||||||
|
{
|
||||||
|
using allocator_type = std::allocator<U>;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct with_exec
|
||||||
|
{
|
||||||
|
using executor_type = executor<U>;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct move_only
|
||||||
|
{
|
||||||
|
move_only() = default;
|
||||||
|
move_only(move_only&&) = default;
|
||||||
|
move_only(move_only const&) = delete;
|
||||||
|
void operator()() const{};
|
||||||
|
};
|
||||||
|
|
||||||
|
template<
|
||||||
|
class H,
|
||||||
|
class E = default_exec,
|
||||||
|
class A = default_alloc>
|
||||||
|
using tested_base =
|
||||||
|
operation_base<H, E, A>;
|
||||||
|
|
||||||
|
struct movable_handler : tested_base<move_only>
|
||||||
|
{
|
||||||
|
movable_handler()
|
||||||
|
: tested_base<move_only>(move_only{})
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct test_handler :
|
||||||
|
tested_base<specialized_handler>
|
||||||
|
{
|
||||||
|
test_handler()
|
||||||
|
: tested_base<
|
||||||
|
specialized_handler>(
|
||||||
|
specialized_handler{})
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool invoked() const noexcept
|
||||||
|
{
|
||||||
|
return this->handler_.invoked;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// no nested allocator type
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
std::is_same<
|
||||||
|
default_alloc,
|
||||||
|
net::associated_allocator_t<
|
||||||
|
tested_base<none>
|
||||||
|
>>::value);
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
std::is_same<
|
||||||
|
default_alloc,
|
||||||
|
decltype(net::get_associated_allocator(
|
||||||
|
std::declval<tested_base<none>>()
|
||||||
|
))>::value);
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
std::is_same<
|
||||||
|
default_alloc,
|
||||||
|
decltype(net::get_associated_allocator(
|
||||||
|
std::declval<tested_base<none>>()
|
||||||
|
))>::value);
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
std::is_same<
|
||||||
|
std::allocator<U>,
|
||||||
|
decltype(net::get_associated_allocator(std::declval<
|
||||||
|
tested_base<none, default_exec, std::allocator<U>>>()
|
||||||
|
))>::value);
|
||||||
|
|
||||||
|
// shouldn't work due to net.ts limitations
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
! std::is_same<
|
||||||
|
std::allocator<U>,
|
||||||
|
decltype(net::get_associated_allocator(
|
||||||
|
std::declval<tested_base<none>>(),
|
||||||
|
std::declval<std::allocator<U>>()
|
||||||
|
))>::value);
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
std::is_same<
|
||||||
|
default_alloc,
|
||||||
|
decltype(net::get_associated_allocator(
|
||||||
|
std::declval<tested_base<none>>(),
|
||||||
|
std::declval<std::allocator<U>>()
|
||||||
|
))>::value);
|
||||||
|
|
||||||
|
// nested allocator_type
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
std::is_same<
|
||||||
|
std::allocator<U>,
|
||||||
|
net::associated_allocator_t<
|
||||||
|
tested_base<with_alloc>
|
||||||
|
>>::value);
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
std::is_same<
|
||||||
|
std::allocator<U>,
|
||||||
|
decltype(net::get_associated_allocator(
|
||||||
|
std::declval<tested_base<with_alloc>>()
|
||||||
|
))>::value);
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
std::is_same<
|
||||||
|
std::allocator<U>,
|
||||||
|
decltype(net::get_associated_allocator(
|
||||||
|
std::declval<tested_base<with_alloc>>(),
|
||||||
|
std::declval<std::allocator<V>>()
|
||||||
|
))>::value);
|
||||||
|
|
||||||
|
// specialization of associated_allocator
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
std::is_same<
|
||||||
|
std::allocator<int>,
|
||||||
|
net::associated_allocator_t<
|
||||||
|
tested_base<
|
||||||
|
specialized_handler>
|
||||||
|
>>::value);
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
std::is_same<
|
||||||
|
std::allocator<int>,
|
||||||
|
decltype(net::get_associated_allocator(
|
||||||
|
std::declval<tested_base<
|
||||||
|
specialized_handler>>()
|
||||||
|
))>::value);
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
std::is_same<
|
||||||
|
std::allocator<int>,
|
||||||
|
decltype(net::get_associated_allocator(
|
||||||
|
std::declval<tested_base<
|
||||||
|
specialized_handler>>(),
|
||||||
|
std::declval<std::allocator<V>>()
|
||||||
|
))>::value);
|
||||||
|
|
||||||
|
// no nested executor type
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
std::is_same<
|
||||||
|
default_exec,
|
||||||
|
net::associated_executor_t<
|
||||||
|
tested_base<none>
|
||||||
|
>>::value);
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
std::is_same<
|
||||||
|
executor<U>,
|
||||||
|
net::associated_executor_t<
|
||||||
|
tested_base<none, executor<U>>
|
||||||
|
>>::value);
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
std::is_same<
|
||||||
|
default_exec,
|
||||||
|
decltype(net::get_associated_executor(
|
||||||
|
std::declval<tested_base<none>>()
|
||||||
|
))>::value);
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
std::is_same<
|
||||||
|
executor<U>,
|
||||||
|
decltype(net::get_associated_executor(std::declval<
|
||||||
|
tested_base<none, executor<U>>>()
|
||||||
|
))>::value);
|
||||||
|
|
||||||
|
// shouldn't work due to net.ts limitations
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
! std::is_same<
|
||||||
|
executor<U>,
|
||||||
|
decltype(net::get_associated_executor(
|
||||||
|
std::declval<tested_base<none>>(),
|
||||||
|
std::declval<executor<U>>()
|
||||||
|
))>::value);
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
std::is_same<
|
||||||
|
default_exec,
|
||||||
|
decltype(net::get_associated_executor(
|
||||||
|
std::declval<tested_base<none>>(),
|
||||||
|
std::declval<executor<U>>()
|
||||||
|
))>::value);
|
||||||
|
|
||||||
|
// nested executor_type
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
std::is_same<
|
||||||
|
executor<U>,
|
||||||
|
net::associated_executor_t<
|
||||||
|
tested_base<with_exec>
|
||||||
|
>>::value);
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
std::is_same<
|
||||||
|
executor<U>,
|
||||||
|
decltype(net::get_associated_executor(
|
||||||
|
std::declval<tested_base<with_exec>>()
|
||||||
|
))>::value);
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
std::is_same<
|
||||||
|
executor<U>,
|
||||||
|
decltype(net::get_associated_executor(
|
||||||
|
std::declval<tested_base<with_exec>>(),
|
||||||
|
std::declval<executor<V>>()
|
||||||
|
))>::value);
|
||||||
|
|
||||||
|
// specialization of associated_executor
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
std::is_same<
|
||||||
|
specialized_handler::executor,
|
||||||
|
net::associated_executor_t<
|
||||||
|
tested_base<
|
||||||
|
specialized_handler>
|
||||||
|
>>::value);
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
std::is_same<
|
||||||
|
specialized_handler::executor,
|
||||||
|
decltype(net::get_associated_executor(std::declval<
|
||||||
|
tested_base<
|
||||||
|
specialized_handler>>()
|
||||||
|
))>::value);
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT(
|
||||||
|
std::is_same<
|
||||||
|
specialized_handler::executor,
|
||||||
|
decltype(net::get_associated_executor(std::declval<
|
||||||
|
tested_base<
|
||||||
|
specialized_handler>>(),
|
||||||
|
std::declval<executor<V>>()
|
||||||
|
))>::value);
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template <class Handler>
|
||||||
|
struct wrapped_handler : operation_base<
|
||||||
|
Handler, net::associated_executor_t<Handler>>
|
||||||
|
{
|
||||||
|
template <class Handler_>
|
||||||
|
explicit wrapped_handler (Handler_&& handler)
|
||||||
|
: operation_base<Handler, net::associated_executor_t <Handler>>(
|
||||||
|
std::forward<Handler_>(handler), net::get_associated_executor(handler))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Args>
|
||||||
|
void operator()(Args&&... args)
|
||||||
|
{
|
||||||
|
this->handler_(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
testJavadocs()
|
||||||
|
{
|
||||||
|
wrapped_handler<none>{none{}}();
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void
|
||||||
|
testLegacyHooks()
|
||||||
|
{
|
||||||
|
// asio_handler_invoke
|
||||||
|
{
|
||||||
|
test_handler h;
|
||||||
|
BEAST_EXPECT(! h.invoked());
|
||||||
|
bool invoked = false;
|
||||||
|
using net::asio_handler_invoke;
|
||||||
|
asio_handler_invoke(
|
||||||
|
[&invoked]
|
||||||
|
{
|
||||||
|
invoked =true;
|
||||||
|
}, &h);
|
||||||
|
BEAST_EXPECT(invoked);
|
||||||
|
BEAST_EXPECT(h.invoked());
|
||||||
|
}
|
||||||
|
|
||||||
|
// asio_handler_allocate
|
||||||
|
{
|
||||||
|
test_handler h;
|
||||||
|
BEAST_EXPECT(! h.invoked());
|
||||||
|
using net::asio_handler_allocate;
|
||||||
|
asio_handler_allocate(0, &h);
|
||||||
|
BEAST_EXPECT(h.invoked());
|
||||||
|
}
|
||||||
|
|
||||||
|
// asio_handler_deallocate
|
||||||
|
{
|
||||||
|
test_handler h;
|
||||||
|
BEAST_EXPECT(! h.invoked());
|
||||||
|
using net::asio_handler_deallocate;
|
||||||
|
asio_handler_deallocate(nullptr, 0, &h);
|
||||||
|
BEAST_EXPECT(h.invoked());
|
||||||
|
}
|
||||||
|
|
||||||
|
// asio_handler_deallocate
|
||||||
|
{
|
||||||
|
test_handler h;
|
||||||
|
BEAST_EXPECT(! h.invoked());
|
||||||
|
using net::asio_handler_is_continuation;
|
||||||
|
asio_handler_is_continuation(&h);
|
||||||
|
BEAST_EXPECT(h.invoked());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
testSpecialMembers()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
test_handler h1;
|
||||||
|
test_handler h2(std::move(h1));
|
||||||
|
test_handler h3(h2);
|
||||||
|
boost::ignore_unused(h3);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
movable_handler h1;
|
||||||
|
movable_handler h2(std::move(h1));
|
||||||
|
boost::ignore_unused(h2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
run() override
|
||||||
|
{
|
||||||
|
testJavadocs();
|
||||||
|
testLegacyHooks();
|
||||||
|
testSpecialMembers();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BEAST_DEFINE_TESTSUITE(beast,core,operation_base);
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
} // beast
|
||||||
|
} // boost
|
132
test/beast/core/basic_stream_socket.cpp
Normal file
132
test/beast/core/basic_stream_socket.cpp
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2018 Vinnie Falco (vinnie dot falco at gmail 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)
|
||||||
|
//
|
||||||
|
// Official repository: https://github.com/boostorg/beast
|
||||||
|
//
|
||||||
|
|
||||||
|
// Test that header file is self-contained.
|
||||||
|
#include <boost/beast/core/basic_stream_socket.hpp>
|
||||||
|
|
||||||
|
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||||
|
#include <boost/beast/core/stream_socket.hpp>
|
||||||
|
#include <boost/asio/read_until.hpp>
|
||||||
|
#include <boost/asio/streambuf.hpp>
|
||||||
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
|
#include <boost/asio/ip/udp.hpp>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace beast {
|
||||||
|
|
||||||
|
class basic_stream_socket_test
|
||||||
|
: public beast::unit_test::suite
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct read_handler
|
||||||
|
{
|
||||||
|
template<class... Args>
|
||||||
|
void operator()(Args&&...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Protocol, class Executor, class ReadHandler>
|
||||||
|
void async_read_line (
|
||||||
|
basic_stream_socket<Protocol, Executor>& stream,
|
||||||
|
net::streambuf& buffer, ReadHandler&& handler)
|
||||||
|
{
|
||||||
|
stream.expires_after(std::chrono::seconds(30));
|
||||||
|
|
||||||
|
net::async_read_until(stream, buffer, "\r\n", std::forward<ReadHandler>(handler));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
testJavadocs()
|
||||||
|
{
|
||||||
|
BEAST_EXPECT((&basic_stream_socket_test::async_read_line<
|
||||||
|
net::ip::tcp, net::io_context::executor_type, read_handler>));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct other_t
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
testMembers()
|
||||||
|
{
|
||||||
|
using tcp = net::ip::tcp;
|
||||||
|
using ep_t = tcp::endpoint;
|
||||||
|
using ioc_t = net::io_context;
|
||||||
|
using ex_t = ioc_t::executor_type;
|
||||||
|
using stream_t = basic_stream_socket<tcp, ex_t>;
|
||||||
|
|
||||||
|
net::io_context ioc;
|
||||||
|
auto ex = ioc.get_executor();
|
||||||
|
|
||||||
|
// construction
|
||||||
|
|
||||||
|
{
|
||||||
|
stream_t{ioc};
|
||||||
|
stream_t{ex};
|
||||||
|
BOOST_STATIC_ASSERT(! std::is_constructible<
|
||||||
|
stream_t, other_t>::value);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
stream_t{ioc, tcp::v4()};
|
||||||
|
stream_t{ex, tcp::v4()};
|
||||||
|
BOOST_STATIC_ASSERT(! std::is_constructible<
|
||||||
|
stream_t, other_t, tcp>::value);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
stream_t{ioc, ep_t{}};
|
||||||
|
stream_t{ex, ep_t{}};
|
||||||
|
BOOST_STATIC_ASSERT(! std::is_constructible<
|
||||||
|
stream_t, other_t, ep_t>::value);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
tcp::socket sock(ioc);
|
||||||
|
stream_t{ioc, std::move(sock)};
|
||||||
|
stream_t{ex, std::move(sock)};
|
||||||
|
BOOST_STATIC_ASSERT(! std::is_constructible<
|
||||||
|
stream_t, other_t, tcp::socket>::value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// move
|
||||||
|
|
||||||
|
{
|
||||||
|
stream_t s1(ioc);
|
||||||
|
stream_t s2(std::move(s1));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
stream_t s1(ioc);
|
||||||
|
stream_t s2(ioc);
|
||||||
|
s2 = std::move(s1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// converting move
|
||||||
|
|
||||||
|
{
|
||||||
|
// We don't have any convertible protocol types
|
||||||
|
#if 0
|
||||||
|
basic_stream_socket<net::ip::udp, ex_t> s1(ioc);
|
||||||
|
stream_t s2(std::move(s1));
|
||||||
|
|
||||||
|
stream_t s3 = std::move(s1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
run()
|
||||||
|
{
|
||||||
|
testJavadocs();
|
||||||
|
testMembers();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BEAST_DEFINE_TESTSUITE(beast,core,basic_stream_socket);
|
||||||
|
|
||||||
|
} // beast
|
||||||
|
} // boost
|
@ -8,19 +8,18 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
// Test that header file is self-contained.
|
// Test that header file is self-contained.
|
||||||
#include <boost/beast/_experimental/core/timeout_socket.hpp>
|
#include <boost/beast/core/stream_socket.hpp>
|
||||||
|
|
||||||
#include <boost/beast/_experimental/core/timeout_service.hpp>
|
|
||||||
|
|
||||||
#include <boost/beast/test/yield_to.hpp>
|
|
||||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||||
|
#include <boost/beast/test/yield_to.hpp>
|
||||||
#include <boost/asio/ip/tcp.hpp>
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
|
#include <array>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
class timeout_socket_test
|
class stream_socket_test
|
||||||
: public beast::unit_test::suite
|
: public beast::unit_test::suite
|
||||||
, public test::enable_yield_to
|
, public test::enable_yield_to
|
||||||
{
|
{
|
||||||
@ -152,18 +151,117 @@ public:
|
|||||||
server srv(ep, log);
|
server srv(ep, log);
|
||||||
{
|
{
|
||||||
net::io_context ioc;
|
net::io_context ioc;
|
||||||
set_timeout_service_options(
|
stream_socket s(ioc);
|
||||||
ioc, std::chrono::seconds(1));
|
|
||||||
timeout_socket s(ioc);
|
|
||||||
s.next_layer().connect(ep);
|
s.next_layer().connect(ep);
|
||||||
char buf[32];
|
char buf[32];
|
||||||
|
error_code ec;
|
||||||
|
s.expires_after(std::chrono::seconds(1));
|
||||||
s.async_read_some(net::buffer(buf),
|
s.async_read_some(net::buffer(buf),
|
||||||
[&](error_code ec, std::size_t n)
|
[&ec](error_code ec_, std::size_t)
|
||||||
{
|
{
|
||||||
log << "read_some: " << ec.message() << "\n";
|
ec = ec_;
|
||||||
boost::ignore_unused(ec, n);
|
|
||||||
});
|
});
|
||||||
ioc.run();
|
ioc.run();
|
||||||
|
BEAST_EXPECTS(
|
||||||
|
ec == error::timeout, ec.message());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
testConnect()
|
||||||
|
{
|
||||||
|
using es_t =
|
||||||
|
std::array<net::ip::tcp::endpoint, 2>;
|
||||||
|
{
|
||||||
|
net::io_context ioc;
|
||||||
|
stream_socket s(ioc);
|
||||||
|
beast::async_connect(s, es_t{},
|
||||||
|
[](error_code, es_t::value_type)
|
||||||
|
{
|
||||||
|
});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
net::io_context ioc;
|
||||||
|
stream_socket s(ioc);
|
||||||
|
beast::async_connect(s, es_t{},
|
||||||
|
[](error_code, es_t::value_type)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
[](error_code, es_t::value_type)
|
||||||
|
{
|
||||||
|
});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
es_t es;
|
||||||
|
net::io_context ioc;
|
||||||
|
stream_socket s(ioc);
|
||||||
|
beast::async_connect(s, es.begin(), es.end(),
|
||||||
|
[](error_code, es_t::iterator)
|
||||||
|
{
|
||||||
|
});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
es_t es;
|
||||||
|
net::io_context ioc;
|
||||||
|
stream_socket s(ioc);
|
||||||
|
beast::async_connect(s, es.begin(), es.end(),
|
||||||
|
[](error_code, es_t::value_type)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
[](error_code, es_t::iterator)
|
||||||
|
{
|
||||||
|
});
|
||||||
|
}
|
||||||
|
pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
void callConnects()
|
||||||
|
{
|
||||||
|
using es_t =
|
||||||
|
std::array<net::ip::tcp::endpoint, 2>;
|
||||||
|
{
|
||||||
|
net::io_context ioc;
|
||||||
|
stream_socket s(ioc);
|
||||||
|
async_connect(s, es_t{},
|
||||||
|
[](error_code, es_t::value_type)
|
||||||
|
{
|
||||||
|
});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
net::io_context ioc;
|
||||||
|
stream_socket s(ioc);
|
||||||
|
async_connect(s, es_t{},
|
||||||
|
[](error_code, es_t::value_type)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
[](error_code, es_t::value_type)
|
||||||
|
{
|
||||||
|
});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
es_t es;
|
||||||
|
net::io_context ioc;
|
||||||
|
stream_socket s(ioc);
|
||||||
|
async_connect(s, es.begin(), es.end(),
|
||||||
|
[](error_code, es_t::iterator)
|
||||||
|
{
|
||||||
|
});
|
||||||
|
}
|
||||||
|
{
|
||||||
|
es_t es;
|
||||||
|
net::io_context ioc;
|
||||||
|
stream_socket s(ioc);
|
||||||
|
async_connect(s, es.begin(), es.end(),
|
||||||
|
[](error_code, es_t::value_type)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
[](error_code, es_t::iterator)
|
||||||
|
{
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,12 +269,11 @@ public:
|
|||||||
run()
|
run()
|
||||||
{
|
{
|
||||||
testAsync();
|
testAsync();
|
||||||
|
testConnect();
|
||||||
pass();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
BEAST_DEFINE_TESTSUITE(beast,core,timeout_socket);
|
BEAST_DEFINE_TESTSUITE(beast,core,stream_socket);
|
||||||
|
|
||||||
} // beast
|
} // beast
|
||||||
} // boost
|
} // boost
|
@ -21,9 +21,6 @@ add_executable (tests-beast-experimental
|
|||||||
icy_stream.cpp
|
icy_stream.cpp
|
||||||
ssl_stream.cpp
|
ssl_stream.cpp
|
||||||
stream.cpp
|
stream.cpp
|
||||||
timeout_socket.cpp
|
|
||||||
timeout_service.cpp
|
|
||||||
timeout_work_guard.cpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set_property(TARGET tests-beast-experimental PROPERTY FOLDER "tests")
|
set_property(TARGET tests-beast-experimental PROPERTY FOLDER "tests")
|
||||||
|
@ -13,9 +13,6 @@ local SOURCES =
|
|||||||
icy_stream.cpp
|
icy_stream.cpp
|
||||||
ssl_stream.cpp
|
ssl_stream.cpp
|
||||||
stream.cpp
|
stream.cpp
|
||||||
timeout_socket.cpp
|
|
||||||
timeout_service.cpp
|
|
||||||
timeout_work_guard.cpp
|
|
||||||
;
|
;
|
||||||
|
|
||||||
local RUN_TESTS ;
|
local RUN_TESTS ;
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail 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)
|
|
||||||
//
|
|
||||||
// Official repository: https://github.com/boostorg/beast
|
|
||||||
//
|
|
||||||
|
|
||||||
// Test that header file is self-contained.
|
|
||||||
#include <boost/beast/_experimental/core/timeout_service.hpp>
|
|
||||||
|
|
||||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace beast {
|
|
||||||
|
|
||||||
class timeout_service_test
|
|
||||||
: public beast::unit_test::suite
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void
|
|
||||||
run() override
|
|
||||||
{
|
|
||||||
net::io_context ctx;
|
|
||||||
set_timeout_service_options(ctx,
|
|
||||||
std::chrono::seconds(1));
|
|
||||||
pass();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
BEAST_DEFINE_TESTSUITE(beast,core,timeout_service);
|
|
||||||
|
|
||||||
} // beast
|
|
||||||
} // boost
|
|
@ -1,11 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail 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)
|
|
||||||
//
|
|
||||||
// Official repository: https://github.com/boostorg/beast
|
|
||||||
//
|
|
||||||
|
|
||||||
// Test that header file is self-contained.
|
|
||||||
#include <boost/beast/_experimental/core/timeout_work_guard.hpp>
|
|
Reference in New Issue
Block a user