您的位置:首页 > 编程语言 > C语言/C++

QNX下三类定时器的C++封装

2008-10-23 12:59 316 查看
QNX下存在三类定时器,使用的难易程度不一样,精度也不一样。分别对其进行了一下封装,使用起来相对简单一点。
一、PtTimer

PtTimer是三者之中使用起来最简单的,但性能也最差,不过它与Rttimer一样,可以直接操作GUI里面的函数,相比HardTimer就不行了。

// QnxPtTimer.h: interface for the CQnxPtTimer class.

//

//////////////////////////////////////////////////////////////////////

#if !defined(AFX_QNXPTTIMER_H__01609CA6_BF75_4F50_93B6_BF323F927AB6__INCLUDED_)

#define AFX_QNXPTTIMER_H__01609CA6_BF75_4F50_93B6_BF323F927AB6__INCLUDED_

/*这个类基于PtTimer控间,存在一些实时性的不足。如英文描述。

PtTimer is easy to use, but doesn't give accurate timer events. In particular,

it doesn't guarantee a constant repeat rate; since the repetition is handled by rearming

the timer for each event, any delays in handling the events accumulate. Kernel timers

guarantee an accurate repeat rate even if your application can't keep up with them.

*/

#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000

#include <Ph.h>

#include <photon/PtTimer.h>

#include <photon/PtWindow.h>

//毫秒为单位

class CQnxPtTimer

{

public:

CQnxPtTimer(unsigned long init=1,//开始时间

unsigned long repeat=500,//重复周期

bool iAutoStart=0/*是否自动启动,1自动启动,0手动启动*/);

virtual ~CQnxPtTimer();

private:

void CreatePareantWin();

public:

void SetInitTime(unsigned long init);

void SetRepeatTime(unsigned long repeat);

void StartTimer();

void StopTimer();

int SetPtTimerParent(PtWidget_t* pParent);

public:

PtWidget_t *GetTimer();

unsigned long GetInitTime();

unsigned long GetRepeatTime();

public:

static int Cb_Timer( PtWidget_t *widget, void *data, PtCallbackInfo_t *cbinfo );

public:

virtual void RepeatTimerThread();

void SetTimerPareant(PtWidget_t *pParent);

protected:

PtWidget_t *m_pPareantWin;

PtWidget_t *m_pPtTimer;

//The time, in milliseconds:

unsigned long m_InitTime; //The time,before the first timer callback is activated

unsigned long m_RepeatTime; //The time, for the repeat rate of the timer once the initial time period has expired.

};

#endif // !defined(AFX_QNXPTTIMER_H__01609CA6_BF75_4F50_93B6_BF323F927AB6__INCLUDED_)

// QnxPtTimer.cpp: implementation of the CQnxPtTimer class.

//

//////////////////////////////////////////////////////////////////////

#include "QnxPtTimer.h"

//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////

CQnxPtTimer::CQnxPtTimer(unsigned long init,unsigned long repeat,bool iAutoStart)

{

m_pPtTimer=NULL;

CreatePareantWin();

m_pPtTimer=PtCreateWidget(PtTimer,m_pPareantWin,0,NULL);

SetInitTime(init);

SetRepeatTime(repeat);

PtAddCallback(m_pPtTimer, Pt_CB_TIMER_ACTIVATE,Cb_Timer, this );

if(iAutoStart)

{

StartTimer();

}

}

CQnxPtTimer::~CQnxPtTimer()

{

PtUnrealizeWidget(m_pPareantWin);

}

void CQnxPtTimer::SetTimerPareant(PtWidget_t *pParent)

{

if (m_pPtTimer)

{

m_pPareantWin=pParent;

PtReparentWidget(m_pPtTimer,m_pPareantWin);

}

}

void CQnxPtTimer::CreatePareantWin()

{

m_pPareantWin=PtCreateWidget(PtWindow,Pt_NO_PARENT,0,NULL);

PhPoint_t pos={-200,-200};

PtSetResource(m_pPareantWin,Pt_ARG_POS,&pos,0);

}

void CQnxPtTimer::SetInitTime(unsigned long init)

{

m_InitTime=init;

if (m_pPtTimer)

{

PtSetResource(m_pPtTimer,Pt_ARG_TIMER_INITIAL,m_InitTime,0);

}

}

void CQnxPtTimer::SetRepeatTime(unsigned long repeat)

{

m_RepeatTime=repeat;

if (m_pPtTimer)

{

PtSetResource(m_pPtTimer,Pt_ARG_TIMER_REPEAT,m_RepeatTime,0);

}

}

void CQnxPtTimer::StartTimer()

{

if (!m_pPtTimer)

{

return;

}

if (m_InitTime==0)

{

m_InitTime=500;

}

PtSetResource(m_pPtTimer,Pt_ARG_TIMER_INITIAL,m_InitTime,0);

PtRealizeWidget(m_pPareantWin);

PtWindowToBack(m_pPareantWin);

}

void CQnxPtTimer::StopTimer()

{

if (!m_pPtTimer)

{

return;

}

PtSetResource(m_pPtTimer,Pt_ARG_TIMER_INITIAL,0,0);

}

PtWidget_t *CQnxPtTimer::GetTimer()

{

return m_pPtTimer;

}

unsigned long CQnxPtTimer::GetInitTime()

{

return m_InitTime;

}

unsigned long CQnxPtTimer::GetRepeatTime()

{

return m_RepeatTime;

}

int CQnxPtTimer::Cb_Timer( PtWidget_t *widget, void *data, PtCallbackInfo_t *cbinfo )

{

CQnxPtTimer *pPtTim=(CQnxPtTimer *)data;

if (pPtTim!=NULL)

{

pPtTim->RepeatTimerThread();

}

return Pt_CONTINUE;

}

int CQnxPtTimer::SetPtTimerParent(PtWidget_t* pParent)

{

return PtReparentWidget( m_pPtTimer,pParent);

}

void CQnxPtTimer::RepeatTimerThread()

{

// printf("CQnxPtTimer::RepeatTimerThread/n");

}

二、Rttimer

// QnxRtTimer.h: interface for the CQnxRtTimer class.

//

//////////////////////////////////////////////////////////////////////

#if !defined(AFX_QNXRTTIMER_H__C504E91B_54FC_46D2_AE62_74CBE0AE5636__INCLUDED_)

#define AFX_QNXRTTIMER_H__C504E91B_54FC_46D2_AE62_74CBE0AE5636__INCLUDED_

#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000

#include <ph.h>

#include <pt.h>

#include <photon/realtime/RtTimer.h>

class CQnxRtTimer

{

public:

CQnxRtTimer(unsigned long init=1,//开始时间

unsigned long repeat=500,//重复周期

bool iAutoStart=0/*是否自动启动,1自动启动,0手动启动*/);

virtual ~CQnxRtTimer();

private:

void MyTimerCreate();

unsigned long GetTv_Sec(unsigned long imSec);//由毫秒转化为秒(不到一秒的舍去)

unsigned long GetTv_nSec(unsigned long imSec);//由毫秒转化为纳秒(只取不到一秒的毫秒部分)

public:

void SetInitTime(unsigned long init);

void SetRepeatTime(unsigned long repeat);

void StartTimer();

void StopTimer();

public:

unsigned long GetInitTime();

unsigned long GetRepeatTime();

public:

static int Cb_RtTimer( RtTimer_t *timer, void *data);

public:

virtual void RepeatTimerThread( );

protected:

//The time, in milliseconds:

unsigned long m_InitTime; //The time,before the first timer callback is activated

unsigned long m_RepeatTime; //The time, for the repeat rate of the timer once the initial time period has expired.

struct itimerspec m_itTimerSpec;

RtTimer_t * m_pRtTimer;

};

#endif // !defined(AFX_QNXRTTIMER_H__C504E91B_54FC_46D2_AE62_74CBE0AE5636__INCLUDED_)

// QnxRtTimer.cpp: implementation of the CQnxRtTimer class.

//

//////////////////////////////////////////////////////////////////////

#include "QnxRtTimer.h"

//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////

CQnxRtTimer::CQnxRtTimer(unsigned long init,unsigned long repeat,bool iAutoStart)

{

m_InitTime=init;

m_RepeatTime=repeat;

m_pRtTimer=NULL;

MyTimerCreate();

if (iAutoStart)

{

StartTimer();

}

}

CQnxRtTimer::~CQnxRtTimer()

{

}

void CQnxRtTimer::MyTimerCreate()

{

// printf("CQnxRtTimer::MyTimerCreate/n");

m_pRtTimer=RtTimerCreate(CLOCK_REALTIME,-1,Cb_RtTimer,this);

}

//由毫秒转化为秒(不到一秒的舍去)

unsigned long CQnxRtTimer::GetTv_Sec(unsigned long imSec)

{

return (imSec/1000) ;

}

//由毫秒转化为纳秒(只取不到一秒的毫秒部分)

unsigned long CQnxRtTimer::GetTv_nSec(unsigned long imSec)

{

return (imSec%1000)*1000000;

}

void CQnxRtTimer::SetInitTime(unsigned long init)

{

m_InitTime=init;

}

void CQnxRtTimer::SetRepeatTime(unsigned long repeat)

{

m_RepeatTime=repeat;

}

void CQnxRtTimer::StartTimer()

{

// printf("CQnxRtTimer::StartTimer/n");

if (m_InitTime==0)//--------消除m_InitTime=0对定时器启动的影响

{

m_InitTime=1;

}

/*

struct timespec it_value

A timespec structure that contains the amount of time left before the timer expires, or zero if the timer is disarmed. This value is expressed as the relative interval until expiration, even if the timer was armed with an absolute time.

struct timespec it_interval

A timespec structure that contains the timer's reload value. If nonzero, it indicates a repetitive timer period.

*/

// Set the timer to trigger every repeat msec

m_itTimerSpec.it_value.tv_sec = GetTv_Sec(m_InitTime);

m_itTimerSpec.it_value.tv_nsec = GetTv_nSec(m_InitTime);

m_itTimerSpec.it_interval.tv_sec = GetTv_Sec(m_RepeatTime);

m_itTimerSpec.it_interval.tv_nsec =GetTv_nSec(m_RepeatTime);

// Activate the timer

RtTimerSetTime(m_pRtTimer, 0, &m_itTimerSpec, NULL);

}

void CQnxRtTimer::StopTimer()

{

//

m_itTimerSpec.it_value.tv_sec = 0;

m_itTimerSpec.it_value.tv_nsec =0;

RtTimerSetTime(m_pRtTimer, 0, &m_itTimerSpec, NULL);

}

unsigned long CQnxRtTimer::GetInitTime()

{

return m_InitTime;

}

unsigned long CQnxRtTimer::GetRepeatTime()

{

return m_RepeatTime;

}

int CQnxRtTimer::Cb_RtTimer( RtTimer_t *timer, void *data)

{

// printf("CQnxRtTimer::Cb_RtTimer/n");

CQnxRtTimer *pRttimer=(CQnxRtTimer *)data;

if (!pRttimer)

{

return Pt_CONTINUE;

}

pRttimer->RepeatTimerThread();

return Pt_CONTINUE;

}

void CQnxRtTimer::RepeatTimerThread( )

{

// printf("CQnxRtTimer::RepeatTimerThread/n");

}

3、HardTimer

// QnxHardTimer.h: interface for the CQnxHardTimer class.

//

//////////////////////////////////////////////////////////////////////

/******************************************************************************

Timers in a separate process from the GUI -- necessary for hard realtime

毫秒为单位

注意,这个线程与Photon GUI是独立的,在这个定时器线程里不能够直接操作GUI

界面程序里的资源,必须使用PtEnter等API,可参考“Parallel Operations”一章

里的描述。如下是使用中的一个示例:

int eval;

if ((eval = PtEnter(0)) < 0 && eval != -EDEADLK){

fprintf( stderr, "Couldn't enter: %s/n", strerror( -eval ) );

}else{

//操作Photon GUI资源,如:

PtSetResource(g_pProgress,Pt_ARG_GAUGE_VALUE ,iCount,0);

//操作完毕离开

PtLeave(eval); // does nothing if eval == -EDEADLK

}

该定时器封装为以毫秒为单位,可以满足一般的程序设计需要。如果需要更高

精度的定时器,只需简单更改构造函数部分。

******************************************************************************/

#if !defined(AFX_QNXHARDTIMER_H__B6E1FA73_C325_4A30_8F2E_67891C02BC1B__INCLUDED_)

#define AFX_QNXHARDTIMER_H__B6E1FA73_C325_4A30_8F2E_67891C02BC1B__INCLUDED_

#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000

#include <time.h>

#include <sys/netmgr.h>

#include <sys/neutrino.h>

#include <pthread.h>

// Define the codes for the pulses

#define PULSE_HARDTIMER _PULSE_CODE_MINAVAIL

#define PULSE_EXIT _PULSE_CODE_MINAVAIL + 1

typedef union {

struct _pulse pulse;

/* your other message structures would go here too,此处不需要 */

} _THREAD_MESSAGE;

class CQnxHardTimer

{

public:

CQnxHardTimer(unsigned long init=1,//开始时间

unsigned long repeat=500,//重复周期

bool iAutoStart=0/*是否自动启动,1自动启动,0手动启动*/);

virtual ~CQnxHardTimer();

private:

void TimerThreadCreate();

unsigned long GetTv_Sec(unsigned long imSec);//由毫秒转化为秒(不到一秒的舍去)

unsigned long GetTv_nSec(unsigned long imSec);//由毫秒转化为纳秒(只取不到一秒的毫秒部分)

public:

void SetInitTime(unsigned long init);

void SetRepeatTime(unsigned long repeat);

void StartTimer();

void StopTimer();

void ExitTimerThread();

public:

unsigned long GetInitTime();

unsigned long GetRepeatTime();

public:

static void* _PeriodicThread(void *vArguments);

public:

virtual void RepeatTimerThread();

protected:

//The time, in milliseconds:

unsigned long m_InitTime; //The time,before the first timer callback is activated

unsigned long m_RepeatTime; //The time, for the repeat rate of the timer once the initial time period has expired.

int m_iTimerChannel;

struct itimerspec m_itTimerSpec;

timer_t m_TimerId;

//PC定时器用到的变量

struct sigevent m_seEvent;

};

#endif // !defined(AFX_QNXHARDTIMER_H__B6E1FA73_C325_4A30_8F2E_67891C02BC1B__INCLUDED_)

// QnxHardTimer.cpp: implementation of the CQnxHardTimer class.

//

//////////////////////////////////////////////////////////////////////

#include "QnxHardTimer.h"

//#include <stdio.h>

//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////

CQnxHardTimer::CQnxHardTimer(unsigned long init,unsigned long repeat,bool iAutoStart)

{

m_InitTime=init;

m_RepeatTime=repeat;

TimerThreadCreate();

if (iAutoStart)

{

StartTimer();

}

}

CQnxHardTimer::~CQnxHardTimer()

{

}

void CQnxHardTimer::TimerThreadCreate()

{

pthread_t ptThread; //定时器线程

pthread_attr_t ptaThreadAttributes;

m_iTimerChannel = ChannelCreate(0);

// Set the timer to send a pulse with the value PULSE_HARDTIMER when triggered

m_seEvent.sigev_notify = SIGEV_PULSE;

m_seEvent.sigev_coid = ConnectAttach(ND_LOCAL_NODE, 0, m_iTimerChannel, _NTO_SIDE_CHANNEL, 0);

m_seEvent.sigev_priority = getprio(0);

m_seEvent.sigev_code = PULSE_HARDTIMER;

timer_create(CLOCK_REALTIME, &m_seEvent, &m_TimerId);

// Create the thread and make it detached - no need to call join or cancel

pthread_attr_init( &ptaThreadAttributes );

pthread_attr_setdetachstate(&ptaThreadAttributes, PTHREAD_CREATE_DETACHED );

pthread_create(&ptThread, &ptaThreadAttributes, &_PeriodicThread, this );

}

//由毫秒转化为秒(不到一秒的舍去)

unsigned long CQnxHardTimer::GetTv_Sec(unsigned long imSec)

{

return (imSec/1000) ;

}

//由毫秒转化为纳秒(只取不到一秒的毫秒部分)

unsigned long CQnxHardTimer::GetTv_nSec(unsigned long imSec)

{

return (imSec%1000)*1000000;

}

void CQnxHardTimer::SetInitTime(unsigned long init)

{

m_InitTime=init;

}

void CQnxHardTimer::SetRepeatTime(unsigned long repeat)

{

m_RepeatTime=repeat;

}

void CQnxHardTimer::StartTimer()

{

if (m_InitTime==0)//--------消除m_InitTime=0对定时器启动的影响

{

m_InitTime=1;

}

/*

struct timespec it_value

A timespec structure that contains the amount of time left before the timer expires, or zero if the timer is disarmed. This value is expressed as the relative interval until expiration, even if the timer was armed with an absolute time.

struct timespec it_interval

A timespec structure that contains the timer's reload value. If nonzero, it indicates a repetitive timer period.

*/

// Set the timer to trigger every repeat msec

m_itTimerSpec.it_value.tv_sec = GetTv_Sec(m_InitTime);

m_itTimerSpec.it_value.tv_nsec = GetTv_nSec(m_InitTime);

m_itTimerSpec.it_interval.tv_sec = GetTv_Sec(m_RepeatTime);

m_itTimerSpec.it_interval.tv_nsec =GetTv_nSec(m_RepeatTime);

// Activate the timer

timer_settime(m_TimerId, 0, &m_itTimerSpec, NULL);

}

void CQnxHardTimer::StopTimer()

{

//

m_itTimerSpec.it_value.tv_sec = 0;

m_itTimerSpec.it_value.tv_nsec =0;

// m_itTimerSpec.it_interval.tv_sec = GetTv_Sec(m_RepeatTime);

// m_itTimerSpec.it_interval.tv_nsec =GetTv_nSec(m_RepeatTime);

// Activate the timer

timer_settime(m_TimerId, 0, &m_itTimerSpec, NULL);

}

//

void CQnxHardTimer::ExitTimerThread()

{

// Send the destruct message

MsgSendPulse(m_seEvent.sigev_coid, 1, PULSE_EXIT, PULSE_EXIT);

}

unsigned long CQnxHardTimer::GetInitTime()

{

return m_InitTime;

}

unsigned long CQnxHardTimer::GetRepeatTime()

{

return m_RepeatTime;

}

/*

* Function: _PeriodicThread

* Description: 定时器定时产生一个pulse,该线程就是捕捉该周期性的pulse

* Input:

* Return:

* DateTime: Mar 4, 2005 8:49:46 AM

* Others:

*/

void* CQnxHardTimer::_PeriodicThread(void *vArguments)

{

// printf("CQnxHardTimer::_PeriodicThread/n");

CQnxHardTimer *pHtimer=(CQnxHardTimer *)vArguments;

_THREAD_MESSAGE tmMessage;

int iReceiveIdentifier;

// Infinite loop

while(1)

{

// Receive the message

iReceiveIdentifier = MsgReceive(pHtimer->m_iTimerChannel, &tmMessage,sizeof(_THREAD_MESSAGE), NULL);

// Check if this is a pulse message

if(iReceiveIdentifier == 0)

{

// Check if this is the timer pulse

if(tmMessage.pulse.code == PULSE_HARDTIMER)//时间基准

{

// Perform periodic code here

pHtimer->RepeatTimerThread();

/* //可以在这里新启动一个线程来处理,例如

pthread_attr_t attr;

//线程初始化

pthread_attr_init( &attr );

pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED );

//启动秒定时器线程

pthread_create( NULL, &attr, &_SecondTimerThread, NULL );

//启动整点定时器线程

pthread_create( NULL, &attr, &_WholeHourTimerThread, NULL );

*/

}

if(tmMessage.pulse.code == PULSE_EXIT)

{

// Break the loop

// printf("Destroying thread/n");

break;

}

}

}

// Display the destruction message

// printf("Destroying thread/n");

return 0;

}

void CQnxHardTimer::RepeatTimerThread()

{

// printf("CQnxHardTimer::RepeatTimerThread/n");

}

四、使用方法

使用时只需要从上述类里继承一个子类,并在子类里实现RepeatTimerThread就可以了。http://blog.csdn.net/Delores/archive/2008/10/23/3127978.aspx里的CCpuUsed 就是一个例子。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: