mirror of
https://gcc.gnu.org/git/gcc.git
synced 2024-11-27 13:54:19 +08:00
Initial commit of Networking TS implementation
* include/Makefile.am: Add new headers. * include/Makefile.in: Regenerate. * include/experimental/bits/net.h: New header for common implementation details of Networking TS. * include/experimental/buffer: New header. * include/experimental/executor: New header. * include/experimental/internet: New header. * include/experimental/io_context: New header. * include/experimental/net: New header. * include/experimental/netfwd: New header. * include/experimental/socket: New header. * include/experimental/timer: New header. * testsuite/experimental/net/buffer/arithmetic.cc: New test. * testsuite/experimental/net/buffer/const.cc: New test. * testsuite/experimental/net/buffer/creation.cc: New test. * testsuite/experimental/net/buffer/mutable.cc: New test. * testsuite/experimental/net/buffer/size.cc: New test. * testsuite/experimental/net/buffer/traits.cc: New test. * testsuite/experimental/net/execution_context/use_service.cc: New test. * testsuite/experimental/net/headers.cc: New test. * testsuite/experimental/net/internet/address/v4/comparisons.cc: New test. * testsuite/experimental/net/internet/address/v4/cons.cc: New test. * testsuite/experimental/net/internet/address/v4/creation.cc: New test. * testsuite/experimental/net/internet/address/v4/members.cc: New test. * testsuite/experimental/net/internet/resolver/base.cc: New test. * testsuite/experimental/net/internet/resolver/ops/lookup.cc: New test. * testsuite/experimental/net/internet/resolver/ops/reverse.cc: New test. * testsuite/experimental/net/timer/waitable/cons.cc: New test. * testsuite/experimental/net/timer/waitable/dest.cc: New test. * testsuite/experimental/net/timer/waitable/ops.cc: New test. From-SVN: r265080
This commit is contained in:
parent
0cfc095c8d
commit
e5989e71ff
@ -1,5 +1,43 @@
|
||||
2018-10-12 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
Initial commit of Networking TS implementation.
|
||||
* include/Makefile.am: Add new headers.
|
||||
* include/Makefile.in: Regenerate.
|
||||
* include/experimental/bits/net.h: New header for common
|
||||
implementation details of Networking TS.
|
||||
* include/experimental/buffer: New header.
|
||||
* include/experimental/executor: New header.
|
||||
* include/experimental/internet: New header.
|
||||
* include/experimental/io_context: New header.
|
||||
* include/experimental/net: New header.
|
||||
* include/experimental/netfwd: New header.
|
||||
* include/experimental/socket: New header.
|
||||
* include/experimental/timer: New header.
|
||||
* testsuite/experimental/net/buffer/arithmetic.cc: New test.
|
||||
* testsuite/experimental/net/buffer/const.cc: New test.
|
||||
* testsuite/experimental/net/buffer/creation.cc: New test.
|
||||
* testsuite/experimental/net/buffer/mutable.cc: New test.
|
||||
* testsuite/experimental/net/buffer/size.cc: New test.
|
||||
* testsuite/experimental/net/buffer/traits.cc: New test.
|
||||
* testsuite/experimental/net/execution_context/use_service.cc: New
|
||||
test.
|
||||
* testsuite/experimental/net/headers.cc: New test.
|
||||
* testsuite/experimental/net/internet/address/v4/comparisons.cc: New
|
||||
test.
|
||||
* testsuite/experimental/net/internet/address/v4/cons.cc: New test.
|
||||
* testsuite/experimental/net/internet/address/v4/creation.cc: New
|
||||
test.
|
||||
* testsuite/experimental/net/internet/address/v4/members.cc: New
|
||||
test.
|
||||
* testsuite/experimental/net/internet/resolver/base.cc: New test.
|
||||
* testsuite/experimental/net/internet/resolver/ops/lookup.cc: New
|
||||
test.
|
||||
* testsuite/experimental/net/internet/resolver/ops/reverse.cc: New
|
||||
test.
|
||||
* testsuite/experimental/net/timer/waitable/cons.cc: New test.
|
||||
* testsuite/experimental/net/timer/waitable/dest.cc: New test.
|
||||
* testsuite/experimental/net/timer/waitable/ops.cc: New test.
|
||||
|
||||
PR libstdc++/77691
|
||||
* include/experimental/memory_resource (__resource_adaptor_imp): Do
|
||||
not allocate sizes smaller than alignment when relying on guaranteed
|
||||
|
@ -671,15 +671,21 @@ experimental_headers = \
|
||||
${experimental_srcdir}/algorithm \
|
||||
${experimental_srcdir}/any \
|
||||
${experimental_srcdir}/array \
|
||||
${experimental_srcdir}/buffer \
|
||||
${experimental_srcdir}/chrono \
|
||||
${experimental_srcdir}/deque \
|
||||
${experimental_srcdir}/executor \
|
||||
${experimental_srcdir}/forward_list \
|
||||
${experimental_srcdir}/functional \
|
||||
${experimental_srcdir}/internet \
|
||||
${experimental_srcdir}/io_context \
|
||||
${experimental_srcdir}/iterator \
|
||||
${experimental_srcdir}/list \
|
||||
${experimental_srcdir}/map \
|
||||
${experimental_srcdir}/memory \
|
||||
${experimental_srcdir}/memory_resource \
|
||||
${experimental_srcdir}/net \
|
||||
${experimental_srcdir}/netfwd \
|
||||
${experimental_srcdir}/numeric \
|
||||
${experimental_srcdir}/optional \
|
||||
${experimental_srcdir}/propagate_const \
|
||||
@ -687,10 +693,12 @@ experimental_headers = \
|
||||
${experimental_srcdir}/ratio \
|
||||
${experimental_srcdir}/regex \
|
||||
${experimental_srcdir}/set \
|
||||
${experimental_srcdir}/socket \
|
||||
${experimental_srcdir}/source_location \
|
||||
${experimental_srcdir}/string \
|
||||
${experimental_srcdir}/string_view \
|
||||
${experimental_srcdir}/system_error \
|
||||
${experimental_srcdir}/timer \
|
||||
${experimental_srcdir}/tuple \
|
||||
${experimental_srcdir}/type_traits \
|
||||
${experimental_srcdir}/unordered_map \
|
||||
@ -704,6 +712,7 @@ experimental_bits_builddir = ./experimental/bits
|
||||
experimental_bits_headers = \
|
||||
${experimental_bits_srcdir}/erase_if.h \
|
||||
${experimental_bits_srcdir}/lfts_config.h \
|
||||
${experimental_bits_srcdir}/net.h \
|
||||
${experimental_bits_srcdir}/shared_ptr.h \
|
||||
${experimental_bits_srcdir}/string_view.tcc \
|
||||
${experimental_bits_filesystem_headers}
|
||||
|
@ -963,15 +963,21 @@ experimental_headers = \
|
||||
${experimental_srcdir}/algorithm \
|
||||
${experimental_srcdir}/any \
|
||||
${experimental_srcdir}/array \
|
||||
${experimental_srcdir}/buffer \
|
||||
${experimental_srcdir}/chrono \
|
||||
${experimental_srcdir}/deque \
|
||||
${experimental_srcdir}/executor \
|
||||
${experimental_srcdir}/forward_list \
|
||||
${experimental_srcdir}/functional \
|
||||
${experimental_srcdir}/internet \
|
||||
${experimental_srcdir}/io_context \
|
||||
${experimental_srcdir}/iterator \
|
||||
${experimental_srcdir}/list \
|
||||
${experimental_srcdir}/map \
|
||||
${experimental_srcdir}/memory \
|
||||
${experimental_srcdir}/memory_resource \
|
||||
${experimental_srcdir}/net \
|
||||
${experimental_srcdir}/netfwd \
|
||||
${experimental_srcdir}/numeric \
|
||||
${experimental_srcdir}/optional \
|
||||
${experimental_srcdir}/propagate_const \
|
||||
@ -979,10 +985,12 @@ experimental_headers = \
|
||||
${experimental_srcdir}/ratio \
|
||||
${experimental_srcdir}/regex \
|
||||
${experimental_srcdir}/set \
|
||||
${experimental_srcdir}/socket \
|
||||
${experimental_srcdir}/source_location \
|
||||
${experimental_srcdir}/string \
|
||||
${experimental_srcdir}/string_view \
|
||||
${experimental_srcdir}/system_error \
|
||||
${experimental_srcdir}/timer \
|
||||
${experimental_srcdir}/tuple \
|
||||
${experimental_srcdir}/type_traits \
|
||||
${experimental_srcdir}/unordered_map \
|
||||
@ -996,6 +1004,7 @@ experimental_bits_builddir = ./experimental/bits
|
||||
experimental_bits_headers = \
|
||||
${experimental_bits_srcdir}/erase_if.h \
|
||||
${experimental_bits_srcdir}/lfts_config.h \
|
||||
${experimental_bits_srcdir}/net.h \
|
||||
${experimental_bits_srcdir}/shared_ptr.h \
|
||||
${experimental_bits_srcdir}/string_view.tcc \
|
||||
${experimental_bits_filesystem_headers}
|
||||
|
174
libstdc++-v3/include/experimental/bits/net.h
Normal file
174
libstdc++-v3/include/experimental/bits/net.h
Normal file
@ -0,0 +1,174 @@
|
||||
// Networking implementation details -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file experimental/bits/net.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{experimental/networking}
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_EXPERIMENTAL_NET_H
|
||||
#define _GLIBCXX_EXPERIMENTAL_NET_H 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
|
||||
#include <type_traits>
|
||||
#include <system_error>
|
||||
#include <experimental/netfwd>
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
namespace net
|
||||
{
|
||||
inline namespace v1
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/**
|
||||
* @ingroup networking
|
||||
* @{
|
||||
*/
|
||||
|
||||
template<typename _CompletionToken, typename _Signature, typename>
|
||||
class async_result;
|
||||
|
||||
// A type denoted by DEDUCED in the TS.
|
||||
template<typename _CompletionToken, typename _Signature>
|
||||
using __deduced_t = typename
|
||||
async_result<decay_t<_CompletionToken>, _Signature, void>::return_type;
|
||||
|
||||
// Trait to check for construction from const/non-const lvalue/rvalue.
|
||||
template<typename _Tp>
|
||||
using __is_value_constructible = typename __and_<
|
||||
is_copy_constructible<_Tp>, is_move_constructible<_Tp>,
|
||||
is_constructible<_Tp, _Tp&>, is_constructible<_Tp, const _Tp&&>
|
||||
>::type;
|
||||
|
||||
struct __throw_on_error
|
||||
{
|
||||
explicit
|
||||
__throw_on_error(const char* __msg) : _M_msg(__msg) { }
|
||||
|
||||
~__throw_on_error() noexcept(false)
|
||||
{
|
||||
if (_M_ec)
|
||||
_GLIBCXX_THROW_OR_ABORT(system_error(_M_ec, _M_msg));
|
||||
}
|
||||
|
||||
__throw_on_error(const __throw_on_error&) = delete;
|
||||
__throw_on_error& operator=(const __throw_on_error&) = delete;
|
||||
|
||||
operator error_code&() noexcept { return _M_ec; }
|
||||
|
||||
const char* _M_msg;
|
||||
error_code _M_ec;
|
||||
};
|
||||
|
||||
// Base class for types meeting IntegerSocketOption requirements.
|
||||
template<typename _Tp>
|
||||
struct __sockopt_base
|
||||
{
|
||||
__sockopt_base() = default;
|
||||
|
||||
explicit __sockopt_base(int __val) : _M_value(__val) { }
|
||||
|
||||
int value() const noexcept { return _M_value; }
|
||||
|
||||
template<typename _Protocol>
|
||||
void*
|
||||
data(const _Protocol&) noexcept
|
||||
{ return std::addressof(_M_value); }
|
||||
|
||||
template<typename _Protocol>
|
||||
const void*
|
||||
data(const _Protocol&) const noexcept
|
||||
{ return std::addressof(_M_value); }
|
||||
|
||||
template<typename _Protocol>
|
||||
size_t
|
||||
size(const _Protocol&) const noexcept
|
||||
{ return sizeof(_M_value); }
|
||||
|
||||
template<typename _Protocol>
|
||||
void
|
||||
resize(const _Protocol&, size_t __s)
|
||||
{
|
||||
if (__s != sizeof(_M_value))
|
||||
__throw_length_error("invalid value for socket option resize");
|
||||
}
|
||||
|
||||
protected:
|
||||
_Tp _M_value { };
|
||||
};
|
||||
|
||||
// Base class for types meeting BooleanSocketOption requirements.
|
||||
template<>
|
||||
struct __sockopt_base<bool> : __sockopt_base<int>
|
||||
{
|
||||
__sockopt_base() = default;
|
||||
|
||||
explicit __sockopt_base(bool __val) : __sockopt_base<int>(__val) { }
|
||||
|
||||
bool value() const noexcept { return __sockopt_base<int>::_M_value; }
|
||||
explicit operator bool() const noexcept { return value(); }
|
||||
bool operator!() const noexcept { return !value(); }
|
||||
};
|
||||
|
||||
template<typename _Derived, typename _Tp = int>
|
||||
struct __sockopt_crtp : __sockopt_base<_Tp>
|
||||
{
|
||||
using __sockopt_base<_Tp>::__sockopt_base;
|
||||
|
||||
_Derived&
|
||||
operator=(_Tp __value)
|
||||
{
|
||||
__sockopt_base<_Tp>::_M_value = __value;
|
||||
return static_cast<_Derived&>(*this);
|
||||
}
|
||||
|
||||
template<typename _Protocol>
|
||||
int
|
||||
level(const _Protocol&) const noexcept
|
||||
{ return _Derived::_S_level; }
|
||||
|
||||
template<typename _Protocol>
|
||||
int
|
||||
name(const _Protocol&) const noexcept
|
||||
{ return _Derived::_S_name; }
|
||||
};
|
||||
|
||||
/// @}
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace v1
|
||||
} // namespace net
|
||||
} // namespace experimental
|
||||
} // namespace std
|
||||
|
||||
#endif // C++14
|
||||
|
||||
#endif // _GLIBCXX_EXPERIMENTAL_NET_H
|
897
libstdc++-v3/include/experimental/buffer
Normal file
897
libstdc++-v3/include/experimental/buffer
Normal file
@ -0,0 +1,897 @@
|
||||
// <experimental/buffer> -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file experimental/buffer
|
||||
* This is a TS C++ Library header.
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_EXPERIMENTAL_BUFFER
|
||||
#define _GLIBCXX_EXPERIMENTAL_BUFFER 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
#include <experimental/string_view>
|
||||
#include <experimental/bits/net.h>
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
namespace net
|
||||
{
|
||||
inline namespace v1
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/**
|
||||
* @ingroup networking
|
||||
* @{
|
||||
*/
|
||||
|
||||
enum class stream_errc { // TODO decide values
|
||||
eof = 1,
|
||||
not_found = 2
|
||||
};
|
||||
|
||||
const error_category& stream_category() noexcept // TODO not inline
|
||||
{
|
||||
struct __cat : error_category
|
||||
{
|
||||
const char* name() const noexcept { return "stream"; }
|
||||
|
||||
std::string message(int __e) const
|
||||
{
|
||||
if (__e == (int)stream_errc::eof)
|
||||
return "EOF";
|
||||
else if (__e == (int)stream_errc::not_found)
|
||||
return "not found";
|
||||
return "stream";
|
||||
}
|
||||
|
||||
virtual void __message(int) { } // TODO dual ABI XXX
|
||||
};
|
||||
static __cat __c;
|
||||
return __c;
|
||||
}
|
||||
|
||||
inline error_code
|
||||
make_error_code(stream_errc __e) noexcept
|
||||
{ return error_code(static_cast<int>(__e), stream_category()); }
|
||||
|
||||
inline error_condition
|
||||
make_error_condition(stream_errc __e) noexcept
|
||||
{ return error_condition(static_cast<int>(__e), stream_category()); }
|
||||
|
||||
class mutable_buffer
|
||||
{
|
||||
public:
|
||||
// constructors:
|
||||
mutable_buffer() noexcept : _M_data(), _M_size() { }
|
||||
|
||||
mutable_buffer(void* __p, size_t __n) noexcept
|
||||
: _M_data(__p), _M_size(__n) { }
|
||||
|
||||
// members:
|
||||
void* data() const noexcept { return _M_data; }
|
||||
size_t size() const noexcept { return _M_size; }
|
||||
|
||||
private:
|
||||
void* _M_data;
|
||||
size_t _M_size;
|
||||
};
|
||||
|
||||
class const_buffer
|
||||
{
|
||||
public:
|
||||
// constructors:
|
||||
const_buffer() noexcept : _M_data(), _M_size() { }
|
||||
|
||||
const_buffer(const void* __p, size_t __n) noexcept
|
||||
: _M_data(__p), _M_size(__n) { }
|
||||
|
||||
const_buffer(const mutable_buffer& __b) noexcept
|
||||
: _M_data(__b.data()), _M_size(__b.size()) { }
|
||||
|
||||
// members:
|
||||
const void* data() const noexcept { return _M_data; }
|
||||
size_t size() const noexcept { return _M_size; }
|
||||
|
||||
private:
|
||||
const void* _M_data;
|
||||
size_t _M_size;
|
||||
};
|
||||
|
||||
|
||||
/** @brief buffer sequence access
|
||||
*
|
||||
* Uniform access to types that meet the BufferSequence requirements.
|
||||
* @{
|
||||
*/
|
||||
|
||||
inline const mutable_buffer*
|
||||
buffer_sequence_begin(const mutable_buffer& __b)
|
||||
{ return std::addressof(__b); }
|
||||
|
||||
inline const const_buffer*
|
||||
buffer_sequence_begin(const const_buffer& __b)
|
||||
{ return std::addressof(__b); }
|
||||
|
||||
inline const mutable_buffer*
|
||||
buffer_sequence_end(const mutable_buffer& __b)
|
||||
{ return std::addressof(__b) + 1; }
|
||||
|
||||
inline const const_buffer*
|
||||
buffer_sequence_end(const const_buffer& __b)
|
||||
{ return std::addressof(__b) + 1; }
|
||||
|
||||
template<typename _Cont>
|
||||
auto
|
||||
buffer_sequence_begin(_Cont& __c) -> decltype(__c.begin())
|
||||
{ return __c.begin(); }
|
||||
|
||||
template<typename _Cont>
|
||||
auto
|
||||
buffer_sequence_begin(const _Cont& __c) -> decltype(__c.begin())
|
||||
{ return __c.begin(); }
|
||||
|
||||
template<typename _Cont>
|
||||
auto
|
||||
buffer_sequence_end(_Cont& __c) -> decltype(__c.end())
|
||||
{ return __c.end(); }
|
||||
|
||||
template<typename _Cont>
|
||||
auto
|
||||
buffer_sequence_end(const _Cont& __c) -> decltype(__c.end())
|
||||
{ return __c.end(); }
|
||||
|
||||
// @}
|
||||
|
||||
|
||||
/** @brief buffer type traits
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
template<typename _Tp, typename _Buffer,
|
||||
typename _Begin
|
||||
= decltype(net::buffer_sequence_begin(std::declval<_Tp&>())),
|
||||
typename _End
|
||||
= decltype(net::buffer_sequence_end(std::declval<_Tp&>()))>
|
||||
using __buffer_sequence = enable_if_t<__and_<
|
||||
__is_value_constructible<_Tp>, is_same<_Begin, _End>,
|
||||
is_convertible<typename iterator_traits<_Begin>::value_type, _Buffer>
|
||||
>::value>;
|
||||
|
||||
template<typename _Tp, typename _Buffer, typename = void>
|
||||
struct __is_buffer_sequence : false_type
|
||||
{ };
|
||||
|
||||
template<typename _Tp, typename _Buffer>
|
||||
struct __is_buffer_sequence<_Tp, _Buffer, __buffer_sequence<_Tp, _Buffer>>
|
||||
: true_type
|
||||
{ };
|
||||
|
||||
template<typename _Tp>
|
||||
struct is_mutable_buffer_sequence
|
||||
: __is_buffer_sequence<_Tp, mutable_buffer>::type
|
||||
{ };
|
||||
|
||||
template<typename _Tp>
|
||||
struct is_const_buffer_sequence
|
||||
: __is_buffer_sequence<_Tp, const_buffer>::type
|
||||
{ };
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr bool is_mutable_buffer_sequence_v
|
||||
= is_mutable_buffer_sequence<_Tp>::value;
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr bool is_const_buffer_sequence_v
|
||||
= is_const_buffer_sequence<_Tp>::value;
|
||||
|
||||
template<typename _Tp, typename = void>
|
||||
struct __is_dynamic_buffer_impl : false_type
|
||||
{ };
|
||||
|
||||
// Check DynamicBuffer requirements.
|
||||
template<typename _Tp, typename _Up = remove_const_t<_Tp>>
|
||||
auto
|
||||
__dynamic_buffer_reqs(_Up* __x = 0, const _Up* __x1 = 0, size_t __n = 0)
|
||||
-> enable_if_t<__and_<
|
||||
is_move_constructible<_Up>,
|
||||
is_const_buffer_sequence<typename _Tp::const_buffers_type>,
|
||||
is_mutable_buffer_sequence<typename _Tp::mutable_buffers_type>,
|
||||
is_same<decltype(__x1->size()), size_t>,
|
||||
is_same<decltype(__x1->max_size()), size_t>,
|
||||
is_same<decltype(__x1->capacity()), size_t>,
|
||||
is_same<decltype(__x1->data()), typename _Tp::const_buffers_type>,
|
||||
is_same<decltype(__x->prepare(__n)), typename _Tp::mutable_buffers_type>,
|
||||
is_void<decltype(__x->commit(__n), __x->consume(__n), void())>
|
||||
>::value>;
|
||||
|
||||
template<typename _Tp>
|
||||
struct __is_dynamic_buffer_impl<_Tp,
|
||||
decltype(__dynamic_buffer_reqs<_Tp>())>
|
||||
: true_type
|
||||
{ };
|
||||
|
||||
template<typename _Tp>
|
||||
struct is_dynamic_buffer : __is_dynamic_buffer_impl<_Tp>::type
|
||||
{ };
|
||||
|
||||
template<typename _Tp>
|
||||
constexpr bool is_dynamic_buffer_v = is_dynamic_buffer<_Tp>::value;
|
||||
|
||||
// @}
|
||||
|
||||
/// buffer size
|
||||
template<typename _ConstBufferSequence>
|
||||
size_t
|
||||
buffer_size(const _ConstBufferSequence& __buffers) noexcept
|
||||
{
|
||||
size_t __total_size = 0;
|
||||
auto __i = net::buffer_sequence_begin(__buffers);
|
||||
const auto __end = net::buffer_sequence_end(__buffers);
|
||||
for (; __i != __end; ++__i)
|
||||
__total_size += const_buffer(*__i).size();
|
||||
return __total_size;
|
||||
}
|
||||
|
||||
template<typename _ConstBufferSequence>
|
||||
bool
|
||||
__buffer_empty(const _ConstBufferSequence& __buffers) noexcept
|
||||
{
|
||||
auto __i = net::buffer_sequence_begin(__buffers);
|
||||
const auto __end = net::buffer_sequence_end(__buffers);
|
||||
for (; __i != __end; ++__i)
|
||||
if (const_buffer(*__i).size() != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// buffer copy:
|
||||
|
||||
template<typename _MutableBufferSequence, typename _ConstBufferSequence>
|
||||
size_t
|
||||
buffer_copy(const _MutableBufferSequence& __dest,
|
||||
const _ConstBufferSequence& __source,
|
||||
size_t __max_size) noexcept
|
||||
{
|
||||
size_t __total_size = 0;
|
||||
auto __to_i = net::buffer_sequence_begin(__dest);
|
||||
const auto __to_end = net::buffer_sequence_end(__dest);
|
||||
auto __from_i = net::buffer_sequence_begin(__source);
|
||||
const auto __from_end = net::buffer_sequence_end(__source);
|
||||
mutable_buffer __to;
|
||||
const_buffer __from;
|
||||
while (((__from_i != __from_end && __to_i != __to_end)
|
||||
|| (__from.size() && __to.size()))
|
||||
&& __total_size < __max_size)
|
||||
{
|
||||
if (__from.size() == 0)
|
||||
__from = const_buffer{*__from_i++};
|
||||
if (__to.size() == 0)
|
||||
__to = mutable_buffer{*__to_i++};
|
||||
|
||||
size_t __n = std::min(__from.size(), __to.size());
|
||||
__n = std::min(__n, __max_size - __total_size);
|
||||
std::memcpy(__to.data(), __from.data(), __n);
|
||||
__from = { (const char*)__from.data() + __n, __from.size() - __n };
|
||||
__to = { (char*)__to.data() + __n, __to.size() - __n };
|
||||
__total_size += __n;
|
||||
}
|
||||
return __total_size;
|
||||
}
|
||||
|
||||
template<typename _MutableBufferSequence, typename _ConstBufferSequence>
|
||||
inline size_t
|
||||
buffer_copy(const _MutableBufferSequence& __dest,
|
||||
const _ConstBufferSequence& __source) noexcept
|
||||
{ return net::buffer_copy(__dest, __source, size_t{-1}); }
|
||||
|
||||
|
||||
// buffer arithmetic:
|
||||
|
||||
inline mutable_buffer
|
||||
operator+(const mutable_buffer& __b, size_t __n) noexcept
|
||||
{
|
||||
if (__n > __b.size())
|
||||
__n = __b.size();
|
||||
return { static_cast<char*>(__b.data()) + __n, __b.size() - __n };
|
||||
}
|
||||
|
||||
inline mutable_buffer
|
||||
operator+(size_t __n, const mutable_buffer& __b) noexcept
|
||||
{ return __b + __n; }
|
||||
|
||||
inline const_buffer
|
||||
operator+(const const_buffer& __b, size_t __n) noexcept
|
||||
{
|
||||
if (__n > __b.size())
|
||||
__n = __b.size();
|
||||
return { static_cast<const char*>(__b.data()) + __n, __b.size() - __n };
|
||||
}
|
||||
|
||||
inline const_buffer
|
||||
operator+(size_t __n, const const_buffer& __b) noexcept
|
||||
{ return __b + __n; }
|
||||
|
||||
// buffer creation:
|
||||
|
||||
inline mutable_buffer
|
||||
buffer(void* __p, size_t __n) noexcept
|
||||
{ return { __p, __n }; }
|
||||
|
||||
inline const_buffer
|
||||
buffer(const void* __p, size_t __n) noexcept
|
||||
{ return { __p, __n }; }
|
||||
|
||||
inline mutable_buffer
|
||||
buffer(const mutable_buffer& __b) noexcept
|
||||
{ return __b; }
|
||||
|
||||
inline mutable_buffer
|
||||
buffer(const mutable_buffer& __b, size_t __n) noexcept
|
||||
{ return { __b.data(), std::min(__b.size(), __n) }; }
|
||||
|
||||
inline const_buffer
|
||||
buffer(const const_buffer& __b) noexcept
|
||||
{ return __b; }
|
||||
|
||||
inline const_buffer
|
||||
buffer(const const_buffer& __b, size_t __n) noexcept
|
||||
{ return { __b.data(), std::min(__b.size(), __n) }; }
|
||||
|
||||
template<typename _Tp>
|
||||
inline mutable_buffer
|
||||
__to_mbuf(_Tp* __data, size_t __n)
|
||||
{ return { __n ? __data : nullptr, __n * sizeof(_Tp) }; }
|
||||
|
||||
template<typename _Tp>
|
||||
inline const_buffer
|
||||
__to_cbuf(const _Tp* __data, size_t __n)
|
||||
{ return { __n ? __data : nullptr, __n * sizeof(_Tp) }; }
|
||||
|
||||
template<typename _Tp, size_t _Nm>
|
||||
inline mutable_buffer
|
||||
buffer(_Tp (&__data)[_Nm]) noexcept
|
||||
{ return net::__to_mbuf(__data, _Nm); }
|
||||
|
||||
template<typename _Tp, size_t _Nm>
|
||||
inline const_buffer
|
||||
buffer(const _Tp (&__data)[_Nm]) noexcept
|
||||
{ return net::__to_cbuf(__data, _Nm); }
|
||||
|
||||
template<typename _Tp, size_t _Nm>
|
||||
inline mutable_buffer
|
||||
buffer(array<_Tp, _Nm>& __data) noexcept
|
||||
{ return net::__to_mbuf(__data.data(), _Nm); }
|
||||
|
||||
template<typename _Tp, size_t _Nm>
|
||||
inline const_buffer
|
||||
buffer(array<const _Tp, _Nm>& __data) noexcept
|
||||
{ return net::__to_cbuf(__data.data(), __data.size()); }
|
||||
|
||||
template<typename _Tp, size_t _Nm>
|
||||
inline const_buffer
|
||||
buffer(const array<_Tp, _Nm>& __data) noexcept
|
||||
{ return net::__to_cbuf(__data.data(), __data.size()); }
|
||||
|
||||
template<typename _Tp, typename _Allocator>
|
||||
inline mutable_buffer
|
||||
buffer(vector<_Tp, _Allocator>& __data) noexcept
|
||||
{ return net::__to_mbuf(__data.data(), __data.size()); }
|
||||
|
||||
template<typename _Tp, typename _Allocator>
|
||||
inline const_buffer
|
||||
buffer(const vector<_Tp, _Allocator>& __data) noexcept
|
||||
{ return net::__to_cbuf(__data.data(), __data.size()); }
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Allocator>
|
||||
inline mutable_buffer
|
||||
buffer(basic_string<_CharT, _Traits, _Allocator>& __data) noexcept
|
||||
{ return net::__to_mbuf(&__data.front(), __data.size()); }
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Allocator>
|
||||
inline const_buffer
|
||||
buffer(const basic_string<_CharT, _Traits, _Allocator>& __data) noexcept
|
||||
{ return net::__to_cbuf(&__data.front(), __data.size()); }
|
||||
|
||||
template<typename _CharT, typename _Traits>
|
||||
inline const_buffer
|
||||
buffer(basic_string_view<_CharT, _Traits> __data) noexcept
|
||||
{ return net::__to_cbuf(__data.data(), __data.size()); }
|
||||
|
||||
template<typename _Tp, size_t _Nm>
|
||||
inline mutable_buffer
|
||||
buffer(_Tp (&__data)[_Nm], size_t __n) noexcept
|
||||
{ return buffer(net::buffer(__data), __n * sizeof(_Tp)); }
|
||||
|
||||
template<typename _Tp, size_t _Nm>
|
||||
inline const_buffer
|
||||
buffer(const _Tp (&__data)[_Nm], size_t __n) noexcept
|
||||
{ return buffer(net::buffer(__data), __n * sizeof(_Tp)); }
|
||||
|
||||
template<typename _Tp, size_t _Nm>
|
||||
inline mutable_buffer
|
||||
buffer(array<_Tp, _Nm>& __data, size_t __n) noexcept
|
||||
{ return buffer(net::buffer(__data), __n * sizeof(_Tp)); }
|
||||
|
||||
template<typename _Tp, size_t _Nm>
|
||||
inline const_buffer
|
||||
buffer(array<const _Tp, _Nm>& __data, size_t __n) noexcept
|
||||
{ return buffer(net::buffer(__data), __n * sizeof(_Tp)); }
|
||||
|
||||
template<typename _Tp, size_t _Nm>
|
||||
inline const_buffer
|
||||
buffer(const array<_Tp, _Nm>& __data, size_t __n) noexcept
|
||||
{ return buffer(net::buffer(__data), __n * sizeof(_Tp)); }
|
||||
|
||||
template<typename _Tp, typename _Allocator>
|
||||
inline mutable_buffer
|
||||
buffer(vector<_Tp, _Allocator>& __data, size_t __n) noexcept
|
||||
{ return buffer(net::buffer(__data), __n * sizeof(_Tp)); }
|
||||
|
||||
template<typename _Tp, typename _Allocator>
|
||||
inline const_buffer
|
||||
buffer(const vector<_Tp, _Allocator>& __data, size_t __n) noexcept
|
||||
{ return buffer(net::buffer(__data), __n * sizeof(_Tp)); }
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Allocator>
|
||||
inline mutable_buffer
|
||||
buffer(basic_string<_CharT, _Traits, _Allocator>& __data,
|
||||
size_t __n) noexcept
|
||||
{ return buffer(net::buffer(__data), __n * sizeof(_CharT)); }
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Allocator>
|
||||
inline const_buffer
|
||||
buffer(const basic_string<_CharT, _Traits, _Allocator>& __data,
|
||||
size_t __n) noexcept
|
||||
{ return buffer(net::buffer(__data), __n * sizeof(_CharT)); }
|
||||
|
||||
template<typename _CharT, typename _Traits>
|
||||
inline const_buffer
|
||||
buffer(basic_string_view<_CharT, _Traits> __data, size_t __n) noexcept
|
||||
{ return buffer(net::buffer(__data), __n * sizeof(_CharT)); }
|
||||
|
||||
|
||||
template<typename _Sequence>
|
||||
class __dynamic_buffer_base
|
||||
{
|
||||
public:
|
||||
// types:
|
||||
typedef const_buffer const_buffers_type;
|
||||
typedef mutable_buffer mutable_buffers_type;
|
||||
|
||||
// constructors:
|
||||
explicit
|
||||
__dynamic_buffer_base(_Sequence& __seq) noexcept
|
||||
: _M_seq(__seq), _M_size(__seq.size()), _M_max_size(__seq.max_size())
|
||||
{ }
|
||||
|
||||
__dynamic_buffer_base(_Sequence& __seq, size_t __maximum_size) noexcept
|
||||
: _M_seq(__seq), _M_size(__seq.size()), _M_max_size(__maximum_size)
|
||||
{ __glibcxx_assert(__seq.size() <= __maximum_size); }
|
||||
|
||||
__dynamic_buffer_base(__dynamic_buffer_base&&) = default;
|
||||
|
||||
// members:
|
||||
size_t size() const noexcept { return _M_size; }
|
||||
size_t max_size() const noexcept { return _M_max_size; }
|
||||
size_t capacity() const noexcept { return _M_seq.capacity(); }
|
||||
|
||||
const_buffers_type
|
||||
data() const noexcept
|
||||
{ return net::buffer(_M_seq, _M_size); }
|
||||
|
||||
mutable_buffers_type
|
||||
prepare(size_t __n)
|
||||
{
|
||||
if ((_M_size + __n) > _M_max_size)
|
||||
__throw_length_error("dynamic_vector_buffer::prepare");
|
||||
|
||||
_M_seq.resize(_M_size + __n);
|
||||
return buffer(net::buffer(_M_seq) + _M_size, __n);
|
||||
}
|
||||
|
||||
void
|
||||
commit(size_t __n)
|
||||
{
|
||||
_M_size += std::min(__n, _M_seq.size() - _M_size);
|
||||
_M_seq.resize(_M_size);
|
||||
}
|
||||
|
||||
void
|
||||
consume(size_t __n)
|
||||
{
|
||||
size_t __m = std::min(__n, _M_size);
|
||||
_M_seq.erase(_M_seq.begin(), _M_seq.begin() + __m);
|
||||
_M_size -= __m;
|
||||
}
|
||||
|
||||
private:
|
||||
_Sequence& _M_seq;
|
||||
size_t _M_size;
|
||||
const size_t _M_max_size;
|
||||
};
|
||||
|
||||
template<typename _Tp, typename _Allocator>
|
||||
class dynamic_vector_buffer
|
||||
: public __dynamic_buffer_base<vector<_Tp, _Allocator>>
|
||||
{
|
||||
public:
|
||||
using __dynamic_buffer_base<vector<_Tp, _Allocator>>::__dynamic_buffer_base;
|
||||
};
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Allocator>
|
||||
class dynamic_string_buffer
|
||||
: public __dynamic_buffer_base<basic_string<_CharT, _Traits, _Allocator>>
|
||||
{
|
||||
public:
|
||||
using __dynamic_buffer_base<basic_string<_CharT, _Traits, _Allocator>>::
|
||||
__dynamic_buffer_base;
|
||||
};
|
||||
|
||||
// dynamic buffer creation:
|
||||
|
||||
template<typename _Tp, typename _Allocator>
|
||||
inline dynamic_vector_buffer<_Tp, _Allocator>
|
||||
dynamic_buffer(vector<_Tp, _Allocator>& __vec) noexcept
|
||||
{ return dynamic_vector_buffer<_Tp, _Allocator>{__vec}; }
|
||||
|
||||
template<typename _Tp, typename _Allocator>
|
||||
inline dynamic_vector_buffer<_Tp, _Allocator>
|
||||
dynamic_buffer(vector<_Tp, _Allocator>& __vec, size_t __n) noexcept
|
||||
{ return {__vec, __n}; }
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Allocator>
|
||||
inline dynamic_string_buffer<_CharT, _Traits, _Allocator>
|
||||
dynamic_buffer(basic_string<_CharT, _Traits, _Allocator>& __str) noexcept
|
||||
{ return dynamic_string_buffer<_CharT, _Traits, _Allocator>{__str}; }
|
||||
|
||||
template<typename _CharT, typename _Traits, typename _Allocator>
|
||||
inline dynamic_string_buffer<_CharT, _Traits, _Allocator>
|
||||
dynamic_buffer(basic_string<_CharT, _Traits, _Allocator>& __str,
|
||||
size_t __n) noexcept
|
||||
{ return {__str, __n}; }
|
||||
|
||||
class transfer_all
|
||||
{
|
||||
public:
|
||||
size_t operator()(const error_code& __ec, size_t) const
|
||||
{ return !__ec ? 1500 : 0; }
|
||||
};
|
||||
|
||||
class transfer_at_least
|
||||
{
|
||||
public:
|
||||
explicit transfer_at_least(size_t __m) : _M_minimum(__m) { }
|
||||
|
||||
size_t operator()(const error_code& __ec, size_t __n) const
|
||||
{ return !__ec && __n < _M_minimum ? _M_minimum - __n : 0; }
|
||||
|
||||
private:
|
||||
size_t _M_minimum;
|
||||
};
|
||||
|
||||
class transfer_exactly
|
||||
{
|
||||
public:
|
||||
explicit transfer_exactly(size_t __e) : _M_exact(__e) { }
|
||||
|
||||
size_t operator()(const error_code& __ec, size_t __n) const
|
||||
{
|
||||
size_t _Nm = -1;
|
||||
return !__ec && __n < _M_exact ? std::min(_M_exact - __n, _Nm) : 0;
|
||||
}
|
||||
|
||||
private:
|
||||
size_t _M_exact;
|
||||
};
|
||||
|
||||
/** @brief synchronous read operations
|
||||
* @{
|
||||
*/
|
||||
|
||||
template<typename _SyncReadStream, typename _MutableBufferSequence,
|
||||
typename _CompletionCondition>
|
||||
enable_if_t<is_mutable_buffer_sequence<_MutableBufferSequence>::value,
|
||||
size_t>
|
||||
read(_SyncReadStream& __stream, const _MutableBufferSequence& __buffers,
|
||||
_CompletionCondition __completion_condition, error_code& __ec)
|
||||
{
|
||||
__ec.clear();
|
||||
auto __i = net::buffer_sequence_begin(__buffers);
|
||||
auto __end = net::buffer_sequence_end(__buffers);
|
||||
mutable_buffer __to;
|
||||
size_t __total = 0;
|
||||
size_t __n;
|
||||
while ((__n = __completion_condition(__ec, __total))
|
||||
&& (__i != __end || __to.size()))
|
||||
{
|
||||
if (__to.size() == 0)
|
||||
__to = mutable_buffer(*__i++);
|
||||
__n = __stream.read_some(buffer(__to, __n), __ec);
|
||||
__to = __to + __n;
|
||||
__total += __n;
|
||||
}
|
||||
return __total;
|
||||
}
|
||||
|
||||
template<typename _SyncReadStream, typename _MutableBufferSequence>
|
||||
inline
|
||||
enable_if_t<is_mutable_buffer_sequence<_MutableBufferSequence>::value,
|
||||
size_t>
|
||||
read(_SyncReadStream& __stream, const _MutableBufferSequence& __buffers)
|
||||
{
|
||||
error_code __ec;
|
||||
return net::read(__stream, __buffers, transfer_all{}, __ec);
|
||||
}
|
||||
|
||||
template<typename _SyncReadStream, typename _MutableBufferSequence>
|
||||
inline
|
||||
enable_if_t<is_mutable_buffer_sequence<_MutableBufferSequence>::value,
|
||||
size_t>
|
||||
read(_SyncReadStream& __stream, const _MutableBufferSequence& __buffers,
|
||||
error_code& __ec)
|
||||
{ return net::read(__stream, __buffers, transfer_all{}, __ec); }
|
||||
|
||||
template<typename _SyncReadStream, typename _MutableBufferSequence,
|
||||
typename _CompletionCondition>
|
||||
inline
|
||||
enable_if_t<is_mutable_buffer_sequence<_MutableBufferSequence>::value,
|
||||
size_t>
|
||||
read(_SyncReadStream& __stream, const _MutableBufferSequence& __buffers,
|
||||
_CompletionCondition __completion_condition)
|
||||
{
|
||||
error_code __ec;
|
||||
return net::read(__stream, __buffers, __completion_condition, __ec);
|
||||
}
|
||||
|
||||
|
||||
template<typename _SyncReadStream, typename _DynamicBuffer,
|
||||
typename _CompletionCondition>
|
||||
enable_if_t<is_dynamic_buffer<decay_t<_DynamicBuffer>>::value, size_t>
|
||||
read(_SyncReadStream& __stream, _DynamicBuffer&& __b,
|
||||
_CompletionCondition __completion_condition, error_code& __ec)
|
||||
{
|
||||
const size_t __limit = 64;
|
||||
__ec.clear();
|
||||
size_t __cap = std::max(__b.capacity() - __b.size(), __limit);
|
||||
size_t __total = 0;
|
||||
size_t __n;
|
||||
while ((__n = __completion_condition(__ec, __total))
|
||||
&& __b.size() != __b.max_size())
|
||||
{
|
||||
__n = std::min(__n, __b.max_size() - __b.size());
|
||||
size_t __cap = std::max(__b.capacity() - __b.size(), __limit);
|
||||
mutable_buffer __to = __b.prepare(std::min(__cap, __n));
|
||||
__n = __stream.read_some(__to, __ec);
|
||||
__to = __to + __n;
|
||||
__total += __n;
|
||||
__b.commit(__n);
|
||||
}
|
||||
return __total;
|
||||
}
|
||||
|
||||
template<typename _SyncReadStream, typename _DynamicBuffer>
|
||||
inline enable_if_t<is_dynamic_buffer<_DynamicBuffer>::value, size_t>
|
||||
read(_SyncReadStream& __stream, _DynamicBuffer&& __b)
|
||||
{
|
||||
error_code __ec;
|
||||
return net::read(__stream, __b, transfer_all{}, __ec);
|
||||
}
|
||||
|
||||
template<typename _SyncReadStream, typename _DynamicBuffer>
|
||||
inline enable_if_t<is_dynamic_buffer<_DynamicBuffer>::value, size_t>
|
||||
read(_SyncReadStream& __stream, _DynamicBuffer&& __b, error_code& __ec)
|
||||
{
|
||||
return net::read(__stream, __b, transfer_all{}, __ec);
|
||||
}
|
||||
|
||||
template<typename _SyncReadStream, typename _DynamicBuffer,
|
||||
typename _CompletionCondition>
|
||||
inline enable_if_t<is_dynamic_buffer<_DynamicBuffer>::value, size_t>
|
||||
read(_SyncReadStream& __stream, _DynamicBuffer&& __b,
|
||||
_CompletionCondition __completion_condition)
|
||||
{
|
||||
error_code __ec;
|
||||
return net::read(__stream, __b, __completion_condition, __ec);
|
||||
}
|
||||
|
||||
// @}
|
||||
|
||||
/** @brief asynchronous read operations
|
||||
* @{
|
||||
*/
|
||||
|
||||
template<typename _AsyncReadStream, typename _MutableBufferSequence,
|
||||
typename _CompletionCondition, typename _CompletionToken>
|
||||
__deduced_t<_CompletionToken, void(error_code, size_t)>
|
||||
async_read(_AsyncReadStream& __stream,
|
||||
const _MutableBufferSequence& __buffers,
|
||||
_CompletionCondition __completion_condition,
|
||||
_CompletionToken&& __token)
|
||||
{
|
||||
error_code __ec;
|
||||
}
|
||||
|
||||
template<typename _AsyncReadStream, typename _MutableBufferSequence,
|
||||
typename _CompletionToken>
|
||||
inline __deduced_t<_CompletionToken, void(error_code, size_t)>
|
||||
async_read(_AsyncReadStream& __stream,
|
||||
const _MutableBufferSequence& __buffers,
|
||||
_CompletionToken&& __token)
|
||||
{
|
||||
return net::async_read(__stream, __buffers, transfer_all{},
|
||||
std::forward<_CompletionToken>(__token));
|
||||
}
|
||||
|
||||
template<typename _AsyncReadStream, typename _DynamicBuffer,
|
||||
typename _CompletionCondition, typename _CompletionToken>
|
||||
__deduced_t<_CompletionToken, void(error_code, size_t)>
|
||||
async_read(_AsyncReadStream& __stream, _DynamicBuffer&& __b,
|
||||
_CompletionCondition __completion_condition,
|
||||
_CompletionToken&& __token)
|
||||
{
|
||||
error_code __ec;
|
||||
}
|
||||
|
||||
template<typename _AsyncReadStream, typename _DynamicBuffer,
|
||||
typename _CompletionToken>
|
||||
inline __deduced_t<_CompletionToken, void(error_code, size_t)>
|
||||
async_read(_AsyncReadStream& __stream, _DynamicBuffer&& __b,
|
||||
_CompletionToken&& __token)
|
||||
{
|
||||
return net::async_read(__stream, __b, transfer_all{},
|
||||
std::forward<_CompletionToken>(__token));
|
||||
}
|
||||
|
||||
// @}
|
||||
|
||||
#if 0
|
||||
/** @brief synchronous write operations:
|
||||
* @{
|
||||
*/
|
||||
|
||||
template<typename _SyncWriteStream, typename _ConstBufferSequence>
|
||||
size_t write(_SyncWriteStream& __stream,
|
||||
const _ConstBufferSequence& __buffers);
|
||||
template<typename _SyncWriteStream, typename _ConstBufferSequence>
|
||||
size_t write(_SyncWriteStream& __stream,
|
||||
const _ConstBufferSequence& __buffers, error_code& __ec);
|
||||
template<typename _SyncWriteStream, typename _ConstBufferSequence,
|
||||
typename _CompletionCondition>
|
||||
size_t write(_SyncWriteStream& __stream,
|
||||
const _ConstBufferSequence& __buffers,
|
||||
_CompletionCondition __completion_condition);
|
||||
template<typename _SyncWriteStream, typename _ConstBufferSequence,
|
||||
typename _CompletionCondition>
|
||||
size_t write(_SyncWriteStream& __stream,
|
||||
const _ConstBufferSequence& __buffers,
|
||||
_CompletionCondition __completion_condition,
|
||||
error_code& __ec);
|
||||
|
||||
template<typename _SyncWriteStream, typename _DynamicBuffer>
|
||||
size_t write(_SyncWriteStream& __stream, _DynamicBuffer&& __b);
|
||||
template<typename _SyncWriteStream, typename _DynamicBuffer>
|
||||
size_t write(_SyncWriteStream& __stream, _DynamicBuffer&& __b, error_code& __ec);
|
||||
template<typename _SyncWriteStream, typename _DynamicBuffer, typename _CompletionCondition>
|
||||
size_t write(_SyncWriteStream& __stream, _DynamicBuffer&& __b,
|
||||
_CompletionCondition __completion_condition);
|
||||
template<typename _SyncWriteStream, typename _DynamicBuffer, typename _CompletionCondition>
|
||||
size_t write(_SyncWriteStream& __stream, _DynamicBuffer&& __b,
|
||||
_CompletionCondition __completion_condition, error_code& __ec);
|
||||
|
||||
// @}
|
||||
|
||||
/** @brief asynchronous write operations
|
||||
* @{
|
||||
*/
|
||||
|
||||
template<typename _AsyncWriteStream, typename _ConstBufferSequence,
|
||||
typename _CompletionToken>
|
||||
DEDUCED async_write(_AsyncWriteStream& __stream,
|
||||
const _ConstBufferSequence& __buffers,
|
||||
_CompletionToken&& __token);
|
||||
template<typename _AsyncWriteStream, typename _ConstBufferSequence,
|
||||
typename _CompletionCondition, typename _CompletionToken>
|
||||
DEDUCED async_write(_AsyncWriteStream& __stream,
|
||||
const _ConstBufferSequence& __buffers,
|
||||
_CompletionCondition __completion_condition,
|
||||
_CompletionToken&& __token);
|
||||
|
||||
template<typename _AsyncWriteStream, typename _DynamicBuffer, typename _CompletionToken>
|
||||
DEDUCED async_write(_AsyncWriteStream& __stream,
|
||||
_DynamicBuffer&& __b, _CompletionToken&& __token);
|
||||
template<typename _AsyncWriteStream, typename _DynamicBuffer,
|
||||
typename _CompletionCondition, typename _CompletionToken>
|
||||
DEDUCED async_write(_AsyncWriteStream& __stream,
|
||||
_DynamicBuffer&& __b,
|
||||
_CompletionCondition __completion_condition,
|
||||
_CompletionToken&& __token);
|
||||
|
||||
// @}
|
||||
|
||||
/** @brief synchronous delimited read operations
|
||||
* @{
|
||||
*/
|
||||
|
||||
template<typename _SyncReadStream, typename _DynamicBuffer>
|
||||
size_t read_until(_SyncReadStream& __s, _DynamicBuffer&& __b, char __delim);
|
||||
template<typename _SyncReadStream, typename _DynamicBuffer>
|
||||
size_t read_until(_SyncReadStream& __s, _DynamicBuffer&& __b,
|
||||
char __delim, error_code& __ec);
|
||||
template<typename _SyncReadStream, typename _DynamicBuffer>
|
||||
size_t read_until(_SyncReadStream& __s, _DynamicBuffer&& __b, string_view __delim);
|
||||
template<typename _SyncReadStream, typename _DynamicBuffer>
|
||||
size_t read_until(_SyncReadStream& __s, _DynamicBuffer&& __b,
|
||||
string_view __delim, error_code& __ec);
|
||||
|
||||
// @}
|
||||
|
||||
/** @brief asynchronous delimited read operations
|
||||
* @{
|
||||
*/
|
||||
|
||||
template<typename _AsyncReadStream, typename _DynamicBuffer, typename _CompletionToken>
|
||||
DEDUCED async_read_until(_AsyncReadStream& __s,
|
||||
_DynamicBuffer&& __b, char __delim,
|
||||
_CompletionToken&& __token);
|
||||
template<typename _AsyncReadStream, typename _DynamicBuffer, typename _CompletionToken>
|
||||
DEDUCED async_read_until(_AsyncReadStream& __s,
|
||||
_DynamicBuffer&& __b, string_view __delim,
|
||||
_CompletionToken&& __token);
|
||||
|
||||
// @}
|
||||
|
||||
#endif
|
||||
/// @}
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
|
||||
} // namespace v1
|
||||
} // namespace net
|
||||
} // namespace experimental
|
||||
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
template<>
|
||||
struct is_error_code_enum<experimental::net::v1::stream_errc>
|
||||
: public true_type {};
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif // C++14
|
||||
|
||||
#endif // _GLIBCXX_EXPERIMENTAL_BUFFER
|
1887
libstdc++-v3/include/experimental/executor
Normal file
1887
libstdc++-v3/include/experimental/executor
Normal file
File diff suppressed because it is too large
Load Diff
2397
libstdc++-v3/include/experimental/internet
Normal file
2397
libstdc++-v3/include/experimental/internet
Normal file
File diff suppressed because it is too large
Load Diff
864
libstdc++-v3/include/experimental/io_context
Normal file
864
libstdc++-v3/include/experimental/io_context
Normal file
@ -0,0 +1,864 @@
|
||||
// <experimental/io_service> -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file experimental/io_service
|
||||
* This is a TS C++ Library header.
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_EXPERIMENTAL_IO_SERVICE
|
||||
#define _GLIBCXX_EXPERIMENTAL_IO_SERVICE 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <forward_list>
|
||||
#include <functional>
|
||||
#include <system_error>
|
||||
#include <thread>
|
||||
#include <experimental/netfwd>
|
||||
#include <experimental/executor>
|
||||
#include <unistd.h>
|
||||
#include <poll.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
namespace net
|
||||
{
|
||||
inline namespace v1
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/**
|
||||
* @ingroup networking
|
||||
* @{
|
||||
*/
|
||||
|
||||
class __socket_impl;
|
||||
|
||||
/// An ExecutionContext for I/O operations.
|
||||
class io_context : public execution_context
|
||||
{
|
||||
public:
|
||||
// types:
|
||||
|
||||
/// An executor for an io_context.
|
||||
class executor_type
|
||||
{
|
||||
public:
|
||||
// construct / copy / destroy:
|
||||
|
||||
executor_type(const executor_type& __other) noexcept = default;
|
||||
executor_type(executor_type&& __other) noexcept = default;
|
||||
|
||||
executor_type& operator=(const executor_type& __other) noexcept = default;
|
||||
executor_type& operator=(executor_type&& __other) noexcept = default;
|
||||
|
||||
// executor operations:
|
||||
|
||||
bool running_in_this_thread() const noexcept
|
||||
{
|
||||
lock_guard<mutex> __lock(_M_ctx->_M_mtx);
|
||||
auto __end = _M_ctx->_M_call_stack.end();
|
||||
return std::find(_M_ctx->_M_call_stack.begin(), __end,
|
||||
this_thread::get_id()) != __end;
|
||||
}
|
||||
|
||||
io_context& context() const noexcept { return *_M_ctx; }
|
||||
|
||||
void on_work_started() const noexcept { ++_M_ctx->_M_work_count; }
|
||||
void on_work_finished() const noexcept { --_M_ctx->_M_work_count; }
|
||||
|
||||
template<typename _Func, typename _ProtoAllocator>
|
||||
void
|
||||
dispatch(_Func&& __f, const _ProtoAllocator& __a) const
|
||||
{
|
||||
if (running_in_this_thread())
|
||||
decay_t<_Func>{std::forward<_Func>(__f)}();
|
||||
else
|
||||
post(std::forward<_Func>(__f), __a);
|
||||
}
|
||||
|
||||
template<typename _Func, typename _ProtoAllocator>
|
||||
void
|
||||
post(_Func&& __f, const _ProtoAllocator& __a) const
|
||||
{
|
||||
lock_guard<mutex> __lock(_M_ctx->_M_mtx);
|
||||
// TODO (re-use functionality in system_context)
|
||||
_M_ctx->_M_reactor._M_notify();
|
||||
}
|
||||
|
||||
template<typename _Func, typename _ProtoAllocator>
|
||||
void
|
||||
defer(_Func&& __f, const _ProtoAllocator& __a) const
|
||||
{ post(std::forward<_Func>(__f), __a); }
|
||||
|
||||
private:
|
||||
friend io_context;
|
||||
|
||||
explicit
|
||||
executor_type(io_context& __ctx) : _M_ctx(std::addressof(__ctx)) { }
|
||||
|
||||
io_context* _M_ctx;
|
||||
};
|
||||
|
||||
using count_type = size_t;
|
||||
|
||||
// construct / copy / destroy:
|
||||
|
||||
io_context() : _M_work_count(0) { }
|
||||
|
||||
explicit
|
||||
io_context(int __concurrency_hint) : _M_work_count(0) { }
|
||||
|
||||
io_context(const io_context&) = delete;
|
||||
io_context& operator=(const io_context&) = delete;
|
||||
|
||||
// io_context operations:
|
||||
|
||||
executor_type get_executor() noexcept { return executor_type(*this); }
|
||||
|
||||
count_type
|
||||
run()
|
||||
{
|
||||
count_type __n = 0;
|
||||
while (run_one())
|
||||
if (__n != numeric_limits<count_type>::max())
|
||||
++__n;
|
||||
return __n;
|
||||
}
|
||||
|
||||
template<typename _Rep, typename _Period>
|
||||
count_type
|
||||
run_for(const chrono::duration<_Rep, _Period>& __rel_time)
|
||||
{ return run_until(chrono::steady_clock::now() + __rel_time); }
|
||||
|
||||
template<typename _Clock, typename _Duration>
|
||||
count_type
|
||||
run_until(const chrono::time_point<_Clock, _Duration>& __abs_time)
|
||||
{
|
||||
count_type __n = 0;
|
||||
while (run_one_until(__abs_time))
|
||||
if (__n != numeric_limits<count_type>::max())
|
||||
++__n;
|
||||
return __n;
|
||||
}
|
||||
|
||||
count_type
|
||||
run_one()
|
||||
{ return _M_do_one(chrono::milliseconds{-1}); }
|
||||
|
||||
template<typename _Rep, typename _Period>
|
||||
count_type
|
||||
run_one_for(const chrono::duration<_Rep, _Period>& __rel_time)
|
||||
{ return run_one_until(chrono::steady_clock::now() + __rel_time); }
|
||||
|
||||
template<typename _Clock, typename _Duration>
|
||||
count_type
|
||||
run_one_until(const chrono::time_point<_Clock, _Duration>& __abs_time)
|
||||
{
|
||||
auto __now = _Clock::now();
|
||||
while (__now < __abs_time)
|
||||
{
|
||||
using namespace std::chrono;
|
||||
auto __ms = duration_cast<milliseconds>(__abs_time - __now);
|
||||
if (_M_do_one(__ms))
|
||||
return 1;
|
||||
__now = _Clock::now();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
count_type
|
||||
poll()
|
||||
{
|
||||
count_type __n = 0;
|
||||
while (poll_one())
|
||||
if (__n != numeric_limits<count_type>::max())
|
||||
++__n;
|
||||
return __n;
|
||||
}
|
||||
|
||||
count_type
|
||||
poll_one()
|
||||
{ return _M_do_one(chrono::milliseconds{0}); }
|
||||
|
||||
void stop()
|
||||
{
|
||||
lock_guard<mutex> __lock(_M_mtx);
|
||||
_M_stopped = true;
|
||||
_M_reactor._M_notify();
|
||||
}
|
||||
|
||||
bool stopped() const noexcept
|
||||
{
|
||||
lock_guard<mutex> __lock(_M_mtx);
|
||||
return _M_stopped;
|
||||
}
|
||||
|
||||
void restart()
|
||||
{
|
||||
_M_stopped = false;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template<typename _Clock, typename _WaitTraits>
|
||||
friend class basic_waitable_timer;
|
||||
|
||||
friend __socket_impl;
|
||||
|
||||
template<typename _Protocol>
|
||||
friend class __basic_socket_impl;
|
||||
|
||||
template<typename _Protocol>
|
||||
friend class basic_socket;
|
||||
|
||||
template<typename _Protocol>
|
||||
friend class basic_datagram_socket;
|
||||
|
||||
template<typename _Protocol>
|
||||
friend class basic_stream_socket;
|
||||
|
||||
template<typename _Protocol>
|
||||
friend class basic_socket_acceptor;
|
||||
|
||||
count_type
|
||||
_M_outstanding_work() const
|
||||
{ return _M_work_count + !_M_ops.empty(); }
|
||||
|
||||
struct __timer_queue_base : execution_context::service
|
||||
{
|
||||
// return milliseconds until next timer expires, or milliseconds::max()
|
||||
virtual chrono::milliseconds _M_next() const = 0;
|
||||
virtual bool run_one() = 0;
|
||||
|
||||
protected:
|
||||
explicit
|
||||
__timer_queue_base(execution_context& __ctx) : service(__ctx)
|
||||
{
|
||||
auto& __ioc = static_cast<io_context&>(__ctx);
|
||||
lock_guard<mutex> __lock(__ioc._M_mtx);
|
||||
__ioc._M_timers.push_back(this);
|
||||
}
|
||||
|
||||
mutable mutex _M_qmtx;
|
||||
};
|
||||
|
||||
template<typename _Timer, typename _Key = typename _Timer::_Key>
|
||||
struct __timer_queue : __timer_queue_base
|
||||
{
|
||||
using key_type = __timer_queue;
|
||||
|
||||
explicit
|
||||
__timer_queue(execution_context& __ctx) : __timer_queue_base(__ctx)
|
||||
{ }
|
||||
|
||||
void shutdown() noexcept { }
|
||||
|
||||
io_context& context() noexcept
|
||||
{ return static_cast<io_context&>(service::context()); }
|
||||
|
||||
// Start an asynchronous wait.
|
||||
void
|
||||
push(const _Timer& __t, function<void(error_code)> __h)
|
||||
{
|
||||
context().get_executor().on_work_started();
|
||||
lock_guard<mutex> __lock(_M_qmtx);
|
||||
_M_queue.emplace(__t, _M_next_id++, std::move(__h));
|
||||
// no need to notify reactor unless this timer went to the front?
|
||||
}
|
||||
|
||||
// Cancel all outstanding waits for __t
|
||||
size_t
|
||||
cancel(const _Timer& __t)
|
||||
{
|
||||
lock_guard<mutex> __lock(_M_qmtx);
|
||||
size_t __count = 0;
|
||||
auto __last = _M_queue.end();
|
||||
for (auto __it = _M_queue.begin(), __end = __last; __it != __end;
|
||||
++__it)
|
||||
{
|
||||
if (__it->_M_key == __t._M_key.get())
|
||||
{
|
||||
__it->cancel();
|
||||
__last = __it;
|
||||
++__count;
|
||||
}
|
||||
}
|
||||
if (__count)
|
||||
_M_queue._M_sort_to(__last);
|
||||
return __count;
|
||||
}
|
||||
|
||||
// Cancel oldest outstanding wait for __t
|
||||
bool
|
||||
cancel_one(const _Timer& __t)
|
||||
{
|
||||
lock_guard<mutex> __lock(_M_qmtx);
|
||||
const auto __end = _M_queue.end();
|
||||
auto __oldest = __end;
|
||||
for (auto __it = _M_queue.begin(); __it != __end; ++__it)
|
||||
if (__it->_M_key == __t._M_key.get())
|
||||
if (__oldest == __end || __it->_M_id < __oldest->_M_id)
|
||||
__oldest = __it;
|
||||
if (__oldest == __end)
|
||||
return false;
|
||||
__oldest->cancel();
|
||||
_M_queue._M_sort_to(__oldest);
|
||||
return true;
|
||||
}
|
||||
|
||||
chrono::milliseconds
|
||||
_M_next() const override
|
||||
{
|
||||
typename _Timer::time_point __exp;
|
||||
{
|
||||
lock_guard<mutex> __lock(_M_qmtx);
|
||||
if (_M_queue.empty())
|
||||
return chrono::milliseconds::max(); // no pending timers
|
||||
if (_M_queue.top()._M_key == nullptr)
|
||||
return chrono::milliseconds::zero(); // cancelled, run now
|
||||
__exp = _M_queue.top()._M_expiry;
|
||||
}
|
||||
auto __dur = _Timer::traits_type::to_wait_duration(__exp);
|
||||
if (__dur < __dur.zero())
|
||||
__dur = __dur.zero();
|
||||
return chrono::duration_cast<chrono::milliseconds>(__dur);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
bool run_one() override
|
||||
{
|
||||
auto __now = _Timer::clock_type::now();
|
||||
function<void(error_code)> __h;
|
||||
error_code __ec;
|
||||
{
|
||||
lock_guard<mutex> __lock(_M_qmtx);
|
||||
|
||||
if (_M_queue.top()._M_key == nullptr) // cancelled
|
||||
{
|
||||
__h = std::move(_M_queue.top()._M_h);
|
||||
__ec = std::make_error_code(errc::operation_canceled);
|
||||
_M_queue.pop();
|
||||
}
|
||||
else if (_M_queue.top()._M_expiry <= _Timer::clock_type::now())
|
||||
{
|
||||
__h = std::move(_M_queue.top()._M_h);
|
||||
_M_queue.pop();
|
||||
}
|
||||
}
|
||||
if (__h)
|
||||
{
|
||||
__h(__ec);
|
||||
context().get_executor().on_work_finished();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
using __timer_id_type = uint64_t;
|
||||
|
||||
struct __pending_timer
|
||||
{
|
||||
__pending_timer(const _Timer& __t, uint64_t __id,
|
||||
function<void(error_code)> __h)
|
||||
: _M_expiry(__t.expiry()), _M_key(__t._M_key.get()), _M_id(__id),
|
||||
_M_h(std::move(__h))
|
||||
{ }
|
||||
|
||||
typename _Timer::time_point _M_expiry;
|
||||
_Key* _M_key;
|
||||
__timer_id_type _M_id;
|
||||
function<void(error_code)> _M_h;
|
||||
|
||||
void cancel() { _M_expiry = _M_expiry.min(); _M_key = nullptr; }
|
||||
|
||||
bool
|
||||
operator<(const __pending_timer& __rhs) const
|
||||
{ return _M_expiry < __rhs._M_expiry; }
|
||||
};
|
||||
|
||||
struct __queue : priority_queue<__pending_timer>
|
||||
{
|
||||
using iterator =
|
||||
typename priority_queue<__pending_timer>::container_type::iterator;
|
||||
|
||||
// expose begin/end/erase for direct access to underlying container
|
||||
iterator begin() { return this->c.begin(); }
|
||||
iterator end() { return this->c.end(); }
|
||||
iterator erase(iterator __it) { return this->c.erase(__it); }
|
||||
|
||||
void
|
||||
_M_sort_to(iterator __it)
|
||||
{ std::stable_sort(this->c.begin(), ++__it); }
|
||||
};
|
||||
|
||||
__queue _M_queue;
|
||||
__timer_id_type _M_next_id = 0;
|
||||
};
|
||||
|
||||
template<typename _Timer, typename _CompletionHandler>
|
||||
void
|
||||
async_wait(const _Timer& __timer, _CompletionHandler&& __h)
|
||||
{
|
||||
auto& __queue = use_service<__timer_queue<_Timer>>(*this);
|
||||
__queue.push(__timer, std::move(__h));
|
||||
_M_reactor._M_notify();
|
||||
}
|
||||
|
||||
// Cancel all wait operations initiated by __timer.
|
||||
template<typename _Timer>
|
||||
size_t
|
||||
cancel(const _Timer& __timer)
|
||||
{
|
||||
if (!has_service<__timer_queue<_Timer>>(*this))
|
||||
return 0;
|
||||
|
||||
auto __c = use_service<__timer_queue<_Timer>>(*this).cancel(__timer);
|
||||
if (__c != 0)
|
||||
_M_reactor._M_notify();
|
||||
return __c;
|
||||
}
|
||||
|
||||
// Cancel the oldest wait operation initiated by __timer.
|
||||
template<typename _Timer>
|
||||
size_t
|
||||
cancel_one(const _Timer& __timer)
|
||||
{
|
||||
if (!has_service<__timer_queue<_Timer>>(*this))
|
||||
return 0;
|
||||
|
||||
if (use_service<__timer_queue<_Timer>>(*this).cancel_one(__timer))
|
||||
{
|
||||
_M_reactor._M_notify();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename _Op>
|
||||
void
|
||||
async_wait(int __fd, int __w, _Op&& __op)
|
||||
{
|
||||
lock_guard<mutex> __lock(_M_mtx);
|
||||
// TODO need push_back, use std::list not std::forward_list
|
||||
auto __tail = _M_ops.before_begin(), __it = _M_ops.begin();
|
||||
while (__it != _M_ops.end())
|
||||
{
|
||||
++__it;
|
||||
++__tail;
|
||||
}
|
||||
using __type = __async_operation_impl<_Op>;
|
||||
_M_ops.emplace_after(__tail,
|
||||
make_unique<__type>(std::move(__op), __fd, __w));
|
||||
_M_reactor._M_fd_interest(__fd, __w);
|
||||
}
|
||||
|
||||
void _M_add_fd(int __fd) { _M_reactor._M_add_fd(__fd); }
|
||||
void _M_remove_fd(int __fd) { _M_reactor._M_remove_fd(__fd); }
|
||||
|
||||
void cancel(int __fd, error_code&)
|
||||
{
|
||||
lock_guard<mutex> __lock(_M_mtx);
|
||||
const auto __end = _M_ops.end();
|
||||
auto __it = _M_ops.begin();
|
||||
auto __prev = _M_ops.before_begin();
|
||||
while (__it != __end && (*__it)->_M_is_cancelled())
|
||||
{
|
||||
++__it;
|
||||
++__prev;
|
||||
}
|
||||
auto __cancelled = __prev;
|
||||
while (__it != __end)
|
||||
{
|
||||
if ((*__it)->_M_fd == __fd)
|
||||
{
|
||||
(*__it)->cancel();
|
||||
++__it;
|
||||
_M_ops.splice_after(__cancelled, _M_ops, __prev);
|
||||
++__cancelled;
|
||||
}
|
||||
else
|
||||
{
|
||||
++__it;
|
||||
++__prev;
|
||||
}
|
||||
}
|
||||
_M_reactor._M_not_interested(__fd);
|
||||
}
|
||||
|
||||
struct __async_operation
|
||||
{
|
||||
__async_operation(int __fd, int __ev) : _M_fd(__fd), _M_ev(__ev) { }
|
||||
|
||||
virtual ~__async_operation() = default;
|
||||
|
||||
int _M_fd;
|
||||
short _M_ev;
|
||||
|
||||
void cancel() { _M_fd = -1; }
|
||||
bool _M_is_cancelled() const { return _M_fd == -1; }
|
||||
virtual void run(io_context&) = 0;
|
||||
};
|
||||
|
||||
template<typename _Op>
|
||||
struct __async_operation_impl : __async_operation
|
||||
{
|
||||
__async_operation_impl(_Op&& __op, int __fd, int __ev)
|
||||
: __async_operation{__fd, __ev}, _M_op(std::move(__op)) { }
|
||||
|
||||
_Op _M_op;
|
||||
|
||||
void run(io_context& __ctx)
|
||||
{
|
||||
if (_M_is_cancelled())
|
||||
_M_op(std::make_error_code(errc::operation_canceled));
|
||||
else
|
||||
_M_op(error_code{});
|
||||
}
|
||||
};
|
||||
|
||||
atomic<count_type> _M_work_count;
|
||||
mutable mutex _M_mtx;
|
||||
queue<function<void()>> _M_op;
|
||||
bool _M_stopped = false;
|
||||
|
||||
struct __monitor
|
||||
{
|
||||
__monitor(io_context& __c) : _M_ctx(__c)
|
||||
{
|
||||
lock_guard<mutex> __lock(_M_ctx._M_mtx);
|
||||
_M_ctx._M_call_stack.push_back(this_thread::get_id());
|
||||
}
|
||||
|
||||
~__monitor()
|
||||
{
|
||||
lock_guard<mutex> __lock(_M_ctx._M_mtx);
|
||||
_M_ctx._M_call_stack.pop_back();
|
||||
if (_M_ctx._M_outstanding_work() == 0)
|
||||
{
|
||||
_M_ctx._M_stopped = true;
|
||||
_M_ctx._M_reactor._M_notify();
|
||||
}
|
||||
}
|
||||
|
||||
__monitor(__monitor&&) = delete;
|
||||
|
||||
io_context& _M_ctx;
|
||||
};
|
||||
|
||||
bool
|
||||
_M_do_one(chrono::milliseconds __timeout)
|
||||
{
|
||||
const bool __block = __timeout != chrono::milliseconds::zero();
|
||||
|
||||
__reactor::__fdvec __fds;
|
||||
|
||||
__monitor __mon{*this};
|
||||
|
||||
__timer_queue_base* __timerq = nullptr;
|
||||
unique_ptr<__async_operation> __async_op;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (__timerq)
|
||||
{
|
||||
if (__timerq->run_one())
|
||||
return true;
|
||||
else
|
||||
__timerq = nullptr;
|
||||
}
|
||||
|
||||
if (__async_op)
|
||||
{
|
||||
__async_op->run(*this);
|
||||
// TODO need to unregister __async_op
|
||||
return true;
|
||||
}
|
||||
|
||||
chrono::milliseconds __ms{0};
|
||||
|
||||
{
|
||||
lock_guard<mutex> __lock(_M_mtx);
|
||||
|
||||
if (_M_stopped)
|
||||
return false;
|
||||
|
||||
// find first timer with something to do
|
||||
for (auto __q : _M_timers)
|
||||
{
|
||||
auto __next = __q->_M_next();
|
||||
if (__next == __next.zero()) // ready to run immediately
|
||||
{
|
||||
__timerq = __q;
|
||||
__ms = __next;
|
||||
break;
|
||||
}
|
||||
else if (__next != __next.max() && __block
|
||||
&& (__next < __ms || __timerq == nullptr))
|
||||
{
|
||||
__timerq = __q;
|
||||
__ms = __next;
|
||||
}
|
||||
}
|
||||
|
||||
if (__timerq && __ms == __ms.zero())
|
||||
continue; // restart loop to run a timer immediately
|
||||
|
||||
if (!_M_ops.empty() && _M_ops.front()->_M_is_cancelled())
|
||||
{
|
||||
_M_ops.front().swap(__async_op);
|
||||
_M_ops.pop_front();
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO run any posted items
|
||||
|
||||
if (__block)
|
||||
{
|
||||
if (__timerq == nullptr)
|
||||
__ms = __timeout;
|
||||
else if (__ms.zero() <= __timeout && __timeout < __ms)
|
||||
__ms = __timeout;
|
||||
else if (__ms.count() > numeric_limits<int>::max())
|
||||
__ms = chrono::milliseconds{numeric_limits<int>::max()};
|
||||
}
|
||||
// else __ms == 0 and poll() will return immediately
|
||||
|
||||
}
|
||||
|
||||
auto __res = _M_reactor.wait(__fds, __ms);
|
||||
|
||||
if (__res == __reactor::_S_retry)
|
||||
continue;
|
||||
|
||||
if (__res == __reactor::_S_timeout)
|
||||
if (__timerq == nullptr)
|
||||
return false;
|
||||
else
|
||||
continue; // timed out, so restart loop and process the timer
|
||||
|
||||
__timerq = nullptr;
|
||||
|
||||
if (__fds.empty()) // nothing to do
|
||||
return false;
|
||||
|
||||
lock_guard<mutex> __lock(_M_mtx);
|
||||
for (auto __it = _M_ops.begin(), __end = _M_ops.end(),
|
||||
__prev = _M_ops.before_begin(); __it != __end; ++__it, ++__prev)
|
||||
{
|
||||
auto& __op = **__it;
|
||||
auto __pos = std::lower_bound(__fds.begin(), __fds.end(),
|
||||
__op._M_fd,
|
||||
[](const auto& __p, int __fd) { return __p.fd < __fd; });
|
||||
if (__pos != __fds.end() && __pos->fd == __op._M_fd
|
||||
&& __pos->revents & __op._M_ev)
|
||||
{
|
||||
__it->swap(__async_op);
|
||||
_M_ops.erase_after(__prev);
|
||||
break; // restart loop and run op
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct __reactor
|
||||
{
|
||||
__reactor() : _M_fds(1)
|
||||
{
|
||||
int __pipe[2];
|
||||
if (::pipe(__pipe) == -1)
|
||||
__throw_system_error(errno);
|
||||
if (::fcntl(__pipe[0], F_SETFL, O_NONBLOCK) == -1
|
||||
|| ::fcntl(__pipe[1], F_SETFL, O_NONBLOCK) == -1)
|
||||
{
|
||||
int __e = errno;
|
||||
::close(__pipe[0]);
|
||||
::close(__pipe[1]);
|
||||
__throw_system_error(__e);
|
||||
}
|
||||
_M_fds.back().events = POLLIN;
|
||||
_M_fds.back().fd = __pipe[0];
|
||||
_M_notify_wr = __pipe[1];
|
||||
}
|
||||
|
||||
~__reactor()
|
||||
{
|
||||
::close(_M_fds.back().fd);
|
||||
::close(_M_notify_wr);
|
||||
}
|
||||
|
||||
// write a notification byte to the pipe (ignoring errors)
|
||||
void _M_notify()
|
||||
{
|
||||
int __n;
|
||||
do {
|
||||
__n = ::write(_M_notify_wr, "", 1);
|
||||
} while (__n == -1 && errno == EINTR);
|
||||
}
|
||||
|
||||
// read all notification bytes from the pipe
|
||||
void _M_on_notify()
|
||||
{
|
||||
// Drain the pipe.
|
||||
char __buf[64];
|
||||
ssize_t __n;
|
||||
do {
|
||||
__n = ::read(_M_fds.back().fd, __buf, sizeof(__buf));
|
||||
} while (__n != -1 || errno == EINTR);
|
||||
}
|
||||
|
||||
void
|
||||
_M_add_fd(int __fd)
|
||||
{
|
||||
auto __pos = _M_lower_bound(__fd);
|
||||
if (__pos->fd == __fd)
|
||||
__throw_system_error((int)errc::invalid_argument);
|
||||
_M_fds.insert(__pos, __fdvec::value_type{})->fd = __fd;
|
||||
_M_notify();
|
||||
}
|
||||
|
||||
void
|
||||
_M_remove_fd(int __fd)
|
||||
{
|
||||
auto __pos = _M_lower_bound(__fd);
|
||||
if (__pos->fd == __fd)
|
||||
_M_fds.erase(__pos);
|
||||
// else bug!
|
||||
_M_notify();
|
||||
}
|
||||
|
||||
void
|
||||
_M_fd_interest(int __fd, int __w)
|
||||
{
|
||||
auto __pos = _M_lower_bound(__fd);
|
||||
if (__pos->fd == __fd)
|
||||
__pos->events |= __w;
|
||||
// else bug!
|
||||
_M_notify();
|
||||
}
|
||||
|
||||
void
|
||||
_M_not_interested(int __fd)
|
||||
{
|
||||
auto __pos = _M_lower_bound(__fd);
|
||||
if (__pos->fd == __fd)
|
||||
__pos->events = 0;
|
||||
_M_notify();
|
||||
}
|
||||
|
||||
using __fdvec = vector<::pollfd>;
|
||||
|
||||
// Find first element p such that !(p.fd < __fd)
|
||||
// N.B. always returns a dereferencable iterator.
|
||||
__fdvec::iterator
|
||||
_M_lower_bound(int __fd)
|
||||
{
|
||||
return std::lower_bound(_M_fds.begin(), _M_fds.end() - 1,
|
||||
__fd, [](const auto& __p, int __fd) { return __p.fd < __fd; });
|
||||
}
|
||||
|
||||
enum __status { _S_retry, _S_timeout, _S_ok, _S_error };
|
||||
|
||||
__status
|
||||
wait(__fdvec& __fds, chrono::milliseconds __timeout)
|
||||
{
|
||||
// XXX not thread-safe!
|
||||
__fds = _M_fds; // take snapshot to pass to poll()
|
||||
|
||||
int __res = ::poll(__fds.data(), __fds.size(), __timeout.count());
|
||||
|
||||
if (__res == -1)
|
||||
{
|
||||
__fds.clear();
|
||||
if (errno == EINTR)
|
||||
return _S_retry;
|
||||
return _S_error; // XXX ???
|
||||
}
|
||||
else if (__res == 0)
|
||||
{
|
||||
__fds.clear();
|
||||
return _S_timeout;
|
||||
}
|
||||
else if (__fds.back().revents != 0) // something changed, restart
|
||||
{
|
||||
__fds.clear();
|
||||
_M_on_notify();
|
||||
return _S_retry;
|
||||
}
|
||||
|
||||
auto __part = std::stable_partition(__fds.begin(), __fds.end() - 1,
|
||||
[](const __fdvec::value_type& __p) { return __p.revents != 0; });
|
||||
__fds.erase(__part, __fds.end());
|
||||
|
||||
return _S_ok;
|
||||
}
|
||||
|
||||
__fdvec _M_fds; // _M_fds.back() is the read end of the self-pipe
|
||||
int _M_notify_wr; // write end of the self-pipe
|
||||
};
|
||||
|
||||
__reactor _M_reactor;
|
||||
|
||||
vector<__timer_queue_base*> _M_timers;
|
||||
forward_list<unique_ptr<__async_operation>> _M_ops;
|
||||
|
||||
vector<thread::id> _M_call_stack;
|
||||
};
|
||||
|
||||
inline bool
|
||||
operator==(const io_context::executor_type& __a,
|
||||
const io_context::executor_type& __b) noexcept
|
||||
{
|
||||
// https://github.com/chriskohlhoff/asio-tr2/issues/201
|
||||
using executor_type = io_context::executor_type;
|
||||
return std::addressof(executor_type(__a).context())
|
||||
== std::addressof(executor_type(__b).context());
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator!=(const io_context::executor_type& __a,
|
||||
const io_context::executor_type& __b) noexcept
|
||||
{ return !(__a == __b); }
|
||||
|
||||
template<> struct is_executor<io_context::executor_type> : true_type {};
|
||||
|
||||
/// @}
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace v1
|
||||
} // namespace net
|
||||
} // namespace experimental
|
||||
} // namespace std
|
||||
|
||||
#endif // C++14
|
||||
|
||||
#endif // _GLIBCXX_EXPERIMENTAL_IO_SERVICE
|
45
libstdc++-v3/include/experimental/net
Normal file
45
libstdc++-v3/include/experimental/net
Normal file
@ -0,0 +1,45 @@
|
||||
// <experimental/net> -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file experimental/net
|
||||
* This is a TS C++ Library header.
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_EXPERIMENTAL_NET
|
||||
#define _GLIBCXX_EXPERIMENTAL_NET
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
|
||||
#include <experimental/executor>
|
||||
#include <experimental/io_context>
|
||||
#include <experimental/timer>
|
||||
#include <experimental/buffer>
|
||||
#include <experimental/socket>
|
||||
#include <experimental/internet>
|
||||
|
||||
#endif // C++14
|
||||
|
||||
#endif // _GLIBCXX_EXPERIMENTAL_NET
|
135
libstdc++-v3/include/experimental/netfwd
Normal file
135
libstdc++-v3/include/experimental/netfwd
Normal file
@ -0,0 +1,135 @@
|
||||
// <experimental/netfwd> -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file experimental/netfwd
|
||||
* This is a TS C++ Library header.
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_EXPERIMENTAL_NETFWD
|
||||
#define _GLIBCXX_EXPERIMENTAL_NETFWD 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
|
||||
// #define __cpp_lib_experimental_net 201803
|
||||
// #define __cpp_lib_experimental_net_extensible 201803
|
||||
|
||||
#include <chrono>
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
namespace net
|
||||
{
|
||||
inline namespace v1
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/**
|
||||
* @ingroup networking
|
||||
* @{
|
||||
*/
|
||||
|
||||
class execution_context;
|
||||
template<typename _Tp, typename _Executor>
|
||||
class executor_binder;
|
||||
template<typename _Executor>
|
||||
class executor_work_guard;
|
||||
class system_executor;
|
||||
class executor;
|
||||
template<typename _Executor>
|
||||
class strand;
|
||||
|
||||
class io_service;
|
||||
|
||||
template<typename _Clock> struct wait_traits;
|
||||
template<typename _Clock, typename _WaitTraits = wait_traits<_Clock>>
|
||||
class basic_waitable_timer;
|
||||
typedef basic_waitable_timer<chrono::system_clock> system_timer;
|
||||
typedef basic_waitable_timer<chrono::steady_clock> steady_timer;
|
||||
typedef basic_waitable_timer<chrono::high_resolution_clock>
|
||||
high_resolution_timer;
|
||||
|
||||
template<typename _Protocol>
|
||||
class basic_socket;
|
||||
template<typename _Protocol>
|
||||
class basic_datagram_socket;
|
||||
template<typename _Protocol>
|
||||
class basic_stream_socket;
|
||||
template<typename _Protocol>
|
||||
class basic_socket_acceptor;
|
||||
template<typename _Protocol, typename _Clock = chrono::steady_clock,
|
||||
typename _WaitTraits = wait_traits<_Clock>>
|
||||
class basic_socket_streambuf;
|
||||
template<typename _Protocol, typename _Clock = chrono::steady_clock,
|
||||
typename _WaitTraits = wait_traits<_Clock>>
|
||||
class basic_socket_iostream;
|
||||
|
||||
/// @}
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
|
||||
namespace ip
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/**
|
||||
* @ingroup networking
|
||||
* @{
|
||||
*/
|
||||
class address;
|
||||
class address_v4;
|
||||
class address_v6;
|
||||
class address_iterator_v4;
|
||||
class address_iterator_v6;
|
||||
class address_range_v4;
|
||||
class address_range_v6;
|
||||
class network_v4;
|
||||
class network_v6;
|
||||
template<typename _InternetProtocol>
|
||||
class basic_endpoint;
|
||||
template<typename _InternetProtocol>
|
||||
class basic_resolver_entry;
|
||||
template<typename _InternetProtocol>
|
||||
class basic_resolver_results;
|
||||
template<typename _InternetProtocol>
|
||||
class basic_resolver;
|
||||
class tcp;
|
||||
class udp;
|
||||
/// @}
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace ip
|
||||
|
||||
|
||||
} // namespace v1
|
||||
} // namespace net
|
||||
} // namespace experimental
|
||||
} // namespace std
|
||||
|
||||
#endif // C++14
|
||||
|
||||
#endif // _GLIBCXX_EXPERIMENTAL_NETFWD
|
2474
libstdc++-v3/include/experimental/socket
Normal file
2474
libstdc++-v3/include/experimental/socket
Normal file
File diff suppressed because it is too large
Load Diff
208
libstdc++-v3/include/experimental/timer
Normal file
208
libstdc++-v3/include/experimental/timer
Normal file
@ -0,0 +1,208 @@
|
||||
// <experimental/timer> -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// Under Section 7 of GPL version 3, you are granted additional
|
||||
// permissions described in the GCC Runtime Library Exception, version
|
||||
// 3.1, as published by the Free Software Foundation.
|
||||
|
||||
// You should have received a copy of the GNU General Public License and
|
||||
// a copy of the GCC Runtime Library Exception along with this program;
|
||||
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file experimental/timer
|
||||
* This is a TS C++ Library header.
|
||||
*/
|
||||
|
||||
#ifndef _GLIBCXX_EXPERIMENTAL_TIMER
|
||||
#define _GLIBCXX_EXPERIMENTAL_TIMER 1
|
||||
|
||||
#pragma GCC system_header
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
|
||||
#include <chrono>
|
||||
#include <system_error>
|
||||
#include <thread>
|
||||
#include <experimental/netfwd>
|
||||
#include <experimental/io_context>
|
||||
#include <experimental/bits/net.h>
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
namespace experimental
|
||||
{
|
||||
namespace net
|
||||
{
|
||||
inline namespace v1
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/**
|
||||
* @ingroup networking
|
||||
* @{
|
||||
*/
|
||||
|
||||
template<typename _Clock>
|
||||
struct wait_traits
|
||||
{
|
||||
static typename _Clock::duration
|
||||
to_wait_duration(const typename _Clock::duration& __d)
|
||||
{ return __d; }
|
||||
|
||||
static typename _Clock::duration
|
||||
to_wait_duration(const typename _Clock::time_point& __t)
|
||||
{
|
||||
auto __now = _Clock::now();
|
||||
auto __diff = __t - __now;
|
||||
if (__diff > _Clock::duration::max())
|
||||
return _Clock::duration::max();
|
||||
if (__diff < _Clock::duration::min())
|
||||
return _Clock::duration::min();
|
||||
return __diff;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename _Clock, typename _WaitTraits>
|
||||
class basic_waitable_timer
|
||||
{
|
||||
public:
|
||||
// types:
|
||||
|
||||
typedef io_context::executor_type executor_type;
|
||||
typedef _Clock clock_type;
|
||||
typedef typename clock_type::duration duration;
|
||||
typedef typename clock_type::time_point time_point;
|
||||
typedef _WaitTraits traits_type;
|
||||
|
||||
// construct / copy / destroy:
|
||||
|
||||
explicit
|
||||
basic_waitable_timer(io_context& __ctx)
|
||||
: _M_ex(__ctx.get_executor()), _M_expiry()
|
||||
{ }
|
||||
|
||||
basic_waitable_timer(io_context& __ctx, const time_point& __t)
|
||||
: _M_ex(__ctx.get_executor()), _M_expiry(__t)
|
||||
{ }
|
||||
|
||||
basic_waitable_timer(io_context& __ctx, const duration& __d)
|
||||
: _M_ex(__ctx.get_executor()), _M_expiry(_Clock::now() + __d)
|
||||
{ }
|
||||
|
||||
basic_waitable_timer(const basic_waitable_timer&) = delete;
|
||||
|
||||
basic_waitable_timer(basic_waitable_timer&& __rhs)
|
||||
: _M_ex(std::move(__rhs._M_ex)), _M_expiry(__rhs._M_expiry)
|
||||
{
|
||||
_M_key.swap(__rhs._M_key);
|
||||
__rhs._M_expiry = time_point{};
|
||||
}
|
||||
|
||||
~basic_waitable_timer() { cancel(); }
|
||||
|
||||
basic_waitable_timer& operator=(const basic_waitable_timer&) = delete;
|
||||
|
||||
basic_waitable_timer&
|
||||
operator=(basic_waitable_timer&& __rhs)
|
||||
{
|
||||
if (this == std::addressof(__rhs))
|
||||
return *this;
|
||||
cancel();
|
||||
_M_ex = std::move(__rhs._M_ex);
|
||||
_M_expiry = __rhs._M_expiry;
|
||||
__rhs._M_expiry = time_point{};
|
||||
_M_key.swap(__rhs._M_key);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// basic_waitable_timer operations:
|
||||
|
||||
executor_type get_executor() noexcept { return _M_ex; }
|
||||
|
||||
size_t cancel() { return _M_ex.context().cancel(*this); }
|
||||
size_t cancel_one() { return _M_ex.context().cancel_one(*this); }
|
||||
|
||||
time_point expiry() const { return _M_expiry; }
|
||||
|
||||
size_t expires_at(const time_point& __t)
|
||||
{
|
||||
size_t __cancelled = cancel();
|
||||
_M_expiry = __t;
|
||||
return __cancelled;
|
||||
}
|
||||
|
||||
size_t expires_after(const duration& __d)
|
||||
{ return expires_at(_Clock::now() + __d); }
|
||||
|
||||
void wait();
|
||||
void wait(error_code& __ec);
|
||||
|
||||
template<typename _CompletionToken>
|
||||
__deduced_t<_CompletionToken, void(error_code)>
|
||||
async_wait(_CompletionToken&& __token)
|
||||
{
|
||||
async_completion<_CompletionToken, void(error_code)> __init(__token);
|
||||
_M_ex.context().async_wait(*this,
|
||||
std::move(__init.completion_handler));
|
||||
return __init.result.get();
|
||||
}
|
||||
|
||||
private:
|
||||
executor_type _M_ex;
|
||||
time_point _M_expiry;
|
||||
|
||||
struct _Key { }; // TODO move _M_expiry into here?
|
||||
unique_ptr<_Key> _M_key{new _Key};
|
||||
|
||||
friend class io_context;
|
||||
};
|
||||
|
||||
typedef basic_waitable_timer<chrono::system_clock> system_timer;
|
||||
typedef basic_waitable_timer<chrono::steady_clock> steady_timer;
|
||||
typedef basic_waitable_timer<chrono::high_resolution_clock>
|
||||
high_resolution_timer;
|
||||
|
||||
template<typename _Clock, typename _WaitTraits>
|
||||
void
|
||||
basic_waitable_timer<_Clock, _WaitTraits>::wait()
|
||||
{
|
||||
_M_ex.dispatch([this] {
|
||||
while (clock_type::now() < _M_expiry)
|
||||
this_thread::sleep_for(traits_type::to_wait_duration(_M_expiry));
|
||||
}, allocator<void>{});
|
||||
}
|
||||
|
||||
template<typename _Clock, typename _WaitTraits>
|
||||
void
|
||||
basic_waitable_timer<_Clock, _WaitTraits>::wait(error_code&)
|
||||
{
|
||||
_M_ex.dispatch([this] {
|
||||
while (clock_type::now() < _M_expiry)
|
||||
this_thread::sleep_for(traits_type::to_wait_duration(_M_expiry));
|
||||
}, allocator<void>{});
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace v1
|
||||
} // namespace net
|
||||
} // namespace experimental
|
||||
} // namespace std
|
||||
|
||||
#endif // C++14
|
||||
|
||||
#endif // _GLIBCXX_EXPERIMENTAL_TIMER
|
107
libstdc++-v3/testsuite/experimental/net/buffer/arithmetic.cc
Normal file
107
libstdc++-v3/testsuite/experimental/net/buffer/arithmetic.cc
Normal file
@ -0,0 +1,107 @@
|
||||
// Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-options "-std=gnu++14" }
|
||||
|
||||
#include <experimental/buffer>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
using std::experimental::net::mutable_buffer;
|
||||
using std::experimental::net::const_buffer;
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
bool test __attribute__((unused)) = false;
|
||||
char c[4];
|
||||
|
||||
mutable_buffer mb;
|
||||
mb = mb + 0;
|
||||
VERIFY( mb.data() == nullptr );
|
||||
VERIFY( mb.size() == 0 );
|
||||
|
||||
mb = 0 + mb;
|
||||
VERIFY( mb.data() == nullptr );
|
||||
VERIFY( mb.size() == 0 );
|
||||
|
||||
mb = mutable_buffer(c, sizeof(c));
|
||||
mb = mb + 1;
|
||||
VERIFY( mb.data() == c+1 );
|
||||
VERIFY( mb.size() == 3 );
|
||||
|
||||
mb = mb + 2;
|
||||
VERIFY( mb.data() == c+3 );
|
||||
VERIFY( mb.size() == 1 );
|
||||
|
||||
mb = mb + 2;
|
||||
VERIFY( mb.data() == c+4 );
|
||||
VERIFY( mb.size() == 0 );
|
||||
|
||||
mb = mutable_buffer(c, sizeof(c));
|
||||
mb = 3 + mb;
|
||||
VERIFY( mb.data() == c+3 );
|
||||
VERIFY( mb.size() == 1 );
|
||||
|
||||
mb = 2 + mb;
|
||||
VERIFY( mb.data() == c+4 );
|
||||
VERIFY( mb.size() == 0 );
|
||||
}
|
||||
|
||||
void
|
||||
test02()
|
||||
{
|
||||
bool test __attribute__((unused)) = false;
|
||||
char c[4];
|
||||
|
||||
const_buffer cb;
|
||||
cb = cb + 0;
|
||||
VERIFY( cb.data() == nullptr );
|
||||
VERIFY( cb.size() == 0 );
|
||||
|
||||
cb = 0 + cb;
|
||||
VERIFY( cb.data() == nullptr );
|
||||
VERIFY( cb.size() == 0 );
|
||||
|
||||
cb = const_buffer(c, sizeof(c));
|
||||
cb = cb + 1;
|
||||
VERIFY( cb.data() == c+1 );
|
||||
VERIFY( cb.size() == 3 );
|
||||
|
||||
cb = cb + 2;
|
||||
VERIFY( cb.data() == c+3 );
|
||||
VERIFY( cb.size() == 1 );
|
||||
|
||||
cb = cb + 2;
|
||||
VERIFY( cb.data() == c+4 );
|
||||
VERIFY( cb.size() == 0 );
|
||||
|
||||
cb = const_buffer(c, sizeof(c));
|
||||
cb = 3 + cb;
|
||||
VERIFY( cb.data() == c+3 );
|
||||
VERIFY( cb.size() == 1 );
|
||||
|
||||
cb = 2 + cb;
|
||||
VERIFY( cb.data() == c+4 );
|
||||
VERIFY( cb.size() == 0 );
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test01();
|
||||
test02();
|
||||
}
|
74
libstdc++-v3/testsuite/experimental/net/buffer/const.cc
Normal file
74
libstdc++-v3/testsuite/experimental/net/buffer/const.cc
Normal file
@ -0,0 +1,74 @@
|
||||
// Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-options "-std=gnu++14" }
|
||||
|
||||
#include <experimental/buffer>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
using std::experimental::net::const_buffer;
|
||||
using std::experimental::net::mutable_buffer;
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
using B = const_buffer;
|
||||
const B b;
|
||||
|
||||
static_assert( std::is_nothrow_default_constructible<B>::value,
|
||||
"const_mutable is nothrow default constructible" );
|
||||
static_assert( std::is_copy_assignable<B>::value,
|
||||
"const_mutable is copy assignable" );
|
||||
static_assert( std::is_nothrow_constructible<B, const void*, size_t>::value,
|
||||
"const_mutable is nothrow constructible from pointer and length" );
|
||||
static_assert( std::is_nothrow_constructible<B, mutable_buffer>::value,
|
||||
"const_mutable is nothrow constructible from mutable_buffer" );
|
||||
static_assert( std::is_same<decltype(b.data()), const void*>::value,
|
||||
"data() return const void*" );
|
||||
static_assert( noexcept(b.data()),
|
||||
"data() is nothrow" );
|
||||
static_assert( std::is_same<decltype(b.size()), size_t>::value,
|
||||
"size() return size_t" );
|
||||
static_assert( noexcept(b.size()),
|
||||
"size() is nothrow" );
|
||||
}
|
||||
|
||||
void
|
||||
test02()
|
||||
{
|
||||
bool test __attribute__((unused)) = false;
|
||||
char c[4];
|
||||
|
||||
const_buffer b;
|
||||
VERIFY( b.data() == nullptr );
|
||||
VERIFY( b.size() == 0 );
|
||||
|
||||
b = const_buffer(c, sizeof(c));
|
||||
VERIFY( b.data() == c );
|
||||
VERIFY( b.size() == sizeof(c) );
|
||||
|
||||
b = const_buffer{};
|
||||
VERIFY( b.data() == nullptr );
|
||||
VERIFY( b.size() == 0 );
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test01();
|
||||
test02();
|
||||
}
|
172
libstdc++-v3/testsuite/experimental/net/buffer/creation.cc
Normal file
172
libstdc++-v3/testsuite/experimental/net/buffer/creation.cc
Normal file
@ -0,0 +1,172 @@
|
||||
// Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-options "-std=gnu++14" }
|
||||
|
||||
#include <experimental/buffer>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
namespace net = std::experimental::net;
|
||||
|
||||
template<typename T>
|
||||
bool is_mutable(const T&)
|
||||
{ return std::is_same<T, net::mutable_buffer>::value; }
|
||||
|
||||
template<typename T>
|
||||
bool is_const(const T&)
|
||||
{ return std::is_same<T, net::const_buffer>::value; }
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
bool test = false;
|
||||
|
||||
auto b1 = net::buffer((void*)&test, sizeof(test));
|
||||
VERIFY( is_mutable(b1) );
|
||||
VERIFY( b1.data() == &test );
|
||||
VERIFY( b1.size() == sizeof(test) );
|
||||
|
||||
auto b2 = net::buffer((const void*)&test, sizeof(test));
|
||||
VERIFY( is_const(b2) );
|
||||
VERIFY( b2.data() == &test );
|
||||
VERIFY( b1.size() == sizeof(test) );
|
||||
|
||||
auto b3 = net::buffer(b1);
|
||||
VERIFY( is_mutable(b3) );
|
||||
VERIFY( b3.data() == b1.data() );
|
||||
VERIFY( b3.size() == b1.size() );
|
||||
|
||||
auto b4 = net::buffer(b2);
|
||||
VERIFY( is_const(b4) );
|
||||
VERIFY( b4.data() == b2.data() );
|
||||
VERIFY( b4.size() == b2.size() );
|
||||
|
||||
auto b5 = net::buffer(b1, 0);
|
||||
VERIFY( is_mutable(b5) );
|
||||
VERIFY( b5.data() == b1.data() );
|
||||
VERIFY( b5.size() == 0 );
|
||||
|
||||
auto b6 = net::buffer(b2, 0);
|
||||
VERIFY( is_const(b6) );
|
||||
VERIFY( b6.data() == b2.data() );
|
||||
VERIFY( b6.size() == 0 );
|
||||
|
||||
int a7[7];
|
||||
auto b7 = net::buffer(a7);
|
||||
VERIFY( is_mutable(b7) );
|
||||
VERIFY( b7.data() == a7 );
|
||||
VERIFY( b7.size() == sizeof(a7) );
|
||||
|
||||
auto b7x = net::buffer(a7, 2);
|
||||
VERIFY( is_mutable(b7x) );
|
||||
VERIFY( b7x.data() == a7 );
|
||||
VERIFY( b7x.size() == sizeof(a7[0]) * 2 );
|
||||
|
||||
const short a8[8] = { };
|
||||
auto b8 = net::buffer(a8);
|
||||
VERIFY( is_const(b8) );
|
||||
VERIFY( b8.data() == a8 );
|
||||
VERIFY( b8.size() == sizeof(a8) );
|
||||
|
||||
auto b8x = net::buffer(a8, 3);
|
||||
VERIFY( is_const(b8x) );
|
||||
VERIFY( b8x.data() == a8 );
|
||||
VERIFY( b8x.size() == sizeof(a8[0]) * 3 );
|
||||
|
||||
std::array<short, 9> a9;
|
||||
auto b9 = net::buffer(a9);
|
||||
VERIFY( is_mutable(b9) );
|
||||
VERIFY( b9.data() == a9.data() );
|
||||
VERIFY( b9.size() == sizeof(a9) );
|
||||
|
||||
auto b9x = net::buffer(a9, 4);
|
||||
VERIFY( is_mutable(b9x) );
|
||||
VERIFY( b9x.data() == a9.data() );
|
||||
VERIFY( b9x.size() == sizeof(a9[0]) * 4 );
|
||||
|
||||
const std::array<long long, 10> a10{};
|
||||
auto b10 = net::buffer(a10);
|
||||
VERIFY( is_const(b10) );
|
||||
VERIFY( b10.data() == a10.data() );
|
||||
VERIFY( b10.size() == sizeof(a10) );
|
||||
|
||||
auto b10x = net::buffer(a10, 5);
|
||||
VERIFY( is_const(b10x) );
|
||||
VERIFY( b10x.data() == a10.data() );
|
||||
VERIFY( b10x.size() == sizeof(a10[0]) * 5 );
|
||||
|
||||
std::array<const int, 11> a11{};
|
||||
auto b11 = net::buffer(a11);
|
||||
VERIFY( is_const(b11) );
|
||||
VERIFY( b11.data() == a11.data() );
|
||||
VERIFY( b11.size() == sizeof(a11) );
|
||||
|
||||
auto b11x = net::buffer(a11, 6);
|
||||
VERIFY( is_const(b11x) );
|
||||
VERIFY( b11x.data() == a11.data() );
|
||||
VERIFY( b11x.size() == sizeof(a11[0]) * 6 );
|
||||
|
||||
std::vector<short> a12(12);
|
||||
auto b12 = net::buffer(a12);
|
||||
VERIFY( is_mutable(b12) );
|
||||
VERIFY( b12.data() == a12.data() );
|
||||
VERIFY( b12.size() == sizeof(a12[0]) * a12.size() );
|
||||
|
||||
auto b12x = net::buffer(a12, 7);
|
||||
VERIFY( is_mutable(b12x) );
|
||||
VERIFY( b12x.data() == a12.data() );
|
||||
VERIFY( b12x.size() == sizeof(a12[0]) * 7 );
|
||||
|
||||
const std::vector<long long> a13(13);
|
||||
auto b13 = net::buffer(a13);
|
||||
VERIFY( is_const(b13) );
|
||||
VERIFY( b13.data() == a13.data() );
|
||||
VERIFY( b13.size() == sizeof(a13[0]) * a13.size() );
|
||||
|
||||
auto b13x = net::buffer(a13, 7);
|
||||
VERIFY( is_const(b13x) );
|
||||
VERIFY( b13x.data() == a13.data() );
|
||||
VERIFY( b13x.size() == sizeof(a13[0]) * 7 );
|
||||
|
||||
std::u32string a14(14, ' ');
|
||||
auto b14 = net::buffer(a14);
|
||||
VERIFY( is_mutable(b14) );
|
||||
VERIFY( b14.data() == a14.data() );
|
||||
VERIFY( b14.size() == sizeof(a14[0]) * a14.size() );
|
||||
|
||||
auto b14x = net::buffer(a14, 8);
|
||||
VERIFY( is_mutable(b14x) );
|
||||
VERIFY( b14x.data() == a14.data() );
|
||||
VERIFY( b14x.size() == sizeof(a14[0]) * 8 );
|
||||
|
||||
const std::u16string a15(15, ' ');
|
||||
auto b15 = net::buffer(std::experimental::u16string_view(a15));
|
||||
VERIFY( is_const(b15) );
|
||||
VERIFY( b15.data() == a15.data() );
|
||||
VERIFY( b15.size() == sizeof(a15[0]) * a15.size() );
|
||||
|
||||
auto b15x = net::buffer(std::experimental::u16string_view(a15), 9);
|
||||
VERIFY( is_const(b15x) );
|
||||
VERIFY( b15x.data() == a15.data() );
|
||||
VERIFY( b15x.size() == sizeof(a15[0]) * 9 );
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test01();
|
||||
}
|
71
libstdc++-v3/testsuite/experimental/net/buffer/mutable.cc
Normal file
71
libstdc++-v3/testsuite/experimental/net/buffer/mutable.cc
Normal file
@ -0,0 +1,71 @@
|
||||
// Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-options "-std=gnu++14" }
|
||||
|
||||
#include <experimental/buffer>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
using std::experimental::net::mutable_buffer;
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
using B = mutable_buffer;
|
||||
const B b;
|
||||
|
||||
static_assert( std::is_nothrow_default_constructible<B>::value,
|
||||
"const_mutable is nothrow default constructible" );
|
||||
static_assert( std::is_copy_assignable<B>::value,
|
||||
"const_mutable is copy assignable" );
|
||||
static_assert( std::is_nothrow_constructible<B, void*, size_t>::value,
|
||||
"const_mutable is nothrow default constructible" );
|
||||
static_assert( std::is_same<decltype(b.data()), void*>::value,
|
||||
"data() return const void*" );
|
||||
static_assert( noexcept(b.data()),
|
||||
"data() is nothrow" );
|
||||
static_assert( std::is_same<decltype(b.size()), size_t>::value,
|
||||
"size() return size_t" );
|
||||
static_assert( noexcept(b.size()),
|
||||
"size() is nothrow" );
|
||||
}
|
||||
|
||||
void
|
||||
test02()
|
||||
{
|
||||
bool test __attribute__((unused)) = false;
|
||||
char c[4];
|
||||
|
||||
mutable_buffer b;
|
||||
VERIFY( b.data() == nullptr );
|
||||
VERIFY( b.size() == 0 );
|
||||
|
||||
b = mutable_buffer(c, sizeof(c));
|
||||
VERIFY( b.data() == c );
|
||||
VERIFY( b.size() == sizeof(c) );
|
||||
|
||||
b = mutable_buffer{};
|
||||
VERIFY( b.data() == nullptr );
|
||||
VERIFY( b.size() == 0 );
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test01();
|
||||
test02();
|
||||
}
|
62
libstdc++-v3/testsuite/experimental/net/buffer/size.cc
Normal file
62
libstdc++-v3/testsuite/experimental/net/buffer/size.cc
Normal file
@ -0,0 +1,62 @@
|
||||
// Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-options "-std=gnu++14" }
|
||||
|
||||
#include <experimental/buffer>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
using std::experimental::net::const_buffer;
|
||||
using std::experimental::net::mutable_buffer;
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
bool test __attribute__((unused)) = false;
|
||||
char c[4];
|
||||
|
||||
mutable_buffer mb;
|
||||
VERIFY( buffer_size(mb) == 0 );
|
||||
|
||||
mb = mutable_buffer(c, sizeof(c));
|
||||
VERIFY( buffer_size(mb) == mb.size() );
|
||||
|
||||
const_buffer cb;
|
||||
VERIFY( buffer_size(cb) == 0 );
|
||||
cb = const_buffer(c, sizeof(c));
|
||||
VERIFY( buffer_size(cb) == cb.size() );
|
||||
}
|
||||
|
||||
void
|
||||
test02()
|
||||
{
|
||||
bool test __attribute__((unused)) = false;
|
||||
char c[32];
|
||||
|
||||
std::vector<mutable_buffer> mv{ {c, 0}, {c, 32}, {c, 16}, {c, 3}, {c, 0} };
|
||||
VERIFY( buffer_size(mv) == (0 + 32 + 16 + 3 + 0) );
|
||||
|
||||
std::vector<const_buffer> cv{ {c, 0}, {c, 32}, {c, 16}, {c, 3}, {c, 0} };
|
||||
VERIFY( buffer_size(cv) == (0 + 32 + 16 + 3 + 0) );
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test01();
|
||||
test02();
|
||||
}
|
96
libstdc++-v3/testsuite/experimental/net/buffer/traits.cc
Normal file
96
libstdc++-v3/testsuite/experimental/net/buffer/traits.cc
Normal file
@ -0,0 +1,96 @@
|
||||
// Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-options "-std=gnu++14" }
|
||||
// { dg-do compile }
|
||||
|
||||
#include <experimental/buffer>
|
||||
|
||||
using namespace std::experimental::net;
|
||||
using std::vector;
|
||||
using std::string;
|
||||
using std::char_traits;
|
||||
using std::allocator;
|
||||
|
||||
template<typename T>
|
||||
struct Seq {
|
||||
struct Buf {
|
||||
operator T() const { return {}; }
|
||||
};
|
||||
|
||||
Buf* begin() const { return nullptr; }
|
||||
Buf* end() const { return nullptr; }
|
||||
};
|
||||
|
||||
static_assert( is_mutable_buffer_sequence<mutable_buffer>::value,
|
||||
"mutable_buffer is a mutable buffer sequence" );
|
||||
static_assert( is_mutable_buffer_sequence<const mutable_buffer>::value,
|
||||
"const mutable_buffer is a mutable buffer sequence" );
|
||||
static_assert( is_mutable_buffer_sequence<vector<mutable_buffer>>::value,
|
||||
"vector<mutable_buffer> is a mutable buffer sequence" );
|
||||
static_assert( is_mutable_buffer_sequence<const vector<mutable_buffer>>::value,
|
||||
"const vector<mutable_buffer> is a mutable buffer sequence" );
|
||||
static_assert( is_mutable_buffer_sequence<Seq<mutable_buffer>>::value,
|
||||
"Seq<mutable_buffer> is a mutable buffer sequence" );
|
||||
static_assert( is_mutable_buffer_sequence<const Seq<mutable_buffer>>::value,
|
||||
"const Seq<mutable_buffer> is a mutable buffer sequence" );
|
||||
static_assert( is_mutable_buffer_sequence<Seq<const mutable_buffer>>::value,
|
||||
"Seq<const mutable_buffer> is a mutable buffer sequence" );
|
||||
static_assert( ! is_mutable_buffer_sequence<const_buffer>::value,
|
||||
"const_buffer is not a mutable buffer sequence" );
|
||||
static_assert( ! is_mutable_buffer_sequence<vector<const_buffer>>::value,
|
||||
"vector<const_buffer> is not a mutable buffer sequence" );
|
||||
static_assert( ! is_mutable_buffer_sequence<Seq<const_buffer>>::value,
|
||||
"Seq<const_buffer> is not a mutable buffer sequence" );
|
||||
|
||||
static_assert( is_const_buffer_sequence<const_buffer>::value,
|
||||
"const_buffer is a const buffer sequence" );
|
||||
static_assert( is_const_buffer_sequence<const const_buffer>::value,
|
||||
"const const_buffer is a const buffer sequence" );
|
||||
static_assert( is_const_buffer_sequence<vector<const_buffer>>::value,
|
||||
"vector<const_buffer> is a const buffer sequence" );
|
||||
static_assert( is_const_buffer_sequence<const vector<const_buffer>>::value,
|
||||
"const vector<const_buffer> is a const buffer sequence" );
|
||||
static_assert( is_const_buffer_sequence<Seq<const_buffer>>::value,
|
||||
"Seq<const_buffer> is a const buffer sequence" );
|
||||
static_assert( is_const_buffer_sequence<const Seq<const_buffer>>::value,
|
||||
"const Seq<const_buffer> is a const buffer sequence" );
|
||||
static_assert( is_const_buffer_sequence<Seq<const const_buffer>>::value,
|
||||
"Seq<const const_buffer> is a const buffer sequence" );
|
||||
static_assert( is_const_buffer_sequence<mutable_buffer>::value,
|
||||
"mutable_buffer is a const buffer sequence" );
|
||||
static_assert( is_const_buffer_sequence<const mutable_buffer>::value,
|
||||
"const mutable_buffer is a const buffer sequence" );
|
||||
static_assert( is_const_buffer_sequence<vector<mutable_buffer>>::value,
|
||||
"vector<mutable_buffer> is a const buffer sequence" );
|
||||
static_assert( is_const_buffer_sequence<const vector<mutable_buffer>>::value,
|
||||
"const vector<mutable_buffer> is a const buffer sequence" );
|
||||
|
||||
// Buf -> mutable_buffer -> const_buffer needs two user-defined conversions:
|
||||
static_assert( ! is_const_buffer_sequence<Seq<mutable_buffer>>::value,
|
||||
"Seq<mutable_buffer> is not a const buffer sequence" );
|
||||
|
||||
static_assert( is_dynamic_buffer<
|
||||
dynamic_vector_buffer<int, allocator<int>>
|
||||
>::value, "dynamic_vector_buffer is a dynamic buffer" );
|
||||
static_assert( is_dynamic_buffer<
|
||||
dynamic_string_buffer<char, char_traits<char>, allocator<int>>
|
||||
>::value, "dynamic_string_buffer is a dynamic buffer" );
|
||||
static_assert( ! is_dynamic_buffer<vector<int>>::value,
|
||||
"vector is not a dynamic buffer" );
|
||||
static_assert( ! is_dynamic_buffer<string>::value,
|
||||
"string is not a dynamic buffer" );
|
@ -0,0 +1,80 @@
|
||||
// Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-options "-std=gnu++14" }
|
||||
|
||||
#include <experimental/executor>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
using std::experimental::net::execution_context;
|
||||
using std::experimental::net::use_service;
|
||||
|
||||
struct service1 : execution_context::service
|
||||
{
|
||||
using key_type = service1;
|
||||
service1(execution_context& c) : service(c) { }
|
||||
void shutdown() noexcept { }
|
||||
};
|
||||
|
||||
struct key2 : execution_context::service
|
||||
{
|
||||
key2(execution_context& c) : service(c) { }
|
||||
};
|
||||
|
||||
struct service2 : key2
|
||||
{
|
||||
using key_type = key2;
|
||||
service2(execution_context& c) : key2(c) { }
|
||||
void shutdown() noexcept { }
|
||||
};
|
||||
|
||||
struct service3 : service1
|
||||
{
|
||||
using service1::service1;
|
||||
};
|
||||
|
||||
struct service4 : service2
|
||||
{
|
||||
using service2::service2;
|
||||
};
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
execution_context ctx;
|
||||
service1& svc1 = use_service<service1>(ctx);
|
||||
service1& svc1a = use_service<service1>(ctx);
|
||||
VERIFY( &svc1a == &svc1 );
|
||||
|
||||
key2& svc2 = use_service<service2>(ctx);
|
||||
key2& svc2a = use_service<service2>(ctx);
|
||||
VERIFY( &svc2a == &svc2 );
|
||||
|
||||
service1& svc3 = use_service<service3>(ctx);
|
||||
VERIFY( &svc3 == &svc1 );
|
||||
|
||||
key2& svc4 = use_service<service4>(ctx);
|
||||
VERIFY( &svc4 == &svc2 );
|
||||
|
||||
// TODO test02() function that puts derived types in first, then tests base comes out
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test01();
|
||||
}
|
30
libstdc++-v3/testsuite/experimental/net/headers.cc
Normal file
30
libstdc++-v3/testsuite/experimental/net/headers.cc
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-options "-std=gnu++14" }
|
||||
// { dg-do compile }
|
||||
|
||||
#include <experimental/net>
|
||||
|
||||
// Re-include:
|
||||
#include <experimental/buffer>
|
||||
#include <experimental/executor>
|
||||
#include <experimental/internet>
|
||||
#include <experimental/io_context>
|
||||
#include <experimental/netfwd>
|
||||
#include <experimental/socket>
|
||||
#include <experimental/timer>
|
@ -0,0 +1,67 @@
|
||||
// Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-options "-std=gnu++14" }
|
||||
|
||||
#include <experimental/internet>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
using std::experimental::net::ip::address_v4;
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
bool test __attribute__((unused)) = false;
|
||||
|
||||
address_v4 addrs[] = {
|
||||
address_v4::any(), address_v4::loopback(), address_v4::broadcast(),
|
||||
address_v4{0x11001100}, address_v4{0xEFEFEFEF}
|
||||
};
|
||||
|
||||
auto begin = std::begin(addrs);
|
||||
auto end = std::end(addrs);
|
||||
for (auto it = begin; it != end; ++it)
|
||||
{
|
||||
auto& a = *it;
|
||||
VERIFY( a == a );
|
||||
VERIFY( a <= a );
|
||||
VERIFY( a >= a );
|
||||
VERIFY( ! (a != a) );
|
||||
VERIFY( ! (a < a) );
|
||||
VERIFY( ! (a > a) );
|
||||
}
|
||||
|
||||
std::sort(begin, end);
|
||||
|
||||
for (auto it = begin + 1; it != end; ++it)
|
||||
{
|
||||
auto& a = *it;
|
||||
auto& b = *begin;
|
||||
VERIFY( ! (a == b) );
|
||||
VERIFY( a != b );
|
||||
VERIFY( b < a );
|
||||
VERIFY( b <= a );
|
||||
VERIFY( a > b );
|
||||
VERIFY( a >= b );
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test01();
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
// Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-options "-std=gnu++14" }
|
||||
|
||||
#include <experimental/internet>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
using std::experimental::net::ip::address_v4;
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
bool test __attribute__((unused)) = false;
|
||||
|
||||
address_v4 a0;
|
||||
VERIFY( a0.to_uint() == 0 );
|
||||
VERIFY( a0.to_bytes() == address_v4::bytes_type{} );
|
||||
}
|
||||
|
||||
void
|
||||
test02()
|
||||
{
|
||||
bool test __attribute__((unused)) = false;
|
||||
|
||||
address_v4 a0{ address_v4::bytes_type{} };
|
||||
VERIFY( a0.to_uint() == 0 );
|
||||
VERIFY( a0.to_bytes() == address_v4::bytes_type{} );
|
||||
|
||||
address_v4::bytes_type b1{ 1, 2, 3, 4 };
|
||||
address_v4 a1{ b1 };
|
||||
VERIFY( a1.to_uint() == ntohl((1 << 24) | (2 << 16) | (3 << 8) | 4) );
|
||||
VERIFY( a1.to_bytes() == b1 );
|
||||
}
|
||||
|
||||
void
|
||||
test03()
|
||||
{
|
||||
bool test __attribute__((unused)) = false;
|
||||
|
||||
address_v4 a0{ 0u };
|
||||
VERIFY( a0.to_uint() == 0 );
|
||||
VERIFY( a0.to_bytes() == address_v4::bytes_type{} );
|
||||
|
||||
address_v4::uint_type u1 = ntohl((5 << 24) | (6 << 16) | (7 << 8) | 8);
|
||||
address_v4 a1{ u1 };
|
||||
VERIFY( a1.to_uint() == u1 );
|
||||
VERIFY( a1.to_bytes() == address_v4::bytes_type( 5, 6, 7, 8 ) );
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test01();
|
||||
test02();
|
||||
test03();
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
// Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-options "-std=gnu++14" }
|
||||
|
||||
#include <experimental/internet>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
namespace ip = std::experimental::net::ip;
|
||||
using ip::address_v4;
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
bool test __attribute__((unused)) = false;
|
||||
|
||||
auto a0 = make_address_v4( address_v4::bytes_type{} );
|
||||
VERIFY( a0.to_uint() == 0 );
|
||||
VERIFY( a0.to_bytes() == address_v4::bytes_type{} );
|
||||
|
||||
address_v4::bytes_type b1{ 1, 2, 3, 4 };
|
||||
auto a1 = make_address_v4( b1 );
|
||||
VERIFY( a1.to_uint() == ntohl((1 << 24) | (2 << 16) | (3 << 8) | 4) );
|
||||
VERIFY( a1.to_bytes() == b1 );
|
||||
}
|
||||
|
||||
void
|
||||
test02()
|
||||
{
|
||||
bool test __attribute__((unused)) = false;
|
||||
|
||||
auto a0 = ip::make_address_v4(0u);
|
||||
VERIFY( a0.to_uint() == 0 );
|
||||
VERIFY( a0.to_bytes() == address_v4::bytes_type{} );
|
||||
|
||||
address_v4::uint_type u1 = ntohl((5 << 24) | (6 << 16) | (7 << 8) | 8);
|
||||
auto a1 = ip::make_address_v4( u1 );
|
||||
VERIFY( a1.to_uint() == u1 );
|
||||
VERIFY( a1.to_bytes() == address_v4::bytes_type( 5, 6, 7, 8 ) );
|
||||
}
|
||||
|
||||
void
|
||||
test03()
|
||||
{
|
||||
bool test __attribute__((unused)) = false;
|
||||
|
||||
auto a1 = ip::make_address_v4("127.0.0.1");
|
||||
VERIFY( a1.is_loopback() );
|
||||
auto a2 = ip::make_address_v4(std::string{"127.0.0.2"});
|
||||
VERIFY( a2.is_loopback() );
|
||||
auto a3 = ip::make_address_v4(std::experimental::string_view{"127.0.0.3"});
|
||||
VERIFY( a3.is_loopback() );
|
||||
|
||||
std::error_code ec;
|
||||
auto a4 = ip::make_address_v4("127...1", ec);
|
||||
VERIFY( ec == std::errc::invalid_argument );
|
||||
|
||||
ip::make_address_v4("127.0.0.1", ec);
|
||||
VERIFY( !ec );
|
||||
|
||||
a4 = ip::make_address_v4(std::string{"256.0.0.1"}, ec);
|
||||
VERIFY( ec == std::errc::invalid_argument );
|
||||
|
||||
ip::make_address_v4(std::string{"127.0.0.1"}, ec);
|
||||
VERIFY( !ec );
|
||||
|
||||
a4 = ip::make_address_v4(std::experimental::string_view{""}, ec);
|
||||
VERIFY( ec == std::errc::invalid_argument );
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test01();
|
||||
test02();
|
||||
test03();
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
// Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-options "-std=gnu++14" }
|
||||
|
||||
#include <experimental/internet>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
using std::experimental::net::ip::address_v4;
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
bool test __attribute__((unused)) = false;
|
||||
|
||||
address_v4 a;
|
||||
VERIFY( a.is_unspecified() );
|
||||
|
||||
a = address_v4::any();
|
||||
VERIFY( a.is_unspecified() );
|
||||
|
||||
a = address_v4::loopback();
|
||||
VERIFY( !a.is_unspecified() );
|
||||
|
||||
a = address_v4::broadcast();
|
||||
VERIFY( !a.is_unspecified() );
|
||||
}
|
||||
|
||||
void
|
||||
test02()
|
||||
{
|
||||
bool test __attribute__((unused)) = false;
|
||||
|
||||
auto a = address_v4::loopback();
|
||||
VERIFY( a.is_loopback() );
|
||||
|
||||
a = address_v4{0x7F000001};
|
||||
VERIFY( a.is_loopback() );
|
||||
|
||||
a = address_v4{0x7F010203};
|
||||
VERIFY( a.is_loopback() );
|
||||
|
||||
a = address_v4{0x7FFFFFFF};
|
||||
VERIFY( a.is_loopback() );
|
||||
|
||||
a = address_v4::any();
|
||||
VERIFY( !a.is_loopback() );
|
||||
|
||||
a = address_v4::broadcast();
|
||||
VERIFY( !a.is_loopback() );
|
||||
}
|
||||
|
||||
void
|
||||
test03()
|
||||
{
|
||||
bool test __attribute__((unused)) = false;
|
||||
|
||||
auto a = address_v4{0xE0000001};
|
||||
VERIFY( a.is_multicast() );
|
||||
|
||||
a = address_v4{0xE0010203};
|
||||
VERIFY( a.is_multicast() );
|
||||
|
||||
a = address_v4{0xE0FFFFFF};
|
||||
VERIFY( a.is_multicast() );
|
||||
|
||||
a = address_v4{0xF0000000};
|
||||
VERIFY( !a.is_multicast() );
|
||||
|
||||
a = address_v4{0xDFFFFFFF};
|
||||
VERIFY( !a.is_multicast() );
|
||||
}
|
||||
|
||||
void
|
||||
test04()
|
||||
{
|
||||
bool test __attribute__((unused)) = false;
|
||||
|
||||
VERIFY( address_v4::any().to_string() == "0.0.0.0" );
|
||||
VERIFY( address_v4::loopback().to_string() == "127.0.0.1" );
|
||||
VERIFY( address_v4::broadcast().to_string() == "255.255.255.255" );
|
||||
}
|
||||
|
||||
void
|
||||
test05()
|
||||
{
|
||||
bool test __attribute__((unused)) = false;
|
||||
|
||||
std::ostringstream ss;
|
||||
ss << address_v4::any() << ' ' << address_v4::loopback() << ' '
|
||||
<< address_v4::broadcast();
|
||||
VERIFY( ss.str() == "0.0.0.0 127.0.0.1 255.255.255.255" );
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test01();
|
||||
test02();
|
||||
test03();
|
||||
test04();
|
||||
test05();
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
// Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-options "-std=gnu++14" }
|
||||
|
||||
#include <experimental/internet>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
bool test __attribute__((unused)) = false;
|
||||
|
||||
using resolver = std::experimental::net::ip::resolver_base;
|
||||
|
||||
resolver::flags f = resolver::passive;
|
||||
|
||||
VERIFY( (f & resolver::numeric_host) == 0);
|
||||
f &= resolver::numeric_host;
|
||||
VERIFY( f == 0 );
|
||||
|
||||
VERIFY( (f | resolver::numeric_host) == resolver::numeric_host);
|
||||
f |= resolver::numeric_host;
|
||||
VERIFY( f == resolver::numeric_host );
|
||||
|
||||
VERIFY( (f ^ resolver::numeric_host) == 0 );
|
||||
f ^= resolver::numeric_host;
|
||||
VERIFY( f == 0 );
|
||||
|
||||
f = ~resolver::numeric_host;
|
||||
VERIFY( (f & resolver::numeric_host) == 0);
|
||||
VERIFY( (f | resolver::numeric_host) == ~resolver::flags{} );
|
||||
|
||||
(void) resolver::passive;
|
||||
(void) resolver::canonical_name;
|
||||
(void) resolver::numeric_host;
|
||||
(void) resolver::numeric_service;
|
||||
(void) resolver::v4_mapped;
|
||||
(void) resolver::all_matching;
|
||||
(void) resolver::address_configured;
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test01();
|
||||
}
|
@ -0,0 +1,110 @@
|
||||
// Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-options "-std=gnu++14" }
|
||||
|
||||
#include <experimental/internet>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
using namespace std::experimental::net;
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
bool test __attribute__((unused)) = false;
|
||||
|
||||
std::error_code ec;
|
||||
io_context ctx;
|
||||
ip::tcp::resolver resolv(ctx);
|
||||
auto addrs = resolv.resolve("localhost", "http", ec);
|
||||
VERIFY( !ec );
|
||||
VERIFY( addrs.size() > 0 );
|
||||
VERIFY( addrs.begin() != addrs.end() );
|
||||
VERIFY( ! addrs.empty() );
|
||||
|
||||
auto addrs2 = resolv.resolve("localhost", "http");
|
||||
VERIFY( addrs == addrs2 );
|
||||
}
|
||||
|
||||
void
|
||||
test02()
|
||||
{
|
||||
bool test __attribute__((unused)) = false;
|
||||
|
||||
std::error_code ec;
|
||||
io_context ctx;
|
||||
ip::tcp::resolver resolv(ctx);
|
||||
auto flags = ip::resolver_base::numeric_host | ip::tcp::resolver::numeric_service;
|
||||
auto addrs = resolv.resolve("127.0.0.1", "42", flags, ec);
|
||||
VERIFY( !ec );
|
||||
VERIFY( addrs.size() > 0 );
|
||||
VERIFY( addrs.begin() != addrs.end() );
|
||||
|
||||
auto addrs2 = resolv.resolve("127.0.0.1", "42", flags);
|
||||
VERIFY( addrs == addrs2 );
|
||||
|
||||
addrs = resolv.resolve("localhost", "42", flags, ec);
|
||||
VERIFY( ec );
|
||||
VERIFY( addrs.empty() );
|
||||
addrs = resolv.resolve("127.0.0.1", "nameserver", flags, ec);
|
||||
VERIFY( ec );
|
||||
VERIFY( addrs.empty() );
|
||||
|
||||
#if __cpp_exceptions
|
||||
bool caught = false;
|
||||
try {
|
||||
resolv.resolve("localhost", "http", flags);
|
||||
} catch (const std::system_error& e) {
|
||||
caught = true;
|
||||
VERIFY( e.code() == ec );
|
||||
}
|
||||
VERIFY( caught );
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
test03()
|
||||
{
|
||||
bool test __attribute__((unused)) = false;
|
||||
|
||||
std::error_code ec;
|
||||
io_context ctx;
|
||||
ip::tcp::resolver resolv(ctx);
|
||||
auto addrs = resolv.resolve("test.invalid", "http", ec);
|
||||
VERIFY( ec );
|
||||
VERIFY( addrs.size() == 0 );
|
||||
VERIFY( addrs.begin() == addrs.end() );
|
||||
VERIFY( addrs.empty() );
|
||||
#if __cpp_exceptions
|
||||
bool caught = false;
|
||||
try {
|
||||
resolv.resolve("test.invalid", "http");
|
||||
} catch (const std::system_error& e) {
|
||||
caught = true;
|
||||
VERIFY( e.code() == ec );
|
||||
}
|
||||
VERIFY( caught );
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test01();
|
||||
test02();
|
||||
test03();
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
// Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-options "-std=gnu++14" }
|
||||
|
||||
#include <experimental/internet>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
using namespace std::experimental::net;
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
bool test __attribute__((unused)) = false;
|
||||
|
||||
std::error_code ec;
|
||||
io_context ctx;
|
||||
ip::tcp::resolver resolv(ctx);
|
||||
ip::tcp::endpoint home{ip::address_v4::loopback(), 80};
|
||||
auto addrs = resolv.resolve(home, ec);
|
||||
VERIFY( !ec );
|
||||
VERIFY( addrs.size() == 1 );
|
||||
VERIFY( addrs.begin() != addrs.end() );
|
||||
VERIFY( ! addrs.empty() );
|
||||
|
||||
auto addrs2 = resolv.resolve(home);
|
||||
VERIFY( addrs == addrs2 );
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test01();
|
||||
}
|
119
libstdc++-v3/testsuite/experimental/net/timer/waitable/cons.cc
Normal file
119
libstdc++-v3/testsuite/experimental/net/timer/waitable/cons.cc
Normal file
@ -0,0 +1,119 @@
|
||||
// Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-options "-std=gnu++14" }
|
||||
|
||||
#include <experimental/timer>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
using std::experimental::net::system_timer;
|
||||
using std::experimental::net::io_context;
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
bool test __attribute__((unused)) = false;
|
||||
|
||||
io_context ctx1, ctx2;
|
||||
|
||||
system_timer timer1(ctx1);
|
||||
VERIFY( timer1.get_executor() == ctx1.get_executor() );
|
||||
VERIFY( timer1.expiry() == system_timer::time_point() );
|
||||
|
||||
system_timer timer2(ctx2);
|
||||
VERIFY( timer2.get_executor() == ctx2.get_executor() );
|
||||
VERIFY( timer2.get_executor() != timer1.get_executor() );
|
||||
VERIFY( timer2.expiry() == system_timer::time_point() );
|
||||
|
||||
system_timer timer3(std::move(timer1));
|
||||
VERIFY( timer3.get_executor() == ctx1.get_executor() );
|
||||
VERIFY( timer3.expiry() == system_timer::time_point() );
|
||||
VERIFY( timer1.expiry() == system_timer::time_point() );
|
||||
|
||||
system_timer timer4(std::move(timer2));
|
||||
VERIFY( timer4.get_executor() == ctx2.get_executor() );
|
||||
VERIFY( timer4.expiry() == system_timer::time_point() );
|
||||
VERIFY( timer2.expiry() == system_timer::time_point() );
|
||||
}
|
||||
|
||||
void
|
||||
test02()
|
||||
{
|
||||
bool test __attribute__((unused)) = false;
|
||||
|
||||
io_context ctx1, ctx2;
|
||||
auto t1 = system_timer::clock_type::now();
|
||||
auto t2 = t1 + system_timer::duration(10);
|
||||
|
||||
system_timer timer1(ctx1, t1);
|
||||
VERIFY( timer1.get_executor() == ctx1.get_executor() );
|
||||
VERIFY( timer1.expiry() == t1 );
|
||||
|
||||
system_timer timer2(ctx2, t2);
|
||||
VERIFY( timer2.get_executor() == ctx2.get_executor() );
|
||||
VERIFY( timer2.get_executor() != timer1.get_executor() );
|
||||
VERIFY( timer2.expiry() == t2 );
|
||||
|
||||
system_timer timer3(std::move(timer1));
|
||||
VERIFY( timer3.get_executor() == ctx1.get_executor() );
|
||||
VERIFY( timer3.expiry() == t1 );
|
||||
VERIFY( timer1.expiry() == system_timer::time_point() );
|
||||
|
||||
system_timer timer4(std::move(timer2));
|
||||
VERIFY( timer4.get_executor() == ctx2.get_executor() );
|
||||
VERIFY( timer4.expiry() == t2 );
|
||||
VERIFY( timer2.expiry() == system_timer::time_point() );
|
||||
}
|
||||
|
||||
void
|
||||
test03()
|
||||
{
|
||||
bool test __attribute__((unused)) = false;
|
||||
|
||||
io_context ctx1, ctx2;
|
||||
auto now = system_timer::clock_type::now();
|
||||
auto d1 = system_timer::duration(10);
|
||||
auto d2 = system_timer::duration(100);
|
||||
|
||||
system_timer timer1(ctx1, d1);
|
||||
VERIFY( timer1.get_executor() == ctx1.get_executor() );
|
||||
VERIFY( timer1.expiry() > now );
|
||||
|
||||
system_timer timer2(ctx2, d2);
|
||||
VERIFY( timer2.get_executor() == ctx2.get_executor() );
|
||||
VERIFY( timer2.get_executor() != timer1.get_executor() );
|
||||
VERIFY( timer2.expiry() > now );
|
||||
VERIFY( timer2.expiry() != timer1.expiry() );
|
||||
|
||||
system_timer timer3(std::move(timer1));
|
||||
VERIFY( timer3.get_executor() == ctx1.get_executor() );
|
||||
VERIFY( timer3.expiry() > now );
|
||||
VERIFY( timer1.expiry() == system_timer::time_point() );
|
||||
|
||||
system_timer timer4(std::move(timer2));
|
||||
VERIFY( timer4.get_executor() == ctx2.get_executor() );
|
||||
VERIFY( timer4.expiry() > now );
|
||||
VERIFY( timer2.expiry() == system_timer::time_point() );
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test01();
|
||||
test02();
|
||||
test03();
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
// Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-options "-std=gnu++14" }
|
||||
|
||||
#include <experimental/timer>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
using std::experimental::net::system_timer;
|
||||
using std::experimental::net::io_context;
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
bool test __attribute__((unused)) = false;
|
||||
|
||||
std::error_code ec;
|
||||
|
||||
io_context ctx;
|
||||
{
|
||||
system_timer timer(ctx, system_timer::duration(3600));
|
||||
timer.async_wait([&ec](std::error_code e) { ec = e; });
|
||||
}
|
||||
auto n = ctx.run();
|
||||
__builtin_printf("ran %lu\n", n);
|
||||
VERIFY( n == 1 );
|
||||
VERIFY( ec == std::errc::operation_canceled );
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test01();
|
||||
}
|
106
libstdc++-v3/testsuite/experimental/net/timer/waitable/ops.cc
Normal file
106
libstdc++-v3/testsuite/experimental/net/timer/waitable/ops.cc
Normal file
@ -0,0 +1,106 @@
|
||||
// Copyright (C) 2015-2018 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-options "-std=gnu++14" }
|
||||
|
||||
#include <experimental/timer>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
using std::experimental::net::system_timer;
|
||||
using std::experimental::net::io_context;
|
||||
using std::error_code;
|
||||
|
||||
void
|
||||
test01()
|
||||
{
|
||||
bool test __attribute__((unused)) = false;
|
||||
|
||||
io_context ctx;
|
||||
error_code ec;
|
||||
bool complete = false;
|
||||
|
||||
auto then = system_timer::clock_type::now() + system_timer::duration(100);
|
||||
|
||||
system_timer timer(ctx, then);
|
||||
VERIFY( timer.cancel_one() == 0 );
|
||||
VERIFY( timer.cancel() == 0 );
|
||||
|
||||
timer.async_wait([&](error_code e) { ec = e; complete = true; });
|
||||
VERIFY( timer.cancel_one() == 1 );
|
||||
VERIFY( !complete );
|
||||
|
||||
VERIFY( timer.cancel_one() == 0 );
|
||||
VERIFY( timer.cancel() == 0 );
|
||||
|
||||
VERIFY( ctx.run() == 1 );
|
||||
VERIFY( ctx.stopped() );
|
||||
VERIFY( complete );
|
||||
VERIFY( ec == std::errc::operation_canceled );
|
||||
}
|
||||
|
||||
void
|
||||
test02()
|
||||
{
|
||||
bool test __attribute__((unused)) = false;
|
||||
|
||||
io_context ctx;
|
||||
error_code ec1, ec2;
|
||||
|
||||
const auto now = system_timer::clock_type::now();
|
||||
const auto t1 = now + std::chrono::seconds(100);
|
||||
const auto t2 = t1 + std::chrono::seconds(100);
|
||||
|
||||
system_timer timer(ctx, t1);
|
||||
VERIFY( timer.expiry() == t1 );
|
||||
|
||||
VERIFY( timer.expires_at(t2) == 0 );
|
||||
VERIFY( timer.expiry() == t2 );
|
||||
|
||||
timer.async_wait([&ec1](error_code e) { ec1 = e; });
|
||||
timer.async_wait([&ec2](error_code e) { ec2 = e; });
|
||||
auto n = timer.expires_at(t1);
|
||||
VERIFY( n == 2 );
|
||||
VERIFY( timer.expiry() == t1 );
|
||||
|
||||
VERIFY( ctx.run_one() == 1 );
|
||||
VERIFY( ! ctx.stopped() );
|
||||
VERIFY( ctx.run_one() == 1 );
|
||||
VERIFY( ctx.stopped() );
|
||||
VERIFY( ec1 == std::errc::operation_canceled );
|
||||
VERIFY( ec2 == std::errc::operation_canceled );
|
||||
|
||||
VERIFY( timer.expires_after(std::chrono::seconds(50)) == 0 );
|
||||
VERIFY( timer.expiry() < t1 );
|
||||
|
||||
ec1.clear();
|
||||
ec2.clear();
|
||||
ctx.restart();
|
||||
timer.async_wait([&ec1](error_code e) { ec1 = e; });
|
||||
timer.async_wait([&ec2](error_code e) { ec2 = e; });
|
||||
VERIFY( timer.expires_after(std::chrono::seconds(10)) == 2 );
|
||||
VERIFY( timer.expiry() < t1 );
|
||||
ctx.run();
|
||||
VERIFY( ec1 == std::errc::operation_canceled );
|
||||
VERIFY( ec2 == std::errc::operation_canceled );
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
test01();
|
||||
test02();
|
||||
}
|
Loading…
Reference in New Issue
Block a user