/usr/include/boost/beast/websocket/detail
Edit: /usr/include/boost/beast/websocket/detail/decorator.hpp (6711B)
//
// 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_DECORATOR_HPP
#define BOOST_BEAST_WEBSOCKET_DETAIL_DECORATOR_HPP
#include
#include
#include
#include
#include
#include
#include
#include
namespace boost {
namespace beast {
namespace websocket {
namespace detail {
// VFALCO NOTE: When this is two traits, one for
// request and one for response,
// Visual Studio 2015 fails.
template
struct can_invoke_with : std::false_type
{
};
template
struct can_invoke_with()(std::declval()))>>
: std::true_type
{
};
template
using is_decorator = std::integral_constant::value ||
can_invoke_with::value>;
class decorator
{
friend class decorator_test;
struct incomplete;
struct exemplar
{
void (incomplete::*mf)();
std::shared_ptr sp;
void* param;
};
union storage
{
void* p_;
void (*fn_)();
typename std::aligned_storage<
sizeof(exemplar),
alignof(exemplar)>::type buf_;
};
struct vtable
{
void (*move)(
storage& dst, storage& src) noexcept;
void (*destroy)(storage& dst) noexcept;
void (*invoke_req)(
storage& dst, request_type& req);
void (*invoke_res)(
storage& dst, response_type& req);
static void move_fn(
storage&, storage&) noexcept
{
}
static void destroy_fn(
storage&) noexcept
{
}
static void invoke_req_fn(
storage&, request_type&)
{
}
static void invoke_res_fn(
storage&, response_type&)
{
}
static vtable const* get_default()
{
static const vtable impl{
&move_fn,
&destroy_fn,
&invoke_req_fn,
&invoke_res_fn
};
return &impl;
}
};
template::value)>
struct vtable_impl;
storage storage_;
vtable const* vtable_ = vtable::get_default();
// VFALCO NOTE: When this is two traits, one for
// request and one for response,
// Visual Studio 2015 fails.
template
struct maybe_invoke
{
void
operator()(T&, U&)
{
}
};
template
struct maybe_invoke()(std::declval()))>>
{
void
operator()(T& t, U& u)
{
t(u);
}
};
public:
decorator() = default;
decorator(decorator const&) = delete;
decorator& operator=(decorator const&) = delete;
~decorator()
{
vtable_->destroy(storage_);
}
decorator(decorator&& other) noexcept
: vtable_(boost::exchange(
other.vtable_, vtable::get_default()))
{
vtable_->move(
storage_, other.storage_);
}
template::value>::type>
explicit
decorator(F&& f)
: vtable_(vtable_impl<
typename std::decay::type>::
construct(storage_, std::forward(f)))
{
}
decorator&
operator=(decorator&& other) noexcept
{
vtable_->destroy(storage_);
vtable_ = boost::exchange(
other.vtable_, vtable::get_default());
vtable_->move(storage_, other.storage_);
return *this;
}
void
operator()(request_type& req)
{
vtable_->invoke_req(storage_, req);
}
void
operator()(response_type& res)
{
vtable_->invoke_res(storage_, res);
}
};
template
struct decorator::vtable_impl
{
template
static
vtable const*
construct(storage& dst, Arg&& arg)
{
::new (static_cast(&dst.buf_)) F(
std::forward(arg));
return get();
}
static
void
move(storage& dst, storage& src) noexcept
{
auto& f = *beast::detail::launder_cast(&src.buf_);
::new (&dst.buf_) F(std::move(f));
}
static
void
destroy(storage& dst) noexcept
{
beast::detail::launder_cast(&dst.buf_)->~F();
}
static
void
invoke_req(storage& dst, request_type& req)
{
maybe_invoke{}(
*beast::detail::launder_cast(&dst.buf_), req);
}
static
void
invoke_res(storage& dst, response_type& res)
{
maybe_invoke{}(
*beast::detail::launder_cast(&dst.buf_), res);
}
static
vtable
const* get()
{
static constexpr vtable impl{
&move,
&destroy,
&invoke_req,
&invoke_res};
return &impl;
}
};
template
struct decorator::vtable_impl
{
template
static
vtable const*
construct(storage& dst, Arg&& arg)
{
dst.p_ = new F(std::forward(arg));
return get();
}
static
void
move(storage& dst, storage& src) noexcept
{
dst.p_ = src.p_;
}
static
void
destroy(storage& dst) noexcept
{
delete static_cast(dst.p_);
}
static
void
invoke_req(
storage& dst, request_type& req)
{
maybe_invoke{}(
*static_cast(dst.p_), req);
}
static
void
invoke_res(
storage& dst, response_type& res)
{
maybe_invoke{}(
*static_cast(dst.p_), res);
}
static
vtable const*
get()
{
static constexpr vtable impl{&move,
&destroy, &invoke_req, &invoke_res};
return &impl;
}
};
} // detail
} // websocket
} // beast
} // boost
#endif