-
Notifications
You must be signed in to change notification settings - Fork 0
/
callback.hpp
147 lines (134 loc) · 2.6 KB
/
callback.hpp
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
138
139
140
141
142
143
144
145
146
147
#ifndef CALLBACK_HPP_INCLUDED
#define CALLBACK_HPP_INCLUDED 1
#include <cstdint>
#include <cstring>
/**
* @brief コールバックID
*
* コールバック毎に与えられるIDで、特定のコールバックを示すために使う。
* 値は必ず0以外とする。0は無効なIDとする。
*/
typedef uint32_t CALLBACK_ID;
/**
* @brief コールバック
*
* @tparam F コールバック関数の型。引数の末尾には必ずvoid *があるものとする。
* @tparam N 登録可能なコールバックの数。
*/
template <class F, size_t N>
class Callback
{
public:
// コンストラクタ
Callback()
: id_(0)
{
memset(items_, 0, sizeof items_);
}
// 登録
CALLBACK_ID set(F func, void *arg)
{
Item *item = get_free_item();
if (item == NULL) {
return 0;
}
item->id = get_next_id();
item->entry = func;
item->arg = arg;
return item->id;
}
// 解除
void unset(const CALLBACK_ID id)
{
Item *item = find_item(id);
if (item != NULL) {
item->id = 0;
item->entry = NULL;
item->arg = NULL;
}
}
/**
* @brief 登録済みのコールバックを全て呼び出す
*/
void call() const
{
for (size_t i = 0; i < N; ++i) {
Item const *item = &items_[i];
if (item->id != 0) {
item->entry(item->arg);
}
}
}
void call()
{
for (size_t i = 0; i < N; ++i) {
Item *item = &items_[i];
if (item->id != 0) {
item->entry(item->arg);
}
}
}
/**
* @brief 登録済みのコールバックを全て呼び出す
*
* @param a0 一つ目の引数。
*/
template <class A0>
void call(A0 a0) const
{
for (size_t i = 0; i < N; ++i) {
Item const *item = &items_[i];
if (item->id != 0) {
item->entry(a0, item->arg);
}
}
}
template <class A0>
void call(A0 a0)
{
for (size_t i = 0; i < N; ++i) {
Item *item = &items_[i];
if (item->id != 0) {
item->entry(a0, item->arg);
}
}
}
private:
struct Item
{
CALLBACK_ID id;
F entry;
void *arg;
};
Item items_[N];
CALLBACK_ID id_;
Item *find_item(const CALLBACK_ID id)
{
for (size_t i = 0; i < N; ++i) {
Item *item = &items_[i];
if (item->id == id) {
return item;
}
}
return NULL;
}
Item *get_free_item()
{
for (size_t i = 0; i < N; ++i) {
Item *item = &items_[i];
if (item->id == 0) {
return item;
}
}
return NULL;
}
CALLBACK_ID get_next_id()
{
++id_;
if (id_ == 0) {
++id_;
}
return id_;
}
};
#endif // !defined(CALLBACK_HPP_INCLUDED)