1#include "channel_load.hpp"
2#include "fully_meshed_state_machine.hpp"
14static constexpr std::size_t N_samples_up = std::chrono::seconds(1) / NDL_minDccSampling;
15static constexpr std::size_t N_samples_down = std::chrono::seconds(5) / NDL_minDccSampling;
17static constexpr double NDL_minChannelLoad = 0.19;
18static constexpr double NDL_maxChannelLoad = 0.59;
20Clock::duration Relaxed::transmission_interval()
const
22 return std::chrono::milliseconds(60);
25const char* Relaxed::name()
const
30Clock::duration Restrictive::transmission_interval()
const
32 return std::chrono::milliseconds(460);
35const char* Restrictive::name()
const
40const std::size_t Active::sc_substates = 5;
42Active::Active() : m_substate(0)
46void Active::update(
double min_cl,
double max_cl)
48 assert(min_cl <= max_cl);
50 static const std::array<double, sc_substates> channel_loads {{
51 0.27, 0.35, 0.43, 0.51, 0.59
54 auto state_up_it = std::upper_bound(channel_loads.begin(), channel_loads.end(), min_cl);
55 auto state_up = std::distance(channel_loads.begin(), state_up_it);
57 auto state_down_it = std::upper_bound(channel_loads.begin(), channel_loads.end(), max_cl);
58 auto state_down = std::distance(channel_loads.begin(), state_down_it);
60 m_substate = std::max(state_up, state_down);
61 m_substate = std::min(sc_substates - 1, m_substate);
62 assert(m_substate < sc_substates);
65Clock::duration Active::transmission_interval()
const
67 static const std::array<Clock::duration, sc_substates> tx_intervals {{
68 std::chrono::milliseconds(100),
69 std::chrono::milliseconds(180),
70 std::chrono::milliseconds(260),
71 std::chrono::milliseconds(340),
72 std::chrono::milliseconds(420),
75 const std::size_t index = std::min(tx_intervals.size() - 1, m_substate);
76 return tx_intervals[index];
79const char* Active::name()
const
81 static const std::array<const char*, sc_substates> names {{
89 assert(m_substate < sc_substates);
90 return names[m_substate];
93FullyMeshedStateMachine::FullyMeshedStateMachine() :
95 m_channel_loads(
std::max(N_samples_up, N_samples_down))
99FullyMeshedStateMachine::~FullyMeshedStateMachine()
105 m_channel_loads.push_front(cl);
107 if (m_state == &m_relaxed) {
108 if (min_channel_load() >= NDL_minChannelLoad) {
110 m_active.update(min_channel_load(), max_channel_load());
112 }
else if (m_state == &m_restrictive) {
113 if (max_channel_load() < NDL_maxChannelLoad) {
115 m_active.update(min_channel_load(), max_channel_load());
118 if (max_channel_load() < NDL_minChannelLoad) {
119 m_state = &m_relaxed;
120 }
else if (min_channel_load() >= NDL_maxChannelLoad) {
121 m_state = &m_restrictive;
124 m_active.update(min_channel_load(), max_channel_load());
129double FullyMeshedStateMachine::message_rate()
const
131 std::chrono::duration<double> one_sec = std::chrono::seconds(1);
132 return one_sec / transmission_interval();
135Clock::duration FullyMeshedStateMachine::transmission_interval()
const
137 return m_state->transmission_interval();
140const State& FullyMeshedStateMachine::state()
const
142 assert(m_state !=
nullptr);
146double FullyMeshedStateMachine::min_channel_load()
const
148 assert(N_samples_up > 0);
149 double min_cl = std::numeric_limits<double>::infinity();
150 std::size_t sample_cnt = 0;
151 for (
auto sample : m_channel_loads) {
152 if (sample_cnt >= N_samples_up) {
154 }
else if (sample.value() < min_cl) {
155 min_cl = sample.value();
160 return std::isinf(min_cl) ? 0.0 : min_cl;
163double FullyMeshedStateMachine::max_channel_load()
const
165 assert(N_samples_down > 0);
167 std::size_t sample_cnt = 0;
168 for (
auto sample : m_channel_loads) {
169 if (sample_cnt >= N_samples_down) {
171 }
else if (sample.value() > max_cl) {
172 max_cl = sample.value();