Timer: smaller glitches with 'sleep time remainder', TimerTest: proper close / wait for Timer enabled applications example

git-svn-id: svn://ultimatepp.org/upp/trunk@2549 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
kohait 2010-07-19 11:23:24 +00:00
parent 335799d2c9
commit cd8510db6e
6 changed files with 58 additions and 13 deletions

View file

@ -4,7 +4,7 @@
Timer::Timer()
{
granularity = 2;
granularity = 10;
run = true;
t.Run(THISBACK(TimerThread));
}
@ -73,7 +73,7 @@ void Timer::KillTimeCallback(void *id) {
KillTimeCallbacks(id);
}
void Timer::TimerProc(dword time)
void Timer::TimerProc(dword time, int & leftsleep)
{
if(IsPanicMode())
return;
@ -87,7 +87,7 @@ void Timer::TimerProc(dword time)
// sTimerLock.Leave();
// //***
// sTimerLock.Enter();
while(list->GetNext() != list && list->GetNext()->time < time) {
while(list->GetNext() != list && ((leftsleep = (list->GetNext()->time - time)) <= 0)) {
TimeEvent *e = list->GetNext();
e->Unlink();
if(e->delay < 0)
@ -98,6 +98,7 @@ void Timer::TimerProc(dword time)
delete e;
}
sTimerLock.Leave();
if(leftsleep < 0) leftsleep = granularity; //if last done has been processed and no more in queue, ensure good sleep
}
//SAME API AS IN Ctrl
@ -145,9 +146,11 @@ void Timer::SetTimerGranularity(int ms)
void Timer::TimerThread()
{
int leftsleep;
while(run)
{
TimerProc(GetTickCount());
Sleep(granularity); //granularity
leftsleep = granularity;
TimerProc(GetTickCount(), leftsleep);
Sleep(min(granularity, leftsleep));
}
}

View file

@ -39,7 +39,7 @@ private:
void KillTimeCallbacks(void *id, void *idlim);
bool ExistsTimeCallback(void *id);
void KillTimeCallback(void *id);
void TimerProc(dword time);
void TimerProc(dword time, int & leftsleep);
void KillTimeCallbacks(void *id);

View file

@ -18,12 +18,14 @@ things wont get to execution, until a current task is finished,
and the timer queue can check whether time has come for the next
task.]&]
[s0;2 &]
[s0;i150;O0; [2 Because of it, the timing is not as accurate as maybe
desired and can have `"timer glitches/jitter`", depending on
work load..]&]
[s0;i150;O0; [2 Thus, the timing is not as accurate as maybe desired
and can have `"timer glitches/jitter`", depending on work load..]&]
[s0;2 &]
[s0;i150;O0; [2 Favorite use is to schedule some `*non`*`-timing`-critical
work for `"somewhere`-around`-in`-the`-future`".]&]
work for `"somewhere`-around`-in`-the`-future`", like i.e. observe
some not too strict timing constraints in custom communication
protocols (answer needs to come in within X time, keep alive
messages..)]&]
[s0;2 &]
[s0;i150;O0; [2 For timing critical stuff, consider using OS native
timer means, for WIN32 SetTimer (in windowing environment, using

View file

@ -14,11 +14,16 @@ class TimerTest : public WithLayout<TopWindow> {
public:
typedef TimerTest CLASSNAME;
TimerTest();
~TimerTest();
void Close0();
virtual void Close();
void Info(const String & s);
void Test();
private:
Timer t;
Atomic demo;
};
#endif

View file

@ -1,3 +1,5 @@
description "Test for Timer package\377";
uses
CtrlLib,
Timer;

View file

@ -3,12 +3,17 @@
#define REPEAT_TEST
TimerTest::TimerTest()
: demo(0)
{
CtrlLayout(*this, "Window title");
int a = AtomicInc(demo);
ASSERT(a==1); //preload, 1 means running demo mode, 2 means a cb is executing
#ifdef REPEAT_TEST
t.SetTimeCallback(-1000, THISBACK(Test), 0);
t.SetTimeCallback(-100, THISBACK(Test), (int)this);
#else
PostCallback(THISBACK(Test));
t.SetTimeCallback(0, THISBACK(Test), (int)this);
#endif
}
@ -20,13 +25,41 @@ void TimerTest::Info(const String & s)
void TimerTest::Test()
{
int a = AtomicInc(demo);
ASSERT(a==2);
Info("O");
RLOG("O");
a = AtomicDec(demo);
if(a<=0)
return;
ASSERT(a>=0);
#ifdef REPEAT_TEST
#else
t.SetTimeCallback(1000, THISBACK(Test), 0);
t.SetTimeCallback(100, THISBACK(Test), (int)this);
#endif
}
void TimerTest::Close()
{
t.KillTimeCallback((int)this);
int a = AtomicDec(demo);
Thread::Start(THISBACK(Close0));
}
void TimerTest::Close0()
{
while(AtomicRead(demo) > 0) Sleep(1);
ASSERT(AtomicRead(demo)==0);
TopWindow::Close();
}
TimerTest::~TimerTest()
{
}
GUI_APP_MAIN
{
TimerTest().Run();