Better handler_ptr (API Change):

fix #242

* Add public constructors
* Add handler_ptr::empty()
* Add handler_ptr::element_type
* Remove make_handler_ptr free function
* Compiler error if element_type is an array type
* handler_ptr::get() returns nullptr if no object is owned
This commit is contained in:
Vinnie Falco
2017-01-29 19:46:17 -05:00
parent e81a2864ab
commit d7e9a7ca3c
17 changed files with 131 additions and 126 deletions

View File

@ -2,6 +2,10 @@
* Fixes for WebSocket echo server * Fixes for WebSocket echo server
API Changes:
* Better handler_ptr
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
1.0.0-b24 1.0.0-b24

View File

@ -59,7 +59,7 @@ your particular build system.
[heading Motivation] [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 C++ standard library, based on Boost.Asio, is under consideration by the
committee and on track for standardization. Since the final approved networking committee and on track for standardization. Since the final approved networking
interface for the C++ standard library will likely closely resemble the current interface for the C++ standard library will likely closely resemble the current

View File

@ -114,9 +114,8 @@ private:
template<class DeducedHandler, class... Args> template<class DeducedHandler, class... Args>
write_op(DeducedHandler&& h, Stream& s, Args&&... args) write_op(DeducedHandler&& h, Stream& s, Args&&... args)
: d_(make_handler_ptr<data, Handler>( : d_(std::forward<DeducedHandler>(h),
std::forward<DeducedHandler>(h), s, s, std::forward<Args>(args)...)
std::forward<Args>(args)...))
{ {
(*this)(error_code{}, false); (*this)(error_code{}, false);
} }

View File

@ -11,23 +11,25 @@
#include <beast/core/detail/type_traits.hpp> #include <beast/core/detail/type_traits.hpp>
#include <atomic> #include <atomic>
#include <cstdint> #include <cstdint>
#include <type_traits>
#include <utility> #include <utility>
namespace beast { 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 This is a smart pointer that retains shared ownership of an
object through a pointer. Memory is managed using the allocation object through a pointer. Memory is managed using the allocation
and deallocation functions associated with a completion handler, and deallocation functions associated with a completion handler,
which is also stored in the object. The object is destroyed and which is also stored in the object. The managed object is
its memory deallocated when one of the following happens: destroyed and its memory deallocated when one of the following
happens:
@li The function @ref invoke is called. @li The function @ref invoke is called.
@li The function @ref release_handler is called @li The function @ref release_handler is called.
@li The last remaining container owning the object is destroyed @li The last remaining container owning the object is destroyed.
Objects of this type are used in the implementation of Objects of this type are used in the implementation of
composed operations. Typically the composed operation's shared 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 @note The reference count is stored using a 16 bit unsigned
integer. Making more than 2^16 copies of one object results integer. Making more than 2^16 copies of one object results
in undefined behavior. in undefined behavior.
@tparam T The type of the owned object.
@tparam Handler The type of the completion handler.
*/ */
template<class T, class Handler> template<class T, class Handler>
class handler_ptr class handler_ptr
@ -60,10 +66,10 @@ class handler_ptr
P* p_; P* p_;
template<class DeducedHandler, class... Args>
handler_ptr(int, DeducedHandler&& handler, Args&&... args);
public: public:
/// The type of element this object stores
using element_type = T;
/// The type of handler this object stores /// The type of handler this object stores
using handler_type = Handler; using handler_type = Handler;
@ -88,6 +94,46 @@ public:
/// Copy constructor /// Copy constructor
handler_ptr(handler_ptr const& other); 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>(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<class... Args>
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>(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<class... Args>
handler_ptr(Handler const& handler, Args&&... args);
/// Returns a reference to the handler /// Returns a reference to the handler
handler_type& handler_type&
handler() const handler() const
@ -95,25 +141,36 @@ public:
return p_->handler; 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* T*
get() const get() const
{ {
return p_->t; return p_ ? p_->t : nullptr;
} }
/// Return a reference to the owned object. /// Return a reference to the owned object.
T& T&
operator*() const operator*() const
{ {
return *get(); return *p_->t;
} }
/// Return a pointer to the owned object. /// Return a pointer to the owned object.
T* T*
operator->() const operator->() const
{ {
return get(); return p_->t;
} }
/** Release ownership of the handler /** Release ownership of the handler
@ -137,33 +194,6 @@ public:
template<class... Args> template<class... Args>
void void
invoke(Args&&... args); 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<class U, class CompletionHandler, class... Args>
friend
handler_ptr<U, CompletionHandler>
make_handler_ptr(
CompletionHandler&& handler, Args&&... args);
template<class U, class CompletionHandler, class... Args>
friend
handler_ptr<U, CompletionHandler>
make_handler_ptr(
CompletionHandler const& handler, Args&&... args);
/** @} */
}; };
} // beast } // beast

View File

@ -45,9 +45,8 @@ public:
template<class DeducedHandler, class... Args> template<class DeducedHandler, class... Args>
read_some_op(DeducedHandler&& h, read_some_op(DeducedHandler&& h,
dynabuf_readstream& srs, Args&&... args) dynabuf_readstream& srs, Args&&... args)
: d_(make_handler_ptr<data, Handler>( : d_(std::forward<DeducedHandler>(h),
std::forward<DeducedHandler>(h), srs, srs, std::forward<Args>(args)...)
std::forward<Args>(args)...))
{ {
(*this)(error_code{}, 0); (*this)(error_code{}, 0);
} }

View File

@ -39,15 +39,6 @@ P(DeducedHandler&& h, Args&&... args)
} }
} }
template<class T, class Handler>
template<class DeducedHandler, class... Args>
handler_ptr<T, Handler>::
handler_ptr(int, DeducedHandler&& handler, Args&&... args)
: p_(new P(std::forward<DeducedHandler>(handler),
std::forward<Args>(args)...))
{
}
template<class T, class Handler> template<class T, class Handler>
handler_ptr<T, Handler>:: handler_ptr<T, Handler>::
~handler_ptr() ~handler_ptr()
@ -82,6 +73,27 @@ handler_ptr(handler_ptr const& other)
++p_->n; ++p_->n;
} }
template<class T, class Handler>
template<class... Args>
handler_ptr<T, Handler>::
handler_ptr(Handler&& handler, Args&&... args)
: p_(new P{std::move(handler),
std::forward<Args>(args)...})
{
static_assert(! std::is_array<T>::value,
"T must not be an array type");
}
template<class T, class Handler>
template<class... Args>
handler_ptr<T, Handler>::
handler_ptr(Handler const& handler, Args&&... args)
: p_(new P{handler, std::forward<Args>(args)...})
{
static_assert(! std::is_array<T>::value,
"T must not be an array type");
}
template<class T, class Handler> template<class T, class Handler>
auto auto
handler_ptr<T, Handler>:: handler_ptr<T, Handler>::
@ -112,27 +124,6 @@ invoke(Args&&... args)
p_->handler(std::forward<Args>(args)...); p_->handler(std::forward<Args>(args)...);
} }
template<
class T, class CompletionHandler, class... Args>
handler_ptr<T, CompletionHandler>
make_handler_ptr(
CompletionHandler&& handler, Args&&... args)
{
return handler_ptr<T, CompletionHandler>{0,
std::move(handler),
std::forward<Args>(args)...};
}
template<
class T, class CompletionHandler, class... Args>
handler_ptr<T, CompletionHandler>
make_handler_ptr(
CompletionHandler const& handler, Args&&... args)
{
return handler_ptr<T, CompletionHandler>{0,
handler, std::forward<Args>(args)...};
}
} // beast } // beast
#endif #endif

View File

@ -53,9 +53,8 @@ public:
template<class DeducedHandler, class... Args> template<class DeducedHandler, class... Args>
parse_op(DeducedHandler&& h, Stream& s, Args&&... args) parse_op(DeducedHandler&& h, Stream& s, Args&&... args)
: d_(make_handler_ptr<data, Handler>( : d_(std::forward<DeducedHandler>(h),
std::forward<DeducedHandler>(h), s, s, std::forward<Args>(args)...)
std::forward<Args>(args)...))
{ {
(*this)(error_code{}, 0, false); (*this)(error_code{}, 0, false);
} }

View File

@ -64,9 +64,8 @@ public:
template<class DeducedHandler, class... Args> template<class DeducedHandler, class... Args>
read_header_op( read_header_op(
DeducedHandler&& h, Stream& s, Args&&... args) DeducedHandler&& h, Stream& s, Args&&... args)
: d_(make_handler_ptr<data, Handler>( : d_(std::forward<DeducedHandler>(h),
std::forward<DeducedHandler>(h), s, s, std::forward<Args>(args)...)
std::forward<Args>(args)...))
{ {
(*this)(error_code{}, false); (*this)(error_code{}, false);
} }
@ -236,9 +235,8 @@ public:
template<class DeducedHandler, class... Args> template<class DeducedHandler, class... Args>
read_op(DeducedHandler&& h, Stream& s, Args&&... args) read_op(DeducedHandler&& h, Stream& s, Args&&... args)
: d_(make_handler_ptr<data, Handler>( : d_(std::forward<DeducedHandler>(h),
std::forward<DeducedHandler>(h), s, s, std::forward<Args>(args)...)
std::forward<Args>(args)...))
{ {
(*this)(error_code{}, false); (*this)(error_code{}, false);
} }

View File

@ -126,9 +126,8 @@ public:
template<class DeducedHandler, class... Args> template<class DeducedHandler, class... Args>
write_streambuf_op(DeducedHandler&& h, Stream& s, write_streambuf_op(DeducedHandler&& h, Stream& s,
Args&&... args) Args&&... args)
: d_(make_handler_ptr<data, Handler>( : d_(std::forward<DeducedHandler>(h),
std::forward<DeducedHandler>(h), s, std::forward<Args>(args)...)
s, std::forward<Args>(args)...))
{ {
(*this)(error_code{}, 0, false); (*this)(error_code{}, 0, false);
} }
@ -373,9 +372,8 @@ public:
template<class DeducedHandler, class... Args> template<class DeducedHandler, class... Args>
write_op(DeducedHandler&& h, Stream& s, Args&&... args) write_op(DeducedHandler&& h, Stream& s, Args&&... args)
: d_(make_handler_ptr<data, Handler>( : d_(std::forward<DeducedHandler>(h),
std::forward<DeducedHandler>(h), s, s, std::forward<Args>(args)...)
std::forward<Args>(args)...))
{ {
auto& d = *d_; auto& d = *d_;
auto sp = d_; auto sp = d_;

View File

@ -64,9 +64,8 @@ public:
template<class DeducedHandler, class... Args> template<class DeducedHandler, class... Args>
response_op(DeducedHandler&& h, response_op(DeducedHandler&& h,
stream<NextLayer>& ws, Args&&... args) stream<NextLayer>& ws, Args&&... args)
: d_(make_handler_ptr<data, Handler>( : d_(std::forward<DeducedHandler>(h),
std::forward<DeducedHandler>(h), ws, ws, std::forward<Args>(args)...)
std::forward<Args>(args)...))
{ {
(*this)(error_code{}, false); (*this)(error_code{}, false);
} }
@ -180,9 +179,8 @@ public:
template<class DeducedHandler, class... Args> template<class DeducedHandler, class... Args>
accept_op(DeducedHandler&& h, accept_op(DeducedHandler&& h,
stream<NextLayer>& ws, Args&&... args) stream<NextLayer>& ws, Args&&... args)
: d_(make_handler_ptr<data, Handler>( : d_(std::forward<DeducedHandler>(h),
std::forward<DeducedHandler>(h), ws, ws, std::forward<Args>(args)...)
std::forward<Args>(args)...))
{ {
(*this)(error_code{}, 0, false); (*this)(error_code{}, 0, false);
} }

View File

@ -56,9 +56,8 @@ public:
template<class DeducedHandler, class... Args> template<class DeducedHandler, class... Args>
close_op(DeducedHandler&& h, close_op(DeducedHandler&& h,
stream<NextLayer>& ws, Args&&... args) stream<NextLayer>& ws, Args&&... args)
: d_(make_handler_ptr<data, Handler>( : d_(std::forward<DeducedHandler>(h),
std::forward<DeducedHandler>(h), ws, ws, std::forward<Args>(args)...)
std::forward<Args>(args)...))
{ {
(*this)(error_code{}, false); (*this)(error_code{}, false);
} }

View File

@ -59,9 +59,8 @@ public:
template<class DeducedHandler, class... Args> template<class DeducedHandler, class... Args>
handshake_op(DeducedHandler&& h, handshake_op(DeducedHandler&& h,
stream<NextLayer>& ws, Args&&... args) stream<NextLayer>& ws, Args&&... args)
: d_(make_handler_ptr<data, Handler>( : d_(std::forward<DeducedHandler>(h),
std::forward<DeducedHandler>(h), ws, ws, std::forward<Args>(args)...)
std::forward<Args>(args)...))
{ {
(*this)(error_code{}, false); (*this)(error_code{}, false);
} }

View File

@ -55,9 +55,8 @@ public:
template<class DeducedHandler, class... Args> template<class DeducedHandler, class... Args>
ping_op(DeducedHandler&& h, ping_op(DeducedHandler&& h,
stream<NextLayer>& ws, Args&&... args) stream<NextLayer>& ws, Args&&... args)
: d_(make_handler_ptr<data, Handler>( : d_(std::forward<DeducedHandler>(h),
std::forward<DeducedHandler>(h), ws, ws, std::forward<Args>(args)...)
std::forward<Args>(args)...))
{ {
(*this)(error_code{}, false); (*this)(error_code{}, false);
} }

View File

@ -76,9 +76,8 @@ public:
template<class DeducedHandler, class... Args> template<class DeducedHandler, class... Args>
read_frame_op(DeducedHandler&& h, read_frame_op(DeducedHandler&& h,
stream<NextLayer>& ws, Args&&... args) stream<NextLayer>& ws, Args&&... args)
: d_(make_handler_ptr<data, Handler>( : d_(std::forward<DeducedHandler>(h),
std::forward<DeducedHandler>(h), ws, ws, std::forward<Args>(args)...)
std::forward<Args>(args)...))
{ {
(*this)(error_code{}, 0, false); (*this)(error_code{}, 0, false);
} }
@ -983,9 +982,8 @@ public:
template<class DeducedHandler, class... Args> template<class DeducedHandler, class... Args>
read_op(DeducedHandler&& h, read_op(DeducedHandler&& h,
stream<NextLayer>& ws, Args&&... args) stream<NextLayer>& ws, Args&&... args)
: d_(make_handler_ptr<data, Handler>( : d_(std::forward<DeducedHandler>(h),
std::forward<DeducedHandler>(h), ws, ws, std::forward<Args>(args)...)
std::forward<Args>(args)...))
{ {
(*this)(error_code{}, false); (*this)(error_code{}, false);
} }

View File

@ -59,9 +59,7 @@ public:
explicit explicit
teardown_ssl_op( teardown_ssl_op(
DeducedHandler&& h, stream_type& stream) DeducedHandler&& h, stream_type& stream)
: d_(make_handler_ptr<data, Handler>( : d_(std::forward<DeducedHandler>(h), stream)
std::forward<DeducedHandler>(
h), stream))
{ {
(*this)(error_code{}, false); (*this)(error_code{}, false);
} }

View File

@ -47,9 +47,7 @@ public:
teardown_tcp_op( teardown_tcp_op(
DeducedHandler&& h, DeducedHandler&& h,
socket_type& socket) socket_type& socket)
: d_(make_handler_ptr<data, Handler>( : d_(std::forward<DeducedHandler>(h), socket)
std::forward<DeducedHandler>(
h), socket))
{ {
(*this)(error_code{}, 0, false); (*this)(error_code{}, 0, false);
} }

View File

@ -67,9 +67,8 @@ public:
template<class DeducedHandler, class... Args> template<class DeducedHandler, class... Args>
write_frame_op(DeducedHandler&& h, write_frame_op(DeducedHandler&& h,
stream<NextLayer>& ws, Args&&... args) stream<NextLayer>& ws, Args&&... args)
: d_(make_handler_ptr<data, Handler>( : d_(std::forward<DeducedHandler>(h),
std::forward<DeducedHandler>(h), ws, std::forward<Args>(args)...)
ws, std::forward<Args>(args)...))
{ {
(*this)(error_code{}, 0, false); (*this)(error_code{}, 0, false);
} }
@ -782,9 +781,8 @@ public:
explicit explicit
write_op(DeducedHandler&& h, write_op(DeducedHandler&& h,
stream<NextLayer>& ws, Args&&... args) stream<NextLayer>& ws, Args&&... args)
: d_(make_handler_ptr<data, Handler>( : d_(std::forward<DeducedHandler>(h),
std::forward<DeducedHandler>(h), ws, ws, std::forward<Args>(args)...)
std::forward<Args>(args)...))
{ {
(*this)(error_code{}, false); (*this)(error_code{}, false);
} }