Boost 상태 기 - 중급 편
원문 은 Camera 를 예 로 들 어 Boost 상태 기 모델 의 사용 방법 을 설명 했다.그리고 본문의 주요 내용 은:
또한 중급 topics 만 포함 되 어 있 으 며, 고급 내용 에 대해 서 는 추 후 다시 쓰 겠 습 니 다.
Camera 버튼:
Camera 상태:
모듈 화 (서로 다른 모듈 간 의 느슨 한 결합, 서로 다른 team 이 동시에 개발 할 수 있 음) 를 높이 기 위해 카 메 라 를 두 개의 큰 상태 로 나 누 었 습 니 다.
Camera 작업 과정:
이벤트 지연 처리:
Camera 작업 중 Camera 가 Focusing 상태 일 때 User 는 모두 셔터 (EvShutterFull 이벤트 발생) 를 누 르 고 초점 이 완료 되 지 않 아 EvShutterFull 이 벤트 를 즉시 처리 할 수 없습니다.이 사건 을 버 리 면 초점 이 완 료 된 후 (Focused 상태 로 들 어가 면) User 는 셔터 를 한 번 더 눌 러 불필요 한 번 거 로 움 을 초래 해 야 합 니 다.하나의 해결 방안 은 이 사건 의 처 리 를 지연 시 키 는 것 이다. 그 과정 은 다음 과 같다.
이 모든 것 은 하나의 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]#
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
【Visual Studio 2017】Boost 도입 방법 【슈퍼 쉬운 해설】이번에는 Visual Studio 2017에서 boost 도입 방법에 대해 설명합니다. そろそろboostに手を出してみようかな라고 생각하는 분이나,Visual Studioでプログラミングしてるけどboostの入れ方がわから...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.