[openrtm-commit:02982] r3116 - in trunk/OpenRTM-aist/src/lib/rtm: . ext
openrtm @ openrtm.org
openrtm @ openrtm.org
2017年 12月 11日 (月) 06:20:20 JST
Author: n-ando
Date: 2017-12-11 06:20:20 +0900 (Mon, 11 Dec 2017)
New Revision: 3116
Added:
trunk/OpenRTM-aist/src/lib/rtm/Macho.cpp
trunk/OpenRTM-aist/src/lib/rtm/Macho.h
Modified:
trunk/OpenRTM-aist/src/lib/rtm/FsmActionListener.h
trunk/OpenRTM-aist/src/lib/rtm/Makefile.am
trunk/OpenRTM-aist/src/lib/rtm/OutPortBase.cpp
trunk/OpenRTM-aist/src/lib/rtm/OutPortPushConnector.cpp
trunk/OpenRTM-aist/src/lib/rtm/PublisherFlush.cpp
trunk/OpenRTM-aist/src/lib/rtm/PublisherNew.cpp
trunk/OpenRTM-aist/src/lib/rtm/RTObject.h
trunk/OpenRTM-aist/src/lib/rtm/ext/
Log:
merged changes from branches/FSM4RTC/OpenRTM-aist r2821-2826, no confliction:
[FSM4RTC,doc,->RELENG_2_0] FSM listeners documentations have been updated. refs #3860
[FSM4RTC,incompat,new funcs,->RELENG_2_0] add/remove functions for FSM listeners have been added. refs #3681
[FSM4RTC,new file,->RELENG_2_0] Macho (Machine object state machine engine) has been introduced to rtm. refs #3683
[FSM4RTC,compat,new prop,->RELENG_2_0] PortProfile/ConnectorProfile "dataport.io_mode" has been added. refs #3688
[prop,->RELENG_2_0] Ignore some generated files.
[prop,->RELENG_2_0] Ignore some generated files.
Modified: trunk/OpenRTM-aist/src/lib/rtm/FsmActionListener.h
===================================================================
--- trunk/OpenRTM-aist/src/lib/rtm/FsmActionListener.h 2017-12-10 21:18:08 UTC (rev 3115)
+++ trunk/OpenRTM-aist/src/lib/rtm/FsmActionListener.h 2017-12-10 21:20:20 UTC (rev 3116)
@@ -5,7 +5,7 @@
* @date $Date$
* @author Noriaki Ando <n-ando at aist.go.jp>
*
- * Copyright (C) 2011
+ * Copyright (C) 2016-2017
* Noriaki Ando
* Intelligent Systems Research Institute,
* National Institute of
@@ -41,12 +41,22 @@
* - FSM¤½¤Î¤â¤Î¤ÎÆ°ºî¤ò¥Õ¥Ã¥¯¤¹¤ë¤¿¤á¤Î¥ê¥¹¥Ê
* - FSM¤Ë´Ø¤¹¤ë¥á¥¿¥Ç¡¼¥¿Êѹ¹Åù¤ÎÆ°ºî¤ò¥Õ¥Ã¥¯¤¹¤ë¤¿¤á¤Î¥ê¥¹¥Ê
*
- * ¤Î2¼ïÎà¤Ëʬ¤±¤é¤ì¤ë¡£
+ * ¤Î2¼ïÎà¤Ëʬ¤±¤é¤ì¤ë¡£¤µ¤é¤ËÁ°¼Ô¤Ï¡¢FSM¤Î¾õÂÖÁ«°ÜÅù¤Î¥¢¥¯¥·¥ç¥ó¤ÎÁ°
+ * ¸å¤½¤ì¤¾¤ì¤ò¥Õ¥Ã¥¯¤¹¤ë¤¿¤á¤Î PreFsmActionListener ¤È
+ * PostFsmActionListener ¤ÎÆó¤Ä¤¬¤¢¤ê¡¢¸å¼Ô¤Ï¡¢FSM¤ÎProfile¤ÎÊѹ¹¤ò¥Õ¥Ã
+ * ¥¯¤¹¤ë FsmProfileListener ¤È FSM¤Î¹½Â¤ (Structure) ¤ÎÊѹ¹¤ò¥Õ¥Ã¥¯
+ * ¤¹¤ë FsmStructureListener ¤ÎÆó¤Ä¤Ëʬ¤±¤é¤ì¤ë¡£°Ê¾å¡¢°Ê²¼¤ÎFSM¤Ë´Ø
+ * ¤¹¤ë°Ê²¼¤Î4¼ïÎà¤Î¥ê¥¹¥Ê¡¼¥¯¥é¥¹·²¤¬Ä󶡤µ¤ì¤Æ¤¤¤ë¡£
*
* - PreFsmActionListener
* - PostFsmActionListener
* - FsmProfileListner
* - FsmStructureListener
+ *
+ * @else
+ *
+ *
+ * @endif
*/
//============================================================
@@ -54,18 +64,30 @@
* @if jp
* @brief PreFsmActionListener ¤Î¥¿¥¤¥×
*
- * - PRE_ON_INIT: on_init ľÁ°
- * - PRE_ON_ENTRY: on_entry ľÁ°
- * - PRE_ON_DO: on_do ľÁ°
- * - PRE_ON_EXIT: on_exit ľÁ°
+ * PreFsmActionListener ¤Ë¤Ï°Ê²¼¤Î¥Õ¥Ã¥¯¥Ý¥¤¥ó¥È¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤ë¡£¤³
+ * ¤ì¤é¤¬¸Æ¤Ó½Ð¤µ¤ì¤ë¤«¤É¤¦¤«¤Ï¡¢FSM¤Î¼ÂÁõ¤Ë°Í¸¤¹¤ë¡£
+ *
+ * - PRE_ON_INIT: init ľÁ°
+ * - PRE_ON_ENTRY: entry ľÁ°
+ * - PRE_ON_DO: do ľÁ°
+ * - PRE_ON_EXIT: exit ľÁ°
* - PRE_ON_STATE_CHANGE: ¾õÂÖÁ«°ÜľÁ°
*
* @else
* @brief The types of ConnectorDataListener
- *
+ *
+ * PreFsmActionListener has the following hook points. If these
+ * listeners are actually called or not called are depends on FSM
+ * implementations.
+ *
+ * - PRE_ON_INIT: just before "init" action
+ * - PRE_ON_ENTRY: just before "entry" action
+ * - PRE_ON_DO: just before "do" action
+ * - PRE_ON_EXIT: just before "exit" action
+ * - PRE_ON_STATE_CHANGE: just before state transition action
+ *
* @endif
*/
-
enum PreFsmActionListenerType
{
PRE_ON_INIT,
@@ -81,28 +103,131 @@
* @class PreFsmActionListener ¥¯¥é¥¹
* @brief PreFsmActionListener ¥¯¥é¥¹
*
- * - on_init()
- * - on_entry()
- * - on_do()
- * - on_exit()
- * - on_state_update()
+ * PreFsmActionListener ¥¯¥é¥¹¤Ï¡¢Fsm¤Î¥¢¥¯¥·¥ç¥ó¤Ë´Ø¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯
+ * ¤ò¼Â¸½¤¹¤ë¥ê¥¹¥Ê¡¼¥ª¥Ö¥¸¥§¥¯¥È¤Î´ðÄ쥯¥é¥¹¤Ç¤¢¤ë¡£FSM¤Î¥¢¥¯¥·¥ç¥ó
+ * ¤ÎľÁ°¤ÎÆ°ºî¤ò¥Õ¥Ã¥¯¤·¤¿¤¤¾ì¹ç¡¢°Ê²¼¤ÎÎã¤Î¤è¤¦¤Ë¡¢¤³¤Î¥¯¥é¥¹¤ò·Ñ¾µ
+ * ¤·¤¿¥³¡¼¥ë¥Ð¥Ã¥¯¥ª¥Ö¥¸¥§¥¯¥È¤òÄêµÁ¤·¡¢Å¬Àڤʥ³¡¼¥ë¥Ð¥Ã¥¯ÀßÄê´Ø¿ô¤«
+ * ¤éRTObject¤ËÂФ·¤Æ¥³¡¼¥ë¥Ð¥Ã¥¯¥ª¥Ö¥¸¥§¥¯¥È¤ò¥»¥Ã¥È¤¹¤ëɬÍפ¬¤¢¤ë¡£
*
- * ³Æ¥¢¥¯¥·¥ç¥ó¤ËÂбþ¤¹¤ë¥æ¡¼¥¶¡¼¥³¡¼¥É¤¬¸Æ¤Ð¤ì¤ëľÁ°¤Î¥¿¥¤¥ß¥ó¥°
- * ¤Ç¥³¡¼¥ë¤µ¤ì¤ë¥ê¥¹¥Ê¥¯¥é¥¹¤Î´ðÄ쥯¥é¥¹¡£
+ * <pre>
+ * class MyListener
+ * : public PreFsmActionListener
+ * {
+ * std::string m_name;
+ * public:
+ * MyListener(const char* name) : m_name(name) {}
+ * virtual ~MyListener() {}
*
- * - PRE_ON_INIT:
- * - PRE_ON_ENTRY:
- * - PRE_ON_DO:
- * - PRE_ON_EXIT:
- * - PRE_ON_STATE_CHANGE:
+ * virtual void operator()(const char* state_name)
+ * {
+ * std::cout << "Listner name: " m_name << std::endl;
+ * std::cout << "Current state: " state_name << std::endl;
+ * };
+ * };
+ * </pre>
*
+ * ¤³¤Î¤è¤¦¤Ë¤·¤ÆÄêµÁ¤µ¤ì¤¿¥ê¥¹¥Ê¥¯¥é¥¹¤Ï¡¢°Ê²¼¤Î¤è¤¦¤ËRTObject¤ËÂФ·
+ * ¤Æ¡¢¥»¥Ã¥È¤µ¤ì¤ë¡£
+ *
+ * <pre>
+ * RTC::ReturnCode_t ConsoleIn::onInitialize()
+ * {
+ * addPreFsmActionListener(PRE_ON_STATE_CHANGE,
+ * new MyListener("init listener"),
+ * true);
+ * :
+ * </pre>
+ *
+ * Âè1°ú¿ô¤Î "PRE_ON_STATE_CHANGE" ¤Ï¡¢¥³¡¼¥ë¥Ð¥Ã¥¯¤ò¥Õ¥Ã¥¯¤¹¤ë¥Ý¥¤¥ó
+ * ¥È¤Ç¤¢¤ê¡¢°Ê²¼¤ÎÃͤò¼è¤ë¤³¤È¤¬²Äǽ¤Ç¤¢¤ë¡£¤Ê¤ª¡¢¤¹¤Ù¤Æ¤Î¥³¡¼¥ë¥Ð¥Ã
+ * ¥¯¥Ý¥¤¥ó¥È¤¬¼ÂÁõ¤µ¤ì¤Æ¤¤¤ë¤È¤Ï¸Â¤é¤º¡¢¤³¤ì¤é¤¬¸Æ¤Ó½Ð¤µ¤ì¤ë¤«¤É¤¦¤«
+ * ¤Ï¡¢FSM¤Î¼ÂÁõ¤Ë°Í¸¤¹¤ë¡£
+ *
+ * - PRE_ON_INIT: init ľÁ°
+ * - PRE_ON_ENTRY: entry ľÁ°
+ * - PRE_ON_DO: do ľÁ°
+ * - PRE_ON_EXIT: exit ľÁ°
+ * - PRE_ON_STATE_CHANGE: ¾õÂÖÁ«°ÜľÁ°
+ *
+ * Âè2°ú¿ô¤Ï¥ê¥¹¥Ê¥ª¥Ö¥¸¥§¥¯¥È¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£Âè3°ú¿ô¤Ï¥ª¥Ö¥¸¥§¥¯¥È
+ * ¼«Æ°ºï½ü¥Õ¥é¥°¤Ç¤¢¤ê¡¢true ¤Î¾ì¹ç¤Ï¡¢RTObjectºï½ü»þ¤Ë¼«Æ°Åª¤Ë¥ê¥¹
+ * ¥Ê¥ª¥Ö¥¸¥§¥¯¥È¤¬ºï½ü¤µ¤ì¤ë¡£false¤Î¾ì¹ç¤Ï¡¢¥ª¥Ö¥¸¥§¥¯¥È¤Î½ê͸¢¤Ï
+ * ¸Æ¤Ó½Ð¤·Â¦¤Ë»Ä¤ê¡¢ºï½ü¤Ï¸Æ¤Ó½Ð¤·Â¦¤ÎÀÕǤ¤Ç¹Ô¤ï¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
+ * RTObject ¤Î¥é¥¤¥Õ¥µ¥¤¥¯¥ëÃæ¤Ë¥³¡¼¥ë¥Ð¥Ã¥¯¤¬É¬Íפʤé¤Ð¾åµ¤Î¤è¤¦¤Ê
+ * ¸Æ¤Ó½Ð¤·Êý¤ÇÂè3°ú¿ô¤ò true ¤È¤·¤Æ¤ª¤¯¤È¤è¤¤¡£µÕ¤Ë¡¢¥³¡¼¥ë¥Ð¥Ã¥¯¤ò
+ * ¾õ¶·Åù¤Ë±þ¤¸¤Æ¥»¥Ã¥È¤·¤¿¤ê¥¢¥ó¥»¥Ã¥È¤·¤¿¤ê¤¹¤ëɬÍפ¬¤¢¤ë¾ì¹ç¤Ï
+ * false¤È¤·¤ÆÃÖ¤¡¢¥ê¥¹¥Ê¥ª¥Ö¥¸¥§¥¯¥È¤Î¥Ý¥¤¥ó¥¿¤ò¥á¥ó¥ÐÊÑ¿ô¤Ê¤É¤ËÊÝ
+ * »ý¤·¤Æ¤ª¤¡¢
+ * RTObject_impl::addPreFsmActionListener()/removePreFsmActionListener()
+ * ¤Ë¤è¤ê¡¢¥»¥Ã¥È¤È¥¢¥ó¥»¥Ã¥È¤ò´ÉÍý¤¹¤ë¤È¤¤¤Ã¤¿»È¤¤Êý¤â²Äǽ¤Ç¤¢¤ë¡£
+ *
* @else
* @class PreFsmActionListener class
* @brief PreFsmActionListener class
*
- * This class is abstract base class for listener classes that
- * provides callbacks for various events in rtobject.
+ * PreFsmActionListener class is a base class for the listener
+ * objects which realize callback to hook FSM related pre-actions.
+ * To hook execution just before a FSM action, the callback object
+ * should be defined as follows, and set to RTObject through
+ * appropriate callback set function.
*
+ * <pre>
+ * class MyListener
+ * : public PreFsmActionListener
+ * {
+ * std::string m_name;
+ * public:
+ * MyListener(const char* name) : m_name(name) {}
+ * virtual ~MyListener() {}
+ *
+ * virtual void operator()(const char* state_name)
+ * {
+ * std::cout << "Listner name: " m_name << std::endl;
+ * std::cout << "Current state: " state_name << std::endl;
+ * };
+ * };
+ * </pre>
+ *
+ * The listener class defined above is set to RTObject as follows.
+ *
+ * <pre>
+ * RTC::ReturnCode_t ConsoleIn::onInitialize()
+ * {
+ * addPreFsmActionListener(PRE_ON_STATE_CHANGE,
+ * new MyListener("init listener"),
+ * true);
+ * :
+ * </pre>
+ *
+ * The first argument "PRE_ON_STATE_CHANGE" specifies callback hook
+ * point, and the following values are available. Not all the
+ * callback points are implemented. It depends on the FSM
+ * implementations.
+ *
+ * - PRE_ON_INIT: just before "init" action
+ * - PRE_ON_ENTRY: just before "entry" action
+ * - PRE_ON_DO: just before "do" action
+ * - PRE_ON_EXIT: just before "exit" action
+ * - PRE_ON_STATE_CHANGE: just before state transition action
+ *
+ * The second argument is a pointers to the listener object. The
+ * third argument is a flag for automatic object destruction. When
+ * "true" is given to the third argument, the given object in second
+ * argument is automatically destructed with RTObject. In the "false
+ * " case, the ownership of the object is left in the caller side,
+ * and then destruction of the object must be done by users'
+ * responsibility.
+ *
+ * It is good for setting "true" as third argument, if the listener
+ * object life span is equals to the RTObject's life cycle. On the
+ * otehr hand, if callbacks are required to set/unset depending on
+ * its situation, the third argument could be "false". In that
+ * case, listener objects pointers must be stored to member
+ * variables, and set/unset of the listener objects shoud be
+ * paerformed throguh
+ * RTObject_impl::addPreFsmActionListener()/removePreFsmActionListener()
+ * functions.
+ *
* @endif
*/
class PreFsmActionListener
@@ -177,17 +302,30 @@
//============================================================
/*!
* @if jp
- * @brief PostCompoenntActionListener ¤Î¥¿¥¤¥×
+ * @brief PreFsmActionListener ¤Î¥¿¥¤¥×
*
- * - POST_ON_INIT:
- * - POST_ON_ENTRY:
- * - POST_ON_DO:
- * - POST_ON_EXIT:
- * - POST_ON_STATE_CHANGE:
+ * PreFsmActionListener ¤Ë¤Ï°Ê²¼¤Î¥Õ¥Ã¥¯¥Ý¥¤¥ó¥È¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤ë¡£¤³
+ * ¤ì¤é¤¬¸Æ¤Ó½Ð¤µ¤ì¤ë¤«¤É¤¦¤«¤Ï¡¢FSM¤Î¼ÂÁõ¤Ë°Í¸¤¹¤ë¡£
*
+ * - POST_ON_INIT: init ľ¸å
+ * - POST_ON_ENTRY: entry ľ¸å
+ * - POST_ON_DO: do ľ¸å
+ * - POST_ON_EXIT: exit ľ¸å
+ * - POST_ON_STATE_CHANGE: ¾õÂÖÁ«°Üľ¸å
+ *
* @else
* @brief The types of ConnectorDataListener
- *
+ *
+ * PreFsmActionListener has the following hook points. If these
+ * listeners are actually called or not called are depends on FSM
+ * implementations.
+ *
+ * - POST_ON_INIT: just after "init" action
+ * - POST_ON_ENTRY: just after "entry" action
+ * - POST_ON_DO: just after "do" action
+ * - POST_ON_EXIT: just after "exit" action
+ * - POST_ON_STATE_CHANGE: just after state transition action
+ *
* @endif
*/
enum PostFsmActionListenerType
@@ -200,37 +338,136 @@
POST_FSM_ACTION_LISTENER_NUM
};
-
/*!
* @if jp
* @class PostFsmActionListener ¥¯¥é¥¹
* @brief PostFsmActionListener ¥¯¥é¥¹
*
- * OMG RTC»ÅÍͤÇÄêµÁ¤µ¤ì¤Æ¤¤¤ë°Ê²¼¤Î¥³¥ó¥Ý¡¼¥Í¥ó¥È¥¢¥¯¥·¥ç¥ó¥È¤Ë¤Ä¤¤
- * ¤Æ¡¢
+ * PostFsmActionListener ¥¯¥é¥¹¤Ï¡¢Fsm¤Î¥¢¥¯¥·¥ç¥ó¤Ë´Ø¤¹¤ë¥³¡¼¥ë¥Ð¥Ã¥¯
+ * ¤ò¼Â¸½¤¹¤ë¥ê¥¹¥Ê¡¼¥ª¥Ö¥¸¥§¥¯¥È¤Î´ðÄ쥯¥é¥¹¤Ç¤¢¤ë¡£FSM¤Î¥¢¥¯¥·¥ç¥ó
+ * ¤Îľ¸å¤ÎÆ°ºî¤ò¥Õ¥Ã¥¯¤·¤¿¤¤¾ì¹ç¡¢°Ê²¼¤ÎÎã¤Î¤è¤¦¤Ë¡¢¤³¤Î¥¯¥é¥¹¤ò·Ñ¾µ
+ * ¤·¤¿¥³¡¼¥ë¥Ð¥Ã¥¯¥ª¥Ö¥¸¥§¥¯¥È¤òÄêµÁ¤·¡¢Å¬Àڤʥ³¡¼¥ë¥Ð¥Ã¥¯ÀßÄê´Ø¿ô¤«
+ * ¤éRTObject¤ËÂФ·¤Æ¥³¡¼¥ë¥Ð¥Ã¥¯¥ª¥Ö¥¸¥§¥¯¥È¤ò¥»¥Ã¥È¤¹¤ëɬÍפ¬¤¢¤ë¡£
*
- * - on_init()
- * - on_entry()
- * - on_do()
- * - on_exit()
- * - on_state_change()
+ * <pre>
+ * class MyListener
+ * : public PostFsmActionListener
+ * {
+ * std::string m_name;
+ * public:
+ * MyListener(const char* name) : m_name(name) {}
+ * virtual ~MyListener() {}
*
- * ³Æ¥¢¥¯¥·¥ç¥ó¤ËÂбþ¤¹¤ë¥æ¡¼¥¶¡¼¥³¡¼¥É¤¬¸Æ¤Ð¤ì¤ëľÁ°¤Î¥¿¥¤¥ß¥ó¥°
- * ¤Ç¥³¡¼¥ë¤µ¤ì¤ë¥ê¥¹¤Ê¥¯¥é¥¹¤Î´ðÄ쥯¥é¥¹¡£
+ * virtual void operator()(const char* state_name, ReturnCode_t ret)
+ * {
+ * std::cout << "Listner name: " m_name << std::endl;
+ * std::cout << "Current state: " state_name << std::endl;
+ * };
+ * };
+ * </pre>
*
- * - POST_ON_INIT:
- * - POST_ON_ENTRY:
- * - POST_ON_DO:
- * - POST_ON_EXIT:
- * - POST_ON_STATE_CHANGE:
+ * ¤³¤Î¤è¤¦¤Ë¤·¤ÆÄêµÁ¤µ¤ì¤¿¥ê¥¹¥Ê¥¯¥é¥¹¤Ï¡¢°Ê²¼¤Î¤è¤¦¤ËRTObject¤ËÂФ·
+ * ¤Æ¡¢¥»¥Ã¥È¤µ¤ì¤ë¡£
*
+ * <pre>
+ * RTC::ReturnCode_t ConsoleIn::onInitialize()
+ * {
+ * addPostFsmActionListener(POST_ON_STATE_CHANGE,
+ * new MyListener("init listener"),
+ * true);
+ * :
+ * </pre>
+ *
+ * Âè1°ú¿ô¤Î "POST_ON_STATE_CHANGE" ¤Ï¡¢¥³¡¼¥ë¥Ð¥Ã¥¯¤ò¥Õ¥Ã¥¯¤¹¤ë¥Ý¥¤¥ó
+ * ¥È¤Ç¤¢¤ê¡¢°Ê²¼¤ÎÃͤò¼è¤ë¤³¤È¤¬²Äǽ¤Ç¤¢¤ë¡£¤Ê¤ª¡¢¤¹¤Ù¤Æ¤Î¥³¡¼¥ë¥Ð¥Ã
+ * ¥¯¥Ý¥¤¥ó¥È¤¬¼ÂÁõ¤µ¤ì¤Æ¤¤¤ë¤È¤Ï¸Â¤é¤º¡¢¤³¤ì¤é¤¬¸Æ¤Ó½Ð¤µ¤ì¤ë¤«¤É¤¦¤«
+ * ¤Ï¡¢FSM¤Î¼ÂÁõ¤Ë°Í¸¤¹¤ë¡£
+ *
+ * - POST_ON_INIT: init ľ¸å
+ * - POST_ON_ENTRY: entry ľ¸å
+ * - POST_ON_DO: do ľ¸å
+ * - POST_ON_EXIT: exit ľ¸å
+ * - POST_ON_STATE_CHANGE: ¾õÂÖÁ«°Üľ¸å
+ *
+ * Âè2°ú¿ô¤Ï¥ê¥¹¥Ê¥ª¥Ö¥¸¥§¥¯¥È¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£Âè3°ú¿ô¤Ï¥ª¥Ö¥¸¥§¥¯¥È
+ * ¼«Æ°ºï½ü¥Õ¥é¥°¤Ç¤¢¤ê¡¢true ¤Î¾ì¹ç¤Ï¡¢RTObjectºï½ü»þ¤Ë¼«Æ°Åª¤Ë¥ê¥¹
+ * ¥Ê¥ª¥Ö¥¸¥§¥¯¥È¤¬ºï½ü¤µ¤ì¤ë¡£false¤Î¾ì¹ç¤Ï¡¢¥ª¥Ö¥¸¥§¥¯¥È¤Î½ê͸¢¤Ï
+ * ¸Æ¤Ó½Ð¤·Â¦¤Ë»Ä¤ê¡¢ºï½ü¤Ï¸Æ¤Ó½Ð¤·Â¦¤ÎÀÕǤ¤Ç¹Ô¤ï¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
+ * RTObject ¤Î¥é¥¤¥Õ¥µ¥¤¥¯¥ëÃæ¤Ë¥³¡¼¥ë¥Ð¥Ã¥¯¤¬É¬Íפʤé¤Ð¾åµ¤Î¤è¤¦¤Ê
+ * ¸Æ¤Ó½Ð¤·Êý¤ÇÂè3°ú¿ô¤ò true ¤È¤·¤Æ¤ª¤¯¤È¤è¤¤¡£µÕ¤Ë¡¢¥³¡¼¥ë¥Ð¥Ã¥¯¤ò
+ * ¾õ¶·Åù¤Ë±þ¤¸¤Æ¥»¥Ã¥È¤·¤¿¤ê¥¢¥ó¥»¥Ã¥È¤·¤¿¤ê¤¹¤ëɬÍפ¬¤¢¤ë¾ì¹ç¤Ï
+ * false¤È¤·¤ÆÃÖ¤¡¢¥ê¥¹¥Ê¥ª¥Ö¥¸¥§¥¯¥È¤Î¥Ý¥¤¥ó¥¿¤ò¥á¥ó¥ÐÊÑ¿ô¤Ê¤É¤ËÊÝ
+ * »ý¤·¤Æ¤ª¤¡¢
+ * RTObject_impl::addPostFsmActionListener()/removePostFsmActionListener()
+ * ¤Ë¤è¤ê¡¢¥»¥Ã¥È¤È¥¢¥ó¥»¥Ã¥È¤ò´ÉÍý¤¹¤ë¤È¤¤¤Ã¤¿»È¤¤Êý¤â²Äǽ¤Ç¤¢¤ë¡£
+ *
* @else
* @class PostFsmActionListener class
* @brief PostFsmActionListener class
*
- * This class is abstract base class for listener classes that
- * provides callbacks for various events in rtobject.
+ * PostFsmActionListener class is a base class for the listener
+ * objects which realize callback to hook FSM related post-actions.
+ * To hook execution just before a FSM action, the callback object
+ * should be defined as follows, and set to RTObject through
+ * appropriate callback set function.
*
+ * <pre>
+ * class MyListener
+ * : public PostFsmActionListener
+ * {
+ * std::string m_name;
+ * public:
+ * MyListener(const char* name) : m_name(name) {}
+ * virtual ~MyListener() {}
+ *
+ * virtual void operator()(const char* state_name, ReturnCode\t ret)
+ * {
+ * std::cout << "Listner name: " m_name << std::endl;
+ * std::cout << "Current state: " state_name << std::endl;
+ * };
+ * };
+ * </pre>
+ *
+ * The listener class defined above is set to RTObject as follows.
+ *
+ * <pre>
+ * RTC::ReturnCode_t ConsoleIn::onInitialize()
+ * {
+ * addPostFsmActionListener(POST_ON_STATE_CHANGE,
+ * new MyListener("init listener"),
+ * true);
+ * :
+ * </pre>
+ *
+ * The first argument "POST_ON_STATE_CHANGE" specifies callback hook
+ * point, and the following values are available. Not all the
+ * callback points are implemented. It depends on the FSM
+ * implementations.
+ *
+ * - POST_ON_INIT: just after "init" action
+ * - POST_ON_ENTRY: just after "entry" action
+ * - POST_ON_DO: just after "do" action
+ * - POST_ON_EXIT: just after "exit" action
+ * - POST_ON_STATE_CHANGE: just after state transition action
+ *
+ * The second argument is a pointers to the listener object. The
+ * third argument is a flag for automatic object destruction. When
+ * "true" is given to the third argument, the given object in second
+ * argument is automatically destructed with RTObject. In the "false
+ * " case, the ownership of the object is left in the caller side,
+ * and then destruction of the object must be done by users'
+ * responsibility.
+ *
+ * It is good for setting "true" as third argument, if the listener
+ * object life span is equals to the RTObject's life cycle. On the
+ * otehr hand, if callbacks are required to set/unset depending on
+ * its situation, the third argument could be "false". In that
+ * case, listener objects pointers must be stored to member
+ * variables, and set/unset of the listener objects shoud be
+ * paerformed throguh
+ * RTObject_impl::addPostFsmActionListener()/removePostFsmActionListener()
+ * functions.
+ *
* @endif
*/
class PostFsmActionListener
@@ -351,19 +588,134 @@
* @class FsmProfileListener ¥¯¥é¥¹
* @brief FsmProfileListener ¥¯¥é¥¹
*
- * ³Æ¥¢¥¯¥·¥ç¥ó¤ËÂбþ¤¹¤ë¥æ¡¼¥¶¡¼¥³¡¼¥É¤¬¸Æ¤Ð¤ì¤ëľÁ°¤Î¥¿¥¤¥ß¥ó¥°
- * ¤Ç¥³¡¼¥ë¤µ¤ì¤ë¥ê¥¹¤Ê¥¯¥é¥¹¤Î´ðÄ쥯¥é¥¹¡£
+ * FsmProfileListener ¥¯¥é¥¹¤Ï¡¢FSM¤ÎProfile¤Ë´ØÏ¢¤·¤¿¥¢¥¯¥·¥ç¥ó¤Î¥³¡¼
+ * ¥ë¥Ð¥Ã¥¯¤ò¼Â¸½¤¹¤ë¥ê¥¹¥Ê¡¼¥ª¥Ö¥¸¥§¥¯¥È¤Î´ðÄ쥯¥é¥¹¤Ç¤¢¤ë¡£FSM
+ * Profile¤Î¥¢¥¯¥·¥ç¥ó¤ÎÆ°ºî¤ò¥Õ¥Ã¥¯¤·¤¿¤¤¾ì¹ç¡¢°Ê²¼¤ÎÎã¤Î¤è¤¦¤Ë¡¢¤³
+ * ¤Î¥¯¥é¥¹¤ò·Ñ¾µ¤·¤¿¥³¡¼¥ë¥Ð¥Ã¥¯¥ª¥Ö¥¸¥§¥¯¥È¤òÄêµÁ¤·¡¢Å¬Àڤʥ³¡¼¥ë¥Ð¥Ã
+ * ¥¯ÀßÄê´Ø¿ô¤«¤éRTObject¤ËÂФ·¤Æ¥³¡¼¥ë¥Ð¥Ã¥¯¥ª¥Ö¥¸¥§¥¯¥È¤ò¥»¥Ã¥È¤¹¤ë
+ * ɬÍפ¬¤¢¤ë¡£
*
- * - ADD_PORT:
- * - REMOVE_PORT:
+ * <pre>
+ * class MyListener
+ * : public FsmProfileListener
+ * {
+ * std::string m_name;
+ * public:
+ * MyListener(const char* name) : m_name(name) {}
+ * virtual ~MyListener() {}
*
+ * virtual void operator()(const ::RTC::FsmProfile& fsmprof)
+ * {
+ * std::cout << "Listner name: " m_name << std::endl;
+ * };
+ * };
+ * </pre>
+ *
+ * ¤³¤Î¤è¤¦¤Ë¤·¤ÆÄêµÁ¤µ¤ì¤¿¥ê¥¹¥Ê¥¯¥é¥¹¤Ï¡¢°Ê²¼¤Î¤è¤¦¤ËRTObject¤ËÂФ·
+ * ¤Æ¡¢¥»¥Ã¥È¤µ¤ì¤ë¡£
+ *
+ * <pre>
+ * RTC::ReturnCode_t ConsoleIn::onInitialize()
+ * {
+ * addFsmProfileListener(SET_FSM_PROFILE,
+ * new MyListener("prof listener"),
+ * true);
+ * :
+ * </pre>
+ *
+ * Âè1°ú¿ô¤Î "SET_FSM_PROFILE" ¤Ï¡¢¥³¡¼¥ë¥Ð¥Ã¥¯¤ò¥Õ¥Ã¥¯¤¹¤ë¥Ý¥¤¥ó
+ * ¥È¤Ç¤¢¤ê¡¢°Ê²¼¤ÎÃͤò¼è¤ë¤³¤È¤¬²Äǽ¤Ç¤¢¤ë¡£¤Ê¤ª¡¢¤¹¤Ù¤Æ¤Î¥³¡¼¥ë¥Ð¥Ã
+ * ¥¯¥Ý¥¤¥ó¥È¤¬¼ÂÁõ¤µ¤ì¤Æ¤¤¤ë¤È¤Ï¸Â¤é¤º¡¢¤³¤ì¤é¤¬¸Æ¤Ó½Ð¤µ¤ì¤ë¤«¤É¤¦¤«
+ * ¤Ï¡¢FSM¥µ¡¼¥Ó¥¹¤Î¼ÂÁõ¤Ë°Í¸¤¹¤ë¡£
+ *
+ * - SET_FSM_PROFILE : FSM ProfileÀßÄê»þ
+ * - GET_FSM_PROFILE : FSM Profile¼èÆÀ»þ
+ * - ADD_FSM_STATE : FSM¤ËState¤¬Äɲ䵤줿
+ * - REMOVE_FSM_STATE : FSM¤«¤éState¤¬ºï½ü¤µ¤ì¤¿
+ * - ADD_FSM_TRANSITION : FSM¤ËÁ«°Ü¤¬Äɲ䵤줿
+ * - REMOVE_FSM_TRANSITION : FSM¤«¤éÁ«°Ü¤¬ºï½ü¤µ¤ì¤¿
+ * - BIND_FSM_EVENT : FSM¤Ë¥¤¥Ù¥ó¥È¤¬¥Ð¥¤¥ó¥É¤µ¤ì¤¿
+ * - UNBIND_FSM_EVENT : FSM¤Ë¥¤¥Ù¥ó¥È¤¬¥¢¥ó¥Ð¥¤¥ó¥É¤µ¤ì¤¿
+ *
+ * Âè2°ú¿ô¤Ï¥ê¥¹¥Ê¥ª¥Ö¥¸¥§¥¯¥È¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£Âè3°ú¿ô¤Ï¥ª¥Ö¥¸¥§¥¯¥È
+ * ¼«Æ°ºï½ü¥Õ¥é¥°¤Ç¤¢¤ê¡¢true ¤Î¾ì¹ç¤Ï¡¢RTObjectºï½ü»þ¤Ë¼«Æ°Åª¤Ë¥ê¥¹
+ * ¥Ê¥ª¥Ö¥¸¥§¥¯¥È¤¬ºï½ü¤µ¤ì¤ë¡£false¤Î¾ì¹ç¤Ï¡¢¥ª¥Ö¥¸¥§¥¯¥È¤Î½ê͸¢¤Ï
+ * ¸Æ¤Ó½Ð¤·Â¦¤Ë»Ä¤ê¡¢ºï½ü¤Ï¸Æ¤Ó½Ð¤·Â¦¤ÎÀÕǤ¤Ç¹Ô¤ï¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
+ * RTObject ¤Î¥é¥¤¥Õ¥µ¥¤¥¯¥ëÃæ¤Ë¥³¡¼¥ë¥Ð¥Ã¥¯¤¬É¬Íפʤé¤Ð¾åµ¤Î¤è¤¦¤Ê
+ * ¸Æ¤Ó½Ð¤·Êý¤ÇÂè3°ú¿ô¤ò true ¤È¤·¤Æ¤ª¤¯¤È¤è¤¤¡£µÕ¤Ë¡¢¥³¡¼¥ë¥Ð¥Ã¥¯¤ò
+ * ¾õ¶·Åù¤Ë±þ¤¸¤Æ¥»¥Ã¥È¤·¤¿¤ê¥¢¥ó¥»¥Ã¥È¤·¤¿¤ê¤¹¤ëɬÍפ¬¤¢¤ë¾ì¹ç¤Ï
+ * false¤È¤·¤ÆÃÖ¤¡¢¥ê¥¹¥Ê¥ª¥Ö¥¸¥§¥¯¥È¤Î¥Ý¥¤¥ó¥¿¤ò¥á¥ó¥ÐÊÑ¿ô¤Ê¤É¤ËÊÝ
+ * »ý¤·¤Æ¤ª¤¡¢addFsmProfileListener()/removeFsmProfileListener() ¤Ë
+ * ¤è¤ê¡¢¥»¥Ã¥È¤È¥¢¥ó¥»¥Ã¥È¤ò´ÉÍý¤¹¤ë¤È¤¤¤Ã¤¿»È¤¤Êý¤â²Äǽ¤Ç¤¢¤ë¡£
+ *
* @else
* @class FsmProfileListener class
* @brief FsmProfileListener class
*
- * This class is abstract base class for listener classes that
- * provides callbacks for various events in rtobject.
+ * FsmProfileListener class is a base class for the listener
+ * objects which realize callback to hook FSM Profile related actions.
+ * To hook execution just before a FSM profile action, the callback object
+ * should be defined as follows, and set to RTObject through
+ * appropriate callback set function.
*
+ * <pre>
+ * class MyListener
+ * : public FsmProfileListener
+ * {
+ * std::string m_name;
+ * public:
+ * MyListener(const char* name) : m_name(name) {}
+ * virtual ~MyListener() {}
+ *
+ * virtual void operator()(const ::RTC::FsmProfile& fsmprof)
+ * {
+ * std::cout << "Listner name: " m_name << std::endl;
+ * };
+ * };
+ * </pre>
+ *
+ * The listener class defined above is set to RTObject as follows.
+ *
+ * <pre>
+ * RTC::ReturnCode_t ConsoleIn::onInitialize()
+ * {
+ * addFsmProfileListener(SET_FSM_PROFILE,
+ * new MyListener("prof listener"),
+ * true);
+ * :
+ * </pre>
+ *
+ * The first argument "SET_FSM_PROFILE" specifies callback hook
+ * point, and the following values are available. Not all the
+ * callback points are implemented. It depends on the FSM service
+ * implementations.
+ *
+ * - SET_FSM_PROFILE : Setting FSM Profile
+ * - GET_FSM_PROFILE : Getting FSM Profile
+ * - ADD_FSM_STATE : A State added to the FSM
+ * - REMOVE_FSM_STATE : A State removed from FSM
+ * - ADD_FSM_TRANSITION : A transition added to the FSM
+ * - REMOVE_FSM_TRANSITION : A transition removed from FSM
+ * - BIND_FSM_EVENT : An event bounded to the FSM
+ * - UNBIND_FSM_EVENT : An event unbounded to the FSM
+ *
+ * The second argument is a pointers to the listener object. The
+ * third argument is a flag for automatic object destruction. When
+ * "true" is given to the third argument, the given object in second
+ * argument is automatically destructed with RTObject. In the "false
+ * " case, the ownership of the object is left in the caller side,
+ * and then destruction of the object must be done by users'
+ * responsibility.
+ *
+ * It is good for setting "true" as third argument, if the listener
+ * object life span is equals to the RTObject's life cycle. On the
+ * otehr hand, if callbacks are required to set/unset depending on
+ * its situation, the third argument could be "false". In that
+ * case, listener objects pointers must be stored to member
+ * variables, and set/unset of the listener objects shoud be
+ * paerformed throguh
+ * addFsmProfileListener()/removeFsmProfileListener() functions.
+ *
* @endif
*/
class FsmProfileListener
@@ -464,16 +816,122 @@
* @class FsmStructureListener ¥¯¥é¥¹
* @brief FsmStructureListener ¥¯¥é¥¹
*
- * ³Æ¥¢¥¯¥·¥ç¥ó¤ËÂбþ¤¹¤ë¥æ¡¼¥¶¡¼¥³¡¼¥É¤¬¸Æ¤Ð¤ì¤ëľÁ°¤Î¥¿¥¤¥ß¥ó¥°
- * ¤Ç¥³¡¼¥ë¤µ¤ì¤ë¥ê¥¹¤Ê¥¯¥é¥¹¤Î´ðÄ쥯¥é¥¹¡£
+ * FsmStructureListener ¥¯¥é¥¹¤Ï¡¢FSM Structure¤Î¥¢¥¯¥·¥ç¥ó¤Ë´Ø¤¹¤ë¥³¡¼
+ * ¥ë¥Ð¥Ã¥¯¤ò¼Â¸½¤¹¤ë¥ê¥¹¥Ê¡¼¥ª¥Ö¥¸¥§¥¯¥È¤Î´ðÄ쥯¥é¥¹¤Ç¤¢¤ë¡£FSM
+ * Structure ¤Î¥¢¥¯¥·¥ç¥ó¤Îľ¸å¤ÎÆ°ºî¤ò¥Õ¥Ã¥¯¤·¤¿¤¤¾ì¹ç¡¢°Ê²¼¤ÎÎã¤Î¤è
+ * ¤¦¤Ë¡¢¤³¤Î¥¯¥é¥¹¤ò·Ñ¾µ¤·¤¿¥³¡¼¥ë¥Ð¥Ã¥¯¥ª¥Ö¥¸¥§¥¯¥È¤òÄêµÁ¤·¡¢Å¬ÀÚ¤Ê
+ * ¥³¡¼¥ë¥Ð¥Ã¥¯ÀßÄê´Ø¿ô¤«¤éRTObject¤ËÂФ·¤Æ¥³¡¼¥ë¥Ð¥Ã¥¯¥ª¥Ö¥¸¥§¥¯¥È¤ò
+ * ¥»¥Ã¥È¤¹¤ëɬÍפ¬¤¢¤ë¡£
*
+ * <pre>
+ * class MyListener
+ * : public FsmStructureListener
+ * {
+ * std::string m_name;
+ * public:
+ * MyListener(const char* name) : m_name(name) {}
+ * virtual ~MyListener() {}
+ * virtual void operator()(::RTC::FsmStructure& pprof)
+ * {
+ * std::cout << "Listner name: " m_name << std::endl;
+ * };
+ * };
+ * </pre>
+ *
+ * ¤³¤Î¤è¤¦¤Ë¤·¤ÆÄêµÁ¤µ¤ì¤¿¥ê¥¹¥Ê¥¯¥é¥¹¤Ï¡¢°Ê²¼¤Î¤è¤¦¤ËRTObject¤ËÂФ·
+ * ¤Æ¡¢¥»¥Ã¥È¤µ¤ì¤ë¡£
+ *
+ * <pre>
+ * RTC::ReturnCode_t ConsoleIn::onInitialize()
+ * {
+ * addFsmStructureListener(SET_FSM_STRUCTURE,
+ * new MyListener("set structure listener"),
+ * true);
+ * :
+ * </pre>
+ *
+ * Âè1°ú¿ô¤Î "SET_FSM_STRUCTURE" ¤Ï¡¢¥³¡¼¥ë¥Ð¥Ã¥¯¤ò¥Õ¥Ã¥¯¤¹¤ë¥Ý¥¤¥ó
+ * ¥È¤Ç¤¢¤ê¡¢°Ê²¼¤ÎÃͤò¼è¤ë¤³¤È¤¬²Äǽ¤Ç¤¢¤ë¡£¤Ê¤ª¡¢¤¹¤Ù¤Æ¤Î¥³¡¼¥ë¥Ð¥Ã
+ * ¥¯¥Ý¥¤¥ó¥È¤¬¼ÂÁõ¤µ¤ì¤Æ¤¤¤ë¤È¤Ï¸Â¤é¤º¡¢¤³¤ì¤é¤¬¸Æ¤Ó½Ð¤µ¤ì¤ë¤«¤É¤¦¤«
+ * ¤Ï¡¢FSM¤Î¼ÂÁõ¤Ë°Í¸¤¹¤ë¡£
+ *
+ * - SET_FSM_STRUCTURE: FSM¹½Â¤¤ÎÀßÄê
+ * - GET_FSM_STRUCTURE: FSM¹½Â¤¤Î¼èÆÀ
+ *
+ * Âè2°ú¿ô¤Ï¥ê¥¹¥Ê¥ª¥Ö¥¸¥§¥¯¥È¤Î¥Ý¥¤¥ó¥¿¤Ç¤¢¤ë¡£Âè3°ú¿ô¤Ï¥ª¥Ö¥¸¥§¥¯¥È
+ * ¼«Æ°ºï½ü¥Õ¥é¥°¤Ç¤¢¤ê¡¢true ¤Î¾ì¹ç¤Ï¡¢RTObjectºï½ü»þ¤Ë¼«Æ°Åª¤Ë¥ê¥¹
+ * ¥Ê¥ª¥Ö¥¸¥§¥¯¥È¤¬ºï½ü¤µ¤ì¤ë¡£false¤Î¾ì¹ç¤Ï¡¢¥ª¥Ö¥¸¥§¥¯¥È¤Î½ê͸¢¤Ï
+ * ¸Æ¤Ó½Ð¤·Â¦¤Ë»Ä¤ê¡¢ºï½ü¤Ï¸Æ¤Ó½Ð¤·Â¦¤ÎÀÕǤ¤Ç¹Ô¤ï¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡£
+ * RTObject ¤Î¥é¥¤¥Õ¥µ¥¤¥¯¥ëÃæ¤Ë¥³¡¼¥ë¥Ð¥Ã¥¯¤¬É¬Íפʤé¤Ð¾åµ¤Î¤è¤¦¤Ê
+ * ¸Æ¤Ó½Ð¤·Êý¤ÇÂè3°ú¿ô¤ò true ¤È¤·¤Æ¤ª¤¯¤È¤è¤¤¡£µÕ¤Ë¡¢¥³¡¼¥ë¥Ð¥Ã¥¯¤ò
+ * ¾õ¶·Åù¤Ë±þ¤¸¤Æ¥»¥Ã¥È¤·¤¿¤ê¥¢¥ó¥»¥Ã¥È¤·¤¿¤ê¤¹¤ëɬÍפ¬¤¢¤ë¾ì¹ç¤Ï
+ * false¤È¤·¤ÆÃÖ¤¡¢¥ê¥¹¥Ê¥ª¥Ö¥¸¥§¥¯¥È¤Î¥Ý¥¤¥ó¥¿¤ò¥á¥ó¥ÐÊÑ¿ô¤Ê¤É¤ËÊÝ
+ * »ý¤·¤Æ¤ª¤¡¢
+ * RTObject_impl::addPostFsmActionListener()/removePostFsmActionListener()
+ * ¤Ë¤è¤ê¡¢¥»¥Ã¥È¤È¥¢¥ó¥»¥Ã¥È¤ò´ÉÍý¤¹¤ë¤È¤¤¤Ã¤¿»È¤¤Êý¤â²Äǽ¤Ç¤¢¤ë¡£
+ *
* @else
* @class FsmStructureListener class
* @brief FsmStructureListener class
*
- * This class is abstract base class for listener classes that
- * provides callbacks for various events in rtobject.
+ * PostFsmActionListener class is a base class for the listener
+ * objects which realize callback to hook FSM structure profile
+ * related actions. To hook execution just before a FSM action, the
+ * callback object should be defined as follows, and set to RTObject
+ * through appropriate callback set function.
*
+ * <pre>
+ * class MyListener
+ * : public FsmStructureListener
+ * {
+ * std::string m_name;
+ * public:
+ * MyListener(const char* name) : m_name(name) {}
+ * virtual ~MyListener() {}
+ * virtual void operator()(::RTC::FsmStructure& pprof)
+ * {
+ * std::cout << "Listner name: " m_name << std::endl;
+ * };
+ * };
+ * </pre>
+ *
+ * The listener class defined above is set to RTObject as follows.
+ *
+ * <pre>
+ * RTC::ReturnCode_t ConsoleIn::onInitialize()
+ * {
+ * addFsmStructureListener(SET_FSM_STRUCTURE,
+ * new MyListener("set structure listener"),
+ * true);
+ * :
+ * </pre>
+ *
+ * The first argument "SET_FSM_STRUCTURE" specifies callback hook
+ * point, and the following values are available. Not all the
+ * callback points are implemented. It depends on the FSM
+ * implementations.
+ *
+ * - SET_FSM_STRUCTURE: Setting FSM structure
+ * - GET_FSM_STRUCTURE: Getting FSM structure
+ *
+ * The second argument is a pointers to the listener object. The
+ * third argument is a flag for automatic object destruction. When
+ * "true" is given to the third argument, the given object in second
+ * argument is automatically destructed with RTObject. In the "false
+ * " case, the ownership of the object is left in the caller side,
+ * and then destruction of the object must be done by users'
+ * responsibility.
+ *
+ * It is good for setting "true" as third argument, if the listener
+ * object life span is equals to the RTObject's life cycle. On the
+ * otehr hand, if callbacks are required to set/unset depending on
+ * its situation, the third argument could be "false". In that
+ * case, listener objects pointers must be stored to member
+ * variables, and set/unset of the listener objects shoud be
+ * paerformed throguh
+ * RTObject_impl::addPostFsmActionListener()/removePostFsmActionListener()
+ * functions.
+ *
* @endif
*/
class FsmStructureListener
@@ -541,7 +999,6 @@
virtual void operator()(::RTC::FsmStructure& pprof) = 0;
};
-
//============================================================
// Holder classes
//============================================================
Copied: trunk/OpenRTM-aist/src/lib/rtm/Macho.cpp (from rev 2826, branches/FSM4RTC/OpenRTM-aist/src/lib/rtm/Macho.cpp)
===================================================================
--- trunk/OpenRTM-aist/src/lib/rtm/Macho.cpp (rev 0)
+++ trunk/OpenRTM-aist/src/lib/rtm/Macho.cpp 2017-12-10 21:20:20 UTC (rev 3116)
@@ -0,0 +1,387 @@
+// Macho - C++ Machine Objects
+//
+// The Machine Objects class library (in short Macho) allows the creation of
+// state machines based on the "State" design pattern in straight C++. It
+// extends the pattern with the option to create hierarchical state machines,
+// making it possible to convert the popular UML statechart notation to working
+// code in a straightforward way. Other features are entry and exit actions,
+// state histories and state variables.
+//
+// Copyright (c) 2005 by Eduard Hiti (feedback to macho at ehiti.de)
+//
+// Version 0.9.6 (released 2007-09-01)
+//
+// See Macho.hpp for more information.
+#include <iostream>
+//#include "Macho.hpp"
+#include <rtm/Macho.h>
+using namespace Macho;
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Helper functions for tracing.
+#ifdef MACHO_TRACE
+# include <iostream>
+
+ void MACHO_TRC1(const char * msg) { std::cout << msg << std::endl; }
+ void MACHO_TRC2(const char * state, const char * msg)
+ { std::cout << "State " << state << ": " << msg << std::endl; }
+ void MACHO_TRC3(const char * state, const char * msg1, const char * msg2)
+ { std::cout << "State " << state << ": " << msg1 << " " << msg2 << std::endl; }
+#else
+# define MACHO_TRC1(MSG)
+# define MACHO_TRC2(STATE, MSG)
+# define MACHO_TRC3(STATE, MSG1, MSG2)
+#endif
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Box for states which don't declare own Box class.
+_EmptyBox _EmptyBox::theEmptyBox;
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Helper functions for box creation
+template<>
+void * Macho::_createBox<_EmptyBox>(void * & place) {
+ return &_EmptyBox::theEmptyBox;
+}
+
+template<>
+void Macho::_deleteBox<_EmptyBox>(void * & box, void * & place) {
+}
+
+#ifdef MACHO_SNAPSHOTS
+template<>
+void * Macho::_cloneBox<_EmptyBox>(void * other) {
+ return &_EmptyBox::theEmptyBox;
+}
+#endif
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Implementation for Alias
+void Alias::setState(_MachineBase & machine) const {
+ machine.setPendingState(key()->instanceGenerator(machine), myInitializer->clone());
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Implementation for StateSpecification
+_StateInstance & _StateSpecification::_getInstance(_MachineBase & machine) {
+ // Look first in machine for existing StateInstance.
+ _StateInstance * & instance = machine.getInstance(0);
+ if (!instance)
+ instance = new _RootInstance(machine, 0);
+
+ return *instance;
+}
+
+void _StateSpecification::_shutdown() {
+ _myStateInstance.machine().shutdown();
+}
+
+void _StateSpecification::_restore(_StateInstance & current) {
+ _myStateInstance.machine().myCurrentState = ¤t;
+}
+
+void _StateSpecification::setState(const Alias & state) {
+ state.setState(_myStateInstance.machine());
+}
+
+#ifdef MACHO_SNAPSHOTS
+void _StateSpecification::setState(_StateInstance & current) {
+ _myStateInstance.machine().setPendingState(current, &_theDefaultInitializer);
+}
+#endif
+
+
+////////////////////////////////////////////////////////////////////////////////
+// StateInstance implementation
+_StateInstance::_StateInstance(_MachineBase & machine, _StateInstance * parent)
+ : myMachine(machine)
+ , mySpecification(0)
+ , myHistory(0)
+ , myParent(parent)
+ , myBox(0)
+ , myBoxPlace(0)
+{}
+
+_StateInstance::~_StateInstance() {
+ if (myBoxPlace)
+ ::operator delete(myBoxPlace);
+
+ delete mySpecification;
+}
+
+void _StateInstance::entry(_StateInstance & previous, bool first) {
+ // Only Root has no parent
+ if (!myParent)
+ return;
+
+ // first entry or previous state is not substate -> perform entry
+ if (first || !previous.isChild(*this)) {
+ myParent->entry(previous, false);
+
+ createBox();
+
+ MACHO_TRC2(name(), "Entry");
+ mySpecification->entry();
+ }
+}
+
+void _StateInstance::exit(_StateInstance & next) {
+ // Only Root has no parent
+ if (!myParent)
+ return;
+
+ // self transition or next state is not substate -> perform exit
+ if (this == &next || !next.isChild(*this)) {
+ MACHO_TRC2(name(), "Exit");
+ mySpecification->exit();
+
+ // EmptyBox should be most common box, so optimize for this case.
+ if (myBox != &_EmptyBox::theEmptyBox)
+ mySpecification->_deleteBox(*this);
+
+ myParent->exit(next);
+ }
+}
+
+void _StateInstance::init(bool history) {
+ if (history && myHistory) {
+ MACHO_TRC3(name(), "History transition to", myHistory->name());
+ myMachine.setPendingState(*myHistory, &_theDefaultInitializer);
+ } else {
+ MACHO_TRC2(name(), "Init");
+ mySpecification->init();
+ }
+
+ myHistory = 0;
+}
+
+#ifdef MACHO_SNAPSHOTS
+void _StateInstance::copy(_StateInstance & original) {
+ if (original.myHistory) {
+ _StateInstance * history = myMachine.getInstance(original.myHistory->id());
+ assert(history);
+ setHistory(history);
+ }
+
+ if (original.myBox)
+ cloneBox(original.myBox);
+}
+
+_StateInstance * _StateInstance::clone(_MachineBase & newMachine) {
+ assert(!newMachine.getInstance(id()));
+
+ _StateInstance * parent = 0;
+ if (myParent)
+ // Tell other machine to clone parent first.
+ parent = newMachine.createClone(myParent->id(), myParent);
+
+ _StateInstance * clone = create(newMachine, parent);
+ return clone;
+}
+#endif
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Base class for Machine objects.
+_MachineBase::_MachineBase()
+ : myCurrentState(0)
+ , myPendingState(0)
+ , myPendingInit(0)
+ , myPendingBox(0) // Deprecated!
+ , myPendingEvent(0)
+{}
+
+_MachineBase::~_MachineBase() {
+ assert(!myPendingInit);
+
+ delete[] myInstances;
+ delete myPendingEvent;
+}
+
+Alias _MachineBase::currentState() const {
+ return myCurrentState->key();
+}
+
+void _MachineBase::setState(_StateInstance & instance, _Initializer * init) {
+ setPendingState(instance, init);
+ rattleOn();
+}
+
+void _MachineBase::setState(const Alias & state) {
+ state.setState(*this);
+ rattleOn();
+}
+
+void _MachineBase::start(_StateInstance & instance) {
+ MACHO_TRC1("Starting Machine");
+
+ // Start with Root state
+ myCurrentState = &_StateSpecification::_getInstance(*this);
+ // Then go to state
+ setState(instance, &_theDefaultInitializer);
+}
+
+void _MachineBase::start(const Alias & state) {
+ MACHO_TRC1("Starting Machine");
+
+ // Start with Root state
+ myCurrentState = &_StateSpecification::_getInstance(*this);
+ // Then go to state
+ setState(state);
+}
+
+void _MachineBase::shutdown() {
+ assert(!myPendingState);
+
+ MACHO_TRC1("Shutting down Machine");
+
+ // Performs exit actions by going to Root (=StateSpecification) state.
+ setState(_StateSpecification::_getInstance(*this), &_theDefaultInitializer);
+
+ myCurrentState = 0;
+}
+
+void _MachineBase::allocate(unsigned int count) {
+ myInstances = new _StateInstance *[count];
+ for (unsigned int i = 0; i < count; ++i)
+ myInstances[i] = 0;
+}
+
+void _MachineBase::free(unsigned int count) {
+ // Free from end of list, so that child states are freed first
+ unsigned int i = count;
+ while (i > 0) {
+ --i;
+ delete myInstances[i];
+ myInstances[i] = 0;
+ }
+}
+
+// Clear history of state and children.
+void _MachineBase::clearHistoryDeep(unsigned int count, const _StateInstance & instance) const {
+ for (unsigned int i = 0; i < count; ++i) {
+ _StateInstance * s = myInstances[i];
+ if (s && s->isChild(instance))
+ s->setHistory(0);
+ }
+}
+
+#ifdef MACHO_SNAPSHOTS
+void _MachineBase::copy(_StateInstance ** others, unsigned int count) {
+ // Create StateInstance objects
+ for (ID i = 0; i < count; ++i)
+ createClone(i, others[i]);
+
+ // Copy StateInstance object's state
+ for (ID i = 0; i < count; ++i) {
+ _StateInstance * state = myInstances[i];
+ if (state) {
+ assert(others[i]);
+ state->copy(*others[i]);
+ }
+ }
+}
+
+_StateInstance * _MachineBase::createClone(ID id, _StateInstance * original) {
+ _StateInstance * & clone = getInstance(id);
+
+ // Object already created?
+ if (!clone && original)
+ clone = original->clone(*this);
+
+ return clone;
+}
+#endif
+
+void _MachineBase::rattleOn() {
+ assert(myCurrentState);
+
+ while (myPendingState || myPendingEvent) {
+
+ // Loop here because init actions might change state again.
+ while (myPendingState) {
+ MACHO_TRC3(myCurrentState->name(), "Transition to", myPendingState->name());
+
+#ifndef NDEBUG
+ // Entry/Exit actions may not dispatch events: set dummy event.
+ if (!myPendingEvent)
+ myPendingEvent = (_IEventBase *) &myPendingEvent;
+#endif
+
+ // Perform exit actions (which exactly depends on new state).
+ myCurrentState->exit(*myPendingState);
+
+ // Store history information for previous state now.
+ // Previous state will be used for deep history.
+ myCurrentState->setHistorySuper(*myCurrentState);
+
+ _StateInstance * previous = myCurrentState;
+ myCurrentState = myPendingState;
+
+ // Deprecated!
+ if (myPendingBox) {
+ myCurrentState->setBox(myPendingBox);
+ myPendingBox = 0;
+ }
+
+ // Perform entry actions on next state's parents (which exactly depends on previous state).
+ myCurrentState->entry(*previous);
+ std::cout << "### State ### " << myCurrentState->name() << std::endl;
+ // State transition complete.
+ // Clear 'pending' information just now so that setState would assert in exits and entries, but not in init.
+ myPendingState = 0;
+
+ // Use initializer to call proper "init" action.
+ myPendingInit->execute(*myCurrentState);
+
+ assert("Init may only transition to proper substates" &&
+ (!myPendingState ||
+ (myPendingState->isChild(*myCurrentState) && (myCurrentState != myPendingState)))
+ );
+
+#ifndef NDEBUG
+ // Clear dummy event if need be
+ if (myPendingEvent == (_IEventBase *) &myPendingEvent)
+ myPendingEvent = 0;
+#endif
+ } // while (myPendingState)
+
+ if (myPendingEvent) {
+ _IEventBase * event = myPendingEvent;
+ myPendingEvent = 0;
+ event->dispatch(*myCurrentState);
+ delete event;
+ }
+
+ } // while (myPendingState || myPendingEvent)
+
+ myPendingInit = 0;
+
+} // rattleOn
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Implementation for _AdaptingInitializer
+
+Key _AdaptingInitializer::adapt(Key key) {
+ ID id = static_cast<_KeyData *>(key)->id;
+ const _StateInstance * instance = myMachine.getInstance(id);
+ _StateInstance * history = 0;
+
+ if (instance)
+ history = instance->history();
+
+ return history ? history->key() : key;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Singleton initializers.
+_DefaultInitializer _theDefaultInitializer;
+_HistoryInitializer _theHistoryInitializer;
+
Copied: trunk/OpenRTM-aist/src/lib/rtm/Macho.h (from rev 2826, branches/FSM4RTC/OpenRTM-aist/src/lib/rtm/Macho.h)
===================================================================
--- trunk/OpenRTM-aist/src/lib/rtm/Macho.h (rev 0)
+++ trunk/OpenRTM-aist/src/lib/rtm/Macho.h 2017-12-10 21:20:20 UTC (rev 3116)
@@ -0,0 +1,1980 @@
+#ifndef __MACHO_HPP__
+#define __MACHO_HPP__
+
+//#if defined(_MSC_VER)
+//#pragma warning(push)
+//#pragma warning(disable:4512 4251)
+//#elif defined(__GNUC__) && (__GNUC_MINOR__ >= 6)
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
+#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
+//#endif
+
+// Macho - C++ Machine Objects
+//
+// The Machine Objects class library (in short Macho) allows the creation of
+// state machines based on the "State" design pattern in straight C++. It
+// extends the pattern with the option to create hierarchical state machines,
+// making it possible to convert the popular UML statechart notation to working
+// code in a straightforward way. Other features are entry and exit actions,
+// state histories and state variables.
+//
+// Copyright (c) 2005 by Eduard Hiti (feedback to macho at ehiti.de)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+//
+// You are encouraged to provide any changes, extensions and corrections for
+// this software to the author at the above-mentioned email address for
+// inclusion into future versions.
+//
+//
+// Description:
+//
+// States are represented as C++ classes. The hierarchy of states follows the
+// inheritance relation between these state classes. A set of state classes for
+// a single state machine derives directly or indirectly from a top state class,
+// making it the composite state holding all other states. Events are processed
+// by calling virtual methods of the top state class. Substates redefine the
+// behaviour of these event handler methods.
+//
+// Special methods "entry", "exit" and "init" are called on state entry, state
+// exit and state initialization of super- and substates (in the order defined
+// by statechart semantics and current machine state).
+//
+// An object of type "Machine" maintains the current state of a state machine
+// and dispatches events to it. The "Machine" type is a template class
+// parametrized with the top state class of the state machine to be run.
+//
+// State data is not kept in state classes (because state class instances are
+// created just once and then reused, whereas state data should be instantiated
+// or destroyed each time its state is entered or left). State data is put in
+// "Box" types specific to each state class instead, which are managed by the
+// Machine object. Boxes are retrieved by calling the "box" method.
+// Superstate boxes are accessible by qualifiying the "box" method with the
+// state class name (e.g. TOP::box()).
+//
+// A history of entered substates can be kept for superstates. With a special
+// transition into the superstate the history substate can be reentered. History
+// can be shallow (only direct substates) or deep (any substate).
+//
+//
+// Example:
+//
+// #include "Macho.hpp"
+// #include <iostream>
+// using namespace std;
+//
+// namespace Example {
+// TOPSTATE(Top) {
+// struct Box {
+// Box() : data(0) {}
+// long data;
+// };
+//
+// STATE(Top)
+//
+// virtual void event1() {}
+// virtual void event2() {}
+//
+// private:
+// void entry();
+// void exit();
+// void init();
+// };
+//
+// SUBSTATE(Super, Top) {
+// STATE(Super)
+// HISTORY()
+//
+// private:
+// void entry();
+// void exit();
+// };
+//
+// SUBSTATE(StateA, Super) {
+// struct Box {
+// Box() : data(0) {}
+// int data;
+// };
+//
+// STATE(StateA)
+//
+// void event1();
+//
+// private:
+// void entry();
+// void exit();
+// void init(int i);
+// };
+//
+// SUBSTATE(StateB, Super) {
+// STATE(StateB)
+//
+// void event2();
+//
+// private:
+// void entry();
+// void exit();
+// };
+//
+// void Top::entry() { cout << "Top::entry" << endl; }
+// void Top::exit() { cout << "Top::exit" << endl; }
+// void Top::init() { setState<StateA>(42); }
+//
+// void Super::entry() { cout << "Super::entry" << endl; }
+// void Super::exit() { cout << "Super::exit" << endl; }
+//
+// void StateA::entry() { cout << "StateA::entry" << endl; }
+// void StateA::init(int i) { box().data = i; }
+// void StateA::exit() { cout << "StateA::exit" << endl; }
+// void StateA::event1() { setState<StateB>(); }
+//
+// void StateB::entry() { cout << "StateB::entry" << endl; }
+// void StateB::exit() { cout << "StateB::exit" << endl; }
+// void StateB::event2() { setState<StateA>(); }
+// }
+//
+// int main() {
+// Macho::Machine<Example::Top> m;
+// m->event1();
+// m->event2();
+//
+// return 0;
+// }
+//
+// Output is:
+//
+// Top::entry
+// Super::entry
+// StateA::entry
+// StateA::exit
+// StateB::entry
+// StateB::exit
+// StateA::entry
+// StateA::exit
+// Super::exit
+// Top::exit
+//
+//
+// Version History:
+//
+// 0.9.6 (released 2007-09-01):
+// - Changes to state transition semantics (see file "changes_0_9_6.txt")
+// - New mechanism for state initialization
+// - Runtime reflection on state relationships now possible
+//
+// 0.9.5 (released 2007-05-01):
+// - Introduction of parametrized state transitions
+//
+// 0.9.4 (released 2006-06-01):
+// - Snapshot functionality added
+//
+// 0.9.3 (released 2006-04-20):
+// - Code reorganization (file Macho.cpp added)
+//
+// 0.9.2 (released 2006-04-10):
+// - Memory leak plugged
+// - MSVC6 version updated
+//
+// 0.9.1 (released 2006-03-30):
+// - Introduction of persistent boxes
+// - Speed and size optimizations
+// - Machine instance can be accessed in event handlers with method "machine"
+//
+// 0.9 (released 2006-01-15):
+// - Introduction of queuable event type
+//
+// 0.8.2 (released 2005-12-15):
+// - Code size reduction by minimizing use of template classes
+//
+// 0.8.1 (released 2005-12-01):
+// - Added MSVC6 variant (see directory "msvc6")
+// - Added method "clearHistoryDeep"
+//
+// 0.8 (released 2005-11-01):
+// - Initial release
+//
+
+#include <new>
+#include <cassert>
+
+class TestAccess;
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Check type equality at compile time.
+template<class T, class U>
+struct __SameType {
+};
+
+template<class T>
+struct __SameType<T, T> {
+ typedef bool Check;
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Various macros for state and history declaration
+
+// Use this macro to define your top state class.
+#define TOPSTATE(TOP) \
+ struct TOP : public ::Macho::Link< TOP, ::Macho::TopBase< TOP > >
+
+// Use this macro for all other state classes.
+#define SUBSTATE(STATE, SUPERSTATE) \
+ struct STATE : public ::Macho::Link< STATE, SUPERSTATE >
+
+// Use this macro in your class definition to give it state functionality
+// (mandatory). If you have a state box declare it BEFORE macro invocation!
+#define STATE(S) \
+public: \
+ typedef S SELF; \
+ /* Constructor and destructor already defined: you can't (and shouldn't) have your own! */ \
+ /* For the user a state class "constructor" and "destructor" are its entry and exit method! */ \
+ S(::Macho::_StateInstance & instance) : ::Macho::Link<S, SUPER>(instance) { \
+ /* Compile time check: S must derive directly from Link<S, SUPER> */ \
+ typedef ::__SameType< ::Macho::Link<S, SUPER>, LINK>::Check MustDeriveFromLink; \
+ } \
+ ~S() {} \
+ static const char * _state_name() { return #S; } \
+ /* Get to your Box with this method: */ \
+ Box & box() { return *static_cast<Box *>(_box()); } \
+ friend class ::_VS8_Bug_101615;
+
+// Use this macro to select deep history strategy.
+#define DEEPHISTORY() \
+private: \
+ /* If no superstate has history, SUPER::_setHistorySuper is a NOOP */ \
+ virtual void _saveHistory(::Macho::_StateInstance & self, ::Macho::_StateInstance & shallow, ::Macho::_StateInstance & deep) \
+ { self.setHistory(&deep); SELF::SUPER::_setHistorySuper(self, deep); } \
+protected: \
+ /* Substates may use _setHistorySuper to bubble up history */ \
+ virtual void _setHistorySuper(::Macho::_StateInstance & self, ::Macho::_StateInstance & deep) \
+ { self.setHistorySuper(deep); } \
+public:
+
+// Use this macro to select shallow history strategy.
+#define HISTORY() \
+private: \
+ /* If no superstate has history, SUPER::_setHistorySuper is a NOOP */ \
+ virtual void _saveHistory(::Macho::_StateInstance & self, ::Macho::_StateInstance & shallow, ::Macho::_StateInstance & deep) \
+ { self.setHistory(&shallow); SELF::SUPER::_setHistorySuper(self, deep); } \
+protected: \
+ /* Substates may use _setHistorySuper to bubble up history */ \
+ virtual void _setHistorySuper(::Macho::_StateInstance & self, ::Macho::_StateInstance & deep) \
+ { self.setHistorySuper(deep); } \
+public:
+
+// Use this macro to have boxes survive state transitions
+#define PERSISTENT() \
+private: \
+ virtual void _deleteBox(::Macho::_StateInstance & instance) {} \
+public:
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Everything else is put into namespace 'Macho'.
+// Some identifiers are prefixed with an underscore to prevent name clashes with
+// deriving classes or to mark things as library internal. Don't touch things
+// with an underscore prefix!
+namespace Macho {
+
+ class _MachineBase;
+
+ template<class T>
+ class Machine;
+
+ template<class T>
+ class IEvent;
+
+ class _StateInstance;
+
+ // Unique identifier of states.
+ typedef void * Key;
+
+ // Also an unique identifier of states, build from consecutive integers.
+ // Use Key to get to ID.
+ typedef unsigned int ID;
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Box for states which don't declare own Box class.
+ class _EmptyBox {
+ _EmptyBox() {}
+ public:
+ static _EmptyBox theEmptyBox;
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Helper functions for box creation
+ template<class B>
+ void * _createBox(void * & place) {
+ if (!place)
+ place = ::operator new(sizeof(B));
+
+ new (place) B;
+
+ void * box = place;
+ place = 0;
+
+ return box;
+ }
+
+ template<class B>
+ void _deleteBox(void * & box, void * & place) {
+ assert(box);
+ assert(!place);
+
+ static_cast<B *>(box)->~B();
+ place = box;
+ box = 0;
+ }
+
+#ifdef MACHO_SNAPSHOTS
+ template<class B>
+ void * _cloneBox(void * other) {
+ assert(other);
+ return new B(*static_cast<B *>(other));
+ }
+#endif
+
+ // Specializations for EmptyBox:
+ // EmptyBox object gets reused over and over and never is deleted.
+ template<>
+ void * _createBox<_EmptyBox>(void * & place);
+
+ template<>
+ void _deleteBox<_EmptyBox>(void * & box, void * & place);
+
+#ifdef MACHO_SNAPSHOTS
+ template<>
+ void * _cloneBox<_EmptyBox>(void * other);
+#endif
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Essential information pointed at by state key.
+ struct _KeyData {
+ typedef _StateInstance & (*Generator)(_MachineBase & machine);
+ typedef bool (*Predicate)(Key);
+ typedef const char * (*NameFn)();
+
+ // Get StateInstance object from key.
+ const Generator instanceGenerator;
+
+ // Is state of given key a child state?
+ const Predicate childPredicate;
+
+ const NameFn name;
+ const ID id;
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Base class for all state classes.
+ // Also serves as 'Root' state. By entering this state we trigger entry
+ // and exit actions of user's top state.
+ class _StateSpecification {
+ public:
+ virtual ~_StateSpecification() {}
+
+ static bool isChild(Key key) {
+ return false;
+ }
+
+ protected:
+ _StateSpecification(_StateInstance & instance)
+ : _myStateInstance(instance)
+ {}
+
+ // Initiate transition to a new state.
+ // Template parameter S is the new state to enter.
+ // Transition is performed AFTER control flow returns to the Machine object.
+ // Initiating more than one transition is considered an error!
+ // The new state may receive parameters for its 'init' methods:
+ // setState<StateA>("someData");
+ template<class S>
+ void setState();
+
+ template<class S, class P1>
+ void setState(const P1 & p1);
+
+ template<class S, class P1, class P2>
+ void setState(const P1 & p1, const P2 & p2);
+
+ template<class S, class P1, class P2, class P3>
+ void setState(const P1 & p1, const P2 & p2, const P3 & p3);
+
+ template<class S, class P1, class P2, class P3, class P4>
+ void setState(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4);
+
+ template<class S, class P1, class P2, class P3, class P4, class P5>
+ void setState(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5);
+
+ template<class S, class P1, class P2, class P3, class P4, class P5, class P6>
+ void setState(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5, const P6 & p6);
+
+ // Initiate transition to a state's history.
+ // If state has no history, transition is to the state itself.
+ template<class S>
+ void setStateHistory();
+
+ // Initiate transition to a new state.
+ // Parameter 'state' is the new state to enter.
+ // See above and class 'Alias' for more information.
+ void setState(const class Alias & state);
+
+ // Deprectated!
+ template<class S>
+ void setStateBox(typename S::Box * box = 0);
+
+ // Deprectated!
+ template<class S>
+ void setStateDirect(typename S::Box * box = 0);
+
+ // 'Restore from snapshot' event: set current state.
+ // Default implementation: Does not trigger entry actions!
+ virtual void _restore(_StateInstance & current);
+
+ // only to be used in _restore
+ void setState(_StateInstance & current);
+
+ // 'Shutdown machine' event: exit all states.
+ // Default implementation: Triggers exit actions!
+ // Override empty to omit calling exit actions.
+ virtual void _shutdown();
+
+ // This is the method to bubble up history information
+ // for states whose superstates have no history (so does nothing).
+ virtual void _setHistorySuper(_StateInstance & self, _StateInstance & deep) {}
+
+ private:
+ // State exit. Not allowed to initiate state change.
+ virtual void exit() {}
+
+ // State entry. Not allowed to initiate state change.
+ virtual void entry() {}
+
+ // Special kind of state entry: Upon transition to a new state,
+ // entry methods of that state and its superstates are called;
+ // 'init' however is called only on the one state the transition
+ // actually goes to.
+ // Is allowed to change state (to child states).
+ virtual void init() {}
+
+ private:
+ // C++ needs something like package visibility
+
+ // for _myStateInstance
+ template<class T>
+ friend class TopBase;
+
+ // for _getInstance
+ template<class C, class P>
+ friend class Link;
+
+ friend class _StateInstance;
+ friend class _RootInstance;
+
+ friend class _MachineBase;
+
+ // Create StateInstance object of state.
+ static _StateInstance & _getInstance(_MachineBase & machine);
+
+ virtual void _deleteBox(_StateInstance & instance) {}
+
+ // Default history strategy (no history).
+ virtual void _saveHistory(_StateInstance & self, _StateInstance & shallow, _StateInstance & deep) {}
+
+ private:
+ _StateInstance & _myStateInstance;
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Base class for user defined top state (and indirectly all other states).
+ template<class T>
+ class TopBase : public _StateSpecification {
+ public:
+ // This typedef is an alias for user defined top state in all (sub)states.
+ typedef T TOP;
+
+ protected:
+ TopBase(_StateInstance & instance)
+ : _StateSpecification(instance)
+ {}
+
+ void dispatch(IEvent<TOP> * event);
+
+ const Machine<TOP> & machine();
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // This class links substate specifications to superstate specifications by
+ // deriving from the superstate and being derived from by the substate.
+ // Substates inherit event handlers from superstates for reuse or redefinition
+ // this way.
+ template<class C, class P>
+ class Link : public P {
+ public:
+ // Alias for superstate.
+ typedef P SUPER;
+
+ // Alias for topstate.
+ typedef typename P::TOP TOP;
+
+ // Default box type.
+ typedef _EmptyBox Box;
+
+ // Get unique key of state.
+ static Key key();
+
+ static Alias alias();
+
+ static bool isChild(Key other) {
+ return key() == other || SUPER::isChild(other);
+ }
+
+ static bool isParent(Key other) {
+ return static_cast<_KeyData *>(other)->childPredicate(key());
+ }
+
+ // Is machine m in this state?
+ static bool isCurrent(const _MachineBase & m);
+
+ // Deprecated!
+ // Is machine m in exactly this state?
+ static bool isCurrentDirect(const _MachineBase & m);
+
+ static void clearHistory(const _MachineBase & m);
+
+ static void clearHistoryDeep(const _MachineBase & m);
+
+ static Alias history(const _MachineBase & m);
+
+ protected:
+ // Needed to perform compile time checks.
+ typedef Link<C, P> LINK;
+
+ Link(_StateInstance & instance);
+
+ // These definitions seem redundant but they are not!
+ // They override parent definitions so each substate gets either
+ // this default or their own, but never its parents definitions.
+ virtual void entry() {}
+ virtual void init() {}
+ virtual void exit() {}
+
+ // This method keeps '_myStateInstance' attribute private.
+ void * _box();
+
+ private:
+ // for _getInstance
+ template<class U, class V>
+ friend class Link;
+
+ // for _getInstance
+ friend class _StateSpecification;
+
+ // for _getInstance
+ friend class Machine<TOP>;
+
+ // for _getInstance
+ friend class Alias;
+
+ // for Tests
+ friend class ::TestAccess;
+
+ // Create StateInstance object of state.
+ static _StateInstance & _getInstance(_MachineBase & machine);
+
+ // Box is by default not persistent. Not redundant!
+ virtual void _deleteBox(_StateInstance & instance);
+
+ // Default history strategy (no history). Not redundant!
+ virtual void _saveHistory(_StateInstance & self, _StateInstance & shallow, _StateInstance & deep) {
+ // Bubble up history. If no superstate has history, _setHistorySuper will do nothing.
+ this->_setHistorySuper(self, deep);
+ }
+
+ private:
+ _StateInstance & _myStateInstance;
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Unique identifier for state S.
+ template<class S>
+ class StateID {
+ public:
+ static const ID value;
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // StateInstance maintains machine specific data about a state. Keeps history, box
+ // and state object for state. StateInstance object is created the first time state
+ // is entered. There is at most one StateInstance object per state per machine
+ // instance.
+ class _StateInstance {
+ protected:
+ _StateInstance(_MachineBase & machine, _StateInstance * parent);
+
+ public:
+ virtual ~_StateInstance();
+
+ // Perform entry actions.
+ // 'first' is true on very first call.
+ void entry(_StateInstance & previous, bool first = true);
+
+ // Perform exit actions.
+ void exit(_StateInstance & next);
+
+ // Perform init action.
+ void init(bool history);
+
+ void saveHistory(_StateInstance & shallow, _StateInstance & deep) {
+ // Check state's history strategy.
+ mySpecification->_saveHistory(*this, shallow, deep);
+ }
+
+ // Update superstate's history information:
+ void setHistorySuper(_StateInstance & deep) {
+ if (myParent)
+ // Let it choose between deep or shallow history.
+ myParent->saveHistory(*this, deep);
+ }
+
+#ifdef MACHO_SNAPSHOTS
+ // Copy state of another StateInstance object.
+ void copy(_StateInstance & original);
+
+ // Create a clone of StateInstance object for another machine.
+ _StateInstance * clone(_MachineBase & newMachine);
+#endif
+
+ void shutdown() {
+ mySpecification->_shutdown();
+ }
+
+ void restore(_StateInstance & instance) {
+ mySpecification->_restore(instance);
+ }
+
+ virtual ID id() = 0;
+
+ virtual Key key() = 0;
+
+ virtual const char * name() = 0;
+
+ // 'Virtual constructor' needed for cloning.
+ virtual _StateInstance * create(_MachineBase & machine, _StateInstance * parent) = 0;
+
+ virtual void createBox() = 0;
+ virtual void deleteBox() = 0;
+#ifdef MACHO_SNAPSHOTS
+ virtual void cloneBox(void * box) = 0;
+#endif
+
+ // Deprecated!
+ void setBox(void * box) {
+ assert(!myBox);
+
+ if (myBoxPlace) {
+ // Free cached memory of previously used box.
+ ::operator delete(myBoxPlace);
+ myBoxPlace = 0;
+ }
+
+ myBox = box;
+ }
+
+ // Is 'instance' a superstate?
+ bool isChild(const _StateInstance & instance) {
+ return this == &instance || (myParent && myParent->isChild(instance));
+ }
+
+ _StateSpecification & specification() {
+ assert(mySpecification);
+ return *mySpecification;
+ }
+
+ void * box() {
+ assert(myBox);
+ return myBox;
+ }
+
+ _MachineBase & machine() {
+ return myMachine;
+ }
+
+ // const: History can be manipulated even on a const object.
+ void setHistory(_StateInstance * history) const {
+ myHistory = history;
+ }
+
+ _StateInstance * history() const {
+ return myHistory;
+ }
+
+ protected:
+ _MachineBase & myMachine;
+ _StateSpecification * mySpecification; // Instance of state class
+ mutable _StateInstance * myHistory;
+ _StateInstance * myParent;
+ void * myBox;
+ void * myBoxPlace; // Reused box heap memory
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // StateInstance for Root state (the real top state).
+ class _RootInstance : public _StateInstance {
+ protected:
+ friend class _StateSpecification;
+
+ _RootInstance(_MachineBase & machine, _StateInstance * parent)
+ : _StateInstance(machine, parent)
+ {
+ mySpecification = new _StateSpecification(*this);
+ }
+
+ public:
+ virtual ID id() {
+ return 0;
+ }
+
+ virtual Key key() {
+ // Can't happen: key is only called by users, and they don't know about Root.
+ assert(false); return 0;
+ }
+
+ virtual void createBox() {}
+ virtual void deleteBox() {}
+#ifdef MACHO_SNAPSHOTS
+ virtual void cloneBox(void * box) {}
+#endif
+
+ virtual const char * name() { return "Root"; }
+
+ // 'Virtual constructor' needed for cloning.
+ virtual _StateInstance * create(_MachineBase & machine, _StateInstance * parent) {
+ return new _RootInstance(machine, parent);
+ }
+
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // StateInstance for substates (including Top ;-)
+ // Has methods to create state specific objects.
+ template<class S>
+ class _SubstateInstance : public _StateInstance {
+ protected:
+ template<class C, class P>
+ friend class Link;
+
+ _SubstateInstance(_MachineBase & machine, _StateInstance * parent)
+ : _StateInstance(machine, parent)
+ {
+ assert(parent);
+ this->mySpecification = new S(*this);
+ }
+
+ public:
+ typedef typename S::Box Box;
+
+ virtual ~_SubstateInstance() {
+ if (this->myBox)
+ Macho::_deleteBox<Box>(myBox, myBoxPlace);
+ }
+
+ virtual const char * name() { return S::_state_name(); }
+
+ virtual ID id() {
+ return StateID<S>::value;
+ }
+
+ virtual Key key() {
+ return S::key();
+ }
+
+ // 'Virtual constructor' needed for cloning.
+ virtual _StateInstance * create(_MachineBase & machine, _StateInstance * parent) {
+ return new _SubstateInstance<S>(machine, parent);
+ }
+
+ virtual void createBox() {
+ if (!this->myBox)
+ this->myBox = Macho::_createBox<Box>(myBoxPlace);
+ }
+
+ virtual void deleteBox() {
+ assert(myBox);
+ Macho::_deleteBox<Box>(myBox, myBoxPlace);
+ }
+
+#ifdef MACHO_SNAPSHOTS
+ virtual void cloneBox(void * box) {
+ assert(!myBox);
+ assert(!myBoxPlace);
+ // Needs copy constructor in ALL box types.
+ myBox = Macho::_cloneBox<Box>(box);
+ }
+#endif
+
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Definitions for queuable event types
+
+ // Generic interface for event objects (available only to MachineBase)
+ class _IEventBase {
+ public:
+ virtual ~_IEventBase() {}
+ virtual void dispatch(_StateInstance &) = 0;
+ };
+
+
+ // Interface for event objects (bound to a top state)
+ template<class TOP>
+ class IEvent : protected _IEventBase {
+ friend class Machine<TOP>;
+ friend class TopBase<TOP>;
+ };
+
+
+ // Event with four parameters
+ template<class TOP, class R, class P1, class P2, class P3, class P4, class P5, class P6>
+ class _Event6 : public IEvent<TOP> {
+ typedef R (TOP::*Signature)(P1, P2, P3, P4, P5, P6);
+
+ public:
+ _Event6(Signature handler, const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5, const P6 & p6)
+ : myHandler(handler)
+ , myParam1(p1)
+ , myParam2(p2)
+ , myParam3(p3)
+ , myParam4(p4)
+ , myParam5(p5)
+ , myParam6(p6)
+ {}
+
+ protected:
+ void dispatch(_StateInstance & instance) {
+ TOP & behaviour = static_cast<TOP &>(instance.specification());
+ (behaviour.*myHandler)(myParam1, myParam2, myParam3, myParam4, myParam5, myParam6);
+ }
+
+ Signature myHandler;
+ P1 myParam1;
+ P2 myParam2;
+ P3 myParam3;
+ P4 myParam4;
+ P5 myParam5;
+ P6 myParam6;
+ };
+
+
+ // Event with four parameters
+ template<class TOP, class R, class P1, class P2, class P3, class P4, class P5>
+ class _Event5 : public IEvent<TOP> {
+ typedef R (TOP::*Signature)(P1, P2, P3, P4, P5);
+
+ public:
+ _Event5(Signature handler, const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5)
+ : myHandler(handler)
+ , myParam1(p1)
+ , myParam2(p2)
+ , myParam3(p3)
+ , myParam4(p4)
+ , myParam5(p5)
+ {}
+
+ protected:
+ void dispatch(_StateInstance & instance) {
+ TOP & behaviour = static_cast<TOP &>(instance.specification());
+ (behaviour.*myHandler)(myParam1, myParam2, myParam3, myParam4, myParam5);
+ }
+
+ Signature myHandler;
+ P1 myParam1;
+ P2 myParam2;
+ P3 myParam3;
+ P4 myParam4;
+ P5 myParam5;
+ };
+
+
+ // Event with four parameters
+ template<class TOP, class R, class P1, class P2, class P3, class P4>
+ class _Event4 : public IEvent<TOP> {
+ typedef R (TOP::*Signature)(P1, P2, P3, P4);
+
+ public:
+ _Event4(Signature handler, const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4)
+ : myHandler(handler)
+ , myParam1(p1)
+ , myParam2(p2)
+ , myParam3(p3)
+ , myParam4(p4)
+ {}
+
+ protected:
+ void dispatch(_StateInstance & instance) {
+ TOP & behaviour = static_cast<TOP &>(instance.specification());
+ (behaviour.*myHandler)(myParam1, myParam2, myParam3, myParam4);
+ }
+
+ Signature myHandler;
+ P1 myParam1;
+ P2 myParam2;
+ P3 myParam3;
+ P4 myParam4;
+ };
+
+
+ // Event with three parameters
+ template<class TOP, class R, class P1, class P2, class P3>
+ class _Event3 : public IEvent<TOP> {
+ typedef R (TOP::*Signature)(P1, P2, P3);
+
+ public:
+ _Event3(Signature handler, const P1 & p1, const P2 & p2, const P3 & p3)
+ : myHandler(handler)
+ , myParam1(p1)
+ , myParam2(p2)
+ , myParam3(p3)
+ {}
+
+ protected:
+ void dispatch(_StateInstance & instance) {
+ TOP & behaviour = static_cast<TOP &>(instance.specification());
+ (behaviour.*myHandler)(myParam1, myParam2, myParam3);
+ }
+
+ Signature myHandler;
+ P1 myParam1;
+ P2 myParam2;
+ P3 myParam3;
+ };
+
+
+ // Event with two parameters
+ template<class TOP, class R, class P1, class P2>
+ class _Event2 : public IEvent<TOP> {
+ typedef R (TOP::*Signature)(P1, P2);
+
+ public:
+ _Event2(Signature handler, const P1 & p1, const P2 & p2)
+ : myHandler(handler)
+ , myParam1(p1)
+ , myParam2(p2)
+ {}
+
+ protected:
+ void dispatch(_StateInstance & instance) {
+ TOP & behaviour = static_cast<TOP &>(instance.specification());
+ (behaviour.*myHandler)(myParam1, myParam2);
+ }
+
+ Signature myHandler;
+ P1 myParam1;
+ P2 myParam2;
+ };
+
+
+ // Event with one parameter
+ template<class TOP, class R, class P1>
+ class _Event1 : public IEvent<TOP> {
+ typedef R (TOP::*Signature)(P1);
+
+ public:
+ _Event1(Signature handler, const P1 & p1)
+ : myHandler(handler)
+ , myParam1(p1)
+ {}
+
+ protected:
+ void dispatch(_StateInstance & instance) {
+ TOP & behaviour = static_cast<TOP &>(instance.specification());
+ (behaviour.*myHandler)(myParam1);
+ }
+
+ Signature myHandler;
+ P1 myParam1;
+ };
+
+
+ // Event with no parameters
+ template<class TOP, class R>
+ class _Event0 : public IEvent<TOP> {
+ typedef R (TOP::*Signature)();
+
+ public:
+ _Event0(Signature handler)
+ : myHandler(handler)
+ {}
+
+ protected:
+ void dispatch(_StateInstance & instance) {
+ TOP & behaviour = static_cast<TOP &>(instance.specification());
+ (behaviour.*myHandler)();
+ }
+
+ Signature myHandler;
+ };
+
+
+ // Event creating functions using type inference
+ template<class TOP, class R, class P1, class P2, class P3, class P4, class P5, class P6>
+ inline IEvent<TOP> * Event(R (TOP::*handler)(P1, P2, P3, P4, P5, P6), const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5, const P6 & p6) {
+ return new _Event6<TOP, R, P1, P2, P3, P4, P5, P6>(handler, p1, p2, p3, p4, p5, p6);
+ }
+
+ // Event creating functions using type inference
+ template<class TOP, class R, class P1, class P2, class P3, class P4, class P5>
+ inline IEvent<TOP> * Event(R (TOP::*handler)(P1, P2, P3, P4, P5), const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5) {
+ return new _Event5<TOP, R, P1, P2, P3, P4, P5>(handler, p1, p2, p3, p4, p5);
+ }
+
+ // Event creating functions using type inference
+ template<class TOP, class R, class P1, class P2, class P3, class P4>
+ inline IEvent<TOP> * Event(R (TOP::*handler)(P1, P2, P3, P4), const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4) {
+ return new _Event4<TOP, R, P1, P2, P3, P4>(handler, p1, p2, p3, p4);
+ }
+
+ template<class TOP, class R, class P1, class P2, class P3>
+ inline IEvent<TOP> * Event(R (TOP::*handler)(P1, P2, P3), const P1 & p1, const P2 & p2, const P3 & p3) {
+ return new _Event3<TOP, R, P1, P2, P3>(handler, p1, p2, p3);
+ }
+
+ template<class TOP, class R, class P1, class P2>
+ inline IEvent<TOP> * Event(R (TOP::*handler)(P1, P2), const P1 & p1, const P2 & p2) {
+ return new _Event2<TOP, R, P1, P2>(handler, p1, p2);
+ }
+
+ template<class TOP, class R, class P1>
+ inline IEvent<TOP> * Event(R (TOP::*handler)(P1), const P1 & p1) {
+ return new _Event1<TOP, R, P1>(handler, p1);
+ }
+
+ template<class TOP, class R>
+ inline IEvent<TOP> * Event(R (TOP::*handler)()) {
+ return new _Event0<TOP, R>(handler);
+ }
+
+} // namespace Macho
+
+
+////////////////////////////////////////////////////////////////////////////////
+// MSVC++ 8.0 does not handle qualified member template friends
+// http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=101615
+// Otherwise call could happen directly in Initializer classes.
+class _VS8_Bug_101615 {
+public:
+ template<class S, class P1>
+ static inline void execute(Macho::_StateInstance & instance, const P1 & p1) {
+ S & behaviour = static_cast<S &>(instance.specification());
+ behaviour.init(p1);
+ }
+
+ template<class S, class P1, class P2>
+ static inline void execute(Macho::_StateInstance & instance, const P1 & p1, const P2 & p2) {
+ S & behaviour = static_cast<S &>(instance.specification());
+ behaviour.init(p1, p2);
+ }
+
+ template<class S, class P1, class P2, class P3>
+ static inline void execute(Macho::_StateInstance & instance, const P1 & p1, const P2 & p2, const P3 & p3) {
+ S & behaviour = static_cast<S &>(instance.specification());
+ behaviour.init(p1, p2, p3);
+ }
+
+ template<class S, class P1, class P2, class P3, class P4>
+ static inline void execute(Macho::_StateInstance & instance, const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4) {
+ S & behaviour = static_cast<S &>(instance.specification());
+ behaviour.init(p1, p2, p3, p4);
+ }
+
+ template<class S, class P1, class P2, class P3, class P4, class P5>
+ static inline void execute(Macho::_StateInstance & instance, const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5) {
+ S & behaviour = static_cast<S &>(instance.specification());
+ behaviour.init(p1, p2, p3, p4, p5);
+ }
+
+ template<class S, class P1, class P2, class P3, class P4, class P5, class P6>
+ static inline void execute(Macho::_StateInstance & instance, const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5, const P6 & p6) {
+ S & behaviour = static_cast<S &>(instance.specification());
+ behaviour.init(p1, p2, p3, p4, p5, p6);
+ }
+
+};
+
+
+////////////////////////////////////////////////////////////////////////////////
+namespace Macho {
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Base class for state initializers.
+ // Initializer are used to provide parameters to states.
+ // The 'execute' method of Initializers will call a state's init method with
+ // the data of the initializer object.
+ class _Initializer {
+ public:
+ virtual ~_Initializer() {}
+
+ // Create copy of initializer.
+ virtual _Initializer * clone() = 0;
+
+ // Deallocate object.
+ virtual void destroy() { delete this; }
+
+ virtual Key adapt(Key key) { return key; }
+
+ // Initialize given state. State is new current state of a state machine.
+ virtual void execute(_StateInstance & instance) = 0;
+ };
+
+
+ // Base class for Singleton initializers.
+ class _StaticInitializer : public _Initializer {
+ // Copy of Singleton is Singleton.
+ virtual _Initializer * clone() { return this; }
+
+ // Singletons are never destroyed.
+ virtual void destroy() {}
+ };
+
+
+ // Default initializer: provides no parameters, calls state's 'init' method
+ // only.
+ class _DefaultInitializer : public _StaticInitializer {
+ public:
+ virtual void execute(_StateInstance & instance) {
+ instance.init(false);
+ }
+ };
+
+
+ // History initializer: provides no parameters, performs transition to
+ // history of state if available.
+ class _HistoryInitializer : public _StaticInitializer {
+ public:
+ virtual void execute(_StateInstance & instance) {
+ instance.init(true);
+ }
+ };
+
+
+ // Special initializer: Helps alias impersonate as history state of given state.
+ class _AdaptingInitializer : public _Initializer {
+ public:
+ _AdaptingInitializer(const _MachineBase & machine) : myMachine(machine) {}
+
+ virtual void execute(_StateInstance & instance) {
+ instance.init(true);
+ }
+
+ virtual _Initializer * clone() {
+ return new _AdaptingInitializer(myMachine);
+ }
+
+ virtual Key adapt(Key key);
+
+ protected:
+ const _MachineBase & myMachine;
+ };
+
+
+ // Initializers with one to six parameters.
+ template<class S, class P1>
+ class _Initializer1 : public _Initializer {
+ public:
+ _Initializer1(const P1 & p1)
+ : myParam1(p1)
+ {}
+
+ virtual _Initializer * clone() {
+ return new _Initializer1<S, P1>(myParam1);
+ }
+
+ virtual void execute(_StateInstance & instance) {
+ ::_VS8_Bug_101615::execute<S, P1>(instance, myParam1);
+ delete this;
+ }
+
+ P1 myParam1;
+ };
+
+
+ template<class S, class P1, class P2>
+ class _Initializer2 : public _Initializer {
+ public:
+ _Initializer2(const P1 & p1, const P2 & p2)
+ : myParam1(p1)
+ , myParam2(p2)
+ {}
+
+ virtual _Initializer * clone() {
+ return new _Initializer2<S, P1, P2>(myParam1, myParam2);
+ }
+
+ void execute(_StateInstance & instance) {
+ ::_VS8_Bug_101615::execute<S, P1, P2>(instance, myParam1, myParam2);
+ delete this;
+ }
+
+ P1 myParam1;
+ P2 myParam2;
+ };
+
+
+ template<class S, class P1, class P2, class P3>
+ class _Initializer3 : public _Initializer {
+ public:
+ _Initializer3(const P1 & p1, const P2 & p2, const P3 & p3)
+ : myParam1(p1)
+ , myParam2(p2)
+ , myParam3(p3)
+ {}
+
+ virtual _Initializer * clone() {
+ return new _Initializer3<S, P1, P2, P3>(myParam1, myParam2, myParam3);
+ }
+
+ void execute(_StateInstance & instance) {
+ ::_VS8_Bug_101615::execute<S, P1, P2, P3>(instance, myParam1, myParam2, myParam3);
+ delete this;
+ }
+
+ P1 myParam1;
+ P2 myParam2;
+ P3 myParam3;
+ };
+
+
+ template<class S, class P1, class P2, class P3, class P4>
+ class _Initializer4 : public _Initializer {
+ public:
+ _Initializer4(const P1 & p1, const P2 & p2, const P3 & p3, P4 & p4)
+ : myParam1(p1)
+ , myParam2(p2)
+ , myParam3(p3)
+ , myParam4(p4)
+ {}
+
+ virtual _Initializer * clone() {
+ return new _Initializer4<S, P1, P2, P3, P4>(myParam1, myParam2, myParam3, myParam4);
+ }
+
+ void execute(_StateInstance & instance) {
+ ::_VS8_Bug_101615::execute<S, P1, P2, P3, P4>(instance, myParam1, myParam2, myParam3, myParam4);
+ delete this;
+ }
+
+ P1 myParam1;
+ P2 myParam2;
+ P3 myParam3;
+ P4 myParam4;
+ };
+
+
+ template<class S, class P1, class P2, class P3, class P4, class P5>
+ class _Initializer5 : public _Initializer {
+ public:
+ _Initializer5(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5)
+ : myParam1(p1)
+ , myParam2(p2)
+ , myParam3(p3)
+ , myParam4(p4)
+ , myParam5(p5)
+ {}
+
+ virtual _Initializer * clone() {
+ return new _Initializer5<S, P1, P2, P3, P4, P5>(myParam1, myParam2, myParam3, myParam4, myParam5);
+ }
+
+ void execute(_StateInstance & instance) {
+ ::_VS8_Bug_101615::execute<S, P1, P2, P3, P4, P5>(instance, myParam1, myParam2, myParam3, myParam4, myParam5);
+ delete this;
+ }
+
+ P1 myParam1;
+ P2 myParam2;
+ P3 myParam3;
+ P4 myParam4;
+ P5 myParam5;
+ };
+
+
+ template<class S, class P1, class P2, class P3, class P4, class P5, class P6>
+ class _Initializer6 : public _Initializer {
+ public:
+ _Initializer6(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5, const P6 & p6)
+ : myParam1(p1)
+ , myParam2(p2)
+ , myParam3(p3)
+ , myParam4(p4)
+ , myParam5(p5)
+ , myParam6(p6)
+ {}
+
+ virtual _Initializer * clone() {
+ return new _Initializer6<S, P1, P2, P3, P4, P5, P6>(myParam1, myParam2, myParam3, myParam4, myParam5, myParam6);
+ }
+
+ void execute(_StateInstance & instance) {
+ _VS8_Bug_101615::execute<S, P1, P2, P3, P4, P5, P6>(instance, myParam1, myParam2, myParam3, myParam4, myParam5, myParam6);
+ delete this;
+ }
+
+ P1 myParam1;
+ P2 myParam2;
+ P3 myParam3;
+ P4 myParam4;
+ P5 myParam5;
+ P6 myParam6;
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Singleton initializers.
+ static _DefaultInitializer _theDefaultInitializer;
+ static _HistoryInitializer _theHistoryInitializer;
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Base class for Machine objects.
+ class _MachineBase {
+ public:
+ class Alias currentState() const;
+
+ protected:
+ _MachineBase();
+ ~_MachineBase();
+
+ // Transition to new state.
+ void setState(_StateInstance & instance, _Initializer * init);
+
+ // Transition to new state specified by state alias.
+ void setState(const Alias & state);
+
+ // Prepare transition to new state (performed on call to 'rattleOn').
+ // There can be only one state transition pending (asserts otherwise)!
+ // 'init' is an initializer for the new state.
+ void setPendingState(_StateInstance & instance, _Initializer * init) {
+ assert( (!myPendingState || myPendingState == &instance) &&
+ "There is already a state transition pending!");
+
+ myPendingState = &instance;
+ myPendingInit = init;
+ }
+
+ // Provide event object to be executed on current state.
+ void setPendingEvent(_IEventBase * event) {
+ assert(event);
+ assert(!myPendingEvent && "There is already an event pending!");
+
+ myPendingEvent = event;
+ }
+
+ // Performs pending state transition.
+ void rattleOn();
+
+ // Get StateInstance object for ID.
+ _StateInstance * & getInstance(ID id) {
+ return myInstances[id];
+ }
+
+ // Get StateInstance object for ID.
+ const _StateInstance * getInstance(ID id) const {
+ return myInstances[id];
+ }
+
+ // Starts the machine with the specified start state.
+ void start(_StateInstance & instance);
+ void start(const Alias & state);
+
+ // Shuts machine down. Will exit any states and free all allocated
+ // resources.
+ void shutdown();
+
+ // Allocate space for pointers to StateInstance objects.
+ void allocate(unsigned int count);
+
+ // Free all StateInstance objects.
+ void free(unsigned int count);
+
+ // const: History can be manipulated even on a const machine.
+ void clearHistoryDeep(unsigned int count, const _StateInstance & instance) const;
+
+#ifdef MACHO_SNAPSHOTS
+ // Create a copy of another machines StateInstance objects (includes boxes).
+ void copy(_StateInstance ** other, unsigned int count);
+
+ // Create a copy of another machines StateInstance object.
+ _StateInstance * createClone(ID id, _StateInstance * original);
+#endif
+
+ protected:
+ // C++ needs something like package visibility
+
+ // for getInstance
+ template<class C, class P>
+ friend class Link;
+
+ // for setPendingEvent
+ template<class T>
+ friend class TopBase;
+
+ // for getInstance
+ friend class _StateSpecification;
+
+ // for getInstance
+ friend class Alias;
+
+ // for getInstance
+ friend class _AdaptingInitializer;
+
+ // for setPendingState
+ friend class _StateInstance;
+
+ // for Tests
+ friend class ::TestAccess;
+
+ // Current state of Machine object.
+ _StateInstance * myCurrentState;
+
+ // Information about pending state transition.
+ _StateInstance * myPendingState;
+ _Initializer * myPendingInit;
+
+ // Deprecated!
+ void * myPendingBox;
+
+ _IEventBase * myPendingEvent;
+
+ // Array of StateInstance objects.
+ _StateInstance ** myInstances;
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // This is the base class for state aliases. A state alias represents a
+ // state of a machine. A transition to that state can be initiated by
+ // giving the alias object to the 'setState' method.
+ //
+ // State aliases are created by the template functions 'State' further below.
+ // Parameters can be provided to these functions that will be used to
+ // initialize the state on transition to it.
+ class Alias {
+ public:
+ Alias(Key key, bool history = false)
+ : myStateKey(key)
+ , myInitializer(
+ history ?
+ static_cast<_Initializer *>(&_theHistoryInitializer)
+ :
+ static_cast<_Initializer *>(&_theDefaultInitializer)
+ )
+ {
+ assert(key);
+ }
+
+ Alias(Key key, _Initializer * init)
+ : myStateKey(key)
+ , myInitializer(init)
+ {
+ assert(key);
+ }
+
+ Alias(const Alias & other)
+ : myStateKey(other.myStateKey)
+ , myInitializer(other.myInitializer->clone())
+ {}
+
+ Alias & operator=(const Alias & other) {
+ if (this == &other) return *this;
+
+ myInitializer->destroy();
+
+ myStateKey = other.myStateKey;
+ myInitializer = other.myInitializer->clone();
+
+ return *this;
+ }
+
+ ~Alias() {
+ myInitializer->destroy();
+ }
+
+ // Use this to test validity: zero means invalid alias.
+ operator Key() const {
+ return key();
+ }
+
+ bool isChild(Key k) const {
+ return key()->childPredicate(k);
+ }
+
+ bool isParent(Key k) const {
+ return static_cast<_KeyData *>(k)->childPredicate(key());
+ }
+
+ const char * name() const {
+ return key()->name();
+ }
+
+ ID id() const {
+ return key()->id;
+ }
+
+ protected:
+ friend class _MachineBase;
+ friend class _StateSpecification;
+
+ void setState(_MachineBase & machine) const;
+
+ _KeyData * key() const { return static_cast<_KeyData *>(myInitializer->adapt(myStateKey)); }
+
+ protected:
+ // Key of specified state.
+ Key myStateKey;
+
+ // Initializer of this alias.
+ _Initializer * myInitializer;
+ };
+
+ // Deprecated!
+ typedef Alias StateAlias;
+
+
+ // Create alias with 0 to 6 parameters.
+ template<class S>
+ Alias State() {
+ return Alias(S::key());
+ }
+
+ template<class S, class P1>
+ Alias State(const P1 & p1) {
+ return Alias(S::key(), new _Initializer1<S, P1>(p1));
+ }
+
+ template<class S, class P1, class P2>
+ Alias State(const P1 & p1, const P2 & p2) {
+ return Alias(S::key(), new _Initializer2<S, P1, P2>(p1, p2));
+ }
+
+ template<class S, class P1, class P2, class P3>
+ Alias State(const P1 & p1, const P2 & p2, const P3 & p3) {
+ return Alias(S::key(), new _Initializer3<S, P1, P2, P3>(p1, p2, p3));
+ }
+
+ template<class S, class P1, class P2, class P3, class P4>
+ Alias State(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4) {
+ return Alias(S::key(), new _Initializer4<S, P1, P2, P3, P4>(p1, p2, p3, p4));
+ }
+
+ template<class S, class P1, class P2, class P3, class P4, class P5>
+ Alias State(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5) {
+ return Alias(S::key(), new _Initializer5<S, P1, P2, P3, P4, P5>(p1, p2, p3, p4, p5));
+ }
+
+ template<class S, class P1, class P2, class P3, class P4, class P5, class P6>
+ Alias State(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5, const P6 & p6) {
+ return Alias(S::key(), new _Initializer6<S, P1, P2, P3, P4, P5, P6>(p1, p2, p3, p4, p5, p6));
+ }
+
+ // Create alias for state's history: not the current history state, but
+ // really the history of a state. This means that the alias may point to
+ // different states during its life. Needs a machine instance to take history from.
+ template<class S>
+ Alias StateHistory(const _MachineBase & machine) {
+ return Alias(S::key(), new _AdaptingInitializer(machine));
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Snapshot of a machine object.
+ // Saves the state of a machine object at a specific point in time to be restored
+ // later (can be used to achieve something like backtracking).
+ // Includes boxes of current state and persistent boxes.
+ // Assign a snapshot to a machine (operator=) to restore state.
+ // Note that no exit/entry actions of the overwritten machine state are performed!
+ // Box destructors however are executed!
+#ifdef MACHO_SNAPSHOTS
+ template<class TOP>
+ class Snapshot : public _MachineBase {
+ public:
+ Snapshot(Machine<TOP> & machine);
+
+ ~Snapshot() {
+ free(Machine<TOP>::theStateCount);
+ }
+
+ private:
+ friend class Machine<TOP>;
+
+ Snapshot(const Snapshot<TOP> & other);
+ Snapshot & operator=(const Snapshot<TOP> & other);
+ };
+#endif
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // A Machine object maintains a current state.
+ // The state can be any substate of template parameter TOP.
+ // TOP is the Machine's top most and inital state. TOP must be defined by
+ // the macro TOPSTATE. Event processing is done by calling methods (event
+ // handlers) on the current state.
+ // This is realized by defining an arrow ('->') operator on Machine,
+ // forwarding to the interface of TOP.
+ // Every possible event handler to be called must therefore appear in the
+ // interface of TOP. Events are dispatched by using this operator on a
+ // Machine object (e.g. 'machine->event()').
+ template<class TOP>
+ class Machine : public _MachineBase {
+ public:
+
+ // This class performs an action in its destructor after an event
+ // handler has finished. Comparable to an After Advice in AOP.
+ struct AfterAdvice {
+ AfterAdvice(Machine<TOP> & m) : myMachine(m) {}
+
+ // Event handler has finished execution. Execute pending transitions now.
+ ~AfterAdvice() { myMachine.rattleOn(); }
+
+ // this arrow operator finally dispatches to TOP interface.
+ TOP * operator->() {
+ return static_cast<TOP *>(& (myMachine.myCurrentState->specification()) );
+ }
+
+ private:
+ Machine<TOP> & myMachine;
+ };
+
+ Machine() {
+ // Compile time check: TOP must directly derive from TopBase<TOP>
+ typedef typename __SameType<TopBase<TOP>, typename TOP::SUPER>::Check MustDeriveFromTopBase;
+
+ allocate(theStateCount);
+ start(TOP::_getInstance(*this));
+ }
+
+ // Initialize with a state alias object to have machine go to a state
+ // other than TOP on startup.
+ Machine(const Alias & state) {
+ // Compile time check: TOP must directly derive from TopBase<TOP>
+ typedef typename __SameType<TopBase<TOP>, typename TOP::SUPER>::Check MustDeriveFromTopBase;
+
+ allocate(theStateCount);
+ start(state);
+ }
+
+#ifdef MACHO_SNAPSHOTS
+ // Create machine from a snapshot.
+ Machine(const Snapshot<TOP> & snapshot) {
+ allocate(theStateCount);
+ copy(snapshot.myInstances, theStateCount);
+ }
+
+ // Overwrite current machine state by snapshot.
+ Machine<TOP> & operator=(const Snapshot<TOP> & snapshot) {
+ assert(!myPendingState);
+ assert(!myPendingEvent);
+
+ myCurrentState->shutdown();
+
+ free(theStateCount);
+ copy(snapshot.myInstances, theStateCount);
+
+ // Go to Root state first
+ myCurrentState = getInstance(0);
+
+ // Then set previous current state
+ _StateInstance * current = getInstance(snapshot.myCurrentState->id());
+ current->restore(*current);
+ rattleOn();
+
+ return *this;
+ }
+#endif
+
+ ~Machine() {
+ myCurrentState->shutdown();
+ free(theStateCount);
+ }
+
+ // Don't return pointer to interface right now: we need to know when the
+ // event handler has finished; return an AfterAdvice object instead:
+ // it allows us to perform actions after access.
+ AfterAdvice operator->() {
+ assert(myCurrentState);
+ assert(!myPendingState);
+
+ // We need to know when the event handler has finished.
+ return AfterAdvice(*this);
+ }
+
+ // Dispatch an event object to machine.
+ void dispatch(IEvent<TOP> * event, bool destroy = true) {
+ assert(event);
+
+ event->dispatch(*myCurrentState);
+ if (destroy) delete event;
+
+ rattleOn();
+ }
+
+ // Allow (const) access to top state's box (for state data extraction).
+ const typename TOP::Box & box() const {
+ assert(myCurrentState);
+ return static_cast<TOP &>(myCurrentState->specification()).TOP::box();
+ }
+
+ private:
+ template<class C, class P>
+ friend class Link;
+
+ private:
+ Machine(const Machine<TOP> & other);
+ Machine<TOP> & operator=(const Machine<TOP> & other);
+
+#ifdef MACHO_SNAPSHOTS
+ friend class Snapshot<TOP>;
+#endif
+
+ template<class T> friend class StateID;
+
+ // Next free identifier for StateInstance objects.
+ static ID theStateCount;
+ };
+
+ // Root is always there and has ID 0, so start from 1
+ template<class TOP>
+ ID Machine<TOP>::theStateCount = 1;
+
+ // Each state has a unique ID number.
+ // The identifiers are consecutive integers starting from zero,
+ // which allows use as index into a vector for fast access.
+ // 'Root' always has zero as id.
+ template<class S>
+ const ID StateID<S>::value = Machine<typename S::TOP>::theStateCount++;
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Implementation for StateSpecification
+
+ // Initiate state transition with 0 to six parameters.
+ template<class S>
+ inline void _StateSpecification::setState() {
+ _MachineBase & m = _myStateInstance.machine();
+ _StateInstance & instance = S::_getInstance(m);
+ m.setPendingState(instance, &_theDefaultInitializer);
+ }
+
+ template<class S, class P1>
+ inline void _StateSpecification::setState(const P1 & p1) {
+ _MachineBase & m = _myStateInstance.machine();
+ _StateInstance & instance = S::_getInstance(m);
+ m.setPendingState(instance, new _Initializer1<S, P1>(p1));
+ }
+
+ template<class S, class P1, class P2>
+ inline void _StateSpecification::setState(const P1 & p1, const P2 & p2) {
+ _MachineBase & m = _myStateInstance.machine();
+ _StateInstance & instance = S::_getInstance(m);
+ m.setPendingState(instance, new _Initializer2<S, P1, P2>(p1, p2));
+ }
+
+ template<class S, class P1, class P2, class P3>
+ inline void _StateSpecification::setState(const P1 & p1, const P2 & p2, const P3 & p3) {
+ _MachineBase & m = _myStateInstance.machine();
+ _StateInstance & instance = S::_getInstance(m);
+ m.setPendingState(instance, new _Initializer3<S, P1, P2, P3>(p1, p2, p3));
+ }
+
+ template<class S, class P1, class P2, class P3, class P4>
+ inline void _StateSpecification::setState(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4) {
+ _MachineBase & m = _myStateInstance.machine();
+ _StateInstance & instance = S::_getInstance(m);
+ m.setPendingState(instance, new _Initializer4<S, P1, P2, P3, P4>(p1, p2, p3, p4));
+ }
+
+ template<class S, class P1, class P2, class P3, class P4, class P5>
+ inline void _StateSpecification::setState(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5) {
+ _MachineBase & m = _myStateInstance.machine();
+ _StateInstance & instance = S::_getInstance(m);
+ m.setPendingState(instance, new _Initializer5<S, P1, P2, P3, P4, P5>(p1, p2, p3, p4, p5));
+ }
+
+ template<class S, class P1, class P2, class P3, class P4, class P5, class P6>
+ inline void _StateSpecification::setState(const P1 & p1, const P2 & p2, const P3 & p3, const P4 & p4, const P5 & p5, const P6 & p6) {
+ _MachineBase & m = _myStateInstance.machine();
+ _StateInstance & instance = S::_getInstance(m);
+ m.setPendingState(instance, new _Initializer6<S, P1, P2, P3, P4, P5, P6>(p1, p2, p3, p4, p5, p6));
+ }
+
+ // Initiate state transition to a state's history.
+ template<class S>
+ inline void _StateSpecification::setStateHistory() {
+ _MachineBase & m = _myStateInstance.machine();
+ _StateInstance & instance = S::_getInstance(m);
+ m.setPendingState(instance, &_theHistoryInitializer);
+ }
+
+ // Deprecated!
+ template<class S>
+ inline void _StateSpecification::setStateBox(typename S::Box * box) {
+ _MachineBase & m = _myStateInstance.machine();
+ _StateInstance & instance = S::_getInstance(m);
+ m.myPendingBox = box;
+ m.setPendingState(instance, &_theHistoryInitializer);
+ }
+
+ // Deprecated!
+ template<class S>
+ inline void _StateSpecification::setStateDirect(typename S::Box * box) {
+ _MachineBase & m = _myStateInstance.machine();
+ _StateInstance & instance = S::_getInstance(m);
+ m.myPendingBox = box;
+ m.setPendingState(instance, &_theDefaultInitializer);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Implementation for TopBase
+ template<class T>
+ inline void TopBase<T>::dispatch(IEvent<TOP> * event) {
+ assert(event);
+ _myStateInstance.machine().setPendingEvent(event);
+ }
+
+ template<class T>
+ // Returns current state machine instance.
+ inline const Machine<T> & TopBase<T>::machine() {
+ return static_cast<Machine<TOP> &>(this->_myStateInstance.machine());
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Implementation for Link
+ template<class C, class P>
+ inline Link<C, P>::Link(_StateInstance & instance)
+ : P(P::_getInstance(instance.machine()))
+ // Can't initialize _myStateInstance with _getInstance,
+ // because this would result in an endless loop (at least for first call)
+ , _myStateInstance(instance)
+ {}
+
+ // This method keeps '_myStateInstance' attribute private.
+ template<class C, class P>
+ inline void * Link<C, P>::_box() {
+ return _myStateInstance.box();
+ }
+
+ // Default behaviour: free box on exit.
+ template<class C, class P>
+ inline void Link<C, P>::_deleteBox(_StateInstance & instance) {
+ instance.deleteBox();
+ }
+
+ // Create StateInstance object of state.
+ template<class C, class P>
+ /* static */ inline _StateInstance & Link<C, P>::_getInstance(_MachineBase & machine) {
+ // Look first in machine for existing StateInstance.
+ _StateInstance * & instance = machine.getInstance(StateID<C>::value);
+ if (!instance)
+ // Will create parent StateInstance object if not already created.
+ instance = new _SubstateInstance<C>(machine, &P::_getInstance(machine));
+
+ return *instance;
+ }
+
+ template<class C, class P>
+ /* static */ inline bool Link<C, P>::isCurrent(const _MachineBase & machine) {
+ return machine.currentState().isChild(key());
+ }
+
+ // Deprecated!
+ template<class C, class P>
+ /* static */ inline bool Link<C, P>::isCurrentDirect(const _MachineBase & machine) {
+ return key() == machine.currentState();
+ }
+
+ template<class C, class P>
+ /* static */ void Link<C, P>::clearHistory(const _MachineBase & machine) {
+ const _StateInstance * instance = machine.getInstance(StateID<C>::value);
+ if (instance)
+ instance->setHistory(0);
+ }
+
+ template<class C, class P>
+ /* static */ void Link<C, P>::clearHistoryDeep(const _MachineBase & machine) {
+ const _StateInstance * instance = machine.getInstance(StateID<C>::value);
+ if (instance)
+ machine.clearHistoryDeep(Machine<TOP>::theStateCount, *instance);
+ }
+
+ template<class C, class P>
+ /* static */ Alias Link<C, P>::history(const _MachineBase & machine) {
+ const _StateInstance * instance = machine.getInstance(StateID<C>::value);
+ _StateInstance * history = 0;
+
+ if (instance)
+ history = instance->history();
+
+ return history ? history->key() : key();
+ }
+
+ template<class C, class P>
+ /* static */ inline Key Link<C, P>::key() {
+ static _KeyData k = { _getInstance, isChild, C::_state_name, StateID<C>::value };
+ return &k;
+ }
+
+ template<class C, class P>
+ /* static */ inline Alias Link<C, P>::alias() {
+ return Alias(key());
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Implementation for Snapshot
+#ifdef MACHO_SNAPSHOTS
+ template<class TOP>
+ Snapshot<TOP>::Snapshot(Machine<TOP> & machine) {
+ assert(!machine.myPendingState);
+ assert(!machine.myPendingEvent);
+ assert(machine.myCurrentState);
+
+ allocate(Machine<TOP>::theStateCount);
+ copy(machine.myInstances, Machine<TOP>::theStateCount);
+
+ myCurrentState = getInstance(machine.myCurrentState->id());
+ }
+#endif
+
+} // namespace Macho
+
+
+#endif // __MACHO_HPP__
Modified: trunk/OpenRTM-aist/src/lib/rtm/Makefile.am
===================================================================
--- trunk/OpenRTM-aist/src/lib/rtm/Makefile.am 2017-12-10 21:18:08 UTC (rev 3115)
+++ trunk/OpenRTM-aist/src/lib/rtm/Makefile.am 2017-12-10 21:20:20 UTC (rev 3116)
@@ -83,6 +83,7 @@
OpenHRPExecutionContext.cpp \
PortAdmin.cpp \
RTObject.cpp \
+ Macho.cpp \
ConfigAdmin.cpp \
ComponentActionListener.cpp \
FsmActionListener.cpp \
Modified: trunk/OpenRTM-aist/src/lib/rtm/OutPortBase.cpp
===================================================================
--- trunk/OpenRTM-aist/src/lib/rtm/OutPortBase.cpp 2017-12-10 21:18:08 UTC (rev 3115)
+++ trunk/OpenRTM-aist/src/lib/rtm/OutPortBase.cpp 2017-12-10 21:20:20 UTC (rev 3116)
@@ -96,6 +96,9 @@
coil::eraseBlank(pubs);
RTC_DEBUG(("available subscription_type: %s", pubs.c_str()));
addProperty("dataport.subscription_type", pubs.c_str());
+ // FSM4RTC formal/16-04-01 p.25
+ // In the FSM4RTC specification, publisher type is defined as "io_mode"
+ addProperty("dataport.io_mode", pubs.c_str());
};
Modified: trunk/OpenRTM-aist/src/lib/rtm/OutPortPushConnector.cpp
===================================================================
--- trunk/OpenRTM-aist/src/lib/rtm/OutPortPushConnector.cpp 2017-12-10 21:18:08 UTC (rev 3115)
+++ trunk/OpenRTM-aist/src/lib/rtm/OutPortPushConnector.cpp 2017-12-10 21:20:20 UTC (rev 3116)
@@ -193,8 +193,14 @@
PublisherBase* OutPortPushConnector::createPublisher(ConnectorInfo& info)
{
std::string pub_type;
- pub_type = info.properties.getProperty("subscription_type",
- "flush");
+ pub_type = info.properties.getProperty("io_mode");
+ if (pub_type.empty())
+ {
+ pub_type = info.properties.getProperty("subscription_type", "flush");
+ if (pub_type == "flush") { info.properties["io_mode"] = "block"; }
+ else if (pub_type == "new") { info.properties["io_mode"] = "nonblock"; }
+ else { info.properties["io_mode"] = pub_type; }
+ }
coil::normalize(pub_type);
return PublisherFactory::instance().createObject(pub_type);
}
Modified: trunk/OpenRTM-aist/src/lib/rtm/PublisherFlush.cpp
===================================================================
--- trunk/OpenRTM-aist/src/lib/rtm/PublisherFlush.cpp 2017-12-10 21:18:08 UTC (rev 3115)
+++ trunk/OpenRTM-aist/src/lib/rtm/PublisherFlush.cpp 2017-12-10 21:20:20 UTC (rev 3116)
@@ -231,6 +231,15 @@
::RTC::PublisherFlush>,
::coil::Destructor< ::RTC::PublisherBase,
::RTC::PublisherFlush>);
+ // FSM4RTC formal/16-04-01 p.25
+ // In the FSM4RTC specification, publisher type is defined as "io_mode"
+ // Publisher "flush" is functionally equals to "io_mode: block".
+ ::RTC::PublisherFactory::
+ instance().addFactory("block",
+ ::coil::Creator< ::RTC::PublisherBase,
+ ::RTC::PublisherFlush>,
+ ::coil::Destructor< ::RTC::PublisherBase,
+ ::RTC::PublisherFlush>);
}
};
Modified: trunk/OpenRTM-aist/src/lib/rtm/PublisherNew.cpp
===================================================================
--- trunk/OpenRTM-aist/src/lib/rtm/PublisherNew.cpp 2017-12-10 21:18:08 UTC (rev 3115)
+++ trunk/OpenRTM-aist/src/lib/rtm/PublisherNew.cpp 2017-12-10 21:20:20 UTC (rev 3116)
@@ -586,5 +586,14 @@
::RTC::PublisherNew>,
::coil::Destructor< ::RTC::PublisherBase,
::RTC::PublisherNew>);
+ // FSM4RTC formal/16-04-01 p.25
+ // In the FSM4RTC specification, publisher type is defined as "io_mode"
+ // Publisher "new" is functionally equals to "io_mode: nonblock".
+ ::RTC::PublisherFactory::
+ instance().addFactory("nonblock",
+ ::coil::Creator< ::RTC::PublisherBase,
+ ::RTC::PublisherNew>,
+ ::coil::Destructor< ::RTC::PublisherBase,
+ ::RTC::PublisherNew>);
}
};
Modified: trunk/OpenRTM-aist/src/lib/rtm/RTObject.h
===================================================================
--- trunk/OpenRTM-aist/src/lib/rtm/RTObject.h 2017-12-10 21:18:08 UTC (rev 3115)
+++ trunk/OpenRTM-aist/src/lib/rtm/RTObject.h 2017-12-10 21:20:20 UTC (rev 3116)
@@ -4887,7 +4887,7 @@
- protected:
+ // protected:
/*!
* @if jp
*
@@ -5049,11 +5049,54 @@
m_actionListeners.ecaction_[EC_DETACHED].notify(ec_id);
}
- inline void onFsmStateChanged(const char* state)
+ /*!
+ * FSM related listeners
+ */
+ inline void preOnFsmInit(const char* state)
{
+ m_fsmActionListeners.preaction_[PRE_ON_INIT].notify(state);
+ }
+ inline void preOnFsmEntry(const char* state)
+ {
+ m_fsmActionListeners.preaction_[PRE_ON_ENTRY].notify(state);
+ }
+ inline void preOnFsmDo(const char* state)
+ {
+ m_fsmActionListeners.preaction_[PRE_ON_DO].notify(state);
+ }
+ inline void preOnFsmExit(const char* state)
+ {
+ m_fsmActionListeners.preaction_[PRE_ON_EXIT].notify(state);
+ }
+ inline void preOnFsmStateChange(const char* state)
+ {
m_fsmActionListeners.preaction_[PRE_ON_STATE_CHANGE].notify(state);
}
+ /*!
+ * FSM related listeners
+ */
+ inline void postOnFsmInit(const char* state, ReturnCode_t ret)
+ {
+ m_fsmActionListeners.postaction_[POST_ON_INIT].notify(state, ret);
+ }
+ inline void postOnFsmEntry(const char* state, ReturnCode_t ret)
+ {
+ m_fsmActionListeners.postaction_[POST_ON_ENTRY].notify(state, ret);
+ }
+ inline void postOnFsmDo(const char* state, ReturnCode_t ret)
+ {
+ m_fsmActionListeners.postaction_[POST_ON_DO].notify(state, ret);
+ }
+ inline void postOnFsmExit(const char* state, ReturnCode_t ret)
+ {
+ m_fsmActionListeners.postaction_[POST_ON_EXIT].notify(state, ret);
+ }
+ inline void postOnFsmStateChange(const char* state, ReturnCode_t ret)
+ {
+ m_fsmActionListeners.postaction_[POST_ON_STATE_CHANGE].notify(state, ret);
+ }
+
ReturnCode_t getInheritedECOptions(coil::Properties& default_opts);
/*!
Index: trunk/OpenRTM-aist/src/lib/rtm/ext
===================================================================
--- trunk/OpenRTM-aist/src/lib/rtm/ext 2017-12-10 21:18:08 UTC (rev 3115)
+++ trunk/OpenRTM-aist/src/lib/rtm/ext 2017-12-10 21:20:20 UTC (rev 3116)
Property changes on: trunk/OpenRTM-aist/src/lib/rtm/ext
___________________________________________________________________
Modified: svn:ignore
## -1 +1,35 ##
+.deps
+skelstub.lst
+CameraCommonInterface.hh
+CameraCommonInterfaceDynSK.cc
+CameraCommonInterfaceSK.cc
+CameraCommonInterfaceSkel.cpp
+CameraCommonInterfaceSkel.h
+CameraCommonInterfaceStub.cpp
+CameraCommonInterfaceStub.h
+Makefile
Makefile.in
+ManipulatorCommonInterface_Common.hh
+ManipulatorCommonInterface_CommonDynSK.cc
+ManipulatorCommonInterface_CommonSK.cc
+ManipulatorCommonInterface_CommonSkel.cpp
+ManipulatorCommonInterface_CommonSkel.h
+ManipulatorCommonInterface_CommonStub.cpp
+ManipulatorCommonInterface_CommonStub.h
+ManipulatorCommonInterface_DataTypes.hh
+ManipulatorCommonInterface_DataTypesDynSK.cc
+ManipulatorCommonInterface_DataTypesSK.cc
+ManipulatorCommonInterface_DataTypesSkel.cpp
+ManipulatorCommonInterface_DataTypesSkel.h
+ManipulatorCommonInterface_DataTypesStub.cpp
+ManipulatorCommonInterface_DataTypesStub.h
+ManipulatorCommonInterface_Middle.hh
+ManipulatorCommonInterface_MiddleDynSK.cc
+ManipulatorCommonInterface_MiddleSK.cc
+ManipulatorCommonInterface_MiddleSkel.cpp
+ManipulatorCommonInterface_MiddleSkel.h
+ManipulatorCommonInterface_MiddleStub.cpp
+ManipulatorCommonInterface_MiddleStub.h
+idl-stamp
+idls.lst
+svn-prop.tmp
More information about the openrtm-commit
mailing list