21 Eylül 2017 Perşembe

statechart

Giriş
Boost içinde iki tane Finite State Machine ile ilgili kütüphane var.
1. Boost Statechart Library
2. Boost Meta State Machine

Derleme
Debug derlemek için RTII desteği gerekir. Açıklaması şöyle
C++ RTTI must be turned on (used by various asserts)
Kütüphane debug derlendiğini NDEBUG ile anlar.

asynchronous_state_machine Sınıfı
Giriş
Şu satırı dahil ederiz.
#include <boost/statechart/asynchronous_state_machine.hpp>
Tanımlama
Şöyle yaparız.
struct state_one;

struct the_fsm : public sc::asynchronous_state_machine<the_fsm, state_one>
{
  explicit the_fsm(my_context ctx) : my_base(ctx) {}
};

state_machine Sınıfı
Giriş
Şu satırı dahil ederiz.
#include <boost/statechart/state_machine.hpp>
Kolay kullanım için şu satırı dahil ederiz.
namespace sc = boost::statechart;
Tanımlama
state_machine template sınıfına geçiline birince parametre kalıtan sınıfın kendisidir. Yani CRTP örüntüsü kullanılır. İkinci parametre ise başlangıç state'ini belirtir.

Örnek
Şöyle yaparız.
struct stInit ;  //Forward declaration

struct state_machine : sc::state_machine< state_machine, stInit > {};
Örnek
4 state'li bir sınıf için şöyle yaparız.
// states
struct A;
struct B;
struct C;
struct D;

// fsm
struct FSM : boost::statechart::state_machine<FSM, B> {};
Constructor
Şöyle yaparız.
Machine fsm;
initiate metodu
Şöyle yaparız. İlk state'e gir anlamına gelir.
sm.initiate();
process_event metodu

Tanımlanan event'lerden birisini girdi olarak sağlar.
Örnek
Şöyle yaparız.
sm.process_event(E2());
Örnek
Şöyle yaparız.
// states
struct A;
struct B;
struct C;
struct D;

// events
struct S : boost::statechart::event<S> {};
struct T : boost::statechart::event<T> {};
struct U : boost::statechart::event<U> {};

// fsm
struct FSM : boost::statechart::state_machine<FSM, B> {};
...
FSM fsm;

fsm.initiate();

fsm.process_event(S());
fsm.process_event(T());
fsm.process_event(S());
fsm.process_event(U());
state_cast metodu
Şöyle yaparız.
const ComponentType &t = fsm.template state_cast<const ComponentType &>();
simple_state Sınıfı
Giriş
Şu satırı dahil ederiz.
#include <boost/statechart/simple_state.hpp>
Tanımlama
Birin parametre state'in kendisi yani CRTP örüntüsü, ikinci parametre state machine sınıfının sınıfıdır.

Örnek - transition olarak reactions
E2 olayı olursa S3'e geçiş için şöyle yaparız.
struct S2 : sc::simple_state<S2, statemachine> {
  typedef sc::transition<E2, S3> reactions;
};
Örnek - custom_reaction olarak reactions
Şu satırı dahil ederiz.
#include <boost/statechart/transition.hpp>
#include <boost/statechart/custom_reaction.hpp>
Şöyle yaparız.
struct state_one : boost::statechart::simple_state<state_one, the_fsm> {
  using reactions = boost::statechart::custom_reaction<event_two>;
  boost::statechart::result react(const event_two &);
};
react olayını kodlama şöyle yaparız.
boost::statechart::result state_one::react(const event_two &) {
  ...
  return transit<state_two>();
}
Örnek
Bitirmek için şöyle yaparız.
struct S4 : sc::simple_state<S4, statemachine> {
};
Örnek - mp::list tipinden reactions
Şu satırı dahil ederiz.
#include <boost/mpl/list.hpp>
mpl::list'in ilk parametresi event, ikinci parametresi ise yeni state'in ismidir.

mpl::list'e kendi react metodumuzu sağlamak istersek şöyle yaparız.
struct C : boost::statechart::simple_state<C, FSM> {
    typedef boost::mpl::list<
                boost::statechart::custom_reaction<T>,
                boost::statechart::transition<U, D> > reactions;

  C() { std::cout << "entered C" << std::endl; }

  boost::statechart::result react(const T&) {

    switch(outermost_context().previous_state) {

      case state_mapping::A:
        return transit<A>();
      case state_mapping::B:
        return  transit<B>();
      default:
        return discard_event();

    }

  }
};
asenkron state machine kullanıyorsak olayları saklamak için şu satırı dahil ederiz. Olay bir geçişe sebep olmuyorsa kuyrukta bekletilir.
#include <boost/statechart/deferral.hpp>
Şöyle yaparız.
struct S1 : sc::simple_state<S1, statemachine> {
    typedef mpl::list<
        sc::transition< E1, S2 >,
        sc::deferral< E2 >,
        sc::deferral< E3 >
    > reactions;

};
Örnek
Çoklu kalıtım istersek şöyle yaparız.
class ComponentType
{
};

struct stInit : ComponentType, sc::simple_state< stInit, statemachine >  {};
event Sınıfı
Giriş
Şu satırı dahil ederiz.
#include <boost/statechart/event.hpp>
Tanımlama
event sınıfı bir template parametresi alır, yani CRTP kullanır.
Örnek
Şöyle yaparız.
// Events
struct E1 : sc::event<E1> {};
struct E2 : sc::event<E2> {};
struct E3 : sc::event<E3> {};
Örnek
Şöyle yaparız.
struct event_one : sc::event<event_one> {};
struct event_two : sc::event<event_two> {};
struct event_three : sc::event<event_three> {};
Örnek
Şöyle yaparız.
// events
struct S : boost::statechart::event<S> {};
struct T : boost::statechart::event<T> {};
struct U : boost::statechart::event<U> {};


Hiç yorum yok:

Yorum Gönder