From 031e13c2530271885cc2424f935594017c85f3b8 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Wed, 27 Feb 2019 15:02:00 -0800 Subject: [PATCH] Add websocket service --- CHANGELOG.md | 1 + .../boost/beast/websocket/detail/service.hpp | 91 +++++++++++++++++++ include/boost/beast/websocket/impl/stream.hpp | 8 ++ .../beast/websocket/impl/stream_impl.hpp | 27 +++++- include/boost/beast/websocket/stream.hpp | 17 +--- test/beast/websocket/stream.cpp | 4 + 6 files changed, 133 insertions(+), 15 deletions(-) create mode 100644 include/boost/beast/websocket/detail/service.hpp diff --git a/CHANGELOG.md b/CHANGELOG.md index fa019f52..7e5ef0e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ Version 223: * Add test::stream::service +* Add websocket service -------------------------------------------------------------------------------- diff --git a/include/boost/beast/websocket/detail/service.hpp b/include/boost/beast/websocket/detail/service.hpp new file mode 100644 index 00000000..62b1dcb8 --- /dev/null +++ b/include/boost/beast/websocket/detail/service.hpp @@ -0,0 +1,91 @@ +// +// Copyright (c) 2016-2019 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_WEBSOCKET_DETAIL_SERVICE_HPP +#define BOOST_BEAST_WEBSOCKET_DETAIL_SERVICE_HPP + +#include +#include +#include +#include +#include + +namespace boost { +namespace beast { +namespace websocket { +namespace detail { + +class service + : public beast::detail::service_base +{ +public: + class impl_type + : public boost::enable_shared_from_this + { + service& svc_; + std::size_t index_; + + friend class service; + + public: + virtual ~impl_type() = default; + + explicit + impl_type(net::execution_context& ctx) + : svc_(net::use_service(ctx)) + { + std::lock_guard g(svc_.m_); + index_ = svc_.v_.size(); + svc_.v_.push_back(this); + } + + BOOST_BEAST_DECL + void + remove() + { + std::lock_guard g(svc_.m_); + auto& other = *svc_.v_.back(); + other.index_ = index_; + svc_.v_[index_] = &other; + svc_.v_.pop_back(); + } + }; + +private: + std::mutex m_; + std::vector v_; + + BOOST_BEAST_DECL + void + shutdown() override + { + std::vector> v; + { + std::lock_guard g(m_); + v.reserve(v_.size()); + for(auto p : v_) + v.emplace_back(p->weak_from_this()); + } + } + +public: + BOOST_BEAST_DECL + explicit + service(net::execution_context& ctx) + : beast::detail::service_base(ctx) + { + } +}; + +} // detail +} // websocket +} // beast +} // boost + +#endif diff --git a/include/boost/beast/websocket/impl/stream.hpp b/include/boost/beast/websocket/impl/stream.hpp index 9ec2ebc9..4de523f6 100644 --- a/include/boost/beast/websocket/impl/stream.hpp +++ b/include/boost/beast/websocket/impl/stream.hpp @@ -43,6 +43,14 @@ namespace boost { namespace beast { namespace websocket { +template +stream:: +~stream() +{ + if(impl_) + impl_->remove(); +} + template template stream:: diff --git a/include/boost/beast/websocket/impl/stream_impl.hpp b/include/boost/beast/websocket/impl/stream_impl.hpp index b9a1ac57..82f526a0 100644 --- a/include/boost/beast/websocket/impl/stream_impl.hpp +++ b/include/boost/beast/websocket/impl/stream_impl.hpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,7 @@ #include #include #include +#include #include namespace boost { @@ -44,13 +46,30 @@ namespace websocket { template< class NextLayer, bool deflateSupported> struct stream::impl_type - : boost::enable_shared_from_this + : boost::empty_value + , detail::service::impl_type , detail::impl_base - , boost::empty_value { NextLayer& stream() noexcept { - return this->boost::empty_value::get(); + return this->boost::empty_value< + NextLayer>::get(); + } + + boost::weak_ptr + weak_from_this() + { + return boost::static_pointer_cast< + impl_type>(this->detail::service:: + impl_type::shared_from_this()); + } + + boost::shared_ptr + shared_this() + { + return boost::static_pointer_cast< + impl_type>(this->detail::service:: + impl_type::shared_from_this()); } net::steady_timer timer; // used for timeouts @@ -110,6 +129,8 @@ struct stream::impl_type : boost::empty_value( boost::empty_init_t{}, std::forward(args)...) + , detail::service::impl_type( + this->stream().get_executor().context()) , timer(this->stream().get_executor()) { timeout_opt.handshake_timeout = none(); diff --git a/include/boost/beast/websocket/stream.hpp b/include/boost/beast/websocket/stream.hpp index e8a39532..f386376b 100644 --- a/include/boost/beast/websocket/stream.hpp +++ b/include/boost/beast/websocket/stream.hpp @@ -178,27 +178,20 @@ public: @note A stream object must not be destroyed while there are pending asynchronous operations associated with it. */ - ~stream() = default; + ~stream(); /** Constructor If `NextLayer` is move constructible, this function will move-construct a new stream from the existing stream. - @note The behavior of move assignment on or from streams - with active or pending operations is undefined. + After the move, the only valid operation on the moved-from + object is destruction. */ stream(stream&&) = default; - /** Assignment - - If `NextLayer` is move assignable, this function - will move-assign a new stream from the existing stream. - - @note The behavior of move assignment on or from streams - with active or pending operations is undefined. - */ - stream& operator=(stream&&) = default; + /// Move assignment (deleted) + stream& operator=(stream&&) = delete; /** Constructor diff --git a/test/beast/websocket/stream.cpp b/test/beast/websocket/stream.cpp index 5214bd79..7471320f 100644 --- a/test/beast/websocket/stream.cpp +++ b/test/beast/websocket/stream.cpp @@ -174,8 +174,10 @@ public: BOOST_STATIC_ASSERT(std::is_move_constructible< stream>::value); + #if 0 BOOST_STATIC_ASSERT(std::is_move_assignable< stream>::value); + #endif BOOST_STATIC_ASSERT(std::is_constructible< stream, test::stream&>::value); @@ -183,8 +185,10 @@ public: // VFALCO Should these be allowed for NextLayer references? BOOST_STATIC_ASSERT(std::is_move_constructible< stream>::value); + #if 0 BOOST_STATIC_ASSERT(std::is_move_assignable< stream>::value); + #endif log << "sizeof(websocket::stream) == " << sizeof(websocket::stream) << std::endl;