-
-
Notifications
You must be signed in to change notification settings - Fork 212
/
Copy pathdispatcher.h
137 lines (108 loc) · 4.8 KB
/
dispatcher.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#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 Unbind a functor with a given name from callable functors.
void unbind(std::string const &name) {
funcs_.erase(name);
}
//! \brief returns a list of all names which functors are binded to
std::vector<std::string> names() const {
std::vector<std::string> names;
for(auto it = funcs_.begin(); it != funcs_.end(); ++it)
names.push_back(it->first);
return names;
}
//! @}
//! \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 */