// CcosSMachine.cpp : 定义 DLL 应用程序的导出函数。 // #include "CcosSMachine.h" #include "common_api.h" #include using namespace std; //Log4CPP::Logger* mLog::gLogger = nullptr; //----------------------------- CcosStMEvt::CcosStMEvt() { m_pEvt = new ResDataObject(); m_pInfo = new ResDataObject(); } CcosStMEvt::CcosStMEvt(const CcosStMEvt &tValue) { m_pEvt = new ResDataObject(); m_pInfo = new ResDataObject(); (*m_pEvt) = (*tValue.m_pEvt); (*m_pInfo) = (*tValue.m_pInfo); } CcosStMEvt::~CcosStMEvt() { delete m_pEvt; m_pEvt = NULL; delete m_pInfo; m_pInfo = NULL; } bool CcosStMEvt::SetEvt(const char* pKey, int Val, const char *pInfo) { m_pEvt->clear(); m_pInfo->clear(); if (pKey) { m_pEvt->add(pKey, Val); m_pInfo->add(pKey, Val); } else { //m_pEvt->add("", Val); //m_pInfo->add("", Val); return true; } if (pInfo) { m_pInfo->add(CcosStmEvtInfo, pInfo); } else { m_pInfo->add(CcosStmEvtInfo, ""); } return true; } bool CcosStMEvt::IsEmpty() { return (m_pEvt->size() == 0); } bool CcosStMEvt::SetEvt(const char* pKey, const char *pVal, const char *pInfo) { bool ret = true; m_pEvt->clear(); m_pInfo->clear(); if (pKey == NULL) { return true; } if (pVal) { ret = m_pEvt->add(pKey, pVal); m_pInfo->add(pKey, pVal); } else { ret = m_pEvt->add(pKey, ""); m_pInfo->add(pKey, ""); } if (pInfo) { m_pInfo->add(CcosStmEvtInfo, pInfo); } else { m_pInfo->add(CcosStmEvtInfo, ""); } return ret; } ResDataObject& CcosStMEvt::GetEvtContext() { return (*m_pEvt); } CcosStMEvt& CcosStMEvt::operator = (const CcosStMEvt &tValue) { if (this != &tValue) { (*m_pEvt) = (*tValue.m_pEvt); (*m_pInfo) = (*tValue.m_pInfo); } return (*this); } bool CcosStMEvt::operator == (const CcosStMEvt &Obj) { return (*m_pEvt == (*(Obj.m_pEvt))); } const char *CcosStMEvt::encode() { return m_pInfo->encode(); } bool CcosStMEvt::decode(const char *pdata) { ResDataObject Obj; bool ret = m_pInfo->decode(pdata); if (ret) { size_t size = m_pInfo->size(); if ((size > 0) && (size <= 2)) { ret = false; string strStmEvtInfo = CcosStmEvtInfo; for (size_t i = 0; i < size; i++) { const char *pKey = (*m_pInfo).GetKey(i); if (strStmEvtInfo == pKey) { continue; } m_pEvt->clear(); m_pEvt->add(pKey, (*m_pInfo)[i]); ret = true; } } else { ret = false; } } if (ret == false) { m_pEvt->clear(); m_pInfo->clear(); } return ret; } //----------------------------- CcosStMRouteLine::CcosStMRouteLine() { m_ActiveState = false; m_InRoute = true; m_pEvt = new CcosStMEvt(); m_pSrcRoutePos = new string(); m_pGuard = new string(); m_pDesRoutePos = new string(); m_Timeout = TIMEOUT_TEMP; } CcosStMRouteLine::CcosStMRouteLine(const CcosStMRouteLine &tValue) { m_ActiveState = false; m_InRoute = true; m_pEvt = new CcosStMEvt(); m_pSrcRoutePos = new string(); m_pGuard = new string(); m_pDesRoutePos = new string(); m_Timeout = TIMEOUT_TEMP; if (tValue.m_InRoute) { SetRoute(*(tValue.m_pEvt), tValue.m_pSrcRoutePos->c_str(), tValue.m_pGuard->c_str(), tValue.m_pDesRoutePos->c_str()); } else { SetRoute(*(tValue.m_pEvt), tValue.m_pGuard->c_str(), tValue.m_pDesRoutePos->c_str()); } } CcosStMRouteLine::~CcosStMRouteLine() { delete m_pEvt; delete m_pSrcRoutePos; delete m_pDesRoutePos; delete m_pGuard; } void CcosStMRouteLine::SetRoute(CcosStMEvt &evt, const char* pGuard, const char* pDes) { m_InRoute = true; (*m_pSrcRoutePos) = ""; (*m_pEvt) = evt; if (pGuard) { (*m_pGuard) = pGuard; } else { (*m_pGuard) = ""; } if (pDes) { (*m_pDesRoutePos) = pDes; } else { (*m_pDesRoutePos) = ""; } } void CcosStMRouteLine::SetRoute(CcosStMEvt &evt, const char* pSrc, const char* pGuard, const char* pDes) { m_InRoute = false; (*m_pEvt) = evt; if (pSrc) { (*m_pSrcRoutePos) = pSrc; } else { (*m_pSrcRoutePos) = ""; } if (pGuard) { (*m_pGuard) = pGuard; } else { (*m_pGuard) = ""; } if (pDes) { (*m_pDesRoutePos) = pDes; } else { (*m_pDesRoutePos) = ""; } } const char* CcosStMRouteLine::GetDesName() { return m_pDesRoutePos->c_str(); } const char* CcosStMRouteLine::GetSrcName() { if (m_InRoute == false) { return m_pSrcRoutePos->c_str(); } return NULL; } const char* CcosStMRouteLine::GetGuardName() { return m_pGuard->c_str(); } //true:in,false:out bool CcosStMRouteLine::GetRouteType() { return m_InRoute; } CcosStMRouteLine::operator CcosStMEvt *() { return m_pEvt; } CcosStMRouteLine& CcosStMRouteLine::operator = (const CcosStMRouteLine &tValue) { if (&tValue != this) { if (tValue.m_InRoute) { SetRoute(*(tValue.m_pEvt), tValue.m_pSrcRoutePos->c_str(), tValue.m_pGuard->c_str(), tValue.m_pDesRoutePos->c_str()); } else { SetRoute(*(tValue.m_pEvt), tValue.m_pGuard->c_str(), tValue.m_pDesRoutePos->c_str()); } } return (*this); } void CcosStMRouteLine::Active(bool state, DWORD timeout) { m_ActiveState = state; if (m_ActiveState == false) { m_Timeout = timeout; } else { //get maximum timeperiod if (timeout > m_Timeout) { m_Timeout = timeout; } } } bool CcosStMRouteLine::GetActiveState() { return m_ActiveState; } DWORD CcosStMRouteLine::GetTimeout() { return m_Timeout; } //================================ CcosStMRoutePos::CcosStMRoutePos() { m_ActiveState = false; m_pRoutePosName = new string(); m_pOutRouteLineVec = new vector(); m_Timeout = TIMEOUT_TEMP; } CcosStMRoutePos::CcosStMRoutePos(const char *pName) { m_ActiveState = false; m_pRoutePosName = new string(); (*m_pRoutePosName) = pName; m_pOutRouteLineVec = new vector(); m_Timeout = TIMEOUT_TEMP; } CcosStMRoutePos::~CcosStMRoutePos() { delete m_pRoutePosName; m_pRoutePosName = NULL; if (m_pOutRouteLineVec != NULL) { if (m_pOutRouteLineVec->size() > 0) { for (size_t i = 0; i < m_pOutRouteLineVec->size(); i++) { CcosStMRouteLine *p = (*m_pOutRouteLineVec)[i]; delete p; } } delete m_pOutRouteLineVec; m_pOutRouteLineVec = NULL; } } void CcosStMRoutePos::Active(bool state,DWORD timeout) { m_ActiveState = state; if (m_ActiveState == false) { m_Timeout = timeout; } else { //get maximum timeperiod if (timeout > m_Timeout) { m_Timeout = timeout; } } } bool CcosStMRoutePos::GetActiveState() { return m_ActiveState; } bool CcosStMRoutePos::IsSMachine() { return false; } bool CcosStMRoutePos::PosAddOutRouteLine(CcosStMEvt &Evt, const char *pSrcPosName, const char *pGuardName, const char *pDesPosName) { CcosStMRouteLine *pLine = new CcosStMRouteLine(); pLine->SetRoute(Evt, pSrcPosName, pGuardName, pDesPosName); m_pOutRouteLineVec->push_back(pLine); return true; } void CcosStMRoutePos::SetName(const char *pName) { (*m_pRoutePosName) = pName; } const char* CcosStMRoutePos::GetName() { return m_pRoutePosName->c_str(); } DWORD CcosStMRoutePos::GetRouteLineCount() { if (m_pOutRouteLineVec) { return (DWORD)m_pOutRouteLineVec->size(); } return 0; } CcosStMRouteLine **CcosStMRoutePos::GetOutRouteLineVec() { if (m_pOutRouteLineVec) { if (m_pOutRouteLineVec->size() > 0) { return &((*m_pOutRouteLineVec)[0]); } } return NULL; } CcosStMRouteLine *CcosStMRoutePos::operator [](CcosStMEvt &Evt) { if (m_pOutRouteLineVec) { if (m_pOutRouteLineVec->size() > 0) { for (size_t i = 0; i < m_pOutRouteLineVec->size(); i++) { if ((*(CcosStMEvt *)(*(*m_pOutRouteLineVec)[i])) == Evt) { return (*m_pOutRouteLineVec)[i]; } } } } return NULL; } DWORD CcosStMRoutePos::GetTimeout() { return m_Timeout; } //================================ CcosSMachineIF::CcosSMachineIF() { m_pStateMachineName = new string(); m_pParent = 0; m_pCurrentRoutePos = NULL; //evt list m_pArrivedEvts = new MsgCircle(); //routepos m_pRoutePosMap = new map(); CcosStMRoutePos *p = NULL; p = new CcosStMRoutePos(CcosStmEntryPosName); p->Active(true, TIMEOUT_TEMP); (*m_pRoutePosMap)[CcosStmEntryPosName] = p; //printf(" == this[% 08X] Add Route Pos [%s] \n", this, CcosStmEntryPosName); p = new CcosStMRoutePos(CcosStmExitPosName); p->Active(true, TIMEOUT_TEMP); (*m_pRoutePosMap)[CcosStmExitPosName] = p; //inline m_pRouteInLineMap = new vector(); //external m_RouteExternalEvtCount = 0; m_pRouteExternalMap = NULL; //running state m_RunningState = LinuxEvent::CreateEvent(LinuxEvent::MANUAL_RESET,false); m_StateCangeEvt = LinuxEvent::CreateEvent(LinuxEvent::AUTO_RESET, false); } CcosSMachineIF::~CcosSMachineIF() { delete m_pStateMachineName; m_pStateMachineName = 0; //cp m_pCurrentRoutePos = NULL; //external m_RouteExternalEvtCount = 0; m_pRouteExternalMap = NULL; //clear inline path for (size_t i = 0; i < m_pRouteInLineMap->size(); i++) { delete (*m_pRouteInLineMap)[i]; } delete m_pRouteInLineMap; m_pRouteInLineMap = NULL; //clear routepos map::iterator iter = m_pRoutePosMap->begin(); while (iter != m_pRoutePosMap->end()) { if (iter->second->IsSMachine()) { CcosSubSMachine* pSub = (CcosSubSMachine*)iter->second; delete pSub; } else { delete iter->second; } ++iter; } delete m_pRoutePosMap; m_pRoutePosMap = NULL; //evt list delete m_pArrivedEvts; m_pArrivedEvts = NULL; return; } void CcosSMachineIF::SetStateMachineName(const char *pszName) { (*m_pStateMachineName) = pszName; } const char *CcosSMachineIF::GetStateMachineName() { return m_pStateMachineName->c_str(); } void CcosSMachineIF::SetParentSMachine(CcosSMachineIF *pParent) { m_pParent = pParent; } void CcosSMachineIF::PushStateChange(ResDataObject &ChangedPos) { if (m_pParent) { m_pParent->PushStateChange(ChangedPos); } } bool CcosSMachineIF::IsSMachine() { return true; } std::shared_ptr CcosSMachineIF::GetStateChangeEvtHandle() { return m_StateCangeEvt; } void CcosSMachineIF::SetRunningState(bool Running) { Thread_Lock(); if (Running) { m_RunningState->SetEvent(); } else { m_RunningState->ResetEvent(); } Thread_UnLock(); } bool CcosSMachineIF::GetRunningState(DWORD waittime) { bool ret = (m_RunningState-> Wait(waittime)); if (ret == false) { //printf("GetRunningState Failed.WTF??\n"); } return ret; } //init state machine //第一个节点的接入比较特殊,所以做了个函数 bool CcosSMachineIF::AddEntryRoutePos(CcosStMRoutePos *pPos) { if (strlen(pPos->GetName()) == 0) { return false; } if ((*m_pRoutePosMap)[CcosStmEntryPosName]->GetRouteLineCount() > 0) { return false; } //add pos (*m_pRoutePosMap)[pPos->GetName()] = pPos; CcosStMEvt evt; //make a line (*m_pRoutePosMap)[CcosStmEntryPosName]->PosAddOutRouteLine(evt, CcosStmEntryPosName, NULL, pPos->GetName()); return true; } bool CcosSMachineIF::AddRoutePos(CcosStMRoutePos *pPos) { if (strlen(pPos->GetName()) == 0) { return false; } //add pos //printf("=== this [%08X] Add RoutePos [%s] \n",this, pPos->GetName()); if (string(pPos->GetName()) == "FrameStart") { //printf("stop"); } (*m_pRoutePosMap)[pPos->GetName()] = pPos; return true; } bool CcosSMachineIF::AddInRouteLine(CcosStMEvt &Evt, const char *pGuardName, const char *pDesPosName) { CcosStMRouteLine *pLine = new CcosStMRouteLine(); pLine->SetRoute(Evt, pGuardName, pDesPosName); pLine->Active(true, 0);//timeout没必要,因为是全局事件 m_pRouteInLineMap->push_back(pLine); return true; } bool CcosSMachineIF::AddOutRouteLine(CcosStMEvt &Evt, const char *pSrcPosName, const char *pGuardName, const char *pDesPosName) { bool ret = true; try{ auto route = (*m_pRoutePosMap)[pSrcPosName]; auto itf = m_pRoutePosMap->find(pSrcPosName); if (itf != m_pRoutePosMap->end()) { //printf("\n Got it %s \n", pSrcPosName); } else { //printf("\n Route Pos %s has not set....\n", pSrcPosName); } ret = route->PosAddOutRouteLine(Evt, pSrcPosName, pGuardName, pDesPosName); } catch (...) { ret = false; } return ret; } //active state machine bool CcosSMachineIF::ActiveRoutePos(const char *pPosName, DWORD timeout) { bool ret = true; try{ map::iterator iterOut = m_pRoutePosMap->find(pPosName); if (iterOut != m_pRoutePosMap->end()) { (*m_pRoutePosMap)[pPosName]->Active(true, timeout); } //find sub route machine iterOut = (*m_pRoutePosMap).begin(); while (iterOut != (*m_pRoutePosMap).end()) { if (iterOut->second->IsSMachine() == true) { CcosSubSMachine *pSub = (CcosSubSMachine *)(iterOut->second); pSub->ActiveRoutePos(pPosName, timeout); } ++iterOut; } } catch (...) { ret = false; } return ret; } //bool CcosSMachineIF::ActiveInRouteLine(CcosStMEvt &Evt, DWORD timeout) //{ // bool ret = false; // try{ // //find In Route Line // for (size_t i = 0; i < m_pRouteInLineMap->size(); i++) // { // if ((*(CcosStMEvt*)(*(*m_pRouteInLineMap)[i])) == Evt) // { // (*m_pRouteInLineMap)[i]->Active(true,timeout); // // ret = true; // // break; // } // } // // } // catch (...) // { // ret = false; // } // // return ret; // //} bool CcosSMachineIF::ActiveRouteLine(CcosStMEvt &Evt, DWORD timeout) { bool ret = true; try{ //out path map::iterator iterOut = (*m_pRoutePosMap).begin(); while (iterOut != (*m_pRoutePosMap).end()) { if (iterOut->second->IsSMachine() == false) { DWORD RouteCount = iterOut->second->GetRouteLineCount(); CcosStMRouteLine **RouteLines = iterOut->second->GetOutRouteLineVec(); for (DWORD i = 0; i < RouteCount; i++) { if ((*(CcosStMEvt *)(*(RouteLines[i]))) == Evt) { RouteLines[i]->Active(true, timeout); } } } else { //子对象自行激活自己 //CcosSubSMachine *pSub = (CcosSubSMachine *)(iterOut->second); //pSub->ActiveRouteLine(Evt, timeout); } ++iterOut; } //in path for (size_t i = 0; i < m_pRouteInLineMap->size(); i++) { if ((*(CcosStMEvt *)(*((*m_pRouteInLineMap)[i]))) == Evt) { (*m_pRouteInLineMap)[i]->Active(true, timeout); } } //CcosStMRouteLine* pLine = (*(*m_pRoutePosMap)[pPosName])[Evt]; //if (pLine) //{ // pLine->Active(true, timeout); // ret = true; //} } catch (...) { ret = false; } return ret; } bool CcosSMachineIF::DeActiveAll() { bool ret = true; try{ //out path map::iterator iterOut = (*m_pRoutePosMap).begin(); while (iterOut != (*m_pRoutePosMap).end()) { if (iterOut->second->IsSMachine() == false) { //deactive pos iterOut->second->Active(false, 0); //deactive line DWORD RouteCount = iterOut->second->GetRouteLineCount(); CcosStMRouteLine **RouteLines = iterOut->second->GetOutRouteLineVec(); for (DWORD i = 0; i < RouteCount; i++) { RouteLines[i]->Active(false, 0); } } else { CcosSubSMachine *pSub = (CcosSubSMachine *)(iterOut->second); pSub->DeActiveAll(); } ++iterOut; } //in path for (size_t i = 0; i < m_pRouteInLineMap->size(); i++) { (*m_pRouteInLineMap)[i]->Active(false, 0); } } catch (...) { ret = false; } return ret; } void CcosSMachineIF::ClearState(bool bClearEvent) { Thread_Lock(); SetRunningState(false); map::iterator iterOut = (*m_pRoutePosMap).begin(); while (iterOut != (*m_pRoutePosMap).end()) { if (iterOut->second->IsSMachine()) { CcosSubSMachine *pSub = (CcosSubSMachine *)(iterOut->second); pSub->ClearState(bClearEvent); } ++iterOut; } m_pCurrentRoutePos = NULL; if(bClearEvent) m_pArrivedEvts->Clear(); m_RouteExternalEvtCount = 0; m_pRouteExternalMap = NULL; Thread_UnLock(); } std::shared_ptr CcosSMachineIF::GetEvtNotifyHandle() { return (*m_pArrivedEvts).GetNotifyHandle(); } bool CcosSMachineIF::PeekEvent(CcosStMEvt &Evt) { //check it's existance return (*m_pArrivedEvts).Peek(Evt); } //evt bool CcosSMachineIF::PopEvent(CcosStMEvt &Evt) { return (*m_pArrivedEvts).DeQueue(Evt); } bool CcosSMachineIF::PushEvent(CcosStMEvt &Evt) { bool ret = false; Thread_Lock(); ResDataObject& EvtContext = Evt.GetEvtContext(); //mLog::FINFO("Push Key[{$}]:Val[{$}]", EvtContext.GetKey(0), (const char*)EvtContext[0]); if (m_pCurrentRoutePos) { if (m_pCurrentRoutePos->IsSMachine()) { CcosSubSMachine* pMachine = (CcosSubSMachine*)m_pCurrentRoutePos; pMachine->Thread_Lock(); if (pMachine->GetRunningState() == true) { //mLog::FINFO("Enter SubStateMachine "); ret = pMachine->PushEvent(Evt); pMachine->Thread_UnLock(); Thread_UnLock(); return ret; } pMachine->Thread_UnLock(); } } Thread_UnLock(); //check it's existance (*m_pArrivedEvts).Lock(); DWORD size = (*m_pArrivedEvts).size(); for (DWORD i = 0; i < size; i++) { if ((*m_pArrivedEvts)[i] == Evt) { (*m_pArrivedEvts).UnLock(); return ret; } } ret = true; //mLog::FINFO("m_pArrivedEvts InQueue This Event"); (*m_pArrivedEvts).InQueue(Evt); (*m_pArrivedEvts).UnLock(); return true; } //for state machine thread CCOSSTMRET CcosSMachineIF::StateMachineEntry(DWORD timeout) { return CCOSSMRET_OK; } CCOSSTMRET CcosSMachineIF::StateMachineExit(DWORD timeout) { return CCOSSMRET_OK; } CCOSSTMRET CcosSMachineIF::StateMachineAction(const char *pAction, DWORD timeout) { return CCOSSMRET_OK; } CCOSSTMRET CcosSMachineIF::StateMachineGuard(const char *pGuard, DWORD timeout) { return CCOSSMRET_OK; } /// /// 实际的状态机等待事件 /// /// /// /// /// /// /// /// /// /// /// 返回值为负:退出状态机;返回值为等到的 事件的下标 /// int CcosSMachineIF::StateMachineWaitForEvents( CcosStMRouteLine *pLocalEvts[], DWORD CountOfLocal, CcosStMRouteLine *pExternalEvts[], DWORD CountOfExternal, CcosStMRouteLine *pOutpathEvts[], DWORD CountOfOutpath, DWORD timeout, CcosStMEvt& Evt ) { //执行最基础的处理 return -1; } CcosStMRoutePos *CcosSMachineIF::GetCurrentRoutePos() { return m_pCurrentRoutePos; } CCOSSTMRET CcosSMachineIF::TransToPos(const char *pPosName) { CCOSSTMRET ret = CCOSSMRET_OK; //des check try{ Thread_Lock(); m_pCurrentRoutePos = (*m_pRoutePosMap)[string(pPosName)]; Thread_UnLock(); m_StateCangeEvt->SetEvent(); //printf("Trans To %s \n", pPosName); } catch (...) { assert(0);//never gonna reach ret = CCOSSMRET_NG; } return ret; } void CcosSMachineIF::PostError(const char *pErrorVal, const char *pErrorInfo) { CcosStMEvt evt; if (pErrorVal) { //printf("--PostError:%s--\n", pErrorVal); } else { //printf("--PostError:Empty--\n"); } evt.SetEvt(CcosErrorType, pErrorVal,pErrorInfo); PushEvent(evt); } CcosStMRouteLine *CcosSMachineIF::GetEntryRouteLine() { //routepos CcosStMRoutePos *pFirst = (*m_pRoutePosMap)[string(CcosStmEntryPosName)]; if (pFirst) { if (pFirst->GetRouteLineCount() == 1) { return ((m_pCurrentRoutePos->GetOutRouteLineVec())[0]); } } return NULL; } void CcosSMachineIF::CopyEvtTo(CcosSMachineIF *pDes) { //排序上先ORG的消息,然后des的消息 bool ret = true; CcosStMEvt Evt; //mLog::FINFO("Begin from {$} To {$}", GetStateMachineName(), pDes->GetStateMachineName()); //copy des to org while (ret) { ret = pDes->PopEvent(Evt); if (ret) { PushEvent(Evt); } } //org -> des ret = true; while (ret) { ret = PopEvent(Evt); if (ret) { pDes->PushEvent(Evt); } } //mLog::FINFO("End with {$}", GetStateMachineName()); } //检查:路径,状态点,以及它们的ActiveState bool CcosSMachineIF::PrePareStateMachine() { //状态点的检查 map::iterator iter = m_pRoutePosMap->begin(); while (iter != m_pRoutePosMap->end()) { if (iter->second->IsSMachine()) { //sub machine CcosSubSMachine* pSub = static_cast(iter->second); if (pSub->PrePareStateMachine() == false) { ostringstream buf; buf << "Sub StateMachine Error.Name:" << (iter->second)->GetName(); PostError(CcosFrameError,buf.str().c_str()); //mLog::FERROR("Post FrameError.{$}",buf.str().c_str()); return false;//submachine err } } else { //route pos bool RouteLineActived = false; //OutRouteLine的检查 DWORD VecCount = iter->second->GetRouteLineCount(); CcosStMRouteLine **pVec = iter->second->GetOutRouteLineVec(); for (DWORD i = 0; i < VecCount; i++) { //Activestate RouteLineActived |= pVec[i]->GetActiveState(); //Des的有效性 const char *pDes = pVec[i]->GetDesName(); map::iterator desok = m_pRoutePosMap->find(string(pDes)); if (desok == m_pRoutePosMap->end()) { //no des //ostringstream buf; string buf; buf = "No Destination of RouteLine.RouteName:" + string(iter->second->GetName()) + "DesName:" + string(pDes); PostError(CcosFrameError, buf.c_str()); //mLog::FERROR("Post FrameError.{$}", buf.c_str()); return false; } } //多个路径情况下,是否有一个Active if (VecCount > 1) { if (RouteLineActived == false) { string buf; buf = "No Specific Route Actived in Multiple OutRouteLines.RouteName:" + string(iter->second->GetName()); PostError(CcosFrameError, buf.c_str()); //mLog::FERROR("Post FrameError.{$}", buf.c_str()); return false; } } } ++iter; } //InRouteLine的检查 for (DWORD i = 0; i < m_pRouteInLineMap->size(); i++) { //Des的有效性 const char *pDes = (*m_pRouteInLineMap)[i]->GetDesName(); map::iterator desok = m_pRoutePosMap->find(string(pDes)); if (desok == m_pRoutePosMap->end()) { //no des string buf; buf = "No Destination of InRouteLine.DesName:" + string(pDes); PostError(CcosFrameError, buf.c_str()); //mLog::FERROR("Post FrameError.{$}", buf.c_str()); return false; } } //第一个RouteLine // 允许有多个 //DWORD firstRTLCount = (*m_pRoutePosMap)[CcosStmEntryPosName]->GetRouteLineCount(); //if (firstRTLCount == 0 || firstRTLCount > 1) //{ // string buf; // buf = "No First RouteLine or Multiple Routeline"; // PostError(CcosFrameError, buf.c_str()); // //mLog::FERROR("Post FrameError.{$}", buf.c_str()); // return false; //} //无法检查全局ERROR事件的状态点 return true; } DWORD CalcMaximumTimeout(CcosStMRouteLine **pVec,DWORD Count) { DWORD timeout = 0; if (pVec != NULL && Count > 0) { for (DWORD i = 0; i < Count; i++) { if (pVec[i]->GetActiveState()) { if (pVec[i]->GetTimeout() > timeout) { timeout = pVec[i]->GetTimeout(); } } } } return timeout; } /// /// 状态机顶层等待事件 /// /// /// /// 实际的状态机 跳转到的状态 CcosStMRouteLine* CcosSMachineIF::StateMachineWaitForEvents(int &ExtEvtIndex, CcosStMEvt& Evt) { ExtEvtIndex = -1; //mLog::FINFO("Begin with {$}", GetStateMachineName()); //after state action,do notify hit a state pos. CcosStMRoutePos *pCurPos = GetCurrentRoutePos(); if (pCurPos) { ResDataObject StatePos; StatePos.add(GetStateMachineName(), pCurPos->GetName()); PushStateChange(StatePos); //mLog::FINFO("PushStateChange {$} with {$}", pCurPos->GetName(), GetStateMachineName()); } CcosStMRouteLine **pLocal = NULL; DWORD LocalCount = (DWORD)m_pRouteInLineMap->size(); if (LocalCount > 0) { pLocal = &((*m_pRouteInLineMap)[0]); } DWORD OutLineCount = m_pCurrentRoutePos->GetRouteLineCount(); CcosStMRouteLine **pOutline = m_pCurrentRoutePos->GetOutRouteLineVec(); DWORD MaxTimeout = CalcMaximumTimeout(pLocal, LocalCount);//local DWORD timeout = CalcMaximumTimeout(pOutline, OutLineCount);//outline if (timeout > MaxTimeout) { MaxTimeout = timeout; } timeout = CalcMaximumTimeout(m_pRouteExternalMap, (DWORD)m_RouteExternalEvtCount);//external if (timeout > MaxTimeout) { MaxTimeout = timeout; } //mLog::FINFO("Wait for Events LocalCount={$} OutLineCount={$} MaxTimeout={$} m_RouteExternalEvtCount={$}", //LocalCount, OutLineCount, MaxTimeout, m_RouteExternalEvtCount); for (int i = 0; i < 2; i++) { int ret = 0; ret = StateMachineWaitForEvents( pLocal, LocalCount, m_pRouteExternalMap, (DWORD)m_RouteExternalEvtCount, pOutline, OutLineCount, MaxTimeout, Evt); //mLog::FINFO("StateMachine {$} WaitForEvents Return={$}", GetStateMachineName(), ret); if (ret >= 0) { if ((DWORD)ret < LocalCount) { //local return pLocal[ret]; } else if ((DWORD)ret < LocalCount + m_RouteExternalEvtCount) { //external ExtEvtIndex = ret - LocalCount; return NULL; } //outline ret -= (LocalCount + (DWORD)m_RouteExternalEvtCount); return pOutline[ret]; } else if (ret == -1) { PostError(CcosFrameError); //mLog::FERROR("Timeout .Post FrameError."); } else if (ret == -2) { PostError(CcosFrameError); //mLog::FERROR("Device Error .Post FrameError."); } else if (ret == -3) { ExtEvtIndex = -2;//thread exit return NULL; } } assert(0);//必须要有异常处理的方案,没有情况直接蹦. //mLog::FERROR("No Exption Method."); return NULL; } int CcosSMachineIF::EnterSubStateMachine(std::shared_ptr ThreadExitEvt, CcosStMEvt& Evt) { CcosSubSMachine* pSub = (CcosSubSMachine*)m_pCurrentRoutePos; size_t WaitCount = m_RouteExternalEvtCount + m_pRouteInLineMap->size(); vector ExternalWaitEvts; //merge externalevts + internalevts for (DWORD i = 0; i < m_RouteExternalEvtCount; i++) { ExternalWaitEvts.push_back(m_pRouteExternalMap[i]); } for (DWORD i = 0; i < m_pRouteInLineMap->size(); i++) { ExternalWaitEvts.push_back((*m_pRouteInLineMap)[i]); } pSub->PushEvent(Evt); return pSub->ExecStateMachine(ThreadExitEvt,&(ExternalWaitEvts[0]), WaitCount, false); } /// /// 状态机主体执行函数,也可以是子状态机 /// /// /// /// /// /// int CcosSMachineIF::ExecStateMachine(std::shared_ptr ThreadExitEvt, CcosStMRouteLine *pExternalWaitEvts[], size_t WaitCount, bool bClear) { CCOSSTMRET ret = CCOSSMRET_OK; ClearState(bClear); SetRunningState(true); if (pExternalWaitEvts != NULL && WaitCount > 0) { m_RouteExternalEvtCount = WaitCount; m_pRouteExternalMap = &pExternalWaitEvts[0]; } //m_pCurrentRoutePos = (*m_pRoutePosMap)[string(CcosStmEntryPosName)]; TransToPos(CcosStmEntryPosName); //入口Action ret = StateMachineEntry(m_pCurrentRoutePos->GetTimeout()); if (ret != CCOSSMRET_OK) { PostError(CcosFrameError); //mLog::FERROR("StateMachineEntry Failed."); } do { //wait events int RouteWay = -1; CcosStMEvt Evt; Evt.SetEvt("TestNoFind", ""); CcosStMRouteLine *pRouteLine = StateMachineWaitForEvents(RouteWay, Evt); RouteLine_Process: if (RouteWay >= 0) { //External way //goto exitpos //mLog::FINFO("StateMachineWaitForEvents got external evt.exit sub state machine [{$}].", Evt.GetEvtContext().encode()); TransToPos(CcosStmExitPosName); //run action without results ret = StateMachineExit(m_pCurrentRoutePos->GetTimeout()); //一旦在Exit出错,会再次进入WaitEvt,再执行Exit,.........dead loop //if (ret != CCOSSMRET_OK) //{ // continue; //} SetRunningState(false); return RouteWay; } else if (RouteWay == -1) { //this machine if (pRouteLine->GetActiveState()) { //Guard const char *pGuard = pRouteLine->GetGuardName(); if (pGuard != NULL && strlen(pGuard) > 0) { ret = StateMachineGuard(pGuard, TIMEOUT_TEMP); if (ret != CCOSSMRET_OK) { continue; } } } //TransToPos TransToPos(pRouteLine->GetDesName()); //mLog::FINFO("TransToPos:{$} from evnt {$}", pRouteLine->GetDesName(), Evt.GetEvtContext().encode()); if (string(CcosStmExitPosName) == m_pCurrentRoutePos->GetName()) { //exit //run action without results ret = StateMachineExit(m_pCurrentRoutePos->GetTimeout()); //check ret if (ret != CCOSSMRET_OK) { PostError(CcosFrameError); //mLog::FERROR("PostError CcosFrameError .curPos:{$}", m_pCurrentRoutePos->GetName()); continue; } //退出的时候,把事件带出去 PushEvent(Evt); //exit here SetRunningState(false); return -1; } //statepos or statemachine if (m_pCurrentRoutePos->GetActiveState()) { if (m_pCurrentRoutePos->IsSMachine()) { //子状态机嵌套 //copy evt in CopyEvtTo((CcosSubSMachine*)m_pCurrentRoutePos); //mLog::FINFO("Enter Sub StateMachine to {$} from Evt[{$}]", m_pCurrentRoutePos->GetName(), Evt.GetEvtContext().GetKey(0)); //run sub state machine int ExitWay = EnterSubStateMachine(ThreadExitEvt, Evt); //mLog::FINFO("exit from Sub StateMachine.{$},ret:{$}", m_pCurrentRoutePos->GetName(),ExitWay); //copy evt out ((CcosSubSMachine*)m_pCurrentRoutePos)->CopyEvtTo(this); //trans to position if (ExitWay >= 0) { if ((size_t)ExitWay < m_RouteExternalEvtCount) { //mLog::FINFO("exit from statemachine.{$} from event {$}", m_pCurrentRoutePos->GetName(), Evt.GetEvtContext().encode()); //external evt TransToPos(CcosStmExitPosName); //run action without results ret = StateMachineExit(m_pCurrentRoutePos->GetTimeout()); //一旦在Exit出错,会再次进入WaitEvt,再执行Exit,.........dead loop //if (ret != CCOSSMRET_OK) //{ // continue; //} SetRunningState(false); return ExitWay; } else { //local evt //trans to pos RouteWay = -1; pRouteLine = (*m_pRouteInLineMap)[ExitWay - m_RouteExternalEvtCount]; goto RouteLine_Process; } } else { //outline .normal exit from statemachine //mLog::FINFO("exit from sub statemachine"); } } else { //just route pos //check exitposition //if (string(CcosStmExitPosName) == m_pCurrentRoutePos->GetName()) //{ // //exit // //run action without results // ret = StateMachineExit(m_pCurrentRoutePos->GetTimeout()); // //check ret // if (ret != CCOSSMRET_OK) // { // PostError(CcosFrameError); // continue; // } // //exit here // SetRunningState(false); // return -1; //} //run action ret = StateMachineAction(m_pCurrentRoutePos->GetName(), m_pCurrentRoutePos->GetTimeout()); //mLog::FINFO("SmAction:{$}.RET:{$}", m_pCurrentRoutePos->GetName(),(int)ret); //check ret if (ret != CCOSSMRET_OK) { if (ret == CCOSSMRET_EXIT) { //exit thread //goto exitpos TransToPos(CcosStmExitPosName); //run action without results ret = StateMachineExit(m_pCurrentRoutePos->GetTimeout()); SetRunningState(false); return -1; } PostError(CcosFrameError); //mLog::FERROR("StateMachineAction Error Post CcosFrameError .curPos:{$}", m_pCurrentRoutePos->GetName()); } } } } else { //exit thread //goto exitpos TransToPos(CcosStmExitPosName); //run action without results ret = StateMachineExit(m_pCurrentRoutePos->GetTimeout()); SetRunningState(false); return -1; } } while (1); SetRunningState(false); return -1; } //------------------------------------- CcosSMachine::CcosSMachine() { m_pStatePosList = new MsgQueue(); m_StateQuedEvent = LinuxEvent::CreateEvent(LinuxEvent::MANUAL_RESET,false); //if (//mLog::gLogger == nullptr) //{ // string strLogPath = GetProcessDirectory() + R"(\Conf\Log4CPP.Config.xml)"; // //LogHost = ((string)getRootpath()).c_str(); // //if (LogHost.length() <= 1) // //{ // // char szName[256]; // // sprintf(szName, "/LogicDevice_%08d", GetCurrentProcessId()); // // LogHost = szName; // //} // Log4CPP::ThreadContext::Map::Set(ECOM::Utility::Hash("LogFileName"), "StateMachine"); // //Log4CPP::GlobalContext::Map::Set("LogHost", LogHost.c_str()); // Log4CPP::ThreadContext::Map::Set(ECOM::Utility::Hash("LogHost"), "StateMachine"); // auto rc = Log4CPP::LogManager::LoadConfigFile(strLogPath.c_str()); // //mLog::gLogger = Log4CPP::LogManager::GetLogger("StateMachine"); // //mLog::FINFO("Code Build datetime [{$} {$}]", __DATE__, __TIME__); //} } CcosSMachine::~CcosSMachine() { delete m_pStatePosList; //if (GetLogger() != 0) //{ // ReleseLogger((Logger*)GetLogger()); // SetLogger(0); //} } void CcosSMachine::SetStateMachineLog(const char *pszLogTitle) { //if (GetLogger() == 0) //{ // string logfile = GetProcessDirectory() + "\\logs\\"; // logfile = FormatstdString("%s%s.log", logfile.c_str(), pszLogTitle); // Logger *pLog = CreateLogger(); // pLog->SetLogFilepath(logfile.c_str()); // SetLogger(pLog); //} } bool CcosSMachine::OnStartThread() { return PrePareStateMachine(); } bool CcosSMachine::Exec() { ExecStateMachine(GetExitEvt(),NULL, 0); return false; } void CcosSMachine::PushStateChange(ResDataObject &ChangedPos) { m_pStatePosList->InQueue(ChangedPos); m_StateQuedEvent->SetEvent(); } bool CcosSMachine::PopStateChange(ResDataObject &LastPos) { bool ret = false; if (m_pStatePosList->size() > 0) { m_pStatePosList->DeQueue(LastPos); m_LastHitStatePos = LastPos; ret = true; } if (m_pStatePosList->size() == 0) { m_StateQuedEvent->ResetEvent(); } else { m_StateQuedEvent->SetEvent(); } if (ret == false) { if (m_LastHitStatePos.size() > 0) { LastPos = m_LastHitStatePos; ret = true; } } return ret; } std::shared_ptr CcosSMachine::GetStateQuedEvent() { return m_StateQuedEvent; } bool CcosSMachine::StartStateMachine(CcosStMRouteLine *pExternalWaitEvts[], DWORD WaitCount) { m_LastHitStatePos.clear(); if (WaitTheThreadEnd(0) == false) { //it's in running state //printf("StartStateMachine Failed.it's in running state\n"); return false; } if (pExternalWaitEvts != NULL && WaitCount > 0) { m_RouteExternalEvtCount = WaitCount; m_pRouteExternalMap = &pExternalWaitEvts[0]; } bool ret = StartThread(); if (ret) { return GetRunningState(TIMEOUT_TEMP); } return ret; } void CcosSMachine::StopStateMachine(DWORD timeout) { //直接StopThread好像不是个办法,得让状态机退出前进行OnExit操作. StopThread(timeout); ClearState(); } CcosSubSMachine::CcosSubSMachine(void) { } CcosSubSMachine::CcosSubSMachine(const char *pName) : CcosStMRoutePos(pName) { SetStateMachineName(pName); } CcosSubSMachine::~CcosSubSMachine(void) { } bool CcosSubSMachine::IsSMachine() { return true; }