2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-09-03 23:45:27 +00:00

[#1095] Made state model code thread safe

This commit is contained in:
Francis Dupont
2020-03-28 15:58:55 +01:00
committed by Razvan Becheriu
parent de0bafbfed
commit 4c7746d5cf
2 changed files with 24 additions and 5 deletions

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2013-2018 Internet Systems Consortium, Inc. ("ISC") // Copyright (C) 2013-2020 Internet Systems Consortium, Inc. ("ISC")
// //
// This Source Code Form is subject to the terms of the Mozilla Public // This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -91,7 +91,7 @@ StateModel::StateModel() : events_(), states_(), dictionaries_initted_(false),
curr_state_(NEW_ST), prev_state_(NEW_ST), curr_state_(NEW_ST), prev_state_(NEW_ST),
last_event_(NOP_EVT), next_event_(NOP_EVT), last_event_(NOP_EVT), next_event_(NOP_EVT),
on_entry_flag_(false), on_exit_flag_(false), on_entry_flag_(false), on_exit_flag_(false),
paused_(false) { paused_(false), mutex_(new std::mutex) {
} }
StateModel::~StateModel(){ StateModel::~StateModel(){
@@ -279,6 +279,7 @@ StateModel::abortModel(const std::string& explanation) {
void void
StateModel::setState(unsigned int state) { StateModel::setState(unsigned int state) {
std::lock_guard<std::mutex> lock(*mutex_);
if (state != END_ST && !states_.isDefined(state)) { if (state != END_ST && !states_.isDefined(state)) {
isc_throw(StateModelError, isc_throw(StateModelError,
"Attempt to set state to an undefined value: " << state ); "Attempt to set state to an undefined value: " << state );
@@ -309,6 +310,7 @@ StateModel::postNextEvent(unsigned int event_value) {
"Attempt to post an undefined event, value: " << event_value); "Attempt to post an undefined event, value: " << event_value);
} }
std::lock_guard<std::mutex> lock(*mutex_);
last_event_ = next_event_; last_event_ = next_event_;
next_event_ = event_value; next_event_ = event_value;
} }
@@ -329,50 +331,61 @@ StateModel::doOnExit() {
unsigned int unsigned int
StateModel::getCurrState() const { StateModel::getCurrState() const {
std::lock_guard<std::mutex> lock(*mutex_);
return (curr_state_); return (curr_state_);
} }
unsigned int unsigned int
StateModel::getPrevState() const { StateModel::getPrevState() const {
std::lock_guard<std::mutex> lock(*mutex_);
return (prev_state_); return (prev_state_);
} }
unsigned int unsigned int
StateModel::getLastEvent() const { StateModel::getLastEvent() const {
std::lock_guard<std::mutex> lock(*mutex_);
return (last_event_); return (last_event_);
} }
unsigned int unsigned int
StateModel::getNextEvent() const { StateModel::getNextEvent() const {
std::lock_guard<std::mutex> lock(*mutex_);
return (next_event_); return (next_event_);
} }
bool bool
StateModel::isModelNew() const { StateModel::isModelNew() const {
std::lock_guard<std::mutex> lock(*mutex_);
return (curr_state_ == NEW_ST); return (curr_state_ == NEW_ST);
} }
bool bool
StateModel::isModelRunning() const { StateModel::isModelRunning() const {
std::lock_guard<std::mutex> lock(*mutex_);
return ((curr_state_ != NEW_ST) && (curr_state_ != END_ST)); return ((curr_state_ != NEW_ST) && (curr_state_ != END_ST));
} }
bool bool
StateModel::isModelWaiting() const { StateModel::isModelWaiting() const {
return (isModelRunning() && (next_event_ == NOP_EVT)); std::lock_guard<std::mutex> lock(*mutex_);
return ((curr_state_ != NEW_ST) && (curr_state_ != END_ST) &&
(next_event_ == NOP_EVT));
} }
bool bool
StateModel::isModelDone() const { StateModel::isModelDone() const {
std::lock_guard<std::mutex> lock(*mutex_);
return (curr_state_ == END_ST); return (curr_state_ == END_ST);
} }
bool bool
StateModel::didModelFail() const { StateModel::didModelFail() const {
return (isModelDone() && (next_event_ == FAIL_EVT)); std::lock_guard<std::mutex> lock(*mutex_);
return ((curr_state_ == END_ST) && (next_event_ == FAIL_EVT));
} }
bool bool
StateModel::isModelPaused() const { StateModel::isModelPaused() const {
std::lock_guard<std::mutex> lock(*mutex_);
return (paused_); return (paused_);
} }
@@ -388,6 +401,7 @@ StateModel::getEventLabel(const int event) const {
std::string std::string
StateModel::getContextStr() const { StateModel::getContextStr() const {
std::lock_guard<std::mutex> lock(*mutex_);
std::ostringstream stream; std::ostringstream stream;
stream << "current state: [ " stream << "current state: [ "
<< curr_state_ << " " << getStateLabel(curr_state_) << curr_state_ << " " << getStateLabel(curr_state_)
@@ -398,6 +412,7 @@ StateModel::getContextStr() const {
std::string std::string
StateModel::getPrevContextStr() const { StateModel::getPrevContextStr() const {
std::lock_guard<std::mutex> lock(*mutex_);
std::ostringstream stream; std::ostringstream stream;
stream << "previous state: [ " stream << "previous state: [ "
<< prev_state_ << " " << getStateLabel(prev_state_) << prev_state_ << " " << getStateLabel(prev_state_)

View File

@@ -1,4 +1,4 @@
// Copyright (C) 2013-2018 Internet Systems Consortium, Inc. ("ISC") // Copyright (C) 2013-2020 Internet Systems Consortium, Inc. ("ISC")
// //
// This Source Code Form is subject to the terms of the Mozilla Public // This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -14,6 +14,7 @@
#include <boost/function.hpp> #include <boost/function.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <map> #include <map>
#include <mutex>
#include <string> #include <string>
namespace isc { namespace isc {
@@ -721,6 +722,9 @@ private:
/// @brief Indicates if the state model is paused. /// @brief Indicates if the state model is paused.
bool paused_; bool paused_;
/// @brief Protects against concurrent transitions.
boost::shared_ptr<std::mutex> mutex_;
}; };
/// @brief Defines a pointer to a StateModel. /// @brief Defines a pointer to a StateModel.