-
Notifications
You must be signed in to change notification settings - Fork 0
/
xn-pending.cpp
101 lines (81 loc) · 2.46 KB
/
xn-pending.cpp
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
#include "xn.h"
/* Handling of the pending commands = sent commands with no response from the command station
* yes (e.g. resending data with no response etc.).
*/
namespace Xn {
void XpressNet::pending_ok() {
if (m_pending.empty()) {
log("Pending buffer underflow!", LogLevel::Warning);
return;
}
PendingItem pending = std::move(m_pending.front());
m_pending.pop_front();
if (nullptr != pending.callback_ok)
pending.callback_ok->func(this, pending.callback_ok->data);
if (!m_out.empty())
send_next_out();
}
void XpressNet::pending_err(bool _log) {
if (m_pending.empty()) {
log("Pending buffer underflow!", LogLevel::Warning);
return;
}
PendingItem pending = std::move(m_pending.front());
m_pending.pop_front();
if (_log)
log("Not responded to command: " + pending.cmd->msg(), LogLevel::Error);
if (nullptr != pending.callback_err)
pending.callback_err->func(this, pending.callback_err->data);
if (!m_out.empty())
send_next_out();
}
void XpressNet::pending_send() {
PendingItem pending = std::move(m_pending.front());
m_pending.pop_front();
// to_send guarantees us that conflict can never occur in pending buffer
// we just check conflict in out buffer
if (this->conflictWithOut(*(pending.cmd))) {
log("Not sending again, conflict: " + pending.cmd->msg(), LogLevel::Warning);
if (nullptr != pending.callback_err)
pending.callback_err->func(this, pending.callback_err->data);
if (!m_out.empty())
send_next_out();
return;
}
log("Sending again: " + pending.cmd->msg(), LogLevel::Warning);
try {
to_send(std::move(pending));
} catch (...) {}
}
void XpressNet::m_pending_timer_tick() {
if (!m_serialPort.isOpen()) {
while (!m_pending.empty())
pending_err();
}
if (m_pending.empty())
return;
if (m_pending.front().timeout < QDateTime::currentDateTime()) {
if (m_pending.front().no_sent >= _PENDING_SEND_MAX)
pending_err();
else
pending_send();
}
}
void XpressNet::pendingClear() {
size_t pending_size = m_pending.size();
for (size_t i = 0; i < pending_size; ++i)
pending_err(); // can add next items to pending!
}
bool XpressNet::conflictWithPending(const Cmd &cmd) const {
for (const PendingItem &pending : m_pending)
if (pending.cmd->conflict(cmd) || cmd.conflict(*(pending.cmd)))
return true;
return false;
}
bool XpressNet::conflictWithOut(const Cmd &cmd) const {
for (const PendingItem &out : m_out)
if (out.cmd->conflict(cmd) || cmd.conflict(*(out.cmd)))
return true;
return false;
}
} // namespace Xn