分类: C/C++
2008-07-19 16:48:30
#define SME_BEGIN_STATE_DECLARE(_app) \
enum _app##_state_enum_t \
{
#define SME_STATE_DECLARE(_state) _state,
#define SME_MAX_STATE(_app)
_app##_max_state
#define SME_END_STATE_DECLARE };
#define SME_ENTRY_FUNC_IDX 0
#define SME_EXIT_FUNC_IDX 1
#define SME_EVENT_HANDLER_FUNC_IDX 2
#define SME_BEGIN_STATE_DEF(_app,_state) \
static const SME_EVENT_TABLE_T _app##_state##_event_hdl_tbl[] \
={
#define SME_STATE_ENTRY_FUNC( _EntryFunc) \
{ SME_INVALID_EVENT_ID, _EntryFunc, 0},
#define SME_STATE_EXIT_FUNC( _ExitFunc) \
{ SME_INVALID_EVENT_ID, _ExitFunc, 0},
#define SME_ON_EVENT(_EventID, _Handler, _NewState) \
{ _EventID, _Handler, _NewState},
#define SME_END_STATE_DEF
{ SME_INVALID_EVENT_ID, 0, SME_INVALID_STATE}};
#define SME_BEGIN_STATE_TREE_DEF(_app) \
extern const SME_STATE_TREE_TABLE_T _app##_state_tree[] = \
{
#define SME_STATE
(_app,_state,_state_parent,_def_substate) \
{(SME_EVENT_TABLE_T *)
_app##_state##_event_hdl_tbl,
_state,_state_parent,_def_substate},
#define SME_END_STATE_TREE_DEF };
4.1.4 Application Definition
#define SME_APPLICATION_DEF(_app,_app_name) \
struct SME_APP_T _app##App = { \
_app_name, NULL, NULL, 0, NULL, NULL, _app##_state_tree,
SME_INVALID_STATE};
/* Get application variable name. */
#define SME_GET_APP_VAR(_app) _app##App
/* Declare application variable that has external linkage. */
#define SME_DEC_EXT_APP_VAR(_app)
extern SME_APP_T _app##App;
/////////////////////////////////////////////////////////////
// State Machine Engine Type Definitions
/////////////////////////////////////////////////////////////
//// State Definition
typedef short SME_STATE_T;
#define SME_APP_STATE 0
#define SME_INVALID_STATE -1
//// Event Definition
// Positive 32-bit integer values are user-defined
// event identifiers.
// Negative 32-bit integer values are state machine
// engine defined event identifiers.
typedef long SME_EVENT_ID_T;
#define SME_INVALID_EVENT_ID -1
#define SME_EVENT_KILL_FOCUS -2
#define SME_EVENT_SET_FOCUS -3
typedef enum
{
SME_EVENT_CAT_UI=0,
SME_EVENT_CAT_OTHER,
};
typedef unsigned char SME_EVENT_CAT_T;
typedef enum
{
SME_EVENT_ORIGIN_INTERNAL=0,
SME_EVENT_ORIGIN_EXTERNAL,
};
typedef unsigned char SME_EVENT_ORIGIN_T;
typedef enum
{
SME_EVENT_DATA_FORMAT_INT=0,
SME_EVENT_DATA_FORMAT_PTR,
};
typedef unsigned char SME_EVENT_DATA_FORMAT_T;
typedef struct SME_INT_DATA_T
{
unsigned long nParam1;
unsigned long nParam2;
} SME_INT_DATA_T;
typedef struct SME_PTR_DATA_T
{
void* pData;
unsigned long nSize;
} SME_PTR_DATA_T;
union SME_EVENT_DATA_T
{
SME_INT_DATA_T Int;
SME_PTR_DATA_T Ptr;
};
typedef struct SME_EVENT_T
{
SME_EVENT_ID_T nEventID;
unsigned long nSequenceNum;
struct SME_EVENT_T *pNext;
/* Provide 2 data formats: integer or pointer */
union SME_EVENT_DATA_T Data;
struct SME_APP_T *pDestApp; /* The destination application. */
unsigned long nOrigin :8; /* */
unsigned long nCategory :8; /* Category of this event. */
unsigned long nDataFormat :8; /* Flag for this event. */
unsigned long bIsConsumed :8; /* Is comsumed. */
}SME_EVENT_T;
typedef struct SME_APP_T
{
const char * sAppName;
struct SME_APP_T *pParent; /* Who starts me */
struct SME_APP_T *pNext; /* Applications are linked together. */
unsigned long nPortId;
void * pPortHandle;
void * pData;
const struct SME_STATE_TREE_TABLE_T *pStateTree;
SME_STATE_T nAppState;
}SME_APP_T;
#define SME_APP_DATA(app) (app.pData)
#define SME_IS_ACTIVATED(app)
(app->nAppState != SME_INVALID_STATE)
typedef int (* SME_EVENT_HANDLER_T)
(SME_APP_T *, SME_EVENT_T *);
#define SME_INTERNAL_TRAN
SME_INVALID_STATE
typedef struct SME_EVENT_TABLE_T {
SME_EVENT_ID_T nEventID;
SME_EVENT_HANDLER_T pHandler;
SME_STATE_T nNewState;
}SME_EVENT_TABLE_T;
typedef struct SME_STATE_TREE_TABLE_T{
SME_EVENT_TABLE_T *pEventTable;
SME_STATE_T nState;
SME_STATE_T nParentState;
SME_STATE_T nDefSubState;
}SME_STATE_TREE_TABLE_T;
/**************************************************************/
* DESCRIPTION: Dispatch the incoming event to an application
* if it is specified, otherwise dispatch to all active
* applications untile it is consumed.
* INPUT:
* 1) pEvent: Incoming event
* 2) pApp: The destination application that event
* will be dispatched.
* OUTPUT: None.
* NOTE:
* 1) Call exit functions in old state
* 2) Call event handler functions
* 3) Call entry functions in new state
* 4) Transit from one state region to another state region.
* All states exit functions that jump out
* the old region will be called. And all states exit
* functions that jump in the new region will be called.
* 5) Although there is a property pEvent->pDestApp in
* SME_EVENT_T, this function will ignore this one,
* because if pEvent->pDestApp is NULL, this
* event have to dispatch to all active applications.
*****************************************************************/
BOOL SmeDispatchEvent(struct SME_EVENT_T *pEvent, struct SME_APP_T *pApp)
{
SME_STATE_T nOldState; /* Old state should be a leaf.*/
SME_STATE_T nState;
SME_STATE_T nNewState;
int i;
BOOL bFoundHandler=FALSE;
SME_EVENT_HANDLER_T pHandler = NULL;
SME_STATE_T OldStateStack[SME_MAX_STATE_TREE_DEPTH];
SME_STATE_T NewStateStack[SME_MAX_STATE_TREE_DEPTH];
SME_STATE_T nOldStateStackTop =0;
SME_STATE_T nNewStateStackTop =0;
/* Trace back from leaf to root,
so as to retrieve all event handler tables.
Find what nNewState is */
struct SME_EVENT_TABLE_T *pStateEventTable;
if (pEvent==NULL || pApp==NULL)
return FALSE;
nOldState = pApp->nAppState; /* Old state should be a leaf. */
nState = nOldState;
pStateEventTable = pApp->pStateTree[nOldState].pEventTable;
/****************************************************************
Check the state's event handler table from leaf to root.
If find it, stop searching, no matter there
is another handler in parent sate's event table.
*/
while (TRUE)
{
/* Check the current state's event handler table.*/
i=SME_EVENT_HANDLER_FUNC_IDX;
while (pStateEventTable[i].nEventID != SME_INVALID_EVENT_ID)
{
if (pStateEventTable[i].nEventID == pEvent->nEventID)
{nNewState=pStateEventTable[i].nNewState;
bFoundHandler = TRUE;
pHandler = pStateEventTable[i].pHandler;break;
} else
i++;
}
if (bFoundHandler || (nState == SME_APP_STATE))break;
/* Get the parent state's event handler table. */
nState = pApp->pStateTree[nState].nParentState;
pStateEventTable = pApp->pStateTree[nState].pEventTable;
}
if (!bFoundHandler)
return FALSE;
/***********************************************************/
if (nNewState != SME_INTERNAL_TRAN)
{
/* It is a state transition.
Push all old state's ancestors.
*/
nState = nOldState;
while (nState!=SME_APP_STATE)
{
OldStateStack[nOldStateStackTop++] = nState;
nState=pApp->pStateTree[nState].nParentState;
if (nOldStateStackTop >= SME_MAX_STATE_TREE_DEPTH)
return FALSE;
}
/* Push all new state's ancestors. */
nState = nNewState;
while (nState!=SME_APP_STATE)
{
NewStateStack[nNewStateStackTop++] = nState;
nState=pApp->pStateTree[nState].nParentState;
if (nNewStateStackTop >
= SME_MAX_STATE_TREE_DEPTH) return FALSE;
}
/* Pop all equal states except the last one.
Special case 1: self transition state1->state1,
leave one item in each stack.
Special case 2: parent state transits to child state,
leave one item in parent state stack.
*/
while ((nOldStateStackTop>1) && (nNewStateStackTop>1)
&& (OldStateStack[nOldStateStackTop-1] ==
NewStateStack[nNewStateStackTop-1]))
{
nOldStateStackTop--;
nNewStateStackTop--;
}
/* Get the leaf of the old state.
Note: Old state should be a leaf state.
Call exit functions from leaf nState to old state stacks top.
*/
for (i=0; i{
nState = OldStateStack[i];
if(pApp->pStateTree[nState].pEventTable[SME_EXIT_FUNC_IDX].pHandler)
pApp->pStateTree[nState].
pEventTable[SME_EXIT_FUNC_IDX].pHandler(pApp,pEvent);
};
}; /* end of not internal transition.*/
/*********************************************************
Call event handler function if given event handler
is available and handler is not empty.
Maybe their is a transition, however handler is empty.
*/
if (bFoundHandler && pHandler)
{
(*pHandler)(pApp,pEvent);
};
/*********************************************************
Call entry functions from new state stack's top to leaf state. */
if (nNewState != SME_INTERNAL_TRAN)
{
/* It is a state transition.
Call entry functions from ancestor to new state.
*/
for (i=nNewStateStackTop-1; i>=0; i--)
{
nState = NewStateStack[i];
if(pApp->pStateTree[nState].pEventTable[SME_ENTRY_FUNC_IDX].pHandler)
pApp->pStateTree[nState].
pEventTable[SME_ENTRY_FUNC_IDX].pHandler(pApp,pEvent);
};
/* Call entry functions from new state's child to leaf. */
nState=nNewState;
while (pApp->pStateTree[nState].nDefSubState
!= SME_INVALID_STATE) /* It is not a leaf. */
{
nState=pApp->pStateTree[nState].nDefSubState;
/* Call default sub-state's entry function.*/
if(pApp->pStateTree[nState].pEventTable[SME_ENTRY_FUNC_IDX].pHandler)
pApp->pStateTree[nState].
pEventTable[SME_ENTRY_FUNC_IDX].pHandler(pApp,pEvent);
}
pApp->nAppState = nState;
/* New application state
is the destination state's leaf. */
};
/************************************************************
Call event handle hook function
if given enent handler is available and no
matter whether handler is empty or not
*/
if (bFoundHandler && g_fnOnEventHandleHook)
(*g_fnOnEventHandleHook)((SME_EVENT_ORIGIN_T)(pEvent->nOrigin),
pEvent,
pApp,
pApp->nAppState);
#ifdef WIN32
#ifdef _DEBUG
if (bFoundHandler)
StateTrack(pEvent, pApp, pApp->nAppState);
#endif
#endif
return TRUE;
}