Created
July 19, 2017 16:13
-
-
Save vinniefalco/93c098eb3048ab8dcef95ac5d1951f59 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Copyright (c) 2013-2017 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) | |
// | |
#ifndef BEAST_BIND_DETAIL_HANDLER_HPP | |
#define BEAST_BIND_DETAIL_HANDLER_HPP | |
#include <beast/core/detail/integer_sequence.hpp> | |
#include <boost/asio/handler_alloc_hook.hpp> | |
#include <boost/asio/handler_continuation_hook.hpp> | |
#include <boost/asio/handler_invoke_hook.hpp> | |
#include <functional> | |
#include <utility> | |
namespace beast { | |
namespace detail { | |
/* Nullary handler that calls Handler with bound arguments. | |
The bound handler provides the same io_service execution | |
guarantees as the original handler. | |
*/ | |
template<class Handler, class... Args> | |
class bound_handler | |
{ | |
private: | |
using args_type = std::tuple< | |
typename std::decay<Args>::type...>; | |
Handler h_; | |
args_type args_; | |
template<class Arg, class Vals> | |
static | |
typename std::enable_if< | |
! std::is_placeholder<typename | |
std::decay<Arg>::type>::value, | |
Arg&&>::type | |
extract(Arg&& arg, Vals& vals) | |
{ | |
return arg; | |
} | |
template<class Arg, class Vals> | |
static | |
typename std::enable_if< | |
std::is_placeholder<typename | |
std::decay<Arg>::type>::value, | |
typename std::tuple_element< | |
std::is_placeholder< | |
typename std::decay<Arg>::type>::value - 1, | |
Vals>::type>::type | |
extract(Arg&&, Vals& vals) | |
{ | |
return std::get<std::is_placeholder< | |
typename std::decay<Arg>::type>::value - 1>(vals); | |
} | |
template< | |
class ArgsTuple, | |
std::size_t... S> | |
static | |
void | |
invoke( | |
Handler& h, | |
ArgsTuple& args, | |
std::tuple<>&&, | |
index_sequence<S...>) | |
{ | |
h(std::get<S>(args)...); | |
} | |
template< | |
class ArgsTuple, | |
class ValsTuple, | |
std::size_t... S> | |
static | |
void | |
invoke( | |
Handler& h, | |
ArgsTuple& args, | |
ValsTuple&& vals, | |
index_sequence<S...>) | |
{ | |
h(extract(std::get<S>(args), vals)...); | |
} | |
public: | |
using result_type = void; | |
template<class DeducedHandler> | |
explicit | |
bound_handler( | |
DeducedHandler&& handler, Args&&... args) | |
: h_(std::forward<DeducedHandler>(handler)) | |
, args_(std::forward<Args>(args)...) | |
{ | |
} | |
template<class... Values> | |
void | |
operator()(Values&&... values) | |
{ | |
invoke(h_, args_, | |
std::forward_as_tuple( | |
std::forward<Values>(values)...), | |
index_sequence_for<Args...>()); | |
} | |
template<class... Values> | |
void | |
operator()(Values&&... values) const | |
{ | |
invoke(h_, args_, | |
std::forward_as_tuple( | |
std::forward<Values>(values)...), | |
index_sequence_for<Args...>()); | |
} | |
friend | |
void* | |
asio_handler_allocate( | |
std::size_t size, bound_handler* h) | |
{ | |
using boost::asio::asio_handler_allocate; | |
return asio_handler_allocate( | |
size, std::addressof(h->h_)); | |
} | |
friend | |
void | |
asio_handler_deallocate( | |
void* p, std::size_t size, bound_handler* h) | |
{ | |
using boost::asio::asio_handler_deallocate; | |
asio_handler_deallocate( | |
p, size, std::addressof(h->h_)); | |
} | |
friend | |
bool | |
asio_handler_is_continuation(bound_handler* h) | |
{ | |
using boost::asio::asio_handler_is_continuation; | |
return asio_handler_is_continuation(std::addressof(h->h_)); | |
} | |
template<class F> | |
friend | |
void | |
asio_handler_invoke(F&& f, bound_handler* h) | |
{ | |
using boost::asio::asio_handler_invoke; | |
asio_handler_invoke( | |
f, std::addressof(h->h_)); | |
} | |
}; | |
} // detail | |
} // beast | |
#include <functional> | |
namespace std { | |
template<class Handler, class... Args> | |
void | |
bind(beast::detail::bound_handler< | |
Handler, Args...>, ...) = delete; | |
} // std | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment