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
API Changes:
* Better handler_ptr
--------------------------------------------------------------------------------
1.0.0-b24

View File

@ -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

View File

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

View File

@ -11,23 +11,25 @@
#include <beast/core/detail/type_traits.hpp>
#include <atomic>
#include <cstdint>
#include <type_traits>
#include <utility>
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 T, class Handler>
class handler_ptr
@ -60,10 +66,10 @@ class handler_ptr
P* p_;
template<class DeducedHandler, class... Args>
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>(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
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<class... Args>
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<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

View File

@ -45,9 +45,8 @@ public:
template<class DeducedHandler, class... Args>
read_some_op(DeducedHandler&& h,
dynabuf_readstream& srs, Args&&... args)
: d_(make_handler_ptr<data, Handler>(
std::forward<DeducedHandler>(h), srs,
std::forward<Args>(args)...))
: d_(std::forward<DeducedHandler>(h),
srs, std::forward<Args>(args)...)
{
(*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>
handler_ptr<T, Handler>::
~handler_ptr()
@ -82,6 +73,27 @@ handler_ptr(handler_ptr const& other)
++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>
auto
handler_ptr<T, Handler>::
@ -112,27 +124,6 @@ invoke(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
#endif

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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