blob: dd9b2a3d8827486789f0e3e992602b11cf57e4ec (
plain)
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
|
#pragma once
#include <functional>
#include <map>
namespace socket {
/* Allows casting R(Args...) */
template <typename T>
class Socket;
/* A class that represents a socket that can
be used to dispatch a function call to different
handlers. Handlers can be connected and disconnected
from the socket at runtime. */
template <typename R, typename... Args>
class Socket<R(Args...)> {
/* The type of handler function or methods */
using HandlerType = std::function<R(Args...)>;
/* The next handler descriptor to be assigned
the descriptor can be used to disconnect
a descriptor */
int descriptor;
/* Map between descriptors and handlers */
std::map<int, HandlerType> handlers;
public:
/* Connect a handler to the socket
handler: the handler to connect to
Returns the handler descriptor */
int connect(HandlerType handler) {
// Get the handler descriptor of next handler
int hd = descriptor++;
// Store the handler
handlers[hd] = handler;
return hd;
}
/* Connect a handler to the socket
and bind the call to an object, this
can be useful if the handler is a method */
template <typename T, typename V>
int connect(T *object, R (V::*handler)(Args...)) {
auto f = [=](Args... args) {
return std::invoke(handler, object, args...);
};
return connect(f);
}
/* Disconnect a handler from the socket
hd: the handle descriptor of the handler
to disconnect */
void disconnect(int hd) {
// Remove the handler from the map
handlers.erase(hd);
}
/* Dispatch a call to all handlers */
void operator()(Args... args) {
for (auto &handler : handlers)
handler.second(args...);
}
};
}
|