Details zur Basisklasse CApp

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;
}