// DiosSMachine.cpp : 定义 DLL 应用程序的导出函数。 // #include "stdafx.h" #include "DiosSMachine.h" #include "common_api.h" #include using namespace std; Log4CPP::Logger* mLog::gLogger = nullptr; //----------------------------- DiosStMEvt::DiosStMEvt() { m_pEvt = new ResDataObject(); m_pInfo = new ResDataObject(); } DiosStMEvt::DiosStMEvt(const DiosStMEvt &tValue) { m_pEvt = new ResDataObject(); m_pInfo = new ResDataObject(); (*m_pEvt) = (*tValue.m_pEvt); (*m_pInfo) = (*tValue.m_pInfo); } DiosStMEvt::~DiosStMEvt() { delete m_pEvt; m_pEvt = NULL; delete m_pInfo; m_pInfo = NULL; } bool DiosStMEvt::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(DiosStmEvtInfo, pInfo); } else { m_pInfo->add(DiosStmEvtInfo, ""); } return true; } bool DiosStMEvt::IsEmpty() { return (m_pEvt->size() == 0); } bool DiosStMEvt::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(DiosStmEvtInfo, pInfo); } else { m_pInfo->add(DiosStmEvtInfo, ""); } return ret; } ResDataObject& DiosStMEvt::GetEvtContext() { return (*m_pEvt); } DiosStMEvt& DiosStMEvt::operator = (const DiosStMEvt &tValue) { if (this != &tValue) { (*m_pEvt) = (*tValue.m_pEvt); (*m_pInfo) = (*tValue.m_pInfo); } return (*this); } bool DiosStMEvt::operator == (const DiosStMEvt &Obj) { return (*m_pEvt == (*(Obj.m_pEvt))); } const char *DiosStMEvt::encode() { return m_pInfo->encode(); } bool DiosStMEvt::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 = DiosStmEvtInfo; 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; } //----------------------------- DiosStMRouteLine::DiosStMRouteLine() { m_ActiveState = false; m_InRoute = true; m_pEvt = new DiosStMEvt(); m_pSrcRoutePos = new string(); m_pGuard = new string(); m_pDesRoutePos = new string(); m_Timeout = TIMEOUT_TEMP; } DiosStMRouteLine::DiosStMRouteLine(const DiosStMRouteLine &tValue) { m_ActiveState = false; m_InRoute = true; m_pEvt = new DiosStMEvt(); 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()); } } DiosStMRouteLine::~DiosStMRouteLine() { delete m_pEvt; delete m_pSrcRoutePos; delete m_pDesRoutePos; delete m_pGuard; } void DiosStMRouteLine::SetRoute(DiosStMEvt &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 DiosStMRouteLine::SetRoute(DiosStMEvt &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* DiosStMRouteLine::GetDesName() { return m_pDesRoutePos->c_str(); } const char* DiosStMRouteLine::GetSrcName() { if (m_InRoute == false) { return m_pSrcRoutePos->c_str(); } return NULL; } const char* DiosStMRouteLine::GetGuardName() { return m_pGuard->c_str(); } //true:in,false:out bool DiosStMRouteLine::GetRouteType() { return m_InRoute; } DiosStMRouteLine::operator DiosStMEvt *() { return m_pEvt; } DiosStMRouteLine& DiosStMRouteLine::operator = (const DiosStMRouteLine &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 DiosStMRouteLine::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 DiosStMRouteLine::GetActiveState() { return m_ActiveState; } DWORD DiosStMRouteLine::GetTimeout() { return m_Timeout; } //================================ DiosStMRoutePos::DiosStMRoutePos() { m_ActiveState = false; m_pRoutePosName = new string(); m_pOutRouteLineVec = new vector(); m_Timeout = TIMEOUT_TEMP; } DiosStMRoutePos::DiosStMRoutePos(const char *pName) { m_ActiveState = false; m_pRoutePosName = new string(); (*m_pRoutePosName) = pName; m_pOutRouteLineVec = new vector(); m_Timeout = TIMEOUT_TEMP; } DiosStMRoutePos::~DiosStMRoutePos() { 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++) { DiosStMRouteLine *p = (*m_pOutRouteLineVec)[i]; delete p; } } delete m_pOutRouteLineVec; m_pOutRouteLineVec = NULL; } } void DiosStMRoutePos::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 DiosStMRoutePos::GetActiveState() { return m_ActiveState; } bool DiosStMRoutePos::IsSMachine() { return false; } bool DiosStMRoutePos::PosAddOutRouteLine(DiosStMEvt &Evt, const char *pSrcPosName, const char *pGuardName, const char *pDesPosName) { DiosStMRouteLine *pLine = new DiosStMRouteLine(); pLine->SetRoute(Evt, pSrcPosName, pGuardName, pDesPosName); m_pOutRouteLineVec->push_back(pLine); return true; } void DiosStMRoutePos::SetName(const char *pName) { (*m_pRoutePosName) = pName; } const char* DiosStMRoutePos::GetName() { return m_pRoutePosName->c_str(); } DWORD DiosStMRoutePos::GetRouteLineCount() { if (m_pOutRouteLineVec) { return (DWORD)m_pOutRouteLineVec->size(); } return 0; } DiosStMRouteLine **DiosStMRoutePos::GetOutRouteLineVec() { if (m_pOutRouteLineVec) { if (m_pOutRouteLineVec->size() > 0) { return &((*m_pOutRouteLineVec)[0]); } } return NULL; } DiosStMRouteLine *DiosStMRoutePos::operator [](DiosStMEvt &Evt) { if (m_pOutRouteLineVec) { if (m_pOutRouteLineVec->size() > 0) { for (size_t i = 0; i < m_pOutRouteLineVec->size(); i++) { if ((*(DiosStMEvt *)(*(*m_pOutRouteLineVec)[i])) == Evt) { return (*m_pOutRouteLineVec)[i]; } } } } return NULL; } DWORD DiosStMRoutePos::GetTimeout() { return m_Timeout; } //================================ DiosSMachineIF::DiosSMachineIF() { m_pStateMachineName = new string(); m_pParent = 0; m_pCurrentRoutePos = NULL; //evt list m_pArrivedEvts = new MsgCircle(); //routepos m_pRoutePosMap = new map(); DiosStMRoutePos *p = NULL; p = new DiosStMRoutePos(DiosStmEntryPosName); p->Active(true, TIMEOUT_TEMP); (*m_pRoutePosMap)[DiosStmEntryPosName] = p; //printf(" == this[% 08X] Add Route Pos [%s] \n", this, DiosStmEntryPosName); p = new DiosStMRoutePos(DiosStmExitPosName); p->Active(true, TIMEOUT_TEMP); (*m_pRoutePosMap)[DiosStmExitPosName] = p; //inline m_pRouteInLineMap = new vector(); //external m_RouteExternalEvtCount = 0; m_pRouteExternalMap = NULL; //running state m_RunningState = CreateEvent(0, 1, 0, 0); m_StateCangeEvt = CreateEvent(0, 0, 0, 0); } DiosSMachineIF::~DiosSMachineIF() { 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()) { DiosSubSMachine* pSub = (DiosSubSMachine*)iter->second; delete pSub; } else { delete iter->second; } ++iter; } delete m_pRoutePosMap; m_pRoutePosMap = NULL; //evt list delete m_pArrivedEvts; m_pArrivedEvts = NULL; CloseHandle(m_RunningState); CloseHandle(m_StateCangeEvt); return; } void DiosSMachineIF::SetStateMachineName(const char *pszName) { (*m_pStateMachineName) = pszName; } const char *DiosSMachineIF::GetStateMachineName() { return m_pStateMachineName->c_str(); } void DiosSMachineIF::SetParentSMachine(DiosSMachineIF *pParent) { m_pParent = pParent; } void DiosSMachineIF::PushStateChange(ResDataObject &ChangedPos) { if (m_pParent) { m_pParent->PushStateChange(ChangedPos); } } bool DiosSMachineIF::IsSMachine() { return true; } HANDLE DiosSMachineIF::GetStateChangeEvtHandle() { return m_StateCangeEvt; } void DiosSMachineIF::SetRunningState(bool Running) { Thread_Lock(); if (Running) { SetEvent(m_RunningState); } else { ResetEvent(m_RunningState); } Thread_UnLock(); } bool DiosSMachineIF::GetRunningState(DWORD waittime) { bool ret = (WaitForSingleObject(m_RunningState, waittime) == WAIT_OBJECT_0); if (ret == false) { //printf("GetRunningState Failed.WTF??\n"); } return ret; } //init state machine //第一个节点的接入比较特殊,所以做了个函数 bool DiosSMachineIF::AddEntryRoutePos(DiosStMRoutePos *pPos) { if (strlen(pPos->GetName()) == 0) { return false; } if ((*m_pRoutePosMap)[DiosStmEntryPosName]->GetRouteLineCount() > 0) { return false; } //add pos (*m_pRoutePosMap)[pPos->GetName()] = pPos; DiosStMEvt evt; //make a line (*m_pRoutePosMap)[DiosStmEntryPosName]->PosAddOutRouteLine(evt, DiosStmEntryPosName, NULL, pPos->GetName()); return true; } bool DiosSMachineIF::AddRoutePos(DiosStMRoutePos *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 DiosSMachineIF::AddInRouteLine(DiosStMEvt &Evt, const char *pGuardName, const char *pDesPosName) { DiosStMRouteLine *pLine = new DiosStMRouteLine(); pLine->SetRoute(Evt, pGuardName, pDesPosName); pLine->Active(true, 0);//timeout没必要,因为是全局事件 m_pRouteInLineMap->push_back(pLine); return true; } bool DiosSMachineIF::AddOutRouteLine(DiosStMEvt &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 DiosSMachineIF::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) { DiosSubSMachine *pSub = (DiosSubSMachine *)(iterOut->second); pSub->ActiveRoutePos(pPosName, timeout); } ++iterOut; } } catch (...) { ret = false; } return ret; } //bool DiosSMachineIF::ActiveInRouteLine(DiosStMEvt &Evt, DWORD timeout) //{ // bool ret = false; // try{ // //find In Route Line // for (size_t i = 0; i < m_pRouteInLineMap->size(); i++) // { // if ((*(DiosStMEvt*)(*(*m_pRouteInLineMap)[i])) == Evt) // { // (*m_pRouteInLineMap)[i]->Active(true,timeout); // // ret = true; // // break; // } // } // // } // catch (...) // { // ret = false; // } // // return ret; // //} bool DiosSMachineIF::ActiveRouteLine(DiosStMEvt &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(); DiosStMRouteLine **RouteLines = iterOut->second->GetOutRouteLineVec(); for (DWORD i = 0; i < RouteCount; i++) { if ((*(DiosStMEvt *)(*(RouteLines[i]))) == Evt) { RouteLines[i]->Active(true, timeout); } } } else { //子对象自行激活自己 //DiosSubSMachine *pSub = (DiosSubSMachine *)(iterOut->second); //pSub->ActiveRouteLine(Evt, timeout); } ++iterOut; } //in path for (size_t i = 0; i < m_pRouteInLineMap->size(); i++) { if ((*(DiosStMEvt *)(*((*m_pRouteInLineMap)[i]))) == Evt) { (*m_pRouteInLineMap)[i]->Active(true, timeout); } } //DiosStMRouteLine* pLine = (*(*m_pRoutePosMap)[pPosName])[Evt]; //if (pLine) //{ // pLine->Active(true, timeout); // ret = true; //} } catch (...) { ret = false; } return ret; } bool DiosSMachineIF::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(); DiosStMRouteLine **RouteLines = iterOut->second->GetOutRouteLineVec(); for (DWORD i = 0; i < RouteCount; i++) { RouteLines[i]->Active(false, 0); } } else { DiosSubSMachine *pSub = (DiosSubSMachine *)(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 DiosSMachineIF::ClearState(bool bClearEvent) { Thread_Lock(); SetRunningState(false); map::iterator iterOut = (*m_pRoutePosMap).begin(); while (iterOut != (*m_pRoutePosMap).end()) { if (iterOut->second->IsSMachine()) { DiosSubSMachine *pSub = (DiosSubSMachine *)(iterOut->second); pSub->ClearState(bClearEvent); } ++iterOut; } m_pCurrentRoutePos = NULL; if(bClearEvent) m_pArrivedEvts->Clear(); m_RouteExternalEvtCount = 0; m_pRouteExternalMap = NULL; Thread_UnLock(); } HANDLE DiosSMachineIF::GetEvtNotifyHandle() { return (*m_pArrivedEvts).GetNotifyHandle(); } bool DiosSMachineIF::PeekEvent(DiosStMEvt &Evt) { //check it's existance return (*m_pArrivedEvts).Peek(Evt); } //evt bool DiosSMachineIF::PopEvent(DiosStMEvt &Evt) { return (*m_pArrivedEvts).DeQueue(Evt); } bool DiosSMachineIF::PushEvent(DiosStMEvt &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()) { DiosSubSMachine* pMachine = (DiosSubSMachine*)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 DIOSSTMRET DiosSMachineIF::StateMachineEntry(DWORD timeout) { return DIOSSMRET_OK; } DIOSSTMRET DiosSMachineIF::StateMachineExit(DWORD timeout) { return DIOSSMRET_OK; } DIOSSTMRET DiosSMachineIF::StateMachineAction(const char *pAction, DWORD timeout) { return DIOSSMRET_OK; } DIOSSTMRET DiosSMachineIF::StateMachineGuard(const char *pGuard, DWORD timeout) { return DIOSSMRET_OK; } /// /// 实际的状态机等待事件 /// /// /// /// /// /// /// /// /// /// /// 返回值为负:退出状态机;返回值为等到的 事件的下标 /// int DiosSMachineIF::StateMachineWaitForEvents( DiosStMRouteLine *pLocalEvts[], DWORD CountOfLocal, DiosStMRouteLine *pExternalEvts[], DWORD CountOfExternal, DiosStMRouteLine *pOutpathEvts[], DWORD CountOfOutpath, DWORD timeout, DiosStMEvt& Evt ) { //执行最基础的处理 return -1; } DiosStMRoutePos *DiosSMachineIF::GetCurrentRoutePos() { return m_pCurrentRoutePos; } DIOSSTMRET DiosSMachineIF::TransToPos(const char *pPosName) { DIOSSTMRET ret = DIOSSMRET_OK; //des check try{ Thread_Lock(); m_pCurrentRoutePos = (*m_pRoutePosMap)[string(pPosName)]; Thread_UnLock(); SetEvent(m_StateCangeEvt); //printf("Trans To %s \n", pPosName); } catch (...) { assert(0);//never gonna reach ret = DIOSSMRET_NG; } return ret; } void DiosSMachineIF::PostError(const char *pErrorVal, const char *pErrorInfo) { DiosStMEvt evt; if (pErrorVal) { //printf("--PostError:%s--\n", pErrorVal); } else { //printf("--PostError:Empty--\n"); } evt.SetEvt(DiosErrorType, pErrorVal,pErrorInfo); PushEvent(evt); } DiosStMRouteLine *DiosSMachineIF::GetEntryRouteLine() { //routepos DiosStMRoutePos *pFirst = (*m_pRoutePosMap)[string(DiosStmEntryPosName)]; if (pFirst) { if (pFirst->GetRouteLineCount() == 1) { return ((m_pCurrentRoutePos->GetOutRouteLineVec())[0]); } } return NULL; } void DiosSMachineIF::CopyEvtTo(DiosSMachineIF *pDes) { //排序上先ORG的消息,然后des的消息 bool ret = true; DiosStMEvt 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 DiosSMachineIF::PrePareStateMachine() { //状态点的检查 map::iterator iter = m_pRoutePosMap->begin(); while (iter != m_pRoutePosMap->end()) { if (iter->second->IsSMachine()) { //sub machine DiosSubSMachine* pSub = static_cast(iter->second); if (pSub->PrePareStateMachine() == false) { ostringstream buf; buf << "Sub StateMachine Error.Name:" << (iter->second)->GetName(); PostError(DiosFrameError,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(); DiosStMRouteLine **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(DiosFrameError, 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(DiosFrameError, 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(DiosFrameError, buf.c_str()); mLog::FERROR("Post FrameError.{$}", buf.c_str()); return false; } } //第一个RouteLine // 允许有多个 //DWORD firstRTLCount = (*m_pRoutePosMap)[DiosStmEntryPosName]->GetRouteLineCount(); //if (firstRTLCount == 0 || firstRTLCount > 1) //{ // string buf; // buf = "No First RouteLine or Multiple Routeline"; // PostError(DiosFrameError, buf.c_str()); // mLog::FERROR("Post FrameError.{$}", buf.c_str()); // return false; //} //无法检查全局ERROR事件的状态点 return true; } DWORD CalcMaximumTimeout(DiosStMRouteLine **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; } /// /// 状态机顶层等待事件 /// /// /// /// 实际的状态机 跳转到的状态 DiosStMRouteLine* DiosSMachineIF::StateMachineWaitForEvents(int &ExtEvtIndex, DiosStMEvt& Evt) { ExtEvtIndex = -1; mLog::FINFO("Begin with {$}", GetStateMachineName()); //after state action,do notify hit a state pos. DiosStMRoutePos *pCurPos = GetCurrentRoutePos(); if (pCurPos) { ResDataObject StatePos; StatePos.add(GetStateMachineName(), pCurPos->GetName()); PushStateChange(StatePos); mLog::FINFO("PushStateChange {$} with {$}", pCurPos->GetName(), GetStateMachineName()); } DiosStMRouteLine **pLocal = NULL; DWORD LocalCount = (DWORD)m_pRouteInLineMap->size(); if (LocalCount > 0) { pLocal = &((*m_pRouteInLineMap)[0]); } DWORD OutLineCount = m_pCurrentRoutePos->GetRouteLineCount(); DiosStMRouteLine **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(DiosFrameError); mLog::FERROR("Timeout .Post FrameError."); } else if (ret == -2) { PostError(DiosFrameError); 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 DiosSMachineIF::EnterSubStateMachine(HANDLE ThreadExitEvt, DiosStMEvt& Evt) { DiosSubSMachine* pSub = (DiosSubSMachine*)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 DiosSMachineIF::ExecStateMachine(HANDLE ThreadExitEvt, DiosStMRouteLine *pExternalWaitEvts[], size_t WaitCount, bool bClear) { DIOSSTMRET ret = DIOSSMRET_OK; ClearState(bClear); SetRunningState(true); if (pExternalWaitEvts != NULL && WaitCount > 0) { m_RouteExternalEvtCount = WaitCount; m_pRouteExternalMap = &pExternalWaitEvts[0]; } //m_pCurrentRoutePos = (*m_pRoutePosMap)[string(DiosStmEntryPosName)]; TransToPos(DiosStmEntryPosName); //入口Action ret = StateMachineEntry(m_pCurrentRoutePos->GetTimeout()); if (ret != DIOSSMRET_OK) { PostError(DiosFrameError); mLog::FERROR("StateMachineEntry Failed."); } do { //wait events INT RouteWay = -1; DiosStMEvt Evt; Evt.SetEvt("TestNoFind", ""); DiosStMRouteLine *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(DiosStmExitPosName); //run action without results ret = StateMachineExit(m_pCurrentRoutePos->GetTimeout()); //一旦在Exit出错,会再次进入WaitEvt,再执行Exit,.........dead loop //if (ret != DIOSSMRET_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 != DIOSSMRET_OK) { continue; } } } //TransToPos TransToPos(pRouteLine->GetDesName()); mLog::FINFO("TransToPos:{$} from evnt {$}", pRouteLine->GetDesName(), Evt.GetEvtContext().encode()); if (string(DiosStmExitPosName) == m_pCurrentRoutePos->GetName()) { //exit //run action without results ret = StateMachineExit(m_pCurrentRoutePos->GetTimeout()); //check ret if (ret != DIOSSMRET_OK) { PostError(DiosFrameError); mLog::FERROR("PostError DiosFrameError .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((DiosSubSMachine*)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 ((DiosSubSMachine*)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(DiosStmExitPosName); //run action without results ret = StateMachineExit(m_pCurrentRoutePos->GetTimeout()); //一旦在Exit出错,会再次进入WaitEvt,再执行Exit,.........dead loop //if (ret != DIOSSMRET_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(DiosStmExitPosName) == m_pCurrentRoutePos->GetName()) //{ // //exit // //run action without results // ret = StateMachineExit(m_pCurrentRoutePos->GetTimeout()); // //check ret // if (ret != DIOSSMRET_OK) // { // PostError(DiosFrameError); // 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 != DIOSSMRET_OK) { if (ret == DIOSSMRET_EXIT) { //exit thread //goto exitpos TransToPos(DiosStmExitPosName); //run action without results ret = StateMachineExit(m_pCurrentRoutePos->GetTimeout()); SetRunningState(false); return -1; } PostError(DiosFrameError); mLog::FERROR("StateMachineAction Error Post DiosFrameError .curPos:{$}", m_pCurrentRoutePos->GetName()); } } } } else { //exit thread //goto exitpos TransToPos(DiosStmExitPosName); //run action without results ret = StateMachineExit(m_pCurrentRoutePos->GetTimeout()); SetRunningState(false); return -1; } } while (1); SetRunningState(false); return -1; } //------------------------------------- DiosSMachine::DiosSMachine() { m_pStatePosList = new MsgQueue(); m_StateQuedEvent = CreateEvent(0, 1, 0, 0); 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__); } } DiosSMachine::~DiosSMachine() { delete m_pStatePosList; CloseHandle(m_StateQuedEvent); //if (GetLogger() != 0) //{ // ReleseLogger((Logger*)GetLogger()); // SetLogger(0); //} } void DiosSMachine::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 DiosSMachine::OnStartThread() { return PrePareStateMachine(); } bool DiosSMachine::Exec() { ExecStateMachine(GetExitEvt(),NULL, 0); return false; } void DiosSMachine::PushStateChange(ResDataObject &ChangedPos) { m_pStatePosList->InQueue(ChangedPos); SetEvent(m_StateQuedEvent); } bool DiosSMachine::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) { ResetEvent(m_StateQuedEvent); } else { SetEvent(m_StateQuedEvent); } if (ret == false) { if (m_LastHitStatePos.size() > 0) { LastPos = m_LastHitStatePos; ret = true; } } return ret; } HANDLE DiosSMachine::GetStateQuedEvent() { return m_StateQuedEvent; } bool DiosSMachine::StartStateMachine(DiosStMRouteLine *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 DiosSMachine::StopStateMachine(DWORD timeout) { //直接StopThread好像不是个办法,得让状态机退出前进行OnExit操作. StopThread(timeout); ClearState(); } DiosSubSMachine::DiosSubSMachine(void) { } DiosSubSMachine::DiosSubSMachine(const char *pName) : DiosStMRoutePos(pName) { SetStateMachineName(pName); } DiosSubSMachine::~DiosSubSMachine(void) { } bool DiosSubSMachine::IsSMachine() { return true; }