📄 statemachine.cpp
字号:
/**********@@@SOFT@@@WARE@@@COPY@@@RIGHT@@@**********************************
* DIALOGIC CONFIDENTIAL
*
* Copyright (C) 2006-2007 Dialogic Corporation. All Rights Reserved.
* The source code contained or described herein and all documents related
* to the source code ("Material") are owned by Dialogic Corporation or its
* suppliers or licensors. Title to the Material remains with Dialogic Corporation
* or its suppliers and licensors. The Material contains trade secrets and
* proprietary and confidential information of Dialogic or its suppliers and
* licensors. The Material is protected by worldwide copyright and trade secret
* laws and treaty provisions. No part of the Material may be used, copied,
* reproduced, modified, published, uploaded, posted, transmitted, distributed,
* or disclosed in any way without Dialogic's prior express written permission.
*
* No license under any patent, copyright, trade secret or other intellectual
* property right is granted to or conferred upon you by disclosure or delivery
* of the Materials, either expressly, by implication, inducement, estoppel or
* otherwise. Any license under such intellectual property rights must be
* express and approved by Dialogic in writing.
*
***********************************@@@SOFT@@@WARE@@@COPY@@@RIGHT@@@**********/
//***********************************************************************
//***********************************************************************
// StateMachine.cpp: implementation of the CStateMachine class.
//
//////////////////////////////////////////////////////////////////////
#include "pdl.h"
//
// Global functions
//
//*****************************************************************************
// Purpose :
// Find state name by given value
// Parameters:
// [in] state
// Returns:
// value or <unknown state> if not found
//*****************************************************************************
const char *common_state_name(int state){
static NAME_TABLE state_tbl[] = {
{ "S_END", S_END },
{ "S_FINAL", S_FINAL },
{ "S_ANY", S_ANY },
{ "S_SAME", S_SAME },
{ "S_BEGIN", S_BEGIN },
{ "S_OPEN", S_OPEN },
{ "S_OPEN_EXIT", S_OPEN_EXIT },
{ "S_RELAX", S_RELAX },
{ "S_RELAXCNF", S_RELAXCNF },
{ "S_WAIT_SUBDEV", S_WAIT_SUBDEV },
{ 0, 0 }
};
const char *name = "<Unknown state>";
str_findname(state, &name, state_tbl);
return name;
} // End of common_state_name()
//*****************************************************************************
// Purpose :
// Find action name by given value
// Parameters:
// [in] action
// Returns:
// value or <unknown action> if not found
//*****************************************************************************
// find action name by value
const char *common_action_name(int action){
static NAME_TABLE action_tbl[] = {
{ "A_NONE", A_NONE },
{ "A_RELAX", A_RELAX },
{ "A_RELAXCNF", A_RELAXCNF },
{ "A_CLOSE", A_CLOSE },
{ "A_ERROR", A_ERROR },
{ "A_EXIT", A_EXIT },
{ "A_GIVEUP", A_GIVEUP },
{ 0, 0 }
};
const char *name = "<Unknown action>";
str_findname(action, &name, action_tbl);
return name;
} // End of common_action_name()
//*****************************************************************************
// Purpose :
// Determine if state machine can stay in given state
// forever without timing out
// Relaxed states are BEGIN (initial state),
// RELAX (waiting for calls, or waiting somebody to join conference
// RELAXCNF (waiting somebody to leave conference)
// Parameters:
// [in] state
// Returns:
// bool = yes, it is
// false = nop
//*****************************************************************************
bool is_relaxed_state(int state){
bool brc = false;
switch (state){
case S_BEGIN:
case S_RELAX:
case S_RELAXCNF:
case S_WAIT_SUBDEV:
case S_FINAL:
brc = true;
break;
default:
break;
} // switch state
return brc;
} // End of is_relaxed_state()
//////////////////////////////////////////////////////////////
// Class members
//////////////////////////////////////////////////////////////
//************************************************************
// Purpose :
// Find appropriate line in table 'actions'
// Match priorities:
// 1. exact match ( current state and event )
// 2. any state, this event
// 3. any event, this state
// 4. any state, any event
// Parameters:
// [in] state
// [in] event
// [out] Holder to place pointer to the line
// Returns:
// true = found
// false = no appropriate line ( state machine error )
//************************************************************
bool CStateMachine::FindInStates(int state,
int event,
PEVENT_STRU *ppNew){
PEVENT_STRU match_with_any_state = 0;
PEVENT_STRU match_with_any_event = 0;
PEVENT_STRU match_with_any_any = 0;
PEVENT_STRU pEvents = m_pEventStru;
while ( S_END != pEvents->current_state ) {
if ( event == pEvents->event) {
if ( state == pEvents->current_state) {
*ppNew = pEvents;
return true;
} else if ( S_ANY == pEvents->current_state ) {
match_with_any_state = pEvents;
}
}else if ( EVENT_ANY == pEvents->event ) {
if ( state == pEvents->current_state ) {
match_with_any_event = pEvents;
}else if ( S_ANY == pEvents->current_state ) {
match_with_any_any = pEvents;
}
}
pEvents++;
}
if (match_with_any_state){
*ppNew = match_with_any_state;
return true;
}
if (match_with_any_event){
*ppNew = match_with_any_event;
return true;
}
if (match_with_any_any){
*ppNew = match_with_any_any;
return true;
}
return false;
} // End of FindInStates()
//****************************************************
// Purpose :
// Find appropriate line in table 'actions'
// Match priorities:
// 1. exact match ( current state and action )
// 2. any state, this action
// Parameters:
// [in] state
// [in] action
// [out] Holder to place pointer to the line
// Returns:
// true = found
// false = no appropriate line ( state machine error )
//****************************************************
bool CStateMachine::FindInActions(int state,
int action,
PACTION_STRU *ppNew){
PACTION_STRU match_with_any_state = 0;
PACTION_STRU pActions= m_pActionStru;
while ( S_END != pActions->current_state ) {
if ( action == pActions->action) {
if ( state == pActions->current_state) {
*ppNew = pActions;
return true;
} else if ( S_ANY == pActions->current_state ) {
match_with_any_state = pActions;
}
}
pActions++;
}
if (match_with_any_state){
*ppNew = match_with_any_state;
return true;
}
return false;
} // End of FindInActions()
//*****************************************************************************
// Purpose :
// Enumerate events that can advance state machine from it's current state
// Parameters:
// [out] holder for event code
// [in / out] handle
// to start enumeration set handle = BEGIN_SEARCH and pass &handle
// to continue search, pass previous &handle
// Returns:
// true = missing event is set to next possible event
//*****************************************************************************
bool CStateMachine::EnumMissingEvents(int *missing_event, int *handle){
while (S_END != m_pEventStru[++(*handle)].current_state ){
if (m_pEventStru[*handle].current_state == m_current_state) {
*missing_event = m_pEventStru[*handle].event;
return true;
}
}
return false;
} // End of FindInActions()
//*****************************************************************************
// Purpose :
// Validate state machine and request exit if it is invalid
// Parameters:
// [in] object (CSrlDevice) that creates state machine
// Returns:
// true = state machine is valid
// false = there are missing elements in event table or in action table
//*****************************************************************************
bool CStateMachine::Validate(PSrlDevice pDev){
EVENT_STRU *pEvent = m_pEventStru;
bool brc = true;
// 1. for each (event,action) in event table
// (same state, same action) should exist in action table
while (S_END != pEvent->current_state ){
PACTION_STRU pAction;
const char *evtname;
evt_getname(pEvent->event, &evtname);
if (!FindInActions(pEvent->current_state, pEvent->action, &pAction) ){
pDev->LOG( LOG_ASSERT, pDev->GetName(),
"Missing action table entry for following event_table item(action)");
pDev->LOG( LOG_ASSERT, pDev->GetName(),
" =>state = %5d %s",
pEvent->current_state, pDev->state_name(pEvent->current_state));
pDev->LOG( LOG_ASSERT, pDev->GetName(),
" event = %5d %s",
pEvent->event, evtname );
pDev->LOG( LOG_ASSERT, pDev->GetName(),
" =>action = %5d %s",
pEvent->action, pDev->action_name(pEvent->action));
brc = false;
}
++pEvent;
}
// 2. for each (state, action, action_if_fail) in action table
// (same state, action_if_fail (as action) should exist in action table
ACTION_STRU *pAction = m_pActionStru;
ACTION_STRU *pTmp;
while (S_END != pAction->current_state ){
if (!FindInActions(pAction->current_state, pAction->action_if_fail, &pTmp) ){
pDev->LOG( LOG_ASSERT, pDev->GetName(),
"Missing action table entry for following action_table item(action_if_fail)");
pDev->LOG( LOG_ASSERT, pDev->GetName(),
" =>state = %5d %s",
pAction->current_state, pDev->state_name(pAction->current_state));
pDev->LOG( LOG_ASSERT, pDev->GetName(),
" action = %5d %s",
pAction->action, pDev->action_name(pAction->action));
pDev->LOG( LOG_ASSERT, pDev->GetName(),
" state_if_pass = %5d %s",
pAction->state_if_pass, pDev->state_name(pAction->state_if_pass));
pDev->LOG( LOG_ASSERT, pDev->GetName(),
" =>action_if_fail = %5d %s",
pAction->action_if_fail, pDev->action_name(pAction->action_if_fail));
brc = false;
}
++pAction;
}
// 3. TBD check if all roads lead to Rome ( S_FINAL in our case )
return brc;
} // End of Validate()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -