diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cf7b65d..9fddae96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ * Fixes for WebSocket echo server +API Changes: + +* Better handler_ptr + -------------------------------------------------------------------------------- 1.0.0-b24 diff --git a/doc/overview.qbk b/doc/overview.qbk index c0639a7c..f0a33461 100644 --- a/doc/overview.qbk +++ b/doc/overview.qbk @@ -59,7 +59,7 @@ your particular build system. [heading Motivation] -Beast is built on Boost.Asio A proposal to add networking functionality to the +Beast is built on Boost.Asio. A proposal to add networking functionality to the C++ standard library, based on Boost.Asio, is under consideration by the committee and on track for standardization. Since the final approved networking interface for the C++ standard library will likely closely resemble the current diff --git a/examples/http_async_server.hpp b/examples/http_async_server.hpp index 2c1df4b4..2e248a39 100644 --- a/examples/http_async_server.hpp +++ b/examples/http_async_server.hpp @@ -114,9 +114,8 @@ private: template write_op(DeducedHandler&& h, Stream& s, Args&&... args) - : d_(make_handler_ptr( - std::forward(h), s, - std::forward(args)...)) + : d_(std::forward(h), + s, std::forward(args)...) { (*this)(error_code{}, false); } diff --git a/include/beast/core/handler_ptr.hpp b/include/beast/core/handler_ptr.hpp index 175be8bb..45285f48 100644 --- a/include/beast/core/handler_ptr.hpp +++ b/include/beast/core/handler_ptr.hpp @@ -11,23 +11,25 @@ #include #include #include +#include #include namespace beast { -/** A smart pointer container. +/** A smart pointer container with associated completion handler. This is a smart pointer that retains shared ownership of an object through a pointer. Memory is managed using the allocation and deallocation functions associated with a completion handler, - which is also stored in the object. The object is destroyed and - its memory deallocated when one of the following happens: + which is also stored in the object. The managed object is + destroyed and its memory deallocated when one of the following + happens: @li The function @ref invoke is called. - - @li The function @ref release_handler is called - - @li The last remaining container owning the object is destroyed + + @li The function @ref release_handler is called. + + @li The last remaining container owning the object is destroyed. Objects of this type are used in the implementation of composed operations. Typically the composed operation's shared @@ -38,6 +40,10 @@ namespace beast { @note The reference count is stored using a 16 bit unsigned integer. Making more than 2^16 copies of one object results in undefined behavior. + + @tparam T The type of the owned object. + + @tparam Handler The type of the completion handler. */ template class handler_ptr @@ -60,10 +66,10 @@ class handler_ptr P* p_; - template - handler_ptr(int, DeducedHandler&& handler, Args&&... args); - public: + /// The type of element this object stores + using element_type = T; + /// The type of handler this object stores using handler_type = Handler; @@ -88,6 +94,46 @@ public: /// Copy constructor handler_ptr(handler_ptr const& other); + /** Construct a new @ref handler_ptr + + This creates a new @ref handler_ptr with an owned object + of type `T`. The allocator associated with the handler will + be used to allocate memory for the owned object. The constructor + for the owned object will be called thusly: + + @code + T(handler, std::forward(args)...) + @endcode + + @param handler The handler to associate with the owned + object. The argument will be moved. + + @param args Optional arguments forwarded to + the owned object's constructor. + */ + template + handler_ptr(Handler&& handler, Args&&... args); + + /** Construct a new @ref handler_ptr + + This creates a new @ref handler_ptr with an owned object + of type `T`. The allocator associated with the handler will + be used to allocate memory for the owned object. The constructor + for the owned object will be called thusly: + + @code + T(handler, std::forward(args)...) + @endcode + + @param handler The handler to associate with the owned + object. The argument will be copied. + + @param args Optional arguments forwarded to + the owned object's constructor. + */ + template + handler_ptr(Handler const& handler, Args&&... args); + /// Returns a reference to the handler handler_type& handler() const @@ -95,25 +141,36 @@ public: return p_->handler; } - /// Returns a pointer to the owned object + /// Returns `true` if `*this` owns an object. + explicit + operator bool() const + { + return p_ && p_->t; + } + + /** Returns a pointer to the owned object. + + If `*this` owns an object, a pointer to the + object is returned, else `nullptr` is returned. + */ T* get() const { - return p_->t; + return p_ ? p_->t : nullptr; } /// Return a reference to the owned object. T& operator*() const { - return *get(); + return *p_->t; } /// Return a pointer to the owned object. T* operator->() const { - return get(); + return p_->t; } /** Release ownership of the handler @@ -137,33 +194,6 @@ public: template void invoke(Args&&... args); - - // VFALCO The free function interface works around - // a horrible Visual Studio 15 Update 3 bug - - /** Construct a new `handler_ptr`. - - @param handler The handler. The allocator associated with - the handler will be used to allocate memory for the owned - object. This argument will be forwarded to the owned object's - constructor. - - @param args Optional arguments forwarded to - the owned object's constructor. - */ - /** @{ */ - template - friend - handler_ptr - make_handler_ptr( - CompletionHandler&& handler, Args&&... args); - - template - friend - handler_ptr - make_handler_ptr( - CompletionHandler const& handler, Args&&... args); - /** @} */ }; } // beast diff --git a/include/beast/core/impl/dynabuf_readstream.ipp b/include/beast/core/impl/dynabuf_readstream.ipp index bcd7a0a5..3981c771 100644 --- a/include/beast/core/impl/dynabuf_readstream.ipp +++ b/include/beast/core/impl/dynabuf_readstream.ipp @@ -45,9 +45,8 @@ public: template read_some_op(DeducedHandler&& h, dynabuf_readstream& srs, Args&&... args) - : d_(make_handler_ptr( - std::forward(h), srs, - std::forward(args)...)) + : d_(std::forward(h), + srs, std::forward(args)...) { (*this)(error_code{}, 0); } diff --git a/include/beast/core/impl/handler_ptr.ipp b/include/beast/core/impl/handler_ptr.ipp index 0f57a24d..eb29e998 100644 --- a/include/beast/core/impl/handler_ptr.ipp +++ b/include/beast/core/impl/handler_ptr.ipp @@ -39,15 +39,6 @@ P(DeducedHandler&& h, Args&&... args) } } -template -template -handler_ptr:: -handler_ptr(int, DeducedHandler&& handler, Args&&... args) - : p_(new P(std::forward(handler), - std::forward(args)...)) -{ -} - template handler_ptr:: ~handler_ptr() @@ -82,6 +73,27 @@ handler_ptr(handler_ptr const& other) ++p_->n; } +template +template +handler_ptr:: +handler_ptr(Handler&& handler, Args&&... args) + : p_(new P{std::move(handler), + std::forward(args)...}) +{ + static_assert(! std::is_array::value, + "T must not be an array type"); +} + +template +template +handler_ptr:: +handler_ptr(Handler const& handler, Args&&... args) + : p_(new P{handler, std::forward(args)...}) +{ + static_assert(! std::is_array::value, + "T must not be an array type"); +} + template auto handler_ptr:: @@ -112,27 +124,6 @@ invoke(Args&&... args) p_->handler(std::forward(args)...); } -template< - class T, class CompletionHandler, class... Args> -handler_ptr -make_handler_ptr( - CompletionHandler&& handler, Args&&... args) -{ - return handler_ptr{0, - std::move(handler), - std::forward(args)...}; -} - -template< - class T, class CompletionHandler, class... Args> -handler_ptr -make_handler_ptr( - CompletionHandler const& handler, Args&&... args) -{ - return handler_ptr{0, - handler, std::forward(args)...}; -} - } // beast #endif diff --git a/include/beast/http/impl/parse.ipp b/include/beast/http/impl/parse.ipp index 913b41b1..c2ddae8b 100644 --- a/include/beast/http/impl/parse.ipp +++ b/include/beast/http/impl/parse.ipp @@ -53,9 +53,8 @@ public: template parse_op(DeducedHandler&& h, Stream& s, Args&&... args) - : d_(make_handler_ptr( - std::forward(h), s, - std::forward(args)...)) + : d_(std::forward(h), + s, std::forward(args)...) { (*this)(error_code{}, 0, false); } diff --git a/include/beast/http/impl/read.ipp b/include/beast/http/impl/read.ipp index 3f3961dd..e009170f 100644 --- a/include/beast/http/impl/read.ipp +++ b/include/beast/http/impl/read.ipp @@ -64,9 +64,8 @@ public: template read_header_op( DeducedHandler&& h, Stream& s, Args&&... args) - : d_(make_handler_ptr( - std::forward(h), s, - std::forward(args)...)) + : d_(std::forward(h), + s, std::forward(args)...) { (*this)(error_code{}, false); } @@ -236,9 +235,8 @@ public: template read_op(DeducedHandler&& h, Stream& s, Args&&... args) - : d_(make_handler_ptr( - std::forward(h), s, - std::forward(args)...)) + : d_(std::forward(h), + s, std::forward(args)...) { (*this)(error_code{}, false); } diff --git a/include/beast/http/impl/write.ipp b/include/beast/http/impl/write.ipp index c2f71043..13a50784 100644 --- a/include/beast/http/impl/write.ipp +++ b/include/beast/http/impl/write.ipp @@ -126,9 +126,8 @@ public: template write_streambuf_op(DeducedHandler&& h, Stream& s, Args&&... args) - : d_(make_handler_ptr( - std::forward(h), - s, std::forward(args)...)) + : d_(std::forward(h), + s, std::forward(args)...) { (*this)(error_code{}, 0, false); } @@ -373,9 +372,8 @@ public: template write_op(DeducedHandler&& h, Stream& s, Args&&... args) - : d_(make_handler_ptr( - std::forward(h), s, - std::forward(args)...)) + : d_(std::forward(h), + s, std::forward(args)...) { auto& d = *d_; auto sp = d_; diff --git a/include/beast/websocket/impl/accept.ipp b/include/beast/websocket/impl/accept.ipp index 5d539c29..7c3683a5 100644 --- a/include/beast/websocket/impl/accept.ipp +++ b/include/beast/websocket/impl/accept.ipp @@ -64,9 +64,8 @@ public: template response_op(DeducedHandler&& h, stream& ws, Args&&... args) - : d_(make_handler_ptr( - std::forward(h), ws, - std::forward(args)...)) + : d_(std::forward(h), + ws, std::forward(args)...) { (*this)(error_code{}, false); } @@ -180,9 +179,8 @@ public: template accept_op(DeducedHandler&& h, stream& ws, Args&&... args) - : d_(make_handler_ptr( - std::forward(h), ws, - std::forward(args)...)) + : d_(std::forward(h), + ws, std::forward(args)...) { (*this)(error_code{}, 0, false); } diff --git a/include/beast/websocket/impl/close.ipp b/include/beast/websocket/impl/close.ipp index 7e929b58..8af2c926 100644 --- a/include/beast/websocket/impl/close.ipp +++ b/include/beast/websocket/impl/close.ipp @@ -56,9 +56,8 @@ public: template close_op(DeducedHandler&& h, stream& ws, Args&&... args) - : d_(make_handler_ptr( - std::forward(h), ws, - std::forward(args)...)) + : d_(std::forward(h), + ws, std::forward(args)...) { (*this)(error_code{}, false); } diff --git a/include/beast/websocket/impl/handshake.ipp b/include/beast/websocket/impl/handshake.ipp index fa7b0b71..1397b52f 100644 --- a/include/beast/websocket/impl/handshake.ipp +++ b/include/beast/websocket/impl/handshake.ipp @@ -59,9 +59,8 @@ public: template handshake_op(DeducedHandler&& h, stream& ws, Args&&... args) - : d_(make_handler_ptr( - std::forward(h), ws, - std::forward(args)...)) + : d_(std::forward(h), + ws, std::forward(args)...) { (*this)(error_code{}, false); } diff --git a/include/beast/websocket/impl/ping.ipp b/include/beast/websocket/impl/ping.ipp index d9e7ba51..1fbf3eb8 100644 --- a/include/beast/websocket/impl/ping.ipp +++ b/include/beast/websocket/impl/ping.ipp @@ -55,9 +55,8 @@ public: template ping_op(DeducedHandler&& h, stream& ws, Args&&... args) - : d_(make_handler_ptr( - std::forward(h), ws, - std::forward(args)...)) + : d_(std::forward(h), + ws, std::forward(args)...) { (*this)(error_code{}, false); } diff --git a/include/beast/websocket/impl/read.ipp b/include/beast/websocket/impl/read.ipp index 30713b83..b495e304 100644 --- a/include/beast/websocket/impl/read.ipp +++ b/include/beast/websocket/impl/read.ipp @@ -76,9 +76,8 @@ public: template read_frame_op(DeducedHandler&& h, stream& ws, Args&&... args) - : d_(make_handler_ptr( - std::forward(h), ws, - std::forward(args)...)) + : d_(std::forward(h), + ws, std::forward(args)...) { (*this)(error_code{}, 0, false); } @@ -983,9 +982,8 @@ public: template read_op(DeducedHandler&& h, stream& ws, Args&&... args) - : d_(make_handler_ptr( - std::forward(h), ws, - std::forward(args)...)) + : d_(std::forward(h), + ws, std::forward(args)...) { (*this)(error_code{}, false); } diff --git a/include/beast/websocket/impl/ssl.ipp b/include/beast/websocket/impl/ssl.ipp index 5b3e5cf2..76f6f4fc 100644 --- a/include/beast/websocket/impl/ssl.ipp +++ b/include/beast/websocket/impl/ssl.ipp @@ -59,9 +59,7 @@ public: explicit teardown_ssl_op( DeducedHandler&& h, stream_type& stream) - : d_(make_handler_ptr( - std::forward( - h), stream)) + : d_(std::forward(h), stream) { (*this)(error_code{}, false); } diff --git a/include/beast/websocket/impl/teardown.ipp b/include/beast/websocket/impl/teardown.ipp index b2ac3991..f1270652 100644 --- a/include/beast/websocket/impl/teardown.ipp +++ b/include/beast/websocket/impl/teardown.ipp @@ -47,9 +47,7 @@ public: teardown_tcp_op( DeducedHandler&& h, socket_type& socket) - : d_(make_handler_ptr( - std::forward( - h), socket)) + : d_(std::forward(h), socket) { (*this)(error_code{}, 0, false); } diff --git a/include/beast/websocket/impl/write.ipp b/include/beast/websocket/impl/write.ipp index 760050a4..a3d2cfd5 100644 --- a/include/beast/websocket/impl/write.ipp +++ b/include/beast/websocket/impl/write.ipp @@ -67,9 +67,8 @@ public: template write_frame_op(DeducedHandler&& h, stream& ws, Args&&... args) - : d_(make_handler_ptr( - std::forward(h), - ws, std::forward(args)...)) + : d_(std::forward(h), + ws, std::forward(args)...) { (*this)(error_code{}, 0, false); } @@ -782,9 +781,8 @@ public: explicit write_op(DeducedHandler&& h, stream& ws, Args&&... args) - : d_(make_handler_ptr( - std::forward(h), ws, - std::forward(args)...)) + : d_(std::forward(h), + ws, std::forward(args)...) { (*this)(error_code{}, false); }