From 34116989f8326379845d152782fd67527a12ee15 Mon Sep 17 00:00:00 2001 From: Thomas Kemmer Date: Sun, 24 Feb 2019 17:56:33 +0100 Subject: [PATCH] Fix #20: Add lock template parameter. --- .travis.yml | 22 ---------- src/fsm.h | 92 ++++++++++++++++++++++++++-------------- tests/test_recursive.cpp | 18 +++----- 3 files changed, 66 insertions(+), 66 deletions(-) diff --git a/.travis.yml b/.travis.yml index 76636df..f806032 100644 --- a/.travis.yml +++ b/.travis.yml @@ -56,17 +56,6 @@ matrix: - MATRIX_EVAL="CC=gcc-8 CXX=g++-8" - CXXFLAGS=-std=c++17 - GCOV=gcov-8 - - os: linux - addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - g++-8 - env: - - MATRIX_EVAL="CC=gcc-8 CXX=g++-8" - - CXXFLAGS=-DNDEBUG - - GCOV=gcov-8 - os: linux addons: apt: @@ -96,17 +85,6 @@ matrix: - clang-7 env: - MATRIX_EVAL="CC=clang-7 CXX=clang++-7" - - os: linux - addons: - apt: - sources: - - ubuntu-toolchain-r-test - - llvm-toolchain-trusty-7 - packages: - - clang-7 - env: - - MATRIX_EVAL="CC=clang-7 CXX=clang++-7" - - CXXFLAGS=-DNDEBUG before_install: - pip install --user cpp-coveralls diff --git a/src/fsm.h b/src/fsm.h index 3c04f64..d43894b 100644 --- a/src/fsm.h +++ b/src/fsm.h @@ -62,6 +62,26 @@ namespace fsmlite { #else #error "fsmlite requires C++11 support." #endif + // C++11 std::lock_guard is in , which may not be + // present on freestanding implementations + template + class lock_guard { + BasicLockable& ref; + + public: + explicit lock_guard(BasicLockable& m) : ref(m) { + m.lock(); + } + + ~lock_guard() { + ref.unlock(); + } + + private: + lock_guard( const lock_guard& ) = delete; + lock_guard& operator=(const lock_guard&) = delete; + }; + // C++11 std::forward() is in , which may not be // present on freestanding implementations template @@ -174,15 +194,49 @@ namespace fsmlite { }; } +#if !__GNUC__ || __EXCEPTIONS + class logic_lock { + bool locked = false; + + public: + void lock() { + if (locked) { + throw std::logic_error("process_event called recursively"); + } + locked = true; + } + + void unlock() { + locked = false; + } + }; +#endif + + struct no_lock { + void lock() {} + void unlock() {} + }; + +#if !__GNUC__ || __EXCEPTIONS + using default_lock = logic_lock; +#else + using default_lock = no_lock; +#endif + /** * Finite state machine (FSM) base class template. * * @tparam Derived the derived state machine class * * @tparam State the FSM's state type, defaults to `int` + * + * @tparam Lock the FSM's lock type, defaults to `default_lock` */ - template + template class fsm { + State state; + Lock lock; + public: /** * The FSM's state type. @@ -195,7 +249,7 @@ namespace fsmlite { * * @param init_state the FSM's initial state */ - fsm(state_type init_state = state_type()) : m_state(init_state) {} + fsm(state_type init_state = state_type()) : state(init_state) {} /** * Process an event. @@ -213,16 +267,16 @@ namespace fsmlite { template void process_event(const Event& event) { using rows = typename by_event_type::type; - processing_lock lock(*this); static_assert(std::is_base_of::value, "must derive from fsm"); Derived& self = static_cast(*this); - m_state = handle_event::execute(self, event, m_state); + detail::lock_guard g(lock); + state = handle_event::execute(self, event, state); } /** * Return the state machine's current state. */ - state_type current_state() const { return m_state; } + state_type current_state() const { return state; } protected: /** @@ -240,7 +294,7 @@ namespace fsmlite { */ template state_type no_transition(const Event& event) { - return m_state; + return state; } private: @@ -417,32 +471,6 @@ namespace fsmlite { return self.no_transition(event); } }; - - private: - state_type m_state; - - private: -#if !defined(NDEBUG) && (!__GNUC__ || __EXCEPTIONS) - class processing_lock { - public: - processing_lock(fsm& m) : processing(m.processing) { - if (processing) { - throw std::logic_error("process_event called recursively"); - } - processing = true; - } - ~processing_lock() { - processing = false; - } - private: - bool& processing; - }; - bool processing = false; -#else - struct processing_lock { - processing_lock(fsm&) {} - }; -#endif }; } diff --git a/tests/test_recursive.cpp b/tests/test_recursive.cpp index a03fc70..47b00a6 100644 --- a/tests/test_recursive.cpp +++ b/tests/test_recursive.cpp @@ -1,4 +1,3 @@ -#include #include #include @@ -9,15 +8,11 @@ class state_machine: public fsmlite::fsm { public: enum states { Init, Exit }; + struct event {}; + private: - void process(const int& event) { - std::cout << "Processing event: " << event << "\n"; -#ifdef NDEBUG - if (event != 0) { - throw std::logic_error("recursive invocation detected"); - } -#endif - process_event(event + 1); + void process(const event& e) { + process_event(e); } private: @@ -26,7 +21,7 @@ class state_machine: public fsmlite::fsm { using transition_table = table< // Start Event Target Action // -----------+-----+------+------+-----------+- - mem_fn_row< Init, int, Exit, &m::process > + mem_fn_row< Init, event, Exit, &m::process > // -----------+-----+------+------+-----------+- >; }; @@ -35,9 +30,8 @@ int main() { state_machine m; try { - m.process_event(0); + m.process_event(state_machine::event{}); } catch (std::logic_error& e) { - std::cerr << e.what() << "\n"; return 0; } return 1; /* LCOV_EXCL_LINE */