Die Basisklasse CApp stellt ein Grundgerüst zur Verfügung, dass für alle Tasks gleich ist. Darin sind die allgemeinen Aufgabe zur Initialisierung der Task enthalten, sowie Methoden zu üblichen Aufgaben: Taskkommunikation, Protokollierung, Zugriff auf die gemeinsamen Datenstrukturen.
class CApp { private: /// denied standard members /// Default constructor CApp() {}; public: /// open member methods /// Standard construction CApp(int argc, char **argv); /// virtual destruction virtual ~CApp(); // usually NOT overwritten by descendant class /// Run method virtual bool Run(int nSleep); /// write log info into standard pipe (LOG) void LogOut(int nLvl, char * pFmt, ...); /// log info into severeal pipes according to tMask void LogOutM(int tMask, int nLvl, char * pFmt, ...); protected: // usually overwritten by descendant class /// creates the usual pipes or opens them virtual bool InitPipes() {return true;}; /// creates the usual modules or links to them, might be overridden in descendant class virtual bool InitModules(); /// do your local apps initialization virtual bool InitLocal() {return true;}; /// internal handling of signals virtual bool CheckSignal(int nSignal) {return true;}; /// internal action after handling signals virtual bool DoAction() {return true;}; /// do local cleanup stuff after leaving the signal loop and before terminating virtual void CleanUpLocal() {}; // local only, do not overwrite /// initialize the commandline arguments object bool InitCommandline(int argc, char ** argv); /// creates one pipe and returns a bit flag for /// pipe access with LogOutM() or NULL on error . long CreatePipe(char * pName, int nSize, char * pMode, ELogFlag eFlagDefault = AUTO); /// closes any open pipe included with nFlags. void ClosePipes(long nFlags); /// output into all pipes included in nPipeFlags. void PipeOut(const char* strText, long nTextLen, long nPipeFlags); // link to a datamodul with a given name and size void * LinkDataModule(char * strModName, int nSize); /// creates a datamodul with a given name and size void * CreateDataModule(char * strName, int nSize); /// returns false on version mismatch bool InitRingDataMod(const char* strAppClass, SRingData& rRingData, long nVersion, long nValCount); /// refresh the life count in SoftwareState data module void RefreshLifeCount(); public: /// send a specified signal to the insps process with nProcNum bool SendI760Signal(long nProcNum, int nSignal); // Liefert ein Bit (Dig-InOut) oder ein Short (IncG). // Bei Fehlern wird -1 geliefert. long GetHardwareData(const TBit& rBit); // Sets a bit (Dig-Out). void SetHardwareData(const TBit& rBit, bool nVal); SSoftwareStateMod* GetSoftwareMod() { return m_pSoftwareMod; } SHardwareStateMod* GetHardwareMod() { return m_pHardwareMod; } // data member protected: /// the OS-9 process ID long m_nProcID; /// the module name char m_strModName[STDNAMELEN]; /// the internal process number in the i760 structure long m_nProcNum; /// the life count value. The controller counts it down and tries to /// restart the task when the life count reaches 0. long m_nLifeCount; /// the apps commandline CCmdLine * m_pCmdLine; /// the logging level (initialized from commandline -L=n) int m_nLogLevel; /// allow output to console bool m_bNonQuiet; /// address of datamodule softwarestate SSoftwareStateMod * m_pSoftwareMod; /// address of datamodule hardwarestate SHardwareStateMod * m_pHardwareMod; /// internal pipe data long m_nPipeCount; long m_nPipeFlags; };
Als Beispiel wird hier die Implementierung der Methode Run() angegeben:
bool CApp::Run(int nSleep) { bool bOk = false; bool bRunning = true; LogOut(5, "CApp::Run() start init"); // initialize pipes InitPipes(); // initialize modules bRunning = InitModules(); // do special init stuff if (bRunning) bRunning = InitLocal(); if (bRunning) { // register the process id for signalling if (NULL != m_pSoftwareMod && m_nProcNum != NOBODY) { m_pSoftwareMod->aProc[m_nProcNum].nProcID = _procid; m_pSoftwareMod->aProc[m_nProcNum].nLifeCount = m_nLifeCount; } } LogOut(5, "CApp::Run() init finished, tsl=%d", nSleep); while (bRunning) { RefreshLifeCount(); while (g_qSignal.size() > 0) { long nSize = 0; RefreshLifeCount(); nSize = g_qSignal.size(); LogOut(7, "CApp::Run() got signal size=%ld", nSize); switch (g_qSignal.front()) { case SIGINT: bRunning = false; LogOut(3, "CApp::Run() got SIGINT, terminate process"); break; case SIGQUIT: bRunning = false; LogOut(3, "CApp::Run() got SIGQUIT, terminate process"); break; case SIGKILL: bRunning = false; LogOut(3, "CApp::Run() got SIGKILL, terminate process"); break; default: // give the descendant classes opportunity to handle additional signals LogOut(5, "CApp::Run() unhandled signal=%d calling CheckSignal()", g_qSignal.front()); bRunning = CheckSignal(g_qSignal.front()); break; } // remove the signal from the queue g_qSignal.pop(); nSize = g_qSignal.size(); LogOut(5, "CApp::Run() after pop size=%ld", nSize); } if (bRunning) { signal_code nSignal = 0; u_int32 nTicks = nSleep; // let the descendants do their work bRunning = DoAction(); _os_sleep(&nTicks, &nSignal); if ((nTicks != 0) && (nSignal != 0)) { if (g_qSignal.size() == 0) { g_qSignal.push(nSignal); } else { if (g_qSignal.back() == nSignal) LogOut(5, "CApp::Run() signal=%d already in queue", nSignal); else g_qSignal.push(nSignal); } LogOut(6, "CApp::Run() got signal=%d while in _os_sleep()", nSignal); } else LogOut(7, "CApp::Run() _os_sleep() slept %d ticks", nSleep - nTicks); } } CleanUpLocal(); // deregister the process id (if there is one) if (m_nProcNum != NOBODY && NULL != m_pSoftwareMod) { m_pSoftwareMod->aProc[m_nProcNum].nProcID = 0; m_pSoftwareMod->aProc[m_nProcNum].nLifeCount = 0; LogOut(7, "CApp::Run() deregistered proc[%d]", m_nProcNum); m_nProcNum = NOBODY; } return bOk; }