-
Notifications
You must be signed in to change notification settings - Fork 0
/
action_buffer.h
91 lines (78 loc) · 1.63 KB
/
action_buffer.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
#pragma once
/**
* @brief A typedef that defines the function to be called on CActionBuffer::RunActions.
*
*/
typedef void(*ACTION)(void *data);
/**
* @brief A struct that defines an object to be passed to the CActionBuffer.
*
*/
struct Action_t
{
Action_t(ACTION a, void *d) : data(d), action(a) { };
/**
* @brief A pointer to the data to be passed when calling action.
*/
void *data;
/**
* @brief A function to be called.
*/
ACTION action;
};
template<class Q, class M>
class CActionBuffer
{
public:
CActionBuffer();
void RunActions();
void AddAction(const Action_t & action);
~CActionBuffer();
private:
M *m_pMutex;
Q *m_pQueue;
Q *m_pActions;
};
template<class Q, class M>
CActionBuffer<Q, M>::CActionBuffer()
{
m_pQueue = new Q();
m_pActions = new Q();
m_pMutex = new M();
}
template<class Q, class M>
void CActionBuffer<Q, M>::RunActions()
{
/* Now we process NextThinkCall hooks. It's okay if this check races. */
if (m_pQueue->size())
{
Q *temp;
/* Very quick lock to move m_pQueue/m_pActions back and forth */
m_pMutex->Lock();
temp = m_pQueue;
m_pQueue = m_pActions;
m_pActions = temp;
m_pMutex->Unlock();
/* The server will now be adding to the other queue, so we can process events. */
while (!m_pActions->empty())
{
Action_t &item = m_pActions->first();
m_pActions->pop();
item.action(item.data);
}
}
}
template<class Q, class M>
void CActionBuffer<Q, M>::AddAction(const Action_t & action)
{
m_pMutex->Lock();
m_pQueue->push(action);
m_pMutex->Unlock();
}
template<class Q, class M>
CActionBuffer<Q, M>::~CActionBuffer()
{
delete m_pQueue;
delete m_pActions;
delete m_pMutex;
}