Use std::function and reference wrapper

This commit is contained in:
Vinnie Falco
2017-07-14 17:26:05 -07:00
parent 3c2d3181fc
commit 8fa8ecb502
3 changed files with 36 additions and 164 deletions

View File

@@ -1,5 +1,6 @@
* Documentation tidying * Documentation tidying
* is_invocable works with move-only types * is_invocable works with move-only types
* Use std::function and reference wrapper
WebSocket WebSocket

View File

@@ -14,16 +14,6 @@
namespace beast { namespace beast {
namespace http { namespace http {
template<bool isRequest, class Body, class Allocator>
parser<isRequest, Body, Allocator>::
~parser()
{
if(cb_h_)
cb_h_->~cb_h_t();
if(cb_b_)
cb_b_->~cb_b_t();
}
template<bool isRequest, class Body, class Allocator> template<bool isRequest, class Body, class Allocator>
parser<isRequest, Body, Allocator>:: parser<isRequest, Body, Allocator>::
parser() parser()
@@ -31,22 +21,6 @@ parser()
{ {
} }
template<bool isRequest, class Body, class Allocator>
parser<isRequest, Body, Allocator>::
parser(parser&& other)
: base_type(std::move(other))
, m_(other.m_)
, wr_(other.wr_)
, wr_inited_(other.wr_inited_)
{
if(other.cb_h_)
cb_h_ = other.cb_h_->move(
&cb_h_buf_);
if(other.cb_b_)
cb_b_ = other.cb_h_->move(
&cb_b_buf_);
}
template<bool isRequest, class Body, class Allocator> template<bool isRequest, class Body, class Allocator>
template<class Arg1, class... ArgN, class> template<class Arg1, class... ArgN, class>
parser<isRequest, Body, Allocator>:: parser<isRequest, Body, Allocator>::
@@ -71,42 +45,6 @@ parser(parser<isRequest, OtherBody, Allocator>&& other,
"moved-from parser has a body"}); "moved-from parser has a body"});
} }
template<bool isRequest, class Body, class Allocator>
template<class Callback>
void
parser<isRequest, Body, Allocator>::
on_chunk_header(Callback& cb)
{
// Callback may not be constant, caller is responsible for
// managing the lifetime of the callback. Copies are not made.
BOOST_STATIC_ASSERT(! std::is_const<Callback>::value);
// Can't set the callback after receiving any chunk data!
BOOST_ASSERT(! wr_inited_);
if(cb_h_)
cb_h_->~cb_h_t();
cb_h_ = new(&cb_h_buf_) cb_h_t_impl<Callback>(cb);
}
template<bool isRequest, class Body, class Allocator>
template<class Callback>
void
parser<isRequest, Body, Allocator>::
on_chunk_body(Callback& cb)
{
// Callback may not be constant, caller is responsible for
// managing the lifetime of the callback. Copies are not made.
BOOST_STATIC_ASSERT(! std::is_const<Callback>::value);
// Can't set the callback after receiving any chunk data!
BOOST_ASSERT(! wr_inited_);
if(cb_b_)
cb_b_->~cb_b_t();
cb_b_ = new(&cb_b_buf_) cb_b_t_impl<Callback>(cb);
}
} // http } // http
} // beast } // beast

View File

@@ -14,6 +14,7 @@
#include <beast/http/type_traits.hpp> #include <beast/http/type_traits.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <boost/throw_exception.hpp> #include <boost/throw_exception.hpp>
#include <functional>
#include <memory> #include <memory>
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
@@ -55,96 +56,6 @@ class parser
template<bool, class, class> template<bool, class, class>
friend class parser; friend class parser;
struct cb_h_exemplar
{
void
operator()(std::uint64_t, string_view, error_code&);
};
struct cb_h_t
{
virtual ~cb_h_t() = default;
virtual cb_h_t* move(void* dest) = 0;
virtual void operator()(
std::uint64_t size,
string_view extensions,
error_code& ec) = 0;
};
template<class Callback>
struct cb_h_t_impl : cb_h_t
{
Callback& cb_;
explicit
cb_h_t_impl(Callback& cb)
: cb_(cb)
{
}
cb_h_t*
move(void* dest) override
{
new(dest) cb_h_t_impl<
Callback>(std::move(*this));
return this;
}
void
operator()(
std::uint64_t size,
string_view extensions,
error_code& ec) override
{
cb_(size, extensions, ec);
}
};
struct cb_b_exemplar
{
std::size_t
operator()(std::uint64_t, string_view, error_code&);
};
struct cb_b_t
{
virtual ~cb_b_t() = default;
virtual cb_b_t* move(void* dest) = 0;
virtual std::size_t operator()(
std::uint64_t remain,
string_view body,
error_code& ec) = 0;
};
template<class Callback>
struct cb_b_t_impl : cb_b_t
{
Callback& cb_;
explicit
cb_b_t_impl(Callback& cb)
: cb_(cb)
{
}
cb_b_t*
move(void* dest) override
{
new(dest) cb_b_t_impl<
Callback>(std::move(*this));
return this;
}
std::size_t
operator()(
std::uint64_t remain,
string_view body,
error_code& ec) override
{
return cb_(remain, body, ec);
}
};
using base_type = basic_parser<isRequest, using base_type = basic_parser<isRequest,
parser<isRequest, Body, Allocator>>; parser<isRequest, Body, Allocator>>;
@@ -152,13 +63,15 @@ class parser
typename Body::writer wr_; typename Body::writer wr_;
bool wr_inited_ = false; bool wr_inited_ = false;
cb_h_t* cb_h_ = nullptr; std::function<void(
typename std::aligned_storage< std::uint64_t,
sizeof(cb_h_t_impl<cb_h_exemplar>)>::type cb_h_buf_; string_view,
error_code&)> cb_h_;
cb_b_t* cb_b_ = nullptr; std::function<std::size_t(
typename std::aligned_storage< std::uint64_t,
sizeof(cb_b_t_impl<cb_b_exemplar>)>::type cb_b_buf_; string_view,
error_code&)> cb_b_;
public: public:
/// The type of message returned by the parser /// The type of message returned by the parser
@@ -166,7 +79,7 @@ public:
message<isRequest, Body, basic_fields<Allocator>>; message<isRequest, Body, basic_fields<Allocator>>;
/// Destructor /// Destructor
~parser(); ~parser() = default;
/// Constructor /// Constructor
parser(); parser();
@@ -182,7 +95,7 @@ public:
After the move, the only valid operation After the move, the only valid operation
on the moved-from object is destruction. on the moved-from object is destruction.
*/ */
parser(parser&& other); parser(parser&& other) = default;
/** Constructor /** Constructor
@@ -324,7 +237,17 @@ public:
*/ */
template<class Callback> template<class Callback>
void void
on_chunk_header(Callback& cb); on_chunk_header(Callback& cb)
{
// Callback may not be constant, caller is responsible for
// managing the lifetime of the callback. Copies are not made.
BOOST_STATIC_ASSERT(! std::is_const<Callback>::value);
// Can't set the callback after receiving any chunk data!
BOOST_ASSERT(! wr_inited_);
cb_h_ = std::ref(cb);
}
/** Set a callback to be invoked on chunk body data /** Set a callback to be invoked on chunk body data
@@ -362,7 +285,17 @@ public:
*/ */
template<class Callback> template<class Callback>
void void
on_chunk_body(Callback& cb); on_chunk_body(Callback& cb)
{
// Callback may not be constant, caller is responsible for
// managing the lifetime of the callback. Copies are not made.
BOOST_STATIC_ASSERT(! std::is_const<Callback>::value);
// Can't set the callback after receiving any chunk data!
BOOST_ASSERT(! wr_inited_);
cb_b_ = std::ref(cb);
}
private: private:
friend class basic_parser<isRequest, parser>; friend class basic_parser<isRequest, parser>;
@@ -460,7 +393,7 @@ private:
error_code& ec) error_code& ec)
{ {
if(cb_h_) if(cb_h_)
return (*cb_h_)(size, extensions, ec); return cb_h_(size, extensions, ec);
ec.assign(0, ec.category()); ec.assign(0, ec.category());
} }
@@ -471,7 +404,7 @@ private:
error_code& ec) error_code& ec)
{ {
if(cb_b_) if(cb_b_)
return (*cb_b_)(remain, body, ec); return cb_b_(remain, body, ec);
return wr_.put(boost::asio::buffer( return wr_.put(boost::asio::buffer(
body.data(), body.size()), ec); body.data(), body.size()), ec);
} }