Git Product home page Git Product logo

hfsm's People

Contributors

andrew-gresyk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

hfsm's Issues

Exception handling from react() methods

Question:

Is there a best-practice for indicating that a certain action is not allowed?

My intuition is to throw an exception from the react() method if that action is not allowed for a particular state. Will that cause problems?

Question about substitute() method

When is the substitute() method called on a State implementation?

From reading through the tests, it looks like it's called on a state before
enter() on the new state, and before leave() is called on the previous state.

Is that always the case? Just want to make sure I understand that correctly.

When would one typically want to implement that method?

Thanks!

Compile Error with Logging Enabled

#include <new>

#define HFSM_ENABLE_LOG_INTERFACE
#include "machine_single.hpp"

struct Logger : hfsm::LoggerInterface {
  void record(const std::type_index&, const char* const stateName, const Method,
              const char* const methodName) override {}
};

struct Context {};

using M = hfsm::Machine<Context>;

struct TestEvent {};

struct TestState : M::Base {
  void react(const TestEvent&, Control&, Context&) {}

  using M::Base::react;
};

using FsmNtag = M::PeerRoot<TestState>;

int main(int argc, char const* argv[]) {
  Context context;
  Logger logger;

  FsmNtag machine(context, &logger);
  machine.react(TestEvent{});

  return 0;
}
>clang++ -std=c++14 .\bug.cpp
In file included from .\bug.cpp:4:
./machine_single.hpp:2127:49: error: use 'template' keyword to treat 'react' as a dependent template name
        HFSM_IF_LOGGER(if (logger) log<decltype(&Head::react<TEvent>), LoggerInterface::Method::React>(*logger));
                                                       ^
                                                       template
./machine_single.hpp:912:31: note: expanded from macro 'HFSM_IF_LOGGER'
        #define HFSM_IF_LOGGER(...)             __VA_ARGS__
                                                ^
1 error generated.

wideForwardRequest fails to build in release mode

/home/kevin/a17/pkg/linux/include/hfsm/machine.inl: In member function ‘void hfsm::M<TContext, TMaxSubstitutions>::_O< <template-parameter-2-1>, <template-parameter-2-2> >::Sub<TN, TI>::wideForwardRequest(unsigned int, enum hfsm::M<TContext, TMaxSubstitutions>::Transition::Type)’:
/home/kevin/a17/pkg/linux/include/hfsm/machine.inl:1146:6: error: ‘prong’ was not declared in this scope
  if (prong == ProngIndex)

Can't use it on the x86 platform

I cant' compile codes of example well by vs 17 on the windows 10.
These are some error information as following.

main.cpp
1>d:\myfile\hfsm-master\include\hfsm\detail\wrap.hpp(49): error C2338:
1>d:\myfile\hfsm-master\include\hfsm\detail\type_info.hpp(14): note: 参见对正在编译的 类 模板 实例化 "hfsm::detail::Wrapstd::type_index" 的引用
1>streetlight.cpp
1>d:\myfile\hfsm-master\include\hfsm\detail\wrap.hpp(49): error C2338:
1>d:\myfile\hfsm-master\include\hfsm\detail\type_info.hpp(14): note: 参见对正在编译的 类 模板 实例化 "hfsm::detail::Wrapstd::type_index" 的引用
1>正在生成代码...
1>已完成生成项目“HFSM-vs.vcxproj”的操作 - 失败。

assert failure when running tests

Reproduced on Ubuntu 16.04 and 17.10.

To reproduce:

$ mkdir build && cd build
$ cmake ..
$ make
$ ./hfsm_test 
hfsm_test: ../test/../hfsm/machine.inl:1671: void hfsm::M<TContext, TMaxSubstitutions>::_R< <template-parameter-2-1> >::requestScheduled(hfsm::M<TContext, TMaxSubstitutions>::Transition) [with TApex = hfsm::M<Context, 4>::_C<hfsm::M<Context, 4>::_B<hfsm::M<Context, 4>::Bare>, hfsm::M<Context, 4>::_C<A, A_1, hfsm::M<Context, 4>::_C<A_2, A_2_1, A_2_2> >, hfsm::M<Context, 4>::_O<B, hfsm::M<Context, 4>::_C<B_1, B_1_1, B_1_2>, hfsm::M<Context, 4>::_C<B_2, B_2_1, B_2_2> > >; TContext = Context; unsigned int TMaxSubstitutions = 4]: Assertion `!forksFork.activeType' failed.
Aborted (core dumped)

Backtrace from gdb:

#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1  0x00007ffff7490f5d in __GI_abort () at abort.c:90
#2  0x00007ffff7486f17 in __assert_fail_base (fmt=<optimized out>, 
    assertion=assertion@entry=0x555555590ae9 "!forksFork.activeType", 
    file=file@entry=0x5555555909db "../test/../hfsm/machine.inl", line=line@entry=1671, 
    function=function@entry=0x555555595720 <hfsm::M<Context, 4u>::_R<hfsm::M<Context, 4u>::_C<hfsm::M<Context, 4u>::_B<hfsm::M<Context, 4u>::Bare>, hfsm::M<Context, 4u>::_C<A, A_1, hfsm::M<Context, 4u>::_C<A_2, A_2_1, A_2_2> >, hfsm::M<Context, 4u>::_O<B, hfsm::M<Context, 4u>::_C<B_1, B_1_1, B_1_2>, hfsm::M<Context, 4u>::_C<B_2, B_2_1, B_2_2> > > >::requestScheduled(hfsm::M<Context, 4u>::Transition)::__PRETTY_FUNCTION__> "void hfsm::M<TContext, TMaxSubstitutions>::_R< <template-parameter-2-1> >::requestScheduled(hfsm::M<TContext, TMaxSubstitutions>::Transition) [with TApex = hfsm::M<Context, 4>::_C<hfsm::M<Context, 4>:"...) at assert.c:92
#3  0x00007ffff7486fc2 in __GI___assert_fail (assertion=0x555555590ae9 "!forksFork.activeType", 
    file=0x5555555909db "../test/../hfsm/machine.inl", line=1671, 
    function=0x555555595720 <hfsm::M<Context, 4u>::_R<hfsm::M<Context, 4u>::_C<hfsm::M<Context, 4u>::_B<hfsm::M<Context, 4u>::Bare>, hfsm::M<Context, 4u>::_C<A, A_1, hfsm::M<Context, 4u>::_C<A_2, A_2_1, A_2_2> >, hfsm::M<Context, 4u>::_O<B, hfsm::M<Context, 4u>::_C<B_1, B_1_1, B_1_2>, hfsm::M<Context, 4u>::_C<B_2, B_2_1, B_2_2> > > >::requestScheduled(hfsm::M<Context, 4u>::Transition)::__PRETTY_FUNCTION__> "void hfsm::M<TContext, TMaxSubstitutions>::_R< <template-parameter-2-1> >::requestScheduled(hfsm::M<TContext, TMaxSubstitutions>::Transition) [with TApex = hfsm::M<Context, 4>::_C<hfsm::M<Context, 4>:"...) at assert.c:101
#4  0x00005555555807c5 in hfsm::M<Context, 4u>::_R<hfsm::M<Context, 4u>::_C<hfsm::M<Context, 4u>::_B<hfsm::M<Context, 4u>::Bare>, hfsm::M<Context, 4u>::_C<A, A_1, hfsm::M<Context, 4u>::_C<A_2, A_2_1, A_2_2> >, hfsm::M<Context, 4u>::_O<B, hfsm::M<Context, 4u>::_C<B_1, B_1_1, B_1_2>, hfsm::M<Context, 4u>::_C<B_2, B_2_1, B_2_2> > > >::requestScheduled (
    this=0x7fffffffd580, request=...) at ../test/../hfsm/machine.inl:1671
#5  0x000055555557fa45 in hfsm::M<Context, 4u>::_R<hfsm::M<Context, 4u>::_C<hfsm::M<Context, 4u>::_B<hfsm::M<Context, 4u>::Bare>, hfsm::M<Context, 4u>::_C<A, A_1, hfsm::M<Context, 4u>::_C<A_2, A_2_1, A_2_2> >, hfsm::M<Context, 4u>::_O<B, hfsm::M<Context, 4u>::_C<B_1, B_1_1, B_1_2>, hfsm::M<Context, 4u>::_C<B_2, B_2_1, B_2_2> > > >::processRequests (
    this=0x7fffffffd580) at ../test/../hfsm/machine.inl:1571
#6  0x000055555557cdfe in hfsm::M<Context, 4u>::_R<hfsm::M<Context, 4u>::_C<hfsm::M<Context, 4u>::_B<hfsm::M<Context, 4u>::Bare>, hfsm::M<Context, 4u>::_C<A, A_1, hfsm::M<Context, 4u>::_C<A_2, A_2_1, A_2_2> >, hfsm::M<Context, 4u>::_O<B, hfsm::M<Context, 4u>::_C<B_1, B_1_1, B_1_2>, hfsm::M<Context, 4u>::_C<B_2, B_2_1, B_2_2> > > >::update (
    this=0x7fffffffd580) at ../test/../hfsm/machine.inl:1536
#7  0x000055555557ad9a in main () at ../test/main.cpp:533

More Complete Examples

I ran across your library and talks, but I'm still having a hard time connecting the dots. It would be nice if some of the examples from your talks were available as more fully worked examples... and some docs might be nice. ;-)

More Documentation

Is there any documentation beyond that in the README.md?

  1. It's not clear to me what is the intended API surface area for a non-advanced state machine usage.
  2. It's not clear to me what exactly is intended with the substitute() method.
  3. You kinda introduce the concept of a timed state in your April 2017 presentation and in the test/main.cpp without any built-in support or introductory documentation how to extend states properly. This would be helped by a more-fully worked player character example via issue #11, of course... but I wonder if perhaps some of those extensions are worth providing in the library.

Single-File Release version of header?

It would be nice if there was a "pre-compiled" version of the library into a single header file (with license included at the top). This would enable playing around with examples of using the library in an online sandbox (other than compiler explorer, which I see can include HFSM). Wandbox lets you create as many headers as you like, but building the complete set for HFSM would be tedious. It does include some header-only libs, but not yet HFSM, and that's not a general solution for the many other useful online sandboxes. The current many-file version is good for maintenance and implementation-hiding, but prohibits these other uses.

In short, could you make an example like this wandbox session "just work"?

FYI, it seems that the ned14/pcpp project is intended for this use case, and one example usage can be found here.

Support passing action data to States

I often need to transition from state A to state B in response to an action. You do this by implementing the react() method on state A for the given action. However, often the information in the action is needed by state B. Currently, the way to accomplish this is to pass the data to state B is to set a member variable in the Context object.

struct SaveAction {
  std::string file_to_save;
}

struct IdleState : M::Bare {
  void react(const SaveAction &action, M::Control &control, Context &context) {
    context.file_to_save = action.file_to_save;
    control.changeTo<SavingState>();
  }
}

struct SavingState : M::Bare {
  void enter(Context &context) {
    // It would be nice to have a better way of accessing file_to_save.
    saveFile(context.file_to_save);
  }
}

This works, but I'm finding that I have a lot of these member variables in my Context that are specific to one state transitioning to another. It would be nice if my IdleState above had some way of passing the file_to_save (or the SaveAction) to the SavingState.

Is there a better way for me to handle this situation? Perhaps I could think differently about how the states are structured?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.