-
Notifications
You must be signed in to change notification settings - Fork 196
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chore(state-machine): Panic in the case of non-handled non-deferred e… #1464
base: feature-c++-client
Are you sure you want to change the base?
Changes from all commits
72bcf04
1548f54
000e106
d21b262
9cad8e7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -156,24 +156,24 @@ class StateMachineRunner : virtual public EventPoster<EventType> { | |
} | ||
|
||
private: | ||
void RunOne() { | ||
vector<State<ContextType, EventType> *> to_run; | ||
vector<State<ContextType, EventType> *> FillRunQueueFrom(queue<EventType> &event_queue) { | ||
vector<State<ContextType, EventType> *> run_queue; | ||
|
||
for (auto machine : machines_) { | ||
if (!machine->state_entered_) { | ||
to_run.push_back(machine->current_state_); | ||
run_queue.push_back(machine->current_state_); | ||
machine->state_entered_ = true; | ||
} | ||
} | ||
|
||
const size_t size = event_queue_.size(); | ||
const size_t size = event_queue.size(); | ||
|
||
for (size_t count = 0; to_run.empty() && count < size; count++) { | ||
for (size_t count = 0; run_queue.empty() && count < size; count++) { | ||
bool deferred = false; | ||
auto event = event_queue_.front(); | ||
event_queue_.pop(); | ||
auto event = event_queue.front(); | ||
event_queue.pop(); | ||
|
||
for (auto machine : machines_) { | ||
for (const auto machine : machines_) { | ||
typename StateMachine<ContextType, EventType>::TransitionCondition cond { | ||
machine->current_state_, event}; | ||
if (machine->deferred_events_.find(event) != machine->deferred_events_.end()) { | ||
|
@@ -187,16 +187,16 @@ class StateMachineRunner : virtual public EventPoster<EventType> { | |
} | ||
|
||
auto &target = match->second; | ||
to_run.push_back(target); | ||
run_queue.push_back(target); | ||
machine->current_state_ = target; | ||
} | ||
|
||
if (to_run.empty()) { | ||
if (run_queue.empty()) { | ||
if (deferred) { | ||
// Put back in the queue to try later. This won't be tried | ||
// again during this run, due to only making `size` | ||
// attempts in the for loop. | ||
event_queue_.push(event); | ||
event_queue.push(event); | ||
} else { | ||
string states = common::BestAvailableTypeName(*machines_[0]->current_state_); | ||
for (size_t i = 1; i < machines_.size(); i++) { | ||
|
@@ -212,8 +212,32 @@ class StateMachineRunner : virtual public EventPoster<EventType> { | |
} | ||
} | ||
|
||
if (!to_run.empty()) { | ||
for (auto &state : to_run) { | ||
return run_queue; | ||
} | ||
|
||
|
||
void FailIfNonDeferredEventsLeftInEventQueue(queue<EventType> queue_copy) { | ||
// Check if there are any non-deferred events in the queue - then fail if | ||
while (not queue_copy.empty()) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's expected to have non-deferred events here, because this is after the handlers have run. I think the check needs to be between the There is also a much easier way to check this. When we are doing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh! Very good idea! I had a suspicion you would come up with something smarter than me here 😆 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alright, new try. I am still using my original approach, but moved it to before we run the machine loop. Ur approach, although clever, did not work when initializing (since we add the start events to the to_run queue, and I didn't feel like special casing it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can be easily fixed too. Just keep a counter for the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. True, I did dabble with the idea. But decided it's not really better. This implementation reads pretty straight forward, and does not have to touch the other pieces of code, and handle special cases. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Copying the queue should just be a couple of elements There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok then, I'll let it go! 🙂 |
||
EventType event = queue_copy.front(); | ||
queue_copy.pop(); | ||
for (const auto machine : machines_) { | ||
if (machine->deferred_events_.find(event) == machine->deferred_events_.end()) { | ||
log::Fatal( | ||
"The state machine has an unprocessed non-deferred event in the queue. This is a programming error!"); | ||
} | ||
} | ||
} | ||
} | ||
|
||
|
||
void RunOne() { | ||
vector<State<ContextType, EventType> *> run_queue = FillRunQueueFrom(event_queue_); | ||
|
||
FailIfNonDeferredEventsLeftInEventQueue(event_queue_); | ||
|
||
if (!run_queue.empty()) { | ||
for (auto &state : run_queue) { | ||
log::Trace("Entering state " + common::BestAvailableTypeName(*state)); | ||
state->OnEnter(ctx_, *this); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.get()
should only be used when it's required to, here it can be omitted.