125 lines
4.4 KiB
C
125 lines
4.4 KiB
C
|
#pragma once
|
||
|
|
||
|
#ifndef DISPATCHER_H_CXIVZD5L
|
||
|
#define DISPATCHER_H_CXIVZD5L
|
||
|
|
||
|
#include <atomic>
|
||
|
#include <functional>
|
||
|
#include <memory>
|
||
|
#include <unordered_map>
|
||
|
|
||
|
#include "rpc/config.h"
|
||
|
#include "rpc/msgpack.hpp"
|
||
|
|
||
|
#include "rpc/detail/call.h"
|
||
|
#include "rpc/detail/func_tools.h"
|
||
|
#include "rpc/detail/func_traits.h"
|
||
|
#include "rpc/detail/log.h"
|
||
|
#include "rpc/detail/not.h"
|
||
|
#include "rpc/detail/response.h"
|
||
|
#include "rpc/detail/make_unique.h"
|
||
|
|
||
|
namespace rpc {
|
||
|
|
||
|
namespace detail {
|
||
|
|
||
|
//! \brief This class maintains a registry of functors associated with their
|
||
|
//! names, and callable using a msgpack-rpc call pack.
|
||
|
class dispatcher {
|
||
|
public:
|
||
|
//! \brief Binds a functor to a name so it becomes callable via RPC.
|
||
|
//! \param name The name of the functor.
|
||
|
//! \param func The functor to bind.
|
||
|
//! \tparam F The type of the functor.
|
||
|
template <typename F> void bind(std::string const &name, F func);
|
||
|
|
||
|
//! \defgroup Tag-dispatched bind implementations for various functor cases.
|
||
|
//! @{
|
||
|
|
||
|
//! \brief Stores a void, zero-arg functor with a name.
|
||
|
template <typename F>
|
||
|
void bind(std::string const &name, F func,
|
||
|
detail::tags::void_result const &,
|
||
|
detail::tags::zero_arg const &);
|
||
|
|
||
|
//! \brief Stores a void, non-zero-arg functor with a name.
|
||
|
template <typename F>
|
||
|
void bind(std::string const &name, F func,
|
||
|
detail::tags::void_result const &,
|
||
|
detail::tags::nonzero_arg const &);
|
||
|
|
||
|
//! \brief Stores a non-void, zero-arg functor with a name.
|
||
|
template <typename F>
|
||
|
void bind(std::string const &name, F func,
|
||
|
detail::tags::nonvoid_result const &,
|
||
|
detail::tags::zero_arg const &);
|
||
|
|
||
|
//! \brief Stores a non-void, non-zero-arg functor with a name.
|
||
|
template <typename F>
|
||
|
void bind(std::string const &name, F func,
|
||
|
detail::tags::nonvoid_result const &,
|
||
|
detail::tags::nonzero_arg const &);
|
||
|
|
||
|
//! @}
|
||
|
|
||
|
//! \brief Processes a message that contains a call according to
|
||
|
//! the Msgpack-RPC spec.
|
||
|
//! \param msg The buffer that contains the messagepack.
|
||
|
//! \throws std::runtime_error If the messagepack does not contain a
|
||
|
//! a call or the types of the parameters are not convertible to the called
|
||
|
//! functions' parameters.
|
||
|
void dispatch(RPCLIB_MSGPACK::sbuffer const &msg);
|
||
|
|
||
|
//! \brief Processes a message that contains a call according to
|
||
|
//! the Msgpack-RPC spec.
|
||
|
//! \param msg The messagepack object that contains the call.
|
||
|
//! \param suppress_exceptions If true, exceptions will be caught and
|
||
|
//! written
|
||
|
//! as response for the client.
|
||
|
//! \throws std::runtime_error If the types of the parameters are not
|
||
|
//! convertible to the called functions' parameters.
|
||
|
detail::response dispatch(RPCLIB_MSGPACK::object const &msg,
|
||
|
bool suppress_exceptions = false);
|
||
|
|
||
|
//! \brief This functor type unifies the interfaces of functions that are
|
||
|
//! called remotely
|
||
|
using adaptor_type = std::function<std::unique_ptr<RPCLIB_MSGPACK::object_handle>(
|
||
|
RPCLIB_MSGPACK::object const &)>;
|
||
|
|
||
|
//! \brief This is the type of messages as per the msgpack-rpc spec.
|
||
|
using call_t = std::tuple<int8_t, uint32_t, std::string, RPCLIB_MSGPACK::object>;
|
||
|
|
||
|
//! \brief This is the type of notification messages.
|
||
|
using notification_t = std::tuple<int8_t, std::string, RPCLIB_MSGPACK::object>;
|
||
|
|
||
|
private:
|
||
|
//! \brief Checks the argument count and throws an exception if
|
||
|
//! it is not the expected amount.
|
||
|
static void enforce_arg_count(std::string const &func, std::size_t found,
|
||
|
std::size_t expected);
|
||
|
|
||
|
void enforce_unique_name(std::string const &func);
|
||
|
|
||
|
//! \brief Dispatches a call (which will have a response).
|
||
|
detail::response dispatch_call(RPCLIB_MSGPACK::object const &msg,
|
||
|
bool suppress_exceptions = false);
|
||
|
|
||
|
//! \brief Dispatches a notification (which will not have a response)
|
||
|
detail::response dispatch_notification(RPCLIB_MSGPACK::object const &msg,
|
||
|
bool suppress_exceptions = false);
|
||
|
|
||
|
template <typename T> RPCLIB_MSGPACK::object pack(T &&arg);
|
||
|
|
||
|
enum class request_type { call = 0, notification = 2 };
|
||
|
|
||
|
private:
|
||
|
std::unordered_map<std::string, adaptor_type> funcs_;
|
||
|
RPCLIB_CREATE_LOG_CHANNEL(dispatcher)
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#include "dispatcher.inl"
|
||
|
|
||
|
#endif /* end of include guard: DISPATCHER_H_CXIVZD5L */
|