From dc02f6305040aebdbc32e27f1b1238ed1816fac1 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Tue, 5 Feb 2019 21:03:20 -0800 Subject: [PATCH] close_socket is in stream_traits.hpp --- CHANGELOG.md | 6 + include/boost/beast/core.hpp | 1 - include/boost/beast/core/close_socket.hpp | 133 --------------------- include/boost/beast/core/stream_traits.hpp | 114 ++++++++++++++++++ test/beast/core/CMakeLists.txt | 1 - test/beast/core/Jamfile | 1 - test/beast/core/close_socket.cpp | 91 -------------- test/beast/core/stream_traits.cpp | 98 +++++++++++++++ 8 files changed, 218 insertions(+), 227 deletions(-) delete mode 100644 include/boost/beast/core/close_socket.hpp diff --git a/CHANGELOG.md b/CHANGELOG.md index cd8ce77b..d7a9dade 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +Version 211: + +* close_socket is in stream_traits.hpp + +-------------------------------------------------------------------------------- + Version 210: * Tidy up read implementation diff --git a/include/boost/beast/core.hpp b/include/boost/beast/core.hpp index 4802ab7a..d8f520cd 100644 --- a/include/boost/beast/core.hpp +++ b/include/boost/beast/core.hpp @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include diff --git a/include/boost/beast/core/close_socket.hpp b/include/boost/beast/core/close_socket.hpp deleted file mode 100644 index 29f32cf4..00000000 --- a/include/boost/beast/core/close_socket.hpp +++ /dev/null @@ -1,133 +0,0 @@ -// -// Copyright (c) 2018 Vinnie Falco (vinnie dot falco at gmail dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// -// Official repository: https://github.com/boostorg/beast -// - -#ifndef BOOST_BEAST_CLOSE_SOCKET_HPP -#define BOOST_BEAST_CLOSE_SOCKET_HPP - -#include -#include -#include - -namespace boost { -namespace beast { - -/** Default socket close function. - - This function is not meant to be called directly. Instead, it - is called automatically when using @ref close_socket. To enable - closure of user-defined types or classes derived from a particular - user-defined type, this function should be overloaded in the - corresponding namespace for the type in question. - - @see close_socket -*/ -template -void -beast_close_socket( - net::basic_socket& sock) -{ - boost::system::error_code ec; - sock.close(ec); -} - -namespace detail { - -struct close_socket_impl -{ - template - void - operator()(T& t) const - { - using beast::beast_close_socket; - beast_close_socket(t); - } -}; - -} // detail - -/** Close a socket or socket-like object. - - This function attempts to close an object representing a socket. - In this context, a socket is an object for which an unqualified - call to the function `void beast_close_socket(Socket&)` is - well-defined. The function `beast_close_socket` is a - customization point, allowing user-defined types to - provide an algorithm for performing the close operation by - overloading this function for the type in question. - - Since the customization point is a function call, the normal - rules for finding the correct overload are applied including - the rules for argument-dependent lookup ("ADL"). This permits - classes derived from a type for which a customization is provided - to inherit the customization point. - - An overload for the networking class template `net::basic_socket` - is provided, which implements the close algorithm for all socket-like - objects (hence the name of this customization point). When used - in conjunction with @ref get_lowest_layer, a generic algorithm - operating on a layered stream can perform a closure of the underlying - socket without knowing the exact list of concrete types. - - @par Example 1 - The following generic function synchronously sends a message - on the stream, then closes the socket. - @code - template - void hello_and_close (WriteStream& stream) - { - net::write(stream, net::const_buffer("Hello, world!", 13)); - close_socket(get_lowest_layer(stream)); - } - @endcode - - To enable closure of user defined types, it is necessary to provide - an overload of the function `beast_close_socket` for the type. - - @par Example 2 - The following code declares a user-defined type which contains a - private socket, and provides an overload of the customization - point which closes the private socket. - @code - class my_socket - { - net::ip::tcp::socket sock_; - - public: - my_socket(net::io_context& ioc) - : sock_(ioc) - { - } - - friend void beast_close_socket(my_socket& s) - { - error_code ec; - s.sock_.close(ec); - // ignore the error - } - }; - @endcode - - @param sock The socket to close. If the customization point is not - defined for the type of this object, or one of its base classes, - then a compiler error results. - - @see beast_close_socket -*/ -#if BOOST_BEAST_DOXYGEN -template -void -close_socket(Socket& sock); -#else -BOOST_BEAST_INLINE_VARIABLE(close_socket, detail::close_socket_impl) -#endif - -} // beast -} // boost - -#endif diff --git a/include/boost/beast/core/stream_traits.hpp b/include/boost/beast/core/stream_traits.hpp index ad169818..f58703df 100644 --- a/include/boost/beast/core/stream_traits.hpp +++ b/include/boost/beast/core/stream_traits.hpp @@ -11,7 +11,9 @@ #define BOOST_BEAST_STREAM_TRAITS_HPP #include +#include #include +#include namespace boost { namespace beast { @@ -424,6 +426,118 @@ using is_async_stream = std::integral_constant::value && is_async_write_stream::value>; #endif +//------------------------------------------------------------------------------ + +/** Default socket close function. + + This function is not meant to be called directly. Instead, it + is called automatically when using @ref close_socket. To enable + closure of user-defined types or classes derived from a particular + user-defined type, this function should be overloaded in the + corresponding namespace for the type in question. + + @see close_socket +*/ +template +void +beast_close_socket( + net::basic_socket& sock) +{ + boost::system::error_code ec; + sock.close(ec); +} + +namespace detail { + +struct close_socket_impl +{ + template + void + operator()(T& t) const + { + using beast::beast_close_socket; + beast_close_socket(t); + } +}; + +} // detail + +/** Close a socket or socket-like object. + + This function attempts to close an object representing a socket. + In this context, a socket is an object for which an unqualified + call to the function `void beast_close_socket(Socket&)` is + well-defined. The function `beast_close_socket` is a + customization point, allowing user-defined types to + provide an algorithm for performing the close operation by + overloading this function for the type in question. + + Since the customization point is a function call, the normal + rules for finding the correct overload are applied including + the rules for argument-dependent lookup ("ADL"). This permits + classes derived from a type for which a customization is provided + to inherit the customization point. + + An overload for the networking class template `net::basic_socket` + is provided, which implements the close algorithm for all socket-like + objects (hence the name of this customization point). When used + in conjunction with @ref get_lowest_layer, a generic algorithm + operating on a layered stream can perform a closure of the underlying + socket without knowing the exact list of concrete types. + + @par Example 1 + The following generic function synchronously sends a message + on the stream, then closes the socket. + @code + template + void hello_and_close (WriteStream& stream) + { + net::write(stream, net::const_buffer("Hello, world!", 13)); + close_socket(get_lowest_layer(stream)); + } + @endcode + + To enable closure of user defined types, it is necessary to provide + an overload of the function `beast_close_socket` for the type. + + @par Example 2 + The following code declares a user-defined type which contains a + private socket, and provides an overload of the customization + point which closes the private socket. + @code + class my_socket + { + net::ip::tcp::socket sock_; + + public: + my_socket(net::io_context& ioc) + : sock_(ioc) + { + } + + friend void beast_close_socket(my_socket& s) + { + error_code ec; + s.sock_.close(ec); + // ignore the error + } + }; + @endcode + + @param sock The socket to close. If the customization point is not + defined for the type of this object, or one of its base classes, + then a compiler error results. + + @see beast_close_socket +*/ +#if BOOST_BEAST_DOXYGEN +template +void +close_socket(Socket& sock); +#else +BOOST_BEAST_INLINE_VARIABLE(close_socket, detail::close_socket_impl) +#endif + } // beast } // boost diff --git a/test/beast/core/CMakeLists.txt b/test/beast/core/CMakeLists.txt index 5be94c3d..a4da6a87 100644 --- a/test/beast/core/CMakeLists.txt +++ b/test/beast/core/CMakeLists.txt @@ -42,7 +42,6 @@ add_executable (tests-beast-core buffers_range.cpp buffers_suffix.cpp buffers_to_string.cpp - close_socket.cpp dynamic_buffer_ref.cpp error.cpp file.cpp diff --git a/test/beast/core/Jamfile b/test/beast/core/Jamfile index 18d4d0f1..c65f2739 100644 --- a/test/beast/core/Jamfile +++ b/test/beast/core/Jamfile @@ -30,7 +30,6 @@ local SOURCES = buffers_range.cpp buffers_suffix.cpp buffers_to_string.cpp - close_socket.cpp dynamic_buffer_ref.cpp error.cpp file.cpp diff --git a/test/beast/core/close_socket.cpp b/test/beast/core/close_socket.cpp index f01a3d46..01703c3f 100644 --- a/test/beast/core/close_socket.cpp +++ b/test/beast/core/close_socket.cpp @@ -25,97 +25,6 @@ namespace beast { class close_socket_test : public beast::unit_test::suite { public: - template - struct layer - { - T t; - - template - explicit - layer(U&& u) - : t(std::forward(u)) - { - } - - T& next_layer() - { - return t; - } - }; - - void - testClose() - { - net::io_context ioc; - { - net::ip::tcp::socket sock(ioc); - sock.open(net::ip::tcp::v4()); - BEAST_EXPECT(sock.is_open()); - close_socket(get_lowest_layer(sock)); - BEAST_EXPECT(! sock.is_open()); - } - { - using type = layer; - type layer(ioc); - layer.next_layer().open(net::ip::tcp::v4()); - BEAST_EXPECT(layer.next_layer().is_open()); - BOOST_STATIC_ASSERT(detail::has_next_layer::value); - BOOST_STATIC_ASSERT((std::is_same< - typename std::decay::type, - lowest_layer_type>::value)); - BOOST_STATIC_ASSERT(std::is_same::value); - BOOST_STATIC_ASSERT(std::is_same>::value); - close_socket(get_lowest_layer(layer)); - BEAST_EXPECT(! layer.next_layer().is_open()); - } - { - test::stream ts(ioc); - close_socket(ts); - } - } - - //-------------------------------------------------------------------------- - - template - void hello_and_close (WriteStream& stream) - { - net::write(stream, net::const_buffer("Hello, world!", 13)); - close_socket(get_lowest_layer(stream)); - } - - class my_socket - { - net::ip::tcp::socket sock_; - - public: - my_socket(net::io_context& ioc) - : sock_(ioc) - { - } - - friend void beast_close_socket(my_socket& s) - { - error_code ec; - s.sock_.close(ec); - // ignore the error - } - }; - - void - testJavadocs() - { - BEAST_EXPECT(&close_socket_test::template hello_and_close); - { - net::io_context ioc; - my_socket s(ioc); - close_socket(s); - } - } - - //-------------------------------------------------------------------------- - void run() override { diff --git a/test/beast/core/stream_traits.cpp b/test/beast/core/stream_traits.cpp index e1acaa8f..18041f14 100644 --- a/test/beast/core/stream_traits.cpp +++ b/test/beast/core/stream_traits.cpp @@ -12,7 +12,12 @@ #include #include +#include +#include #include +#include +#include +#include namespace boost { namespace beast { @@ -267,6 +272,97 @@ public: //-------------------------------------------------------------------------- + template + struct layer + { + T t; + + template + explicit + layer(U&& u) + : t(std::forward(u)) + { + } + + T& next_layer() + { + return t; + } + }; + + void + testClose() + { + net::io_context ioc; + { + net::ip::tcp::socket sock(ioc); + sock.open(net::ip::tcp::v4()); + BEAST_EXPECT(sock.is_open()); + close_socket(get_lowest_layer(sock)); + BEAST_EXPECT(! sock.is_open()); + } + { + using type = layer; + type layer(ioc); + layer.next_layer().open(net::ip::tcp::v4()); + BEAST_EXPECT(layer.next_layer().is_open()); + BOOST_STATIC_ASSERT(detail::has_next_layer::value); + BOOST_STATIC_ASSERT((std::is_same< + typename std::decay::type, + lowest_layer_type>::value)); + BOOST_STATIC_ASSERT(std::is_same::value); + BOOST_STATIC_ASSERT(std::is_same>::value); + close_socket(get_lowest_layer(layer)); + BEAST_EXPECT(! layer.next_layer().is_open()); + } + { + test::stream ts(ioc); + close_socket(ts); + } + } + + //-------------------------------------------------------------------------- + + template + void hello_and_close (WriteStream& stream) + { + net::write(stream, net::const_buffer("Hello, world!", 13)); + close_socket(get_lowest_layer(stream)); + } + + class my_socket + { + net::ip::tcp::socket sock_; + + public: + my_socket(net::io_context& ioc) + : sock_(ioc) + { + } + + friend void beast_close_socket(my_socket& s) + { + error_code ec; + s.sock_.close(ec); + // ignore the error + } + }; + + void + testCloseJavadoc() + { + BEAST_EXPECT(&stream_traits_test::template hello_and_close); + { + net::io_context ioc; + my_socket s(ioc); + close_socket(s); + } + } + + //-------------------------------------------------------------------------- + void run() override { @@ -274,6 +370,8 @@ public: testGetLowestLayerJavadoc(); testExecutorType(); testExecutorTypeJavadoc(); + testClose(); + testCloseJavadoc(); } };