2020-05-21 Jonathan Wakely <jwakely@redhat.com>
+ * include/experimental/executor (use_future_t::use_future_t()): Fix
+ incorrect noexcept-specifier.
+ * include/experimental/internet (basic_resolver_results): Adjust
+ whitespace.
+ * include/experimental/socket (__basic_socket_impl::release): Add
+ member function.
+ (basic_socket(io_context&, const endpoint_type&)): Fix argument to
+ target constructor.
+ (basic_socket::release(), basic_socket::release(error_code&)): Add
+ missing member functions.
+ (basic_socket::is_open()): Add nodiscard attribute.
+ (basic_socket::close(error_code&)): Pass argument to base function.
+ (basic_socket_acceptor::release())
+ (basic_socket_acceptor::release(error_code&)): Add missing member
+ functions.
+ (basic_socket_acceptor::is_open()): Add nodiscard attribute.
+ (basic_socket_streambuf::error()): Add noexcept.
+ (basic_socket_iostream::error()): Likewise.
+ * testsuite/experimental/net/socket/basic_socket.cc: New test.
+
* include/experimental/buffer: Replace typedefs with
alias-declarations.
* include/experimental/executor: Likewise.
using allocator_type = _ProtoAllocator;
// use_future_t members:
- constexpr use_future_t() noexcept : _M_alloc() { }
+ constexpr
+ use_future_t()
+ noexcept(is_nothrow_default_constructible<_ProtoAllocator>::value)
+ : _M_alloc() { }
explicit
use_future_t(const _ProtoAllocator& __a) noexcept : _M_alloc(__a) { }
// size:
size_type size() const noexcept { return _M_size; }
size_type max_size() const noexcept { return _M_results.max_size(); }
- _GLIBCXX_NODISCARD bool empty() const noexcept { return _M_results.empty(); }
+
+ _GLIBCXX_NODISCARD bool
+ empty() const noexcept { return _M_results.empty(); }
// element access:
const_iterator begin() const { return _M_results.begin(); }
// TODO SettableSocket reqs
// TODO BooleanSocketOption reqs
// TODO IntegerSocketOption reqs
- // TODO _IoControlCommand reqs
- // TODO _ConnectCondition reqs
+ // TODO IoControlCommand reqs
+ // TODO ConnectCondition reqs
/** @brief Sockets
* @{
}
}
+ native_handle_type release(error_code& __ec)
+ {
+ __glibcxx_assert(is_open());
+ cancel(__ec);
+ return std::exchange(_M_sockfd, -1);
+ }
+
template<typename _SettableSocketOption>
void
set_option(const _SettableSocketOption& __option, error_code& __ec)
#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
socklen_t __endpoint_len = __endpoint.capacity();
if (::getsockname(_M_sockfd, (sockaddr*)__endpoint.data(),
- &__endpoint_len) == -1)
+ &__endpoint_len) == -1)
{
__ec.assign(errno, generic_category());
return endpoint_type{};
error_code& __ec)
{ __base::assign(__protocol, __native_socket, __ec); }
- bool is_open() const noexcept { return __base::is_open(); }
+ native_handle_type release()
+ { return release(__throw_on_error{"basic_socket::release"}); }
+
+ native_handle_type release(error_code& __ec)
+ { return __base::release(__ec); }
+
+ [[__nodiscard__]] bool
+ is_open() const noexcept { return __base::is_open(); }
void close() { close(__throw_on_error{"basic_socket::close"}); }
- void close(error_code& __ec) { __base::close(); }
+ void close(error_code& __ec) { __base::close(__ec); }
void cancel() { cancel(__throw_on_error{"basic_socket::cancel"}); }
#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
socklen_t __endpoint_len = __endpoint.capacity();
if (::getpeername(this->_M_sockfd, (sockaddr*)__endpoint.data(),
- &__endpoint_len)
+ &__endpoint_len)
== -1)
{
__ec.assign(errno, generic_category());
void
connect(const endpoint_type& __endpoint, error_code& __ec)
{
+#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
if (!is_open())
{
open(__endpoint.protocol(), __ec);
if (__ec)
return;
}
-#ifdef _GLIBCXX_HAVE_SYS_SOCKET_H
if (::connect(native_handle(), (const sockaddr*)__endpoint.data(),
__endpoint.size()) == -1)
__ec.assign(errno, generic_category());
auto __a = get_associated_allocator(
__init.completion_handler, std::allocator<void>());
__ex.post(
- [__h=std::move(__init.completion_handler), __ec]
+ [__h = std::move(__init.completion_handler), __ec]
() mutable
{ __h(__ec); }, __a);
return __init.result.get();
{ open(__protocol); }
basic_socket(io_context& __ctx, const endpoint_type& __endpoint)
- : basic_socket(std::addressof(__ctx), __endpoint.protocol())
+ : basic_socket(__ctx, __endpoint.protocol())
{ bind(__endpoint); }
basic_socket(io_context& __ctx, const protocol_type& __protocol,
error_code& __ec)
{ __base::assign(__protocol, __native_acceptor, __ec); }
- bool
+ native_handle_type release()
+ { return release(__throw_on_error{"basic_socket_acceptor::release"}); }
+
+ native_handle_type release(error_code& __ec)
+ { return __base::release(__ec); }
+
+ [[__nodiscard__]] bool
is_open() const noexcept { return __base::is_open(); }
void
basic_socket_streambuf* close(); // TODO
basic_socket<protocol_type>& socket() { return _M_socket; }
- error_code error() const { return _M_ec; }
+
+ error_code error() const noexcept { return _M_ec; }
time_point expiry() const { return _M_expiry; }
{ return const_cast<__streambuf_type*>(std::addressof(_M_sb)); }
basic_socket<protocol_type>& socket() { return rdbuf()->socket(); }
- error_code error() const { return rdbuf()->error(); }
+ error_code error() const noexcept { return rdbuf()->error(); }
time_point expiry() const { return rdbuf()->expiry(); }
void expires_at(const time_point& __t) { rdbuf()->expires_at(__t); }
--- /dev/null
+// Copyright (C) 2020 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-do compile { target c++14 } }
+
+#include <experimental/socket>
+
+namespace net = std::experimental::net;
+using namespace std;
+
+namespace test
+{
+}
+
+void
+test01(net::io_context& io)
+{
+ struct proto
+ {
+ struct endpoint
+ {
+ using protocol_type = proto;
+ protocol_type protocol() const { return {}; }
+
+ void* data() { return nullptr; }
+ const void* data() const { return nullptr; }
+ std::size_t size() const { return 0; }
+ void resize(std::size_t) { }
+ std::size_t capacity() const { return 0; }
+ };
+
+ int family() const { return 0; }
+ int type() const { return 0; }
+ int protocol() const { return 0; }
+ };
+
+ static_assert( ! is_default_constructible<net::basic_socket<proto>>::value,
+ "no default ctor" );
+ static_assert( ! is_copy_constructible<net::basic_socket<proto>>::value,
+ "copy ctor is deleted" );
+ static_assert( ! is_move_constructible<net::basic_socket<proto>>::value,
+ "move ctor is protected" );
+ static_assert( ! is_move_assignable<net::basic_socket<proto>>::value,
+ "move assignment op is protected" );
+
+ struct socket : net::basic_socket<proto>
+ {
+ explicit
+ socket(net::io_context& io)
+ : basic_socket(io) { }
+
+ socket(net::io_context& io, const proto& p)
+ : basic_socket(io, p) { }
+
+ socket(net::io_context& io, const proto::endpoint& e)
+ : basic_socket(io, e) { }
+
+ socket(net::io_context& io, const proto& p, int n)
+ : basic_socket(io, p, n) { }
+ };
+
+ static_assert( ! is_copy_constructible<socket>::value, "deleted" );
+ static_assert( is_move_constructible<socket>::value, "" );
+ static_assert( is_move_assignable<socket>::value, "" );
+
+ error_code ec;
+ proto p;
+ proto::endpoint e;
+
+ socket s(io);
+ s = socket(io, p);
+ s = socket(io, e);
+ s = socket(io, p, s.release());
+
+ static_assert( is_same<decltype(s.get_executor()),
+ net::io_context::executor_type>::value, "" );
+ static_assert( noexcept(s.get_executor()), "" );
+ static_assert( is_same<decltype(s.native_handle()),
+ socket::native_handle_type>::value, "" );
+ static_assert( noexcept(s.native_handle()), "GNU extension" );
+
+ s.open();
+ s.open(p);
+ s.open(p, ec);
+
+ s.assign(p, s.release());
+ s.assign(p, s.release(ec), ec);
+
+ static_assert( is_same<decltype(const_cast<const socket&>(s).is_open()),
+ bool>::value, "" );
+ static_assert( noexcept(const_cast<const socket&>(s).is_open()), "" );
+
+ s.close();
+ s.close(ec);
+
+ s.cancel();
+ s.cancel(ec);
+
+ s.bind(e);
+ s.bind(e, ec);
+
+ s.shutdown(net::socket_base::shutdown_both);
+ s.shutdown(net::socket_base::shutdown_both, ec);
+
+ e = s.local_endpoint();
+ e = s.local_endpoint(ec);
+ e = s.remote_endpoint();
+ e = s.remote_endpoint(ec);
+
+ s.connect(e);
+ s.connect(e, ec);
+
+ s.wait(net::socket_base::wait_read);
+ s.wait(net::socket_base::wait_read, ec);
+}