mirror of
https://github.com/boostorg/msm.git
synced 2026-07-21 13:23:45 +00:00
fix(back, back11): event deferral in orthogonal regions
This commit is contained in:
committed by
Christian Granzin
parent
ebd17cc9f9
commit
cac5d8d657
@@ -20,6 +20,7 @@
|
||||
** The deprecated APIs `process_queued_events()` and `process_single_queued_event()` are removed, use `process_event_pool(...)` instead
|
||||
** The default active state switch policy is set to "after source exit" in compliance to the UML specification. The other options are not UML-compliant and will be removed (https://github.com/boostorg/msm/issues/222[#222])
|
||||
** The back-end uses its own `process_result` type with new enum values instead of aliasing the enum of the `back` namespace. The old enum values are deprecated (https://github.com/boostorg/msm/issues/242[#242]) and will be removed
|
||||
* fix(back, back11): Infinite recursion with event deferral in orthogonal regions (regression from 1.78) (https://github.com/boostorg/msm/issues/184[#184])
|
||||
|
||||
== Boost 1.91
|
||||
|
||||
|
||||
@@ -1983,7 +1983,7 @@ public:
|
||||
deferred_fct next = pair.first;
|
||||
m_events_queue.m_deferred_events_queue.pop_front();
|
||||
boost::msm::back::execute_return res = next();
|
||||
if (res != ::boost::msm::back::HANDLED_FALSE && res != ::boost::msm::back::HANDLED_DEFERRED)
|
||||
if (res != ::boost::msm::back::HANDLED_FALSE && !(res & ::boost::msm::back::HANDLED_DEFERRED))
|
||||
{
|
||||
not_only_deferred = true;
|
||||
}
|
||||
|
||||
@@ -2010,7 +2010,7 @@ protected: // interface for the derived class
|
||||
deferred_fct next = pair.first;
|
||||
m_events_queue.m_deferred_events_queue.pop_front();
|
||||
boost::msm::back::execute_return res = next();
|
||||
if (res != ::boost::msm::back::HANDLED_FALSE && res != ::boost::msm::back::HANDLED_DEFERRED)
|
||||
if (res != ::boost::msm::back::HANDLED_FALSE && !(res & ::boost::msm::back::HANDLED_DEFERRED))
|
||||
{
|
||||
not_only_deferred = true;
|
||||
}
|
||||
|
||||
+2
-1
@@ -34,9 +34,10 @@ add_executable(boost_msm_tests
|
||||
History.cpp
|
||||
KleeneDeferred.cpp
|
||||
ManyDeferTransitions.cpp
|
||||
OrthogonalDeferred.cpp
|
||||
OrthogonalDeferred2.cpp
|
||||
OrthogonalDeferred3.cpp
|
||||
OrthogonalDeferred.cpp
|
||||
OrthogonalDeferred4.cpp
|
||||
Serialize.cpp
|
||||
SerializeWithHistory.cpp
|
||||
SetStates.cpp
|
||||
|
||||
@@ -49,6 +49,7 @@ test-suite msm-unit-tests
|
||||
[ run OrthogonalDeferred.cpp ]
|
||||
[ run OrthogonalDeferred2.cpp ]
|
||||
[ run OrthogonalDeferred3.cpp ]
|
||||
[ run OrthogonalDeferred4.cpp ]
|
||||
# MSVC 32-bit runs out of memory when compiling this test
|
||||
[ run OrthogonalDeferredEuml.cpp : : : <toolset>msvc-14.3,<address-model>32:<build>no ]
|
||||
# GCC has a bug in std::type_info::before() that leads to a segfault.
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
// Copyright 2010 Christophe Henry
|
||||
// henry UNDERSCORE christophe AT hotmail DOT com
|
||||
// This is an extended version of the state machine available in the boost::mpl library
|
||||
// Distributed under the same license as the original.
|
||||
// Copyright for the original version:
|
||||
// Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed
|
||||
// under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_MSM_NONSTANDALONE_TEST
|
||||
#define BOOST_TEST_MODULE orthogonal_deferred4_test
|
||||
#endif
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
// back-end
|
||||
#include "BackCommon.hpp"
|
||||
//front-end
|
||||
#include "FrontCommon.hpp"
|
||||
|
||||
namespace mpl = boost::mpl;
|
||||
using namespace boost::msm::front;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// Events
|
||||
struct Ping {};
|
||||
|
||||
// Actions
|
||||
struct Action
|
||||
{
|
||||
template <typename Event, typename Fsm, typename Source, typename Target>
|
||||
void operator()(const Event&, Fsm& fsm, Source&, Target&)
|
||||
{
|
||||
fsm.action_counter++;
|
||||
}
|
||||
};
|
||||
|
||||
// Guards
|
||||
struct Conditional
|
||||
{
|
||||
template <typename Event, typename Fsm, typename Source, typename Target>
|
||||
bool operator()(const Event&, Fsm& fsm, Source&, Target&)
|
||||
{
|
||||
return fsm.conditional;
|
||||
}
|
||||
};
|
||||
|
||||
struct Machine_ : test::StateMachineBase_<Machine_>
|
||||
{
|
||||
typedef int activate_deferred_events;
|
||||
|
||||
struct Deferring : state<> {};
|
||||
struct Acting : state<> {};
|
||||
|
||||
// Two orthogonal regions
|
||||
typedef mpl::vector<Deferring, Acting> initial_state;
|
||||
|
||||
using transition_table = mpl::vector<
|
||||
// Source Event Target Action Guard
|
||||
Row< Deferring, Ping, none, Defer , none>, // region 1: defer
|
||||
Row< Acting , Ping, none, Action, Conditional> // region 2: handle conditionally
|
||||
>;
|
||||
|
||||
size_t action_counter{};
|
||||
bool conditional{};
|
||||
};
|
||||
|
||||
using TestMachines = get_test_machines<Machine_>;
|
||||
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE(guard_reject_test, test_machine, TestMachines)
|
||||
{
|
||||
test_machine sm;
|
||||
sm.start();
|
||||
|
||||
sm.process_event(Ping{});
|
||||
BOOST_REQUIRE(sm.action_counter == 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE_TEMPLATE(handle_discard_test, TestMachine, TestMachines)
|
||||
{
|
||||
TestMachine sm;
|
||||
sm.conditional = true;
|
||||
sm.start();
|
||||
|
||||
sm.process_event(Ping{});
|
||||
// Action called one times too many in old-backends
|
||||
// (though behavior exists since 1.78).
|
||||
size_t expected_action_counter = 2;
|
||||
#ifndef BOOST_MSM_TEST_SKIP_BACKMP11
|
||||
if (boost::msm::backmp11::is_backmp11_state_machine<TestMachine>::value)
|
||||
{
|
||||
expected_action_counter = 1;
|
||||
}
|
||||
#endif
|
||||
BOOST_REQUIRE(sm.action_counter == expected_action_counter);
|
||||
}
|
||||
|
||||
} // nmespace
|
||||
Reference in New Issue
Block a user