Boost 상태 기 - 중급 편

28108 단어 상태 기boost
원문http://www.cs.washington.edu/research/projects/uns/F9/src/boost_1_37_0/libs/statechart/doc/tutorial.html
원문 은 Camera 를 예 로 들 어 Boost 상태 기 모델 의 사용 방법 을 설명 했다.그리고 본문의 주요 내용 은:
  • 원문의 Camera 모델 을 약간 수정 하고 보완 한다.
  • 전체 코드 를 썼 습 니 다.컴 파일 가능 실행;
  • 각 대상 (이벤트 대상 과 상태 대상) 의 생명 주 기 를 보 여 줍 니 다.
  • 더욱 뚜렷 한 모듈 화 각 구성 요소 (사건, 상태);그래서 간단 한 코드 프레임 워 크 로 사용 할 수 있 습 니 다.

  • 또한 중급 topics 만 포함 되 어 있 으 며, 고급 내용 에 대해 서 는 추 후 다시 쓰 겠 습 니 다.
    Camera 버튼:
  • 설정 키 (설정 버튼): 이 키 를 누 르 면 EvConfig 이벤트 가 발생 합 니 다. EvConfig 이 벤트 는 빈 상태 (Idle) 와 설정 상태 (Configuring) 사 이 를 전환 하 는 데 사 용 됩 니 다.
  • 셔터 키 (Shutter Button): 반 쯤 누 를 수 있 습 니 다 (반 시간 에 EvShutter Half 사건 이 발생 합 니 다). 모두 누 를 수 있 습 니 다 (모두 시간 에 EvShutter Full 사건 이 발생 합 니 다). 그리고 방출 (방출 시 EvShutter Release 사건 이 발생 합 니 다).

  • Camera 상태:
    모듈 화 (서로 다른 모듈 간 의 느슨 한 결합, 서로 다른 team 이 동시에 개발 할 수 있 음) 를 높이 기 위해 카 메 라 를 두 개의 큰 상태 로 나 누 었 습 니 다.
  • 비 촬영 상태 (NotShooting): 두 개의 키 상태, 남 은 상태 (Idle) 와 설정 상태 (Configuring) 를 포함 합 니 다.EvConfig 이 벤트 는 둘 사이 의 전환 에 사 용 됩 니 다.
  • 촬영 상태 (촬영):      초점 상태 (Focusing), 초점 상태 (Focused) 와 사진 저장 상태 (Storing) 를 포함 합 니 다.

  • Camera 작업 과정:
  • 카메라 의 초기 상 태 는 NotShooting 이 고 NotShooting 의 초기 상 태 는 Idle 이기 때문에 카메라 가 시 작 될 때 자동 으로 Idle 상태 로 들 어 갑 니 다.
  • Idle 상태 일 때 사용자 가 Config 단추 (EvConfig 이벤트 발생) 를 누 르 면 카메라 가 설정 상태 (Configuring) 에 들 어 갑 니 다.반대로 Configuring 상태 일 때 사용자 가 Config 버튼 을 누 르 면 카메라 가 Idle 상태 로 들 어가 절전 모드 (powerSavingMode) 를 사용 합 니 다.
  • NotShooting (Idle 또는 Configuring) 상태 에 있 을 때 사용자 가 셔터 키 를 반 쯤 누 르 면 (EvShutter Half 이벤트 가 발생) 전력 이 충분 하고 (isBattery Low 가 비) 카메라 가 초점 상태 (Focusing) 에 들 어가 면 렌즈 앞 뒤로 이동 하여 자동 으로 초점 을 맞춘다.
  • Focusing 상태 에 있 을 때 자동 으로 초점 을 맞 추 면 카메라 가 초점 을 맞 춘 물체 (display Focused) 를 표시 하고 자신의 내부 에 EvConfig 사건 이 발생 한 다음 에 카메라 가 초점 을 맞 춘 상태 (Focused) 에 들 어 갑 니 다.
  • Focused 상태 에 있 을 때 사용 자 는 모두 셔터 (EvShutter Full 이벤트 발생) 를 누 르 고 메모리 가 충분 하면 메모리 (allocMem) 를 분배 하고 사진 저장 상태 (Storing) 에 들 어 갑 니 다.메모리 가 부족 하면 Foused 상태 로 멈 춥 니 다.

  • 이벤트 지연 처리:
    Camera 작업 중 Camera 가 Focusing 상태 일 때 User 는 모두 셔터 (EvShutterFull 이벤트 발생) 를 누 르 고 초점 이 완료 되 지 않 아 EvShutterFull 이 벤트 를 즉시 처리 할 수 없습니다.이 사건 을 버 리 면 초점 이 완 료 된 후 (Focused 상태 로 들 어가 면) User 는 셔터 를 한 번 더 눌 러 불필요 한 번 거 로 움 을 초래 해 야 합 니 다.하나의 해결 방안 은 이 사건 의 처 리 를 지연 시 키 는 것 이다. 그 과정 은 다음 과 같다.
  • 카메라 가 Focusing 상태 에 있 을 때 사용자 가 모두 셔터 를 눌 렀 을 때 EvShutter Full 이벤트 가 발생 하여 이 사건 을 복사 합 니 다 (복사 구조 함수).
  • 사건 의 복사 본 을 단독 queue 에 넣 기;
  • 원 EvShutterFull 이벤트 (석조 함수) 를 소각 합 니 다.
  • 카메라 가 Focusing 상태 에서 벗 어 나 Focused 상태 로 들 어 갈 때 queue 에서 이벤트 (EvShutter Full 의 복사) 를 꺼 내 처리 합 니 다.
  • EvShutterFull 이벤트 의 복사 (석조 함수) 를 소각 합 니 다.

  • 이 모든 것 은 하나의 deferral 을 통 해 이 루어 진다.
    전체 상태 그림:
    코드:
    [root@localhost camera]# tree . ├── bin ├── Makefile └── src     ├── camera     │   ├── camera.cpp     │   └── camera.hpp     ├── event     │   ├── events.cpp     │   └── events.hpp     └── state         ├── istate.hpp         ├── notshoot         │   ├── configuring.cpp         │   ├── configuring.hpp         │   ├── idle.cpp         │   ├── idle.hpp         │   ├── notshooting.cpp         │   └── notshooting.hpp         └── shoot             ├── focused.cpp             ├── focused.hpp             ├── focusing.cpp             ├── focusing.hpp             ├── shooting.cpp             ├── shooting.hpp             ├── storing.cpp             └── storing.hpp
    Makefile
    INCLUDES=
    
    LIBLINKS=
    
    SOURCES=                                     \
        src/camera/camera.cpp                    \
        src/event/*.cpp                          \
        src/state/notshoot/idle.cpp              \
        src/state/notshoot/notshooting.cpp       \
        src/state/notshoot/configuring.cpp       \
        src/state/shoot/shooting.cpp             \
        src/state/shoot/focusing.cpp             \
        src/state/shoot/focused.cpp              \
        src/state/shoot/storing.cpp              \
    
    EXE=bin/run
    
    
    all: clean build
    
    build:
            mkdir -p bin
            g++ -g -o $(EXE) $(INCLUDES) $(SOURCES) $(LIBLINKS)
    
    clean:
            rm -f $(EXE)
    
    test:
            ./$(EXE)
    

    src/event/events.hpp
    #ifndef __EVENTS_HPP__
    #define __EVENTS_HPP__
    
    #include <boost/statechart/event.hpp>
    
    using namespace boost::statechart;
    
    class EvConfig : public event< EvConfig >
    {
      public:
        EvConfig();
        ~EvConfig();
    };
    
    class EvShutterHalf : public event< EvShutterHalf >
    {
      public:
        EvShutterHalf();
        ~EvShutterHalf();
    };
    
    class EvShutterFull : public event< EvShutterFull >
    {
      public:
        EvShutterFull();
        EvShutterFull(const EvShutterFull & other);
        ~EvShutterFull();
    };
    
    class EvShutterRelease : public event< EvShutterRelease >
    {
      public:
        EvShutterRelease();
        ~EvShutterRelease();
    };
    
    class EvInFocus : public event< EvInFocus >
    {
      public:
        EvInFocus();
        ~EvInFocus();
    };
    class EvStored : public event< EvStored >
    {
      public:
        EvStored();
        ~EvStored();
    };
    
    #endif
    

    src/event/events.cpp
    #include <iostream>
    #include "events.hpp"
    
    using namespace std;
    
    //============EvConfig============//
    EvConfig::EvConfig()
    {
      cout<<"Construct EvConfig"<<endl;
    }
    EvConfig::~EvConfig()
    {
      cout<<"Destruct EvConfig"<<endl;
    }
    
    //============EvShutterHalf============//
    EvShutterHalf::EvShutterHalf()
    {
      cout<<"Construct EvShutterHalf"<<endl;
    }
    EvShutterHalf::~EvShutterHalf()
    {
      cout<<"Destruct EvShutterHalf"<<endl;
    }
    
    //============EvShutterFull============//
    EvShutterFull::EvShutterFull()
    {
      cout<<"Construct EvShutterFull"<<endl;
    }
    EvShutterFull::EvShutterFull(const EvShutterFull & other)
    {
      cout<<"Copy Construct EvShutterFull"<<endl;
    }
    
    EvShutterFull::~EvShutterFull()
    {
      cout<<"Destruct EvShutterFull"<<endl;
    }
    
    //============EvShutterRelease============//
    EvShutterRelease::EvShutterRelease()
    {
      cout<<"Construct EvShutterRelease"<<endl;
    }
    EvShutterRelease::~EvShutterRelease()
    {
      cout<<"Destruct EvShutterRelease"<<endl;
    }
    
    
    //============EvInFocus============//
    EvInFocus::EvInFocus()
    {
      cout<<"Construct EvInFocus"<<endl;
    }
    EvInFocus::~EvInFocus()
    {
      cout<<"Destruct EvInFocus"<<endl;
    }
    
    
    //============EvStored============//
    EvStored::EvStored()
    {
      cout<<"Construct EvStored"<<endl;
    }
    EvStored::~EvStored()
    {
      cout<<"Destruct EvStored"<<endl;
    }
    

    src/camera/camera.hpp
    #ifndef __CAMERA_HPP__
    #define __CAMERA_HPP__
    
    #include <boost/statechart/state_machine.hpp>
    #include "../event/events.hpp"
    
    using namespace boost::statechart;
    using namespace std;
    
    //Yuanguo: forward declaration
    class NotShooting;
    
    class Camera : public state_machine< Camera, NotShooting >
    {
      public:
        Camera();
        ~Camera();
        bool isMemAvail() const;
        bool isBatteryLow() const;
    
        string getCurState() const;
    
        //transition actions
        void displayFocused(const EvInFocus & evInFocus);
        void allocMem(const EvShutterFull & evShutterFull);
        void powerSavingMode(const EvConfig & evConfig);
    };
    
    #endif
    

    src/camera/camera.cpp
    #include <iostream>
    #include "camera.hpp"
    
    #include "../state/istate.hpp"
    //Yuanguo: although the full definition of the initial state "NotShooting" is not needed when
    //declare Camera (thus only forward declaration is needed), the full definition of the states
    //are necessary for
    //       camera.initiate();
    //thus, include NotShooting and its inner states definition here;
    #include "../state/notshoot/notshooting.hpp"
    #include "../state/notshoot/idle.hpp"
    #include "../state/shoot/shooting.hpp"
    
    using namespace std;
    
    Camera::Camera()
    {
      cout<<"Construct Camera"<<endl;
    }
    
    Camera::~Camera()
    {
      cout<<"Destruct Camera"<<endl;
    }
    
    bool Camera::isMemAvail() const
    {
      return true;
    }
    
    bool Camera::isBatteryLow() const
    {
      return false;
    }
    
    string Camera::getCurState() const
    {
      return string("CurrentState ------> ") + state_cast< const IState & >().getStateName();
    }
    
    void Camera::displayFocused(const EvInFocus & evInFocus)
    {
      cout<<"[Transition Action]: Camera focused on objects"<<endl;
    }
    
    void Camera::allocMem(const EvShutterFull & evShutterFull)
    {
      cout<<"[Transition Action]: Memory allocated for storing the picture"<<endl;
    }
    
    void Camera::powerSavingMode(const EvConfig & evConfig)
    {
      cout<<"[Transition Action]: Camera goes into Power Saving Mode"<<endl;
    }
    
    int main()
    {
      Camera camera;
    
      camera.initiate();
      cout<<camera.getCurState()<<endl;
    
      camera.process_event(EvConfig());  //   Config 
      cout<<camera.getCurState()<<endl;
    
      camera.process_event(EvConfig());  //<span style="font-family: Arial, Helvetica, sans-serif;">   Config </span>
      cout<<camera.getCurState()<<endl;
    
      camera.process_event(EvShutterHalf());  //      
      cout<<camera.getCurState()<<endl;
    
      cout<<"Press Shutter Full before focused"<<endl;
      camera.process_event(EvShutterFull());  //       ,      
      cout<<camera.getCurState()<<endl;
    
      camera.process_event(EvInFocus());      //        
      cout<<camera.getCurState()<<endl;
    
      camera.process_event(EvShutterRelease()); //      
      cout<<camera.getCurState()<<endl;
    
      camera.process_event(EvStored());         //      
      cout<<camera.getCurState()<<endl;
    
      return 0;
    }
    

    src/state/notshoot/notshooting.hpp
    #ifndef __NOTSHOOTING_HPP__
    #define __NOTSHOOTING_HPP__
    
    #include <boost/statechart/simple_state.hpp>
    #include <boost/statechart/custom_reaction.hpp>
    
    #include "../istate.hpp"
    #include "../../event/events.hpp"
    
    //Yuanguo: NotShooting is the initial state of Camera, and Camera is the context of NotShooting, so
    //  1. forward declaration of NotShooting is needed when defining Camera, see camera.hpp;
    //  2. full definition of Camera is needed when defining NotShooting, thus include camera.hpp here;
    #include "../../camera/camera.hpp"
    
    using namespace boost::statechart;
    
    //Yuanguo: forward declaration;
    class Idle;
    
    class NotShooting : public simple_state< NotShooting, Camera, Idle >, public IState
    {
      public:
        typedef custom_reaction< EvShutterHalf > reactions;
    
        NotShooting();
        ~NotShooting();
        string getStateName() const;
        result react(const EvShutterHalf & evShutterHalf);
    };
    
    #endif
    

    src/state/notshoot/notshooting.cpp
    #include <iostream>
    #include "notshooting.hpp"
    
    //Yuanguo:
    //We need a full definition of Shooting in line
    //      return transit<Shooting>();
    //Focusing is the initial state of Shooting, thus we have to include focusing.hpp
    //here, otherwise, compiler will complain about error like
    //      incomplete type 'boost::statechart::simple_state ...
    //      ... MostDerived = NotShooting, Context = Camera ....'
    //inclusion of non-initial states of Shooting is not necessary;
    #include "../shoot/shooting.hpp"
    #include "../shoot/focusing.hpp"
    
    using namespace std;
    
    NotShooting::NotShooting()
    {
      cout<<"Enter NotShooting"<<endl;
    }
    
    NotShooting::~NotShooting()
    {
      cout<<"Exit NotShooting"<<endl;
    }
    
    string NotShooting::getStateName() const
    {
      return string("NotShooting");
    }
    
    result NotShooting::react(const EvShutterHalf & evShutterHalf)
    {
      cout<<"NotShooting::react(const EvShutterHalf & evShutterHalf), ";
      if( context< Camera >().isBatteryLow() )
      {
        cout<<"Guard: isBatteryLow() is true"<<endl;
        //Yuanguo: We cannot react to the event ourselves, so we forward it
        //to our outer state (this is also the default if a state
        //defines no reaction for a given event).
        return forward_event();
      }
      else
      {
        cout<<"Guard: isBatteryLow() is false"<<endl;
        return transit<Shooting>();  //no transition action
      }
    }
    

    src/state/notshoot/idle.hpp
    #ifndef __IDLE_HPP__
    #define __IDLE_HPP__
    
    #include <boost/statechart/simple_state.hpp>
    #include <boost/statechart/custom_reaction.hpp>
    
    #include "../istate.hpp"
    #include "../../event/events.hpp"
    
    //Yuanguo: Idle is the initial state of NotShooting, and NotShooting is the context of Idle, so
    //  1. forward declaration of Idle is needed when defining NotShooting, see notshooting.hpp;
    //  2. full definition of NotShooting is needed when defining Idle, thus include notshooting.hpp here;
    #include "notshooting.hpp"
    
    using namespace boost::statechart;
    
    class Idle : public simple_state< Idle, NotShooting >, public IState
    {
      public:
        typedef custom_reaction< EvConfig > reactions;
    
        Idle();
        ~Idle();
        string getStateName() const;
        result react(const EvConfig & evConfig);
    };
    
    #endif
    

    src/state/notshoot/idle.cpp
    #include <iostream>
    #include "configuring.hpp"
    #include "idle.hpp"
    
    using namespace std;
    
    Idle::Idle()
    {
      cout<<"Enter Idle"<<endl;
    }
    
    Idle::~Idle()
    {
      cout<<"Exit Idle"<<endl;
    }
    
    string Idle::getStateName() const
    {
      return string("Idle");
    }
    
    result Idle::react(const EvConfig & evConfig)
    {
      cout<<"Idle::react(const EvConfig & evConfig)"<<endl;
      return transit<Configuring>(); //no transition action
    }
    

    src/state/notshoot/configuring.hpp
    #ifndef __CONFIGURING_HPP__
    #define __CONFIGURING_HPP__
    
    #include <boost/statechart/simple_state.hpp>
    #include <boost/statechart/transition.hpp>
    
    #include "../../event/events.hpp"
    #include "../istate.hpp"
    
    //Yuanguo: NotShooting is the context of Configuring, so
    //   full definition of NotShooting is needed when defining Configuring, thus include notshooting.hpp here;
    #include "notshooting.hpp"
    
    //Yuanguo: full definition of Idle is needed in line
    //      typedef transition< EvConfig, Idle >
    #include "idle.hpp"
    
    using namespace boost::statechart;
    
    class Configuring : public simple_state< Configuring, NotShooting >, public IState
    {
      public:
        //Yuanguo: a short way for:
        //      typedef custom_reaction< EvConfig > reactions;
        //      result react( const EvConfig & evConfig)
        //      {
        //        return transit< Idle >(&Camera::powerSavingMode, evConfig);  //transition action is Camera::powerSavingMode()
        //        //return transit< Idle >();    //no transition action
        //      }
        typedef transition< EvConfig, Idle, Camera, &Camera::powerSavingMode > reactions;  //transition action is Camera::powerSavingMode()
        //typedef transition< EvConfig, Idle > reactions;         //no transition action
    
        Configuring();
        ~Configuring();
        string getStateName() const;
    };
    
    #endif
    

    src/state/notshoot/configuring.cpp
    #include <iostream>
    #include "configuring.hpp"
    
    using namespace std;
    
    Configuring::Configuring()
    {
      cout<<"Enter Configuring"<<endl;
    }
    
    Configuring::~Configuring()
    {
      cout<<"Exit Configuring"<<endl;
    }
    
    string Configuring::getStateName() const
    {
      return string("Configuring");
    }
    

    src/state/shoot/shooting.hpp
    #ifndef __SHOOTING_HPP__
    #define __SHOOTING_HPP__
    
    #include <boost/statechart/simple_state.hpp>
    #include <boost/statechart/custom_reaction.hpp>
    #include <boost/statechart/transition.hpp>
    
    #include "../istate.hpp"
    #include "../../event/events.hpp"
    
    //Yuanguo: Camera is the context of Shooting, so
    //  full definition of Camera is needed when defining Shooting, thus include camera.hpp here;
    #include "../../camera/camera.hpp"
    
    using namespace boost::statechart;
    
    //Yuanguo: forward declaration
    class Focusing;
    
    class Shooting : public simple_state< Shooting, Camera, Focusing >, public IState
    {
      public:
        typedef custom_reaction< EvShutterRelease > reactions;
    
        Shooting();
        ~Shooting();
        string getStateName() const;
        result react(const EvShutterRelease & evShutterRelease);
    };
    
    #endif
    

    src/state/shoot/shooting.cpp
    #include <iostream>
    
    #include "shooting.hpp"
    //Yuanguo:
    //We need a full definition of NotShooting in line
    //      return transit< NotShooting >();
    //Idle is the initial state of NotShooting, thus we have to include idle.hpp
    //here, otherwise, compiler will complain about error like
    //      incomplete type 'boost::statechart::simple_state ...
    //      ... MostDerived = NotShooting, Context = Camera ....'
    //inclusion of non-initial states of NotShooting is not necessary;
    #include "../notshoot/notshooting.hpp"
    #include "../notshoot/idle.hpp"
    
    using namespace std;
    
    Shooting::Shooting()
    {
      cout<<"Enter Shooting"<<endl;
    }
    
    Shooting::~Shooting()
    {
      cout<<"Exit Shooting"<<endl;
    }
    
    string Shooting::getStateName() const
    {
      return string("Shooting");
    }
    
    result Shooting::react(const EvShutterRelease & evShutterRelease)
    {
      cout<<"Shooting::react(const EvShutterRelease & evShutterRelease)"<<endl;
      return transit< NotShooting >();
    }
    

    src/state/shoot/focusing.hpp
    #ifndef __FOCUSING_HPP__
    #define __FOCUSING_HPP__
    
    #include <boost/statechart/simple_state.hpp>
    #include <boost/statechart/custom_reaction.hpp>
    #include <boost/mpl/list.hpp>
    #include <boost/statechart/deferral.hpp>
    
    #include "../../event/events.hpp"
    #include "../istate.hpp"
    
    //Yuanguo: Shooting is the context of Focusing, so
    //   full definition of Shooting is needed when defining Focusing, thus include
    //   shooting.hpp here;
    #include "shooting.hpp"
    
    using namespace boost::statechart;
    
    class Focusing : public simple_state< Focusing, Shooting >, public IState
    {
      public:
        //Yuanguo:
        //if the user fully press shutter when the camera is still in focusing (has
        //not focused yet), we defer the event until focused.
        //that means:
        //when an event of EvShutterFull comes:
        //    copy the EvShutterFull event by copy-constructor;
        //    put the copy in a separated queue;
        //    destruct the EvShutterFull event;
        //when camera exits Focusing state (e.g. gets into Focused state):
        //    let Focused state process the events in the queue;
        //    empty the queue and destruct the copied events;
        typedef boost::mpl::list<
          custom_reaction< EvInFocus >,
          deferral< EvShutterFull > > reactions;
    
        Focusing();
        ~Focusing();
        string getStateName() const;
        result react(const EvInFocus & evInFocus);
    };
    
    #endif
    

    src/state/shoot/focusing.cpp
    #include <iostream>
    #include "focusing.hpp"
    #include "focused.hpp"
    #include "../../camera/camera.hpp"
    
    using namespace std;
    
    Focusing::Focusing()
    {
      cout<<"Enter Focusing"<<endl;
    }
    Focusing::~Focusing()
    {
      cout<<"Exit Focusing"<<endl;
    }
    string Focusing::getStateName() const
    {
      return string("Focusing");
    }
    result Focusing::react(const EvInFocus & evInFocus)
    {
      cout<<"Focusing::react(const EvInFocus & evInFocus)"<<endl;
      return transit< Focused >(&Camera::displayFocused, evInFocus); //transition action is Camera::displayFocused()
    }
    

    src/state/shoot/focused.hpp
    #ifndef __FOCUSED_HPP__
    #define __FOCUSED_HPP__
    
    #include <boost/statechart/simple_state.hpp>
    #include <boost/statechart/custom_reaction.hpp>
    
    #include "../../event/events.hpp"
    #include "../istate.hpp"
    
    //Yuanguo: Shooting is the context of Focused, so
    //   full definition of Shooting is needed when defining Focused, thus include shooting.hpp here;
    #include "shooting.hpp"
    
    class Focused : public simple_state< Focused, Shooting >, public IState
    {
      public:
        typedef custom_reaction < EvShutterFull > reactions;
    
        Focused();
        ~Focused();
        string getStateName() const;
        result react(const EvShutterFull & evShutterFull );
    };
    
    #endif
    

    src/state/shoot/focused.cpp
    #include <iostream>
    #include "focused.hpp"
    #include "storing.hpp"
    #include "../../camera/camera.hpp"
    
    using namespace std;
    
    Focused::Focused()
    {
      cout<<"Enter Focused"<<endl;
    }
    Focused::~Focused()
    {
      cout<<"Exit Focused"<<endl;
    }
    string Focused::getStateName() const
    {
      return string("Focused");
    }
    result Focused::react(const EvShutterFull & evShutterFull )
    {
      cout<<"Focused::react(const EvShutterFull & evShutterFull ), ";
      if( context< Camera >().isMemAvail() )
      {
        cout<<"Guard: isMemAvail() is true"<<endl;
        return transit<Storing>(&Camera::allocMem, evShutterFull); //transition action is Camera::allocMem()
      }
      else
      {
        cout<<"Guard: isMemAvail() is false"<<endl;
        //Yuanguo: Indicate that the event can be discarded. So, the
        // dispatch algorithm will stop looking for a reaction
        // and the machine remains in the Focused state.
        return discard_event();
      }
    }
    

    src/state/shoot/storing.hpp
    #ifndef __STORING_HPP__
    #define __STORING_HPP__
    
    #include <boost/statechart/simple_state.hpp>
    #include <boost/statechart/custom_reaction.hpp>
    #include <boost/statechart/deferral.hpp>
    #include <boost/mpl/list.hpp>
    
    #include "../../event/events.hpp"
    #include "../istate.hpp"
    
    //Yuanguo: Shooting is the context of Storing, so
    //   full definition of Shooting is needed when defining Storing, thus include shooting.hpp here;
    #include "shooting.hpp"
    
    using namespace boost::statechart;
    
    class Storing : public simple_state< Storing, Shooting >, public IState
    {
      public:
        //Yuanguo: we have multiple reactions for different events;
        typedef boost::mpl::list<
          custom_reaction < EvStored >,
          custom_reaction < EvShutterRelease > > reactions;
    
        Storing();
        ~Storing();
        string getStateName() const;
        result react(const EvStored & evStored);
        result react(const EvShutterRelease & evShutterRelease);
    };
    
    #endif
    

    src/state/shoot/storing.cpp
    #include <iostream>
    #include "storing.hpp"
    
    //Yuanguo:
    //We need a full definition of NotShooting in line
    //      return transit< NotShooting >();
    //Idle is the initial state of NotShooting, thus we have to include idle.hpp
    //here, otherwise, compiler will complain about error like
    //      incomplete type 'boost::statechart::simple_state ...
    //      ... MostDerived = NotShooting, Context = Camera ....'
    //inclusion of non-initial states of NotShooting is not necessary;
    #include "../notshoot/notshooting.hpp"
    #include "../notshoot/idle.hpp"
    
    using namespace std;
    
    Storing::Storing()
    {
      cout<<"Enter Storing"<<endl;
    }
    Storing::~Storing()
    {
      cout<<"Exit Storing"<<endl;
    }
    string Storing::getStateName() const
    {
      return string("Storing");
    }
    result Storing::react(const EvStored & evStored)
    {
      cout<<"Storing::react(const EvStored & evStored)"<<endl;
      //Yuanguo: goto NotShooting when storing is finished;
      return transit< NotShooting >();
    }
    result Storing::react(const EvShutterRelease & evShutterRelease)
    {
      cout<<"Storing::react(const EvShutterRelease & evShutterRelease)"<<endl;
      cout<<"Discard EvShutterRelease"<<endl;
      //Yuanguo: Don't go to NotShooting until storing is finished, even if the user
      //releases the shutter
      return discard_event();
    }
    

    테스트 (이벤트 와 상태 대상 의 생명주기 주의):
    [root@localhost camera]# make; make test
    rm -f bin/run
    mkdir -p bin
    g++ -g -o bin/run  src/camera/camera.cpp src/event/*.cpp src/state/notshoot/idle.cpp src/state/notshoot/notshooting.cpp src/state/notshoot/configuring.cpp src/state/shoot/shooting.cpp src/state/shoot/focusing.cpp src/state/shoot/focused.cpp src/state/shoot/storing.cpp
    ./bin/run
    Construct Camera
    Enter NotShooting
    Enter Idle
    CurrentState ------> Idle                  //     Idle  
    Construct EvConfig                         //   Config ,  Idle Configuring   
    Idle::react(const EvConfig & evConfig)     //  EvConfig  
    Exit Idle                                  
    Enter Configuring                          
    Destruct EvConfig                          //   “     ” ,    
    CurrentState ------> Configuring
    Construct EvConfig                         //     Config ,  Configuring Idle   
    Exit Configuring                           
    [Transition Action]: Camera goes into Power Saving Mode      //transition action   “     ”  ,  “     ”    
    Enter Idle
    Destruct EvConfig
    CurrentState ------> Idle
    Construct EvShutterHalf                     //      
    NotShooting::react(const EvShutterHalf & evShutterHalf), Guard: isBatteryLow() is false  //  EvShutterHalf  
    Exit Idle
    Exit NotShooting
    Enter Shooting
    Enter Focusing
    Destruct EvShutterHalf
    CurrentState ------> Focusing               //      
    Press Shutter Full before focused           //        
    Construct EvShutterFull                     //<span style="font-family: Arial, Helvetica, sans-serif;">          ,  EvShutterFull  </span>
    Copy Construct EvShutterFull                //  EvShutterFull     queue
    Destruct EvShutterFull                      //   EvShutterFull  
    CurrentState ------> Focusing
    Construct EvInFocus                         //      
    Focusing::react(const EvInFocus & evInFocus)
    Exit Focusing
    [Transition Action]: Camera focused on objects //transition action   “     ”  ,  “     ”    
    </span>Enter Focused                                   
    Focused::react(const EvShutterFull & evShutterFull ), Guard: isMemAvail() is true    //  “     ” ,          
    Exit Focused                                 //      EvShutterFull  ,  Camera  Focused  
    [Transition Action]: Memory allocated for storing the picture
    Enter Storing
    Destruct EvShutterFull                       //  EvShutterFull   
    Destruct EvInFocus                           
    CurrentState ------> Storing
    Construct EvShutterRelease                   //      
    Storing::react(const EvShutterRelease & evShutterRelease)
    Discard EvShutterRelease                     //EvShutterRelease   ,  storing    
    Destruct EvShutterRelease
    CurrentState ------> Storing                 //    Storing  
    Construct EvStored                           //  storing    
    Storing::react(const EvStored & evStored)
    Exit Storing                                 //storing  ,  Storing  
    Exit Shooting                                //        (      ),  “     ” “     ” “        ”
    Enter NotShooting
    Enter Idle                                   //    “     ”(      )
    Destruct EvStored
    CurrentState ------> Idle                    
    Destruct Camera                              //      ,        ;
    Exit Idle
    Exit NotShooting
    [root@localhost camera]#
    

    좋은 웹페이지 즐겨찾기