• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

jharwell / rcppsw / 7670959353

26 Jan 2024 04:49PM UTC coverage: 89.072% (+0.3%) from 88.788%
7670959353

push

github

jharwell
refactor(#326): Add automatic log4cxx client logger name calculation

- Deduced from typeid()
- Ensures that the name of the logger for a class is ALWAYS the same as the
  fully qualified name, reducing refactoring errors. Principle of Least Surprise.

30 of 32 new or added lines in 8 files covered. (93.75%)

8 existing lines in 4 files now uncovered.

1296 of 1455 relevant lines covered (89.07%)

512.55 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

51.72
/src/patterns/state_machine/base_fsm.cpp
1
/**
2
 * \file base_fsm.cpp
3
 *
4
 * \copyright 2017 John Harwell, All rights reserved.
5
 *
6
 * SPDX-License-Identifier: MIT
7
 */
8

9
/*******************************************************************************
10
 * Includes
11
 ******************************************************************************/
12
#include "rcppsw/patterns/fsm/base_fsm.hpp"
13

14
#include <cassert>
15

16
/*******************************************************************************
17
 * Namespaces/Decls
18
 ******************************************************************************/
19
namespace rcppsw::patterns::fsm {
20

21
/*******************************************************************************
22
 * Constructors/Destructor
23
 ******************************************************************************/
24
base_fsm::base_fsm(uint8_t max_states, uint8_t initial_state)
48✔
25
    : ER_CLIENT_INIT(),
48✔
26
      mc_max_states(max_states),
48✔
27
      m_current_state(initial_state),
48✔
28
      m_initial_state(initial_state) {
72✔
29
  ER_ASSERT(mc_max_states < event_signal::ekIGNORED, "Too many states");
48✔
30
}
48✔
31

32
base_fsm::base_fsm(const base_fsm& other)
×
NEW
33
    : ER_CLIENT_INIT(),
×
34
      mc_max_states(other.mc_max_states),
×
35
      m_current_state(other.current_state()),
×
36
      m_next_state(other.next_state()),
×
37
      m_initial_state(other.current_state()),
×
38
      m_previous_state(other.previous_state()),
×
39
      m_last_state(other.last_state()) {
×
40
  ER_ASSERT(mc_max_states < event_signal::ekIGNORED, "Too many states");
×
41
}
×
42

43
base_fsm& base_fsm::operator=(const base_fsm& other) {
×
44
  m_current_state = other.m_current_state;
×
45
  m_next_state = other.m_next_state;
×
46
  m_initial_state = other.m_initial_state;
×
47
  m_previous_state = other.m_previous_state;
×
48
  m_last_state = other.m_last_state;
×
49
  return *this;
×
50
}
51

52
/*******************************************************************************
53
 * Member Functions
54
 ******************************************************************************/
55
void base_fsm::init(void) {
60✔
56
  m_event_generated = false;
60✔
57
  update_state(initial_state());
60✔
58
  next_state(initial_state());
60✔
59
  m_event_data.reset(nullptr);
60✔
60
} /* init() */
60✔
61

62
void base_fsm::external_event(uint8_t new_state,
120✔
63
                              std::unique_ptr<class event_data> data) {
64
  ER_TRACE("Received external event: new_state=%d data=%p",
240✔
65
           new_state,
66
           reinterpret_cast<const void*>(data.get()));
60✔
67

68
  ER_ASSERT(event_signal::ekFATAL != new_state,
120✔
69
            "Received FATAL event: current_state=%u",
70
            current_state());
60✔
71

72
  if (new_state == event_signal::ekIGNORED) {
120✔
73
    return;
12✔
74
  }
75
  /* We are not supposed to ignore this event */
76

77
  /*
78
   * Generate the event and execute the state engine. If data was passed in,
79
   * pass that along to the handler function.
80
   */
81
  internal_event(new_state, std::move(data));
96✔
82
  m_event_data_hold = false;
96✔
83
  state_engine();
96✔
84

85
  /*
86
   * Derived FSMs may want/need access to the same event data across multiple
87
   * invocations of the FSM, which might even span multiple states, so if the
88
   * derived FSM signals NOT to reset the event data, then hold onto it;
89
   * otherwise reset it after each invocation of state_engine().
90
   */
91
  if (!m_event_data_hold) {
96✔
92
    m_event_data.reset(nullptr);
132✔
93
  }
94
} /* external_event() */
95

96
void base_fsm::internal_event(uint8_t new_state,
120✔
97
                              std::unique_ptr<class event_data> data) {
98
  ER_TRACE("Generated internal event: current_state=%d new_state=%d data=%p",
240✔
99
           current_state(),
100
           new_state,
101
           reinterpret_cast<const void*>(data.get()));
60✔
102
  next_state(new_state);
120✔
103
  m_event_generated = true;
120✔
104
  if (m_event_data != data) {
120✔
105
    event_data(std::move(data));
60✔
106
  }
107
}
120✔
108

109
void base_fsm::state_engine(void) {
96✔
110
  const state_map_row* map = state_map(0);
96✔
111
  const state_map_ex_row* map_ex = state_map_ex(0);
96✔
112

113
  if (nullptr != map) {
96✔
114
    state_engine_map();
96✔
115
  } else if (nullptr != map_ex) {
×
116
    state_engine_map_ex();
×
117
  } else {
118
    ER_FATAL_SENTINEL("Both state maps are NULL!");
×
119
  }
120
} /* state_engine() */
96✔
121

122
void base_fsm::state_engine_map(void) {
96✔
123
  /* While events are being generated keep executing states */
124
  while (m_event_generated) {
216✔
125
    /* verity new state is valid */
126
    ER_ASSERT(next_state() < max_states(),
120✔
127
              "New state %u is out of range [0-%u]",
128
              next_state(),
129
              max_states() - 1);
60✔
130

131
    /* ready to update to new state */
132
    m_event_generated = false;
120✔
133
    update_state(next_state());
120✔
134
    const state_map_row* row = state_map(current_state());
120✔
135
    state_engine_step(row);
120✔
136
  } /* while() */
137
} /* state_engine_map() */
96✔
138

139
void base_fsm::state_engine_map_ex(void) {
×
140
  /*
141
   * While events are being generated keep executing states.
142
   */
143
  while (m_event_generated) {
×
144
    m_event_generated = false;
×
145
    /* verify new state is valid */
146
    ER_ASSERT(next_state() < max_states(),
×
147
              "New state %u is out of range [0-%u]",
148
              next_state(),
149
              max_states() - 1);
150
    const state_guard* guard = state_map_ex(next_state())->guard();
×
151
    const state_entry* entry = state_map_ex(next_state())->entry();
×
152
    const state_exit* exit = state_map_ex(current_state())->exit();
×
153

154
    /* execute guard condition */
155
    bool guard_res = true;
×
156
    if (nullptr != guard) {
×
157
      ER_TRACE("Executing guard condition for state %d", current_state());
×
158
      guard_res = guard->invoke_guard_condition(this, m_event_data.get());
×
159
    }
160

161
    if (!guard_res) {
×
162
      continue;
×
163
    }
164

165
    /* transitioning to a new state? */
166
    if (next_state() != current_state()) {
×
167
      /* execute state exit action before switching to new state */
168
      if (nullptr != exit) {
×
169
        ER_TRACE("Executing exit action for state %d", current_state());
×
170
        exit->invoke_exit_action(this);
×
171
      }
172

173
      /* execute state entry action on the new state */
174
      if (nullptr != entry) {
×
175
        ER_TRACE("Executing entry action for new state %d", next_state());
×
176
        entry->invoke_entry_action(this, m_event_data.get());
×
177
      }
178

179
      /* Ensure exit/entry actions didn't call interval_event() by accident */
180
      ER_ASSERT(!m_event_generated,
×
181
                "entry/exit actions called internal_event()!");
182
    }
183
    /* Now we're ready to switch to the new state */
184
    update_state(next_state());
×
185
    const state_map_ex_row* row = state_map_ex(current_state());
×
186
    state_engine_step(row);
×
187
  } /* while() */
188
} /* state_engine_map_ex() */
×
189

190
void base_fsm::state_engine_step(const state_map_row* const c_row) {
60✔
191
  ER_ASSERT(nullptr != c_row->state(), "null state?");
60✔
192
  ER_TRACE("Invoking state action: state%d, data=%p",
120✔
193
           current_state(),
194
           reinterpret_cast<const void*>(m_event_data.get()));
30✔
195
  c_row->state()->invoke_state_action(this, event_data());
60✔
196
} /* state_engine_step() */
60✔
197

198
void base_fsm::state_engine_step(const state_map_ex_row* const c_row_ex) {
×
199
  ER_ASSERT(nullptr != c_row_ex->state(), "null state?");
×
200
  ER_TRACE("Invoking state action: state%d, data=%p",
×
201
           current_state(),
202
           reinterpret_cast<const void*>(m_event_data.get()));
203
  c_row_ex->state()->invoke_state_action(this, event_data());
×
204
} /* state_engine_step() */
×
205

206
void base_fsm::update_state(uint8_t new_state) {
180✔
207
  if (new_state != m_current_state) {
180✔
208
    m_previous_state = m_current_state;
144✔
209
  }
210
  m_last_state = m_current_state;
180✔
211
  m_current_state = new_state;
180✔
212
} /* update_state() */
180✔
213

214
void base_fsm::inject_event(int signal, int type) {
×
215
  inject_event(std::make_unique<class event_data>(signal, type));
×
216
} /* inject event */
×
217

218
void base_fsm::inject_event(std::unique_ptr<class event_data> event) {
×
219
  external_event(current_state(), std::move(event));
×
220
} /* inject_event(std::unique_ptr<event_data> event)() */
×
221

222
} /* namespace rcppssw::patterns::fsm */
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc