求一个可以随时加减法时间的计时器

象棋竞赛计时器的设计.doc修改版_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
评价文档:
29页免费15页免费11页免费16页免费9页1下载券 20页1下载券27页1下载券4页免费24页2下载券16页2下载券
喜欢此文档的还喜欢12页免费24页2下载券16页2下载券
象棋竞赛计时器的设计.doc修改版|
把文档贴到Blog、BBS或个人站等:
普通尺寸(450*500pix)
较大尺寸(630*500pix)
你可能喜欢比赛计时器程序设计报告_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
评价文档:
38页免费13页免费10页免费28页1下载券8页免费 8页免费18页3下载券17页7下载券17页7下载券6页免费
喜欢此文档的还喜欢50页1下载券17页免费3页免费10页免费16页免费
比赛计时器程序设计报告|单​片​机​ ​汇​编​语​言
把文档贴到Blog、BBS或个人站等:
普通尺寸(450*500pix)
较大尺寸(630*500pix)
你可能喜欢豆丁精品文档: 单片机计时器程序 单片机的计时器 计时器 倒计时器 魔方计时器 计..
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
单片机计时器
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer-4.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口◆相关文章◆
编辑推荐 ◆
您要为您所发的言论的后果负责,故请各位遵纪守法并注意语言文明。(60个字以内)
●本站所有内容均来自网络,以学习为目的,如果侵犯了您的利益,请来信告知,立即删除,站长邮件为"",请将"+"变更为"@"
●电子制作存在风险,请注意人身安全,如果您在根据本站电路进行制作过程中发生伤害,本站不负任何责任。
本站信息产业部备案:[转载]一个带自适应功能的高精度计时器
这应该算我近期的工作了。我最近在做一个HashCache,里面有个回写功能,即将有更新的节点内容写入磁盘。这带来一个问题,这个HashCache是多线程访问环境,必须考虑加锁,由于HashCache内部有淘汰机制,需要利用到一个最近访问的时间戳来判定,也就是说,无论读还是写操作,最终都会对这个时间戳实现写动作,因此,不存在单写多读锁的调用可能性,只能用普通锁。
也就是说,这个HashCache,必须通过锁域封装,每个客户来访问的动作都是排他的,HashCache每次只能由一个客户访问。但这会带来效率问题,由于多任务开发的“大锁”问题,必然效率低下。但这又是维护正常逻辑必须的,没有办法折中。唯一的解决之道,就是尽量缩减每个访问动作的时间,使每个锁域粒度最小化,大家快进快出,保证效率。
这其实也是我使用Hash来做这个Cache的原因,Hash的访问复杂度,基本上是O(1)的,这保证我每个锁域都是O(1)的宽度,这使我的HashCache获得了最大交换能力,也就是访问能力最大化。
但是,回到开始的问题,我必须考虑回写逻辑,以一个线程不断遍历Hash表的每个节点,把内容有更新的节点,写回磁盘,这个动作,由于涉及磁盘交互,必然是一个高loading的动作,肯定不是O(1)啦,这没有办法,那我就得想个什么办法来控制这个回写逻辑的时间片不至于太宽,免得把锁占据太久,导致上层正常的访问逻辑被长时间挂住,甚至超时报错。
这就要求我必须在毫秒级控制时间片的精度。而且,误差不能太大,我预设大约每次回写线程工作5ms就退出,等待15ms再继续,这样我可以以20ms为周期,每秒钟完成50个周期左右,外部业务线程获得750ms左右的时间,而回写线程获得250ms的时间,各自完成自己的业务。我试图通过这种对时间片的精确控制,来保证业务访问的精度要求。
不过,这就有点麻烦了,我的工程库,在《0bug-C/C++商用工程之道》中,大家可以看到一个CDeltaTime的类,这是我常用的一个计时器(5.5.3小节,P194页),不过呢,这个计时器有个缺点,精度只有1秒,这显然不够,我没办法,昨天就重写了一个高精度计时器,不过一写起来才发现,这个问题没想的那么简单,呵呵,本来想喝口绿茶,结果被灌了一口二锅头。
我花了整整一个下午来做这件事情,中间呢,出于工程化开发的原则,我考虑了很多细节,我想了一下,还是写篇博文把这个过程展示一下,也许能给大家一点启发也说不定哈。
这个计时器,我本意还是仿照CDeltaTime类来做一个统计性的类,内部计算DeltaTime,供外部查询。在《0bug-C/C++商用工程之道》的P193页,我呢,有个CCountSub的类,它能处理unsigned
long的数值,看起来还可以,但我仔细一想,发现一个问题。32bits的OS下,unsigned
long的范围是4Bytes,这个用来存秒呢,可以存几十年的,不过,要是存毫秒,完蛋了,我算了一下,差不多49天就溢出,这肯定不行。没办法,我首先重新做了个统计模块,专门处理溢出问题。
CDWORDCount&&&
public:&&&
CDWORDCount(){Reset();}&&&
~CDWORDCount(){}&&&
Reset(DWORD dwValue=0){return
m_dwBegin=m_dwEnd=dwV}&&&
SetBegin(DWORD dwValue){return
(m_dwBegin=dwValue);}&&&
SetEnd(DWORD dwValue){return
m_dwEnd=dwV}&&&
GetBegin(void){return
GetEnd(void){return
GetX(void)&&&
if(m_dwEnd&m_dwBegin)&&&
&&&&&&&&&&&
//处理溢出问题&&&
&&&&&&&&&&&
nBeginX=abs(0-m_dwBegin);&&&&&&
//求得m_dwBegin与0之间的差值nBeginX&&&
&&&&&&&&&&&
m_dwEnd+(DWORD)nBeginX;&&&&&
//m_dwEnd此时的值是相对0之间的溢出部分&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//真实的差值是nBeginX与m_dwEnd之和&&&
(m_dwEnd-m_dwBegin);&&&
private:&&&
大家注意GetX这个函数,是求Begin和End的差值,由于windows下,求毫秒的函数GetTickCount返回的是DWORD,因此,我这个工具类也主要处理DWORD这个类型。具体函数意思我不用写注释了吧,看英文都看得懂。
当然,按我团队的规矩,还是要给一个测试函数,大家可以看看其对溢出逻辑的处理是正确的:
inline void
TestCDWORDCount(void)&&&
&&& CDWORDCount
Count.SetBegin(0xFFFFFFFF);&&&
Count.SetEnd(5);&&&&&&&&&&&&&&&&&&&&&&&&&&&
//此时的End相当于0x&&&
printf("%ldn",Count.GetX());&&&
printf("%ldn",abs(0-0xFFFFFFFF));&&&
ok,有了这个工具,我准备开始写计时器,我先完成了基本部分,嗯,大家注意,为了保证精度,这里面全部使用的是C++的内联函数写法,即函数会在编译时在调用处展开,节约压栈、弹栈的动作开销,我们这是在计时,省一点总是好的。
先给大家一个宏吧,这是求毫秒级精度的系统函数的跨平台封装。《0bug-C/C++商用工程之道》里面有,各位读者可以看看。
#define _GetTimeOfDay
GetTickCount&&&
由于写这个计时器一波三折,我也是分几次才写好,因此,这里先给基本类,后面再逐渐介绍几套计时方案。
CTonyDeltaMicroSeconds&&&
public:&&&
CTonyDeltaMicroSeconds(){Reset();}&&&
~CTonyDeltaMicroSeconds(){}&&&
Reset(void)&&&
m_Count.Reset(_GetTimeOfDay());&&&
m_nFix=0;&
//这个回头再说&&&
m_Mean.Reset();&
//这个回头再说&&&
PrintInfo(void)&&&
printf("m_nFix=%dn",m_nFix);&&&
m_Mean.PrintInfo();&&&
TouchBegin(void){return
m_Count.SetBegin(_GetTimeOfDay());}&&&
TouchEnd(void){return
m_Count.SetEnd(_GetTimeOfDay());}&&&
GetBegin(void){return
m_Count.GetBegin();}&&&
GetEnd(void){return
m_Count.GetEnd();}&&&
GetDeltaMicroSeconds(void){return
m_Count.GetX();}&&&
private:&&&
&&& CDWORDCount
&&& CTonyMean
//这个回头再说&&&
//这个回头再说&&&
大家注意,其实基本类很简单,都在调用前一个类,仅仅是把基数绑定在系统取得的毫秒数上。
然后,我开始考虑怎么样计时,其实基本原理很简单,我内部保存了Begin和End,两次时间点的毫秒差,就是内部的DeltaTime,这个和外部传进来的时间段MaxDelta比较一下,如果内部DeltaTime&外部时差,则表示时间到了,可以返回真,否则返回假,所以,我写了第一个计时函数TimeIsUp0。
bool TimeIsUp0(const DWORD
dwMaxDeltaMicroSeconds)&&&
//直接比较内部的时间差和外部的判断时长,&&&
//如果外部的判断时长&=内部时间差,则返回真&&&
//无修订,精度误差15ms左右&&&
&&& return
(dwMaxDeltaMicroSeconds&=GetDeltaMicroSeconds());&&&
简单吧,呵呵。
可是效果不好,我测了一下,其精度误差在15~16ms左右,即我要求睡眠1ms,它返回真的时候是15ms。晕哦,这咋控制精度。
没办法,我开始试图修订这个算法。
这中间肯定要修订误差,不过,这个误差方法是我以前写游戏的经验,其实就是路径跟踪算法啦。当玩家控制的主角在屏幕上跑来跑去的时候,计算机控制的敌人要追踪主角的位置,总是不断计算自己和主角之间的坐标差(自己坐标
主角坐标),如果这个坐标差为-,表示目前自己的坐标小了,需要增加,反之则需要减少。X、Y都可以这么计算。这个体现增加和减少的变量,叫做修订因子,它和自己的绝对坐标之和,就是新的坐标。
当然,这个修订因子还可以调整加速度,即如果每次都少,则修订因子不断+1,每次和自己坐标之和,步距就大,而每次都多,步距其实也大,但是,随着两人逐渐靠近,如果两人的,比如X坐标,很接近,要么大一点,要么小一点,则根据算法,这个修订因子就在-1,0,+1之间跳变,其实相当于X不怎么变动。这是动态的计算变化。
这段可能有点绕,大家仔细看吧,我已经很努力了,但是也没办法讲更清楚,个别朋友可以给我发信息询问。
我是这么考虑的:
1、每次判定时间到了,会得到一个真,此时,内部的DeltaTime和外部要求的时间段MaxDelta,肯定不太可能一样,有误差是正常的。
2、但是,可以考虑修订,即我内部保留一个修订因子int
m_nF,这个值本来是0,但是,如果我求得一个真,此时可以计算一个差值DeltaTime-MaxDelta,这表示误差,这个误差如果&0,则表示小了,修订因子需要+1,反之-1。
3、每次进来判定,判定的是MaxDelta+m_nFix的值,即利用m_nFix修订因子来影响判定结果。最终得出较为精确的时间。
由于上述思想,我写了第二个判定函数:
bool TimeIsUp1(const DWORD
dwMaxDeltaMicroSeconds)&&&
//初级修订,每次判断时,外部条件需要加上一个修订值再判断&&&
//以这个修订值来抵消误差&&&
//dwMaxDeltaMicroSeconds=100,nDeltaT=110,表示外部程序循环精度不高,110ms才访问一次本接口&&&
//则nDeltaT-dwMaxDeltaMicroSeconds=10&0,修订值-1(初值为0)&&&
//下次判断时,dwMaxDeltaMicroSeconds=100+(-1)=99,&&&
//这使得nCompNumber更容易&=nDeltaT,也就是说,更快地返回时间到的真标志&&&
//dwMaxDeltaMicroSeconds=100,nDeltaT=90,表示外部程序循环精度太高,90ms就访问一次本接口&&&
//则nDeltaT-dwMaxDeltaMicroSeconds=-10&0,修订值+1(初值为0)&&&
//下次判断时,dwMaxDeltaMicroSeconds=100+(1)=101,&&&
//这使得nCompNumber更不容易&=nDeltaT,也就是说,更慢地返回时间到的真标志&&&
//修订值总是在跳变,当出现一次为真的成功比较,即时间到,&&&
//此时nDeltaT大约相当于外部要求的dwMaxDeltaMicroSeconds,&&&
//二者之间的差值nDeltaT-nMaxDeltaMicroSeconds即作为修订值的调整依据&&&
//调整后的修订值,影响下面几轮的比较动作&&&
//由于这是使用绝对差值nDeltaT-nMaxDeltaMicroSeconds在调整修订值m_nFix,&&&
//导致m_nFix的抖动很大,误差还是比较大,经实测,误差在+-6~7ms左右,&&&
//即100ms的求精,得到94~106左右的范围,误差还是很大&&&
nDeltaT=(int)GetDeltaMicroSeconds();&&&&&&&&&&&&&&&&&&&
//获得Begin和End之间的时间差&&&
nMaxDeltaMicroSeconds=(int)dwMaxDeltaMicroS&&&&&
//业务判断的毫秒数取整型&&&
nCompNumber=nMaxDeltaMicroSeconds+m_nF&&&&&&&&&&&&&&
//业务判断毫秒数和修正值累加,获得比较值&&&
bRet=(nCompNumber&=nDeltaT);&&&&&&&&&&&&&&&&&&&&&&&&&&
//比较值和内部保存的时间差比较&&&
if(bRet)&&&
//如果为真,表示时间到,调整修正值&&&
nFixX=nDeltaT-nMaxDeltaMicroS&&&&&&&&&&&&&&&
//取得修订系数,实际存储的时间差减去外部给定的差值&&&
if(0&nFixX)
m_nFix--;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//如果修订系数为负数,表示nMaxDeltaMicroSeconds太大,&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//修正值-1,下次的nCompNumber就会小1&&&
else if(0&nFixX)
m_nFix++;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//否则,修正值+1,下次的nCompNumber就会大1&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//这种修订方法取绝对值,m_nFix抖动很大,精度不高&&&
&&& return
不过出来一测,发现精度还是太低,有改善,我获得了7~8ms的误差精度,即我要1ms,得到7~8ms,要100ms,得到93~107ms的误差范围。
我仔细分析了一下,推测可能是直接使用DeltaTime-MaxDelta的绝对值来做判定,动作太大了,m_nFix跳变抖动得厉害,影响了精度。
那,有个简单的办法来实现这个逻辑,就是使用多次DeltaTime-MaxDelta的平均值来影响m_nFix,减小抖动。不过,这带来一个问题,我手边还没有一个合用的平均值计算模块,想了一下,我干脆写了一个。
&float.h&&&&
//判定一个double数是否为0.0,相当于if(0.0==dValue)&&&
inline bool DoubleIsZero(double dValue){return
(abs(dValue)&DBL_EPSILON);}&&&
//判定两个double数是否绝对相等,相当于if(dA==dB)&&&
inline bool DoubleIsEqual(double dA,double dB){return
DoubleIsZero(dA-dB);}&&&
CTonyMean&&&
public:&&&
CTonyMean(){Reset();}&&&
~CTonyMean(){}&&&
Reset(void)&&&
m_dAllCount=0.0;&&&
m_nTimes=0;&&&
m_dMean=0.0;&&&
m_nOnlyPositiveNumberFlag=0;&&&
m_nOnlyNegativeNumberFlag=0;&&&
&&& double
Push(double
dValue)&&&
//printf("Push(%f)n",dValue);&
//调试代码,可以删除&&&
//统计是否只处理单一数据种类(正数或者负数)&&&
if(0&dValue)
m_nOnlyPositiveNumberFlag=1;&&&
if(0&dValue)
m_nOnlyNegativeNumberFlag=1;&&&
m_nTimes++;&&&
//由于本类没有限定输入的dValue值是否为正数或者&&&
//因此m_dAllCount可能会由于单一数种溢出导致为0.0,&&&
//也可能因为正负数抵消为0.0&&&
//必须分别处理&&&
m_dAllCount+=dV&&&
//如果据统计,有史以来只使用纯正数,或者纯负数,&&&
//则处理总累加器溢出&&&
//否则则认为是正负数抵消的0.0,无需处理&&&
if(OnlyOneTypeNumber())&&&
&&&&&&&&&&&
if(DoubleIsZero(m_dAllCount))&&&
&&&&&&&&&&&&&&&
ResetByOverflow();&&&
//由于m_nTimes总是先+1后使用,&&&
//因此,此处的m_nTimes==0一定是溢出&&&
//使用溢出处理方案&&&
if(!m_nTimes)
ResetByOverflow();&&&
//计算平均值&&&
m_dMean=m_dAllCount/(double)(m_nTimes);&&&
GetMean();&&&
//友好接口,大多数时候,大家在用整数做值,因此,允许直接输入整数值&&&
&&& double
Push(int nValue){return
Push((double)nValue);}&&&
//求得平均数&&&
&&& double
GetMean(void){return
//内部打印&&&
PrintInfo(void)&&&
printf("CTonyMean: AllCount=%f, Times=%d,
Mean=%fn",&&&
&&&&&&&&&&&
m_dAllCount,m_nTimes,m_dMean);&&&
printf("Positive=%d, Negative=%d,
OnlyOneTypeNumber()=%dn",&&&
&&&&&&&&&&&
m_nOnlyPositiveNumberFlag,&&&
&&&&&&&&&&&
m_nOnlyNegativeNumberFlag,&&&
&&&&&&&&&&&
OnlyOneTypeNumber());&&&
private:&&&
//是否是相同类型的数字判断&&&
OnlyOneTypeNumber(void)&&&
&&& {return
(m_nOnlyPositiveNumberFlag^m_nOnlyNegativeNumberFlag);}&&&
//溢出处理方案,设置次数为1,&&&
//设置总累计数为以前求的平均值&&&
//二者相除,平均值不变&&&
//以便保留以往的平均值继续计算结果。&&&
ResetByOverflow(void)&&&
//把总累加器恢复为上一轮的平均值&&&
m_dAllCount=m_dM&&&
//m_nTimes无条件设置为1&&&
m_nTimes=1;&&&
&&& unsigned int
m_nT&&&&&&&&&&&&&&&&&
//总次数&&&
&&& double
m_dAllC&&&&&&&&&&&&&&&&&&&&
//总累加器&&&
&&& double
m_dM&&&&&&&&&&&&&&&&&&&&&&&&
//平均值&&&
&&& unsigned int
m_nOnlyPositiveNumberF
//有史以来,存储过正数标志&&&
&&& unsigned int
m_nOnlyNegativeNumberF
//有史以来,存储过负数标志&&&
inline void
TestCTonyMean(void)&&&
&&& CTonyMean
Mean.Reset();&&&
Mean.Push(1);&&&
Mean.Push(2);&&&
Mean.PrintInfo();&&&
Mean.Reset();&&&
Mean.Push(-1);&&&
Mean.Push(-2);&&&
Mean.PrintInfo();&&&
Mean.Reset();&&&
Mean.Push(-1);&&&
Mean.Push(2);&&&
Mean.PrintInfo();&&&
我想我注释挺明白的,就不多说了吧。大家现在知道计时器里面的CTonyMean m_M怎么来的了吧。呵呵。
嗯,这段代码调整过,原来的老代码,只能处理纯正数或者有正负数,现在调整为可以同时处理纯正数,正负数,以及纯负数三种情况,这样适用面更广一点。嗯,我顺手加了个测试代码,大家有兴趣可以run起来看看。
然后,我写了第三段精确计时逻辑。
bool TimeIsUp2(const DWORD
dwMaxDeltaMicroSeconds)&&&
//高级修订,利用平均值来优化m_nFix的算法,降低抖动&&&
//计算原理同TimeIsUp1&&&
//每次不再以nDeltaT-nMaxDeltaMicroSeconds作为m_nFix的修订依据&&&
//而是以多次nDeltaT-nMaxDeltaMicroSeconds的平均值,作为m_nFix的修订依据&&&
//经实测,m_nFix的抖动较小,获得+-0.003ms的左右时间精度&&&
//即100ms,获得99.997ms~100.003ms的时间精度,1ms求精,可以得到0.997~1.003ms的计时精度&&&
nDeltaT=(int)GetDeltaMicroSeconds();&&&&&&&&&&&&&&&&&&&
//获得Begin和End之间的时间差&&&
nMaxDeltaMicroSeconds=(int)dwMaxDeltaMicroS&&&&&
//业务判断的毫秒数取整型&&&
nCompNumber=nMaxDeltaMicroSeconds+m_nF&&&&&&&&&&&&&&
//业务判断毫秒数和修正值累加,获得比较值&&&
bRet=(nCompNumber&=nDeltaT);&&&&&&&&&&&&&&&&&&&&&&&&&&
//比较值和内部保存的时间差比较&&&
if(bRet)&&&
m_Mean.Push(nDeltaT-nMaxDeltaMicroSeconds);&&&&&&&&&&&&
//此处计算平均值&&&
if(0.0&m_Mean.GetMean())
m_nFix--;&&&&&&&&&&&&&&&&&&&&&
//以平均值的正负性来调整修订值&&&
else if(0.0&m_Mean.GetMean())
m_nFix++;&&&
&&& return
大家请注意平均值计算的代入。
这段代码效果很好,我测试了一下,获得了+-0.003ms左右的精度。
当然,我想了一下,干脆,这些个代码全部提供,所以我写了个集中的函数,利用switch选择用哪种计时精度。
bool TimeIsUp(const DWORD dwMaxDeltaMicroSeconds,int
nModel=2)&&&
TouchEnd();&&&
switch(nModel)&&&
default:&&&&&&&
//其他数取默认值&&&
0:&&&&&&&&
//普通模式&&&
bRet=TimeIsUp0(dwMaxDeltaMicroSeconds);&&&
1:&&&&&&&&
//加入了误差修订&&&
bRet=TimeIsUp1(dwMaxDeltaMicroSeconds);&&&
2:&&&&&&&&
//加入了平均值误差修订&&&
bRet=TimeIsUp2(dwMaxDeltaMicroSeconds);&&&
&&& return
嗯,这是判定逻辑,有时候,业务层可能不想自己做个循环频繁判定,因此需要这个逻辑自己提供一个等待睡眠的函数,我也写了一个。
void Wait4(const DWORD dwMaxDeltaMicroSeconds,int
nModel=2)&&&
{while(!TimeIsUp(dwMaxDeltaMicroSeconds,nModel)){TonyXiaoMinSleep();}}&&
嗯,没有看过《0bug-C/C++商用工程之道》这本书的朋友,可能看不懂TonyXiaoMinSleep();这个函数,那简单,直接用Sleep(0)代替好了。
最后,我写了一段代码测试一下,由于这里面有动态跟踪逻辑,因此,前面几次测试肯定不准,需要工作一段时间,m_nFix调整得差不多了,精度就高了,因此,我写了如下逻辑。每种模式,0、1、2三种,分别测试5轮,每轮测试1000次,取平均值,来看测试的精度。
精度测试很简单,我用个计数器,每次叠加DeltaTime这个模块内部的Delta值,最后除以总的访问次数,就得到平均每次的毫秒数。
#define TestCDeltaMicroSeconds_MAX_COUNT
inline void
TestCDeltaMicroSeconds(void)&&&
&&& CTonyMean
TimeMeadPreM&&&
CTonyDeltaMicroSeconds
nCount=0;&&&
&&& double
dMS=0.0;&&&
for(i=0;i&3;i++)&&&
TimeMeadPreModel.Reset();&&&
for(j=0;j&5;j++)&&&
&&&&&&&&&&&
printf("Test: model=%d, try=%d, test %d times pre
tryn",i,j,TestCDeltaMicroSeconds_MAX_COUNT);&&&
&&&&&&&&&&&
nCount=0;&&&
&&&&&&&&&&&
dms.Reset();&&&
&&&&&&&&&&&
for(k=0;k&TestCDeltaMicroSeconds_MAX_COUNT;k++)&&&
&&&&&&&&&&&
&&&&&&&&&&&&&&&
dms.TouchBegin();&&&
&&&&&&&&&&&&&&&
//while(!dms.TimeIsUp(1,i)){}//{Sleep(10);}&&&
&&&&&&&&&&&&&&&
dms.Wait4(1,i);&&&
&&&&&&&&&&&&&&&
nCount+=dms.GetDeltaMicroSeconds();&&&
&&&&&&&&&&&
&&&&&&&&&&&
dMS=(double)nCount/(double)TestCDeltaMicroSeconds_MAX_COUNT;&&&
&&&&&&&&&&&
TimeMeadPreModel.Push(dMS);&&&
&&&&&&&&&&&
printf("Model %d, try=%d %d times: Mean= %f
msn",i,j,TestCDeltaMicroSeconds_MAX_COUNT,dMS);&&&
&&&&&&&&&&&
printf("-----------n");&&&
printf("Model %d Mean: %f
msn",i,TimeMeadPreModel.GetMean());&&&
printf("=====================================n");&&&
运行结果如下:
Test: model=0, try=0, test 1000 times pre
Model 0, try=0 1000 times: Mean= 15.625000
-----------&&&
Test: model=0, try=1, test 1000 times pre
Model 0, try=1 1000 times: Mean= 15.625000
-----------&&&
Test: model=0, try=2, test 1000 times pre
Model 0, try=2 1000 times: Mean= 15.625000
-----------&&&
Test: model=0, try=3, test 1000 times pre
Model 0, try=3 1000 times: Mean= 15.625000
-----------&&&
Test: model=0, try=4, test 1000 times pre
Model 0, try=4 1000 times: Mean= 15.625000
-----------&&&
Model 0 Mean: 15.625000
//第一种模式,差不多15.625ms的精度&&&
=====================================&&&
Test: model=1, try=0, test 1000 times pre
Model 1, try=0 1000 times: Mean= 7.813000
-----------&&&
Test: model=1, try=1, test 1000 times pre
Model 1, try=1 1000 times: Mean= 7.812000
-----------&&&
Test: model=1, try=2, test 1000 times pre
Model 1, try=2 1000 times: Mean= 7.813000
-----------&&&
Test: model=1, try=3, test 1000 times pre
Model 1, try=3 1000 times: Mean= 7.812000
-----------&&&
Test: model=1, try=4, test 1000 times pre
Model 1, try=4 1000 times: Mean= 7.813000
-----------&&&
Model 1 Mean: 7.812600
//第二种模式,差不多7.8ms的精度&&&
=====================================&&&
Test: model=2, try=0, test 1000 times pre
Model 2, try=0 1000 times: Mean= 1.000000
-----------&&&
Test: model=2, try=1, test 1000 times pre
Model 2, try=1 1000 times: Mean= 1.000000
-----------&&&
Test: model=2, try=2, test 1000 times pre
Model 2, try=2 1000 times: Mean= 1.000000
-----------&&&
Test: model=2, try=3, test 1000 times pre
Model 2, try=3 1000 times: Mean= 1.000000
-----------&&&
Test: model=2, try=4, test 1000 times pre
Model 2, try=4 1000 times: Mean= 1.000000
-----------&&&
Model 2 Mean: 1.000000
//第三种模式,精确计量出1ms&&&
=====================================&&
呵呵,当然,由于这个模块本意是要跨线程工作,我这里给出它的资源锁封装版本。
CTonyDeltaMicroSecondsWithLock&&&
public:&&&
CTonyDeltaMicroSecondsWithLock(){}&&&
~CTonyDeltaMicroSecondsWithLock(){}&&&
public:&&&
Reset(void){TONY_LOCK_CALL(m_TonyDeltaMicroSeconds.Reset())}&&&
PrintInfo(void){TONY_LOCK_CALL(m_TonyDeltaMicroSeconds.PrintInfo());}&&&
TouchBegin(void){TONY_DWORD_LOCK_CALL(m_TonyDeltaMicroSeconds.TouchBegin());}&&&
TouchEnd(void){TONY_DWORD_LOCK_CALL(m_TonyDeltaMicroSeconds.TouchEnd());}&&&
GetBegin(void){TONY_DWORD_LOCK_CALL(m_TonyDeltaMicroSeconds.GetBegin());}&&&
GetEnd(void){TONY_DWORD_LOCK_CALL(m_TonyDeltaMicroSeconds.GetEnd());}&&&
GetDeltaMicroSeconds(void){TONY_DWORD_LOCK_CALL(m_TonyDeltaMicroSeconds.GetDeltaMicroSeconds());}&&&
TimeIsUp(const DWORD dwMaxDeltaMicroSeconds,int
nModel=2)&&&
{TONY_BOOL_LOCK_CALL(m_TonyDeltaMicroSeconds.TimeIsUp(dwMaxDeltaMicroSeconds,nModel));}&&&
private:&&&
CTonyDeltaMicroSeconds
m_TonyDeltaMicroS&&&
&&& CMutexLock
嗯,中间用到几个宏,是我图省事,写的。0bug里面讲过没有,我忘了,嘿嘿。这里给出来。
#define TONY_LOCK_CALL(func)
m_Lock.Lock();
m_Lock.Unlock();
#define TONY_DWORD_LOCK_CALL(func)
&&& DWORD dwR
m_Lock.Lock();
&&& dwRet=
m_Lock.Unlock();
&&& return
#define TONY_BOOL_READ_LOCK_CALL(func)
&&& bool bR
m_Lock.AddRead();
m_Lock.DecRead();
&&& return bR
差不多就这么多吧,内容有点多,大家慢慢看哈。呵呵。
没办法,有那么多细节要考虑,我也写了整整一个下午呢。本程序在VS2008下测试通过。
===================================================
肖舸 《0bug-C/C++商用工程之道》
QQ:712123
MSN/Email:
如果你喜欢我的文章,请点击这里加我为好友:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

我要回帖

更多关于 加减法 的文章

 

随机推荐