mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-21 06:45:39 -06:00
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:
parent
335799d2c9
commit
cd8510db6e
6 changed files with 58 additions and 13 deletions
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
Timer::Timer()
|
Timer::Timer()
|
||||||
{
|
{
|
||||||
granularity = 2;
|
granularity = 10;
|
||||||
run = true;
|
run = true;
|
||||||
t.Run(THISBACK(TimerThread));
|
t.Run(THISBACK(TimerThread));
|
||||||
}
|
}
|
||||||
|
|
@ -73,7 +73,7 @@ void Timer::KillTimeCallback(void *id) {
|
||||||
KillTimeCallbacks(id);
|
KillTimeCallbacks(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Timer::TimerProc(dword time)
|
void Timer::TimerProc(dword time, int & leftsleep)
|
||||||
{
|
{
|
||||||
if(IsPanicMode())
|
if(IsPanicMode())
|
||||||
return;
|
return;
|
||||||
|
|
@ -87,7 +87,7 @@ void Timer::TimerProc(dword time)
|
||||||
// sTimerLock.Leave();
|
// sTimerLock.Leave();
|
||||||
// //***
|
// //***
|
||||||
// sTimerLock.Enter();
|
// sTimerLock.Enter();
|
||||||
while(list->GetNext() != list && list->GetNext()->time < time) {
|
while(list->GetNext() != list && ((leftsleep = (list->GetNext()->time - time)) <= 0)) {
|
||||||
TimeEvent *e = list->GetNext();
|
TimeEvent *e = list->GetNext();
|
||||||
e->Unlink();
|
e->Unlink();
|
||||||
if(e->delay < 0)
|
if(e->delay < 0)
|
||||||
|
|
@ -98,6 +98,7 @@ void Timer::TimerProc(dword time)
|
||||||
delete e;
|
delete e;
|
||||||
}
|
}
|
||||||
sTimerLock.Leave();
|
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
|
//SAME API AS IN Ctrl
|
||||||
|
|
@ -145,9 +146,11 @@ void Timer::SetTimerGranularity(int ms)
|
||||||
|
|
||||||
void Timer::TimerThread()
|
void Timer::TimerThread()
|
||||||
{
|
{
|
||||||
|
int leftsleep;
|
||||||
while(run)
|
while(run)
|
||||||
{
|
{
|
||||||
TimerProc(GetTickCount());
|
leftsleep = granularity;
|
||||||
Sleep(granularity); //granularity
|
TimerProc(GetTickCount(), leftsleep);
|
||||||
|
Sleep(min(granularity, leftsleep));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -39,7 +39,7 @@ private:
|
||||||
void KillTimeCallbacks(void *id, void *idlim);
|
void KillTimeCallbacks(void *id, void *idlim);
|
||||||
bool ExistsTimeCallback(void *id);
|
bool ExistsTimeCallback(void *id);
|
||||||
void KillTimeCallback(void *id);
|
void KillTimeCallback(void *id);
|
||||||
void TimerProc(dword time);
|
void TimerProc(dword time, int & leftsleep);
|
||||||
|
|
||||||
void KillTimeCallbacks(void *id);
|
void KillTimeCallbacks(void *id);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
and the timer queue can check whether time has come for the next
|
||||||
task.]&]
|
task.]&]
|
||||||
[s0;2 &]
|
[s0;2 &]
|
||||||
[s0;i150;O0; [2 Because of it, the timing is not as accurate as maybe
|
[s0;i150;O0; [2 Thus, the timing is not as accurate as maybe desired
|
||||||
desired and can have `"timer glitches/jitter`", depending on
|
and can have `"timer glitches/jitter`", depending on work load..]&]
|
||||||
work load..]&]
|
|
||||||
[s0;2 &]
|
[s0;2 &]
|
||||||
[s0;i150;O0; [2 Favorite use is to schedule some `*non`*`-timing`-critical
|
[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;2 &]
|
||||||
[s0;i150;O0; [2 For timing critical stuff, consider using OS native
|
[s0;i150;O0; [2 For timing critical stuff, consider using OS native
|
||||||
timer means, for WIN32 SetTimer (in windowing environment, using
|
timer means, for WIN32 SetTimer (in windowing environment, using
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,16 @@ class TimerTest : public WithLayout<TopWindow> {
|
||||||
public:
|
public:
|
||||||
typedef TimerTest CLASSNAME;
|
typedef TimerTest CLASSNAME;
|
||||||
TimerTest();
|
TimerTest();
|
||||||
|
~TimerTest();
|
||||||
|
|
||||||
|
void Close0();
|
||||||
|
virtual void Close();
|
||||||
|
|
||||||
void Info(const String & s);
|
void Info(const String & s);
|
||||||
void Test();
|
void Test();
|
||||||
private:
|
private:
|
||||||
Timer t;
|
Timer t;
|
||||||
|
Atomic demo;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
description "Test for Timer package\377";
|
||||||
|
|
||||||
uses
|
uses
|
||||||
CtrlLib,
|
CtrlLib,
|
||||||
Timer;
|
Timer;
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,17 @@
|
||||||
#define REPEAT_TEST
|
#define REPEAT_TEST
|
||||||
|
|
||||||
TimerTest::TimerTest()
|
TimerTest::TimerTest()
|
||||||
|
: demo(0)
|
||||||
{
|
{
|
||||||
CtrlLayout(*this, "Window title");
|
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
|
#ifdef REPEAT_TEST
|
||||||
t.SetTimeCallback(-1000, THISBACK(Test), 0);
|
t.SetTimeCallback(-100, THISBACK(Test), (int)this);
|
||||||
#else
|
#else
|
||||||
PostCallback(THISBACK(Test));
|
t.SetTimeCallback(0, THISBACK(Test), (int)this);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -20,13 +25,41 @@ void TimerTest::Info(const String & s)
|
||||||
|
|
||||||
void TimerTest::Test()
|
void TimerTest::Test()
|
||||||
{
|
{
|
||||||
|
int a = AtomicInc(demo);
|
||||||
|
ASSERT(a==2);
|
||||||
|
|
||||||
Info("O");
|
Info("O");
|
||||||
|
RLOG("O");
|
||||||
|
|
||||||
|
a = AtomicDec(demo);
|
||||||
|
if(a<=0)
|
||||||
|
return;
|
||||||
|
ASSERT(a>=0);
|
||||||
|
|
||||||
#ifdef REPEAT_TEST
|
#ifdef REPEAT_TEST
|
||||||
#else
|
#else
|
||||||
t.SetTimeCallback(1000, THISBACK(Test), 0);
|
t.SetTimeCallback(100, THISBACK(Test), (int)this);
|
||||||
#endif
|
#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
|
GUI_APP_MAIN
|
||||||
{
|
{
|
||||||
TimerTest().Run();
|
TimerTest().Run();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue