diff -r f345bda72bc4 -r 43e37759235e Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/_periodic_8cpp-source.html --- a/Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/_periodic_8cpp-source.html Tue Mar 30 11:56:28 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,414 +0,0 @@ - -
-00001 // Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies). -00002 // All rights reserved. -00003 // This component and the accompanying materials are made available -00004 // under the terms of "Eclipse Public License v1.0" -00005 // which accompanies this distribution, and is available -00006 // at the URL "http://www.eclipse.org/legal/epl-v10.html". -00007 // -00008 // Initial Contributors: -00009 // Nokia Corporation - initial contribution. -00010 // -00011 // Contributors: -00012 // -00013 // Description: -00014 // Shows difference between CPeriodic and CHeartBeat -00015 // CPeriodic uses repeated RTimer::After() requests to get -00016 // a periodic tick - simple, but the time the tick is serviced lags -00017 // increasingly. -00018 // As a nuance of CPeriodic, it takes a TCallBack to service -00019 // its requests. -00020 // CHeartbeat uses repeated RTimer::Lock() requests: its -00021 // requests complete in synchronization with the beating -00022 // of the system clock. -00023 // As a nuance of CHeartbeat, it takes an MBeating* mixin: -00024 // the MBeating's Beat() function is called when completion -00025 // occurs in sync, and Synchronize() is called when -00026 // synchronization has been lost. -00027 // -00028 -00029 -00030 -00031 // standard example header -00032 #include "CommonFramework.h" -00033 -00034 // beginning of real example -00035 -00036 #include <e32math.h> -00037 -00038 void RandomDelay(TInt64& aSeed, TInt /*aTimerNumber*/) -00039 { -00040 // initialize seed first time through -00041 if (aSeed==0) -00042 { -00043 TTime time; -00044 time.HomeTime(); -00045 aSeed=time.Int64(); -00046 } -00047 // ok, here we go -00048 TReal randomZeroToOne; -00049 randomZeroToOne = Math::FRand(aSeed); -00050 TReal realDelay; -00051 realDelay = randomZeroToOne * randomZeroToOne * 2000000; -00052 TInt32 intDelay; -00053 Math::Int(intDelay, realDelay); -00054 TTimeIntervalMicroSeconds32 delayMicroSeconds; -00055 delayMicroSeconds=intDelay; -00056 User::After(delayMicroSeconds); -00057 } -00058 -00059 // A version of the RandomDelay function which is not random ! -00060 // The delay is fixed at 1000000us and may be useful to -00061 // experiment with. -00062 // -00063 // -00064 //void RandomDelay(TInt64& /* aSeed */, TInt aTimerNumber) -00065 // { -00066 // User::After(1000000); -00067 // _LIT(KFormatMisc,"Delay for timer %d: 1000000us\n"); -00068 // console->Printf(KFormatMisc, aTimerNumber); -00069 // } -00070 -00071 -00072 class TAppRunner -00073 { -00074 public: -00075 TAppRunner(); -00076 void NotifyFinished(); // notify an active object has finished -00077 void NotifyStarted(); // notify an active object has started -00078 // private: -00079 TInt iActiveObjects; // count of active objects -00080 }; -00081 -00082 TAppRunner::TAppRunner() -00083 { -00084 iActiveObjects=0; -00085 } -00086 -00087 void TAppRunner::NotifyStarted() -00088 { -00089 iActiveObjects++; -00090 } -00091 -00092 void TAppRunner::NotifyFinished() -00093 { -00094 iActiveObjects--; -00095 if (iActiveObjects==0) CActiveScheduler::Stop(); -00096 } -00097 -00098 /* -00099 CPeriodicRunner class -00100 -00101 Constructor makes a CPeriodic and sets it off with one-second ticks. -00102 These are fielded by the callback function, the static Tick(TAny*), -00103 which simply casts the pointer to a CPeriodicRunner* and calls -00104 the non-static callback, DoTick(). -00105 -00106 Processing gets behind: when the ticks left have counted down to zero, -00107 it should be behind by a second or two. The destructor indicates how many -00108 seconds since the object's creation. -00109 */ -00110 -00111 class CPeriodicRunner : public CBase -00112 { -00113 public: -00114 // construct, add CPeriodic to active scheduler, and start it -00115 static CPeriodicRunner* NewL(TInt aTickInterval, TInt aTotalTicks, TAppRunner& aAppRunner); -00116 ~CPeriodicRunner(); // destruct and give statistics -00117 protected: -00118 CPeriodicRunner(TInt aTickInterval, TInt aTotalTicks, TAppRunner& aAppRunner); -00119 private: -00120 void ConstructL(); // second construction phase -00121 // functions for TCallBack protocol -00122 static TInt Tick(TAny* aObject); // directly called -00123 void DoTick(); // indirectly called -00124 private: -00125 // constructor parameters -00126 TAppRunner& iAppRunner; // notify when started and finished -00127 TInt iTotalTicks; // total number of ticks requested -00128 TInt iTickInterval; // the tick interval in microseconds -00129 -00130 // things set up by ConstructL() -00131 TTime iStartTime; // when we were started -00132 CPeriodic* iPeriodic; // periodic timer active object -00133 -00134 // remaining ticks will be decremented as we go -00135 TInt iTicksLeft; // number of ticks before we expire -00136 TInt iTimerNumber; // indentifying number for the timer -00137 -00138 // seed for random delay generator -00139 TInt64 iDelaySeed; -00140 }; -00141 -00142 // protected C++ constructor -00143 CPeriodicRunner::CPeriodicRunner(TInt aTickInterval, TInt aTotalTicks, TAppRunner& aAppRunner) -00144 : iAppRunner(aAppRunner), iTotalTicks(aTotalTicks), iTickInterval(aTickInterval) -00145 {} -00146 -00147 // private second-phase constructor -00148 void CPeriodicRunner::ConstructL() -00149 { -00150 iStartTime.HomeTime(); -00151 iPeriodic =CPeriodic::NewL(0); // neutral priority -00152 iAppRunner.NotifyStarted(); -00153 iTimerNumber = iAppRunner.iActiveObjects; // set idenfifying number for timer -00154 iTicksLeft = iTotalTicks; -00155 // variable (actually 1 second) delay and interval -00156 iPeriodic->Start(iTickInterval,iTickInterval,TCallBack(Tick, this)); -00157 } -00158 -00159 // construct, add CPeriodic to active scheduler, and start it -00160 CPeriodicRunner* CPeriodicRunner::NewL(TInt aTickInterval, TInt aTotalTicks, TAppRunner& aAppRunner) -00161 { -00162 CPeriodicRunner* self=new (ELeave) CPeriodicRunner(aTickInterval, aTotalTicks, aAppRunner); -00163 CleanupStack::PushL(self); -00164 self->ConstructL(); -00165 CleanupStack::Pop(); -00166 return self; -00167 } -00168 -00169 // destruct and give statistics -00170 CPeriodicRunner::~CPeriodicRunner() -00171 { -00172 TTimeIntervalMicroSeconds elapsedTime; -00173 TTime currentTime; -00174 // set current time -00175 currentTime.HomeTime(); // set currentTime to now -00176 // find and show elapsed time & ticks -00177 elapsedTime = currentTime.MicroSecondsFrom(iStartTime); -00178 -00179 _LIT(KFormat1,"Periodic timer %d finished after: %Ld microseconds for %d %dus ticks\n"); -00180 console->Printf(KFormat1,iTimerNumber,elapsedTime.Int64(),iTotalTicks,iTickInterval); -00181 -00182 -00183 -00184 // cancel any outstanding request; delete owned CPeriodic object -00185 iPeriodic->Cancel(); -00186 delete iPeriodic; -00187 // tell app runner we've finished (if we're last, scheduler will stop) -00188 iAppRunner.NotifyFinished(); -00189 } -00190 -00191 // private -00192 TInt CPeriodicRunner::Tick(TAny* aObject) -00193 { -00194 ((CPeriodicRunner*)aObject)->DoTick(); // cast, and call non-static function -00195 return 1; -00196 } -00197 -00198 // private -00199 void CPeriodicRunner::DoTick() -00200 { -00201 iTicksLeft--; -00202 _LIT(KFormat2,"Periodic timer %d: %d ticks done\n"); -00203 console->Printf(KFormat2, iTimerNumber, iTotalTicks - iTicksLeft); -00204 if(iTicksLeft==0) -00205 { -00206 delete this; -00207 } -00208 RandomDelay(iDelaySeed,iTimerNumber); // a random delay to mess up the timing -00209 } -00210 -00211 /* -00212 CHeartbeatRunner class -00213 -00214 This class receives beats in sync with the system clock. It also has a much -00215 nicer interface than for periodic timers - the MBeating mixin, which is nicely -00216 object-oriented. -00217 -00218 Most of the time, the Beat() function is called which trivially updates the tick -00219 count. Occasionally, synchronization is lost, and the Synchronize() function -00220 is called instead: this must find out from the system time how many ticks should -00221 have been counted, and update things accordingly. -00222 -00223 The destructor gives the same comparisons as the CPeriodic's. The discrepancy -00224 between the number of ticks and the number of seconds since construction should -00225 never be more than is accounted for by the last heartbeat. -00226 */ -00227 -00228 class CHeartbeatRunner : public CBase, public MBeating -00229 { -00230 public: -00231 // construct, add CHeartbeat to active scheduler, and start it -00232 static CHeartbeatRunner* NewL(TInt aTickInterval, TInt aTotalTicks, TAppRunner& aAppRunner); -00233 ~CHeartbeatRunner(); // destruct and give statistics -00234 protected: -00235 CHeartbeatRunner(TInt aTickInterval, TInt aTotalTicks, TAppRunner& aAppRunner); -00236 private: -00237 void ConstructL(); -00238 // functions for MBeating protocol -00239 void Beat(); // called when beat works ok -00240 void Synchronize(); // called when we need to synchronize -00241 private: -00242 // constructor parameters -00243 TAppRunner& iAppRunner; // notify when started and finished -00244 TInt iTotalTicks; // number of ticks requested -00245 TInt iTickInterval; // tick length in microseconds -00246 // things set up by ConstructL -00247 TTime iStartTime; // when we were started -00248 CHeartbeat* iHeartbeat; // heartbeat active object -00249 // ticks left decrements as we go -00250 TInt iTicksLeft; // number of ticks before we expire -00251 TInt iTimerNumber; // indentifying number for the timer -00252 // seed for random delay generator -00253 TInt64 iDelaySeed; -00254 }; -00255 -00256 // protected C++ constructor -00257 CHeartbeatRunner::CHeartbeatRunner(TInt aTickInterval, TInt aTotalTicks, TAppRunner& aAppRunner) -00258 :iAppRunner(aAppRunner), iTotalTicks(aTotalTicks), iTickInterval(aTickInterval) -00259 {} -00260 -00261 // private second-phase constructor -00262 void CHeartbeatRunner::ConstructL() -00263 { -00264 iStartTime.HomeTime(); -00265 iHeartbeat=CHeartbeat::NewL(0); // neutral priority -00266 iAppRunner.NotifyStarted(); -00267 iTimerNumber = iAppRunner.iActiveObjects; // set idenfifying number for timer -00268 iTicksLeft = iTotalTicks; -00269 // start the heartbeat timer, beating exactly on the second -00270 iHeartbeat->Start(ETwelveOClock,this); -00271 } -00272 -00273 // construct, add CHeartbeat to active scheduler, and start it -00274 CHeartbeatRunner* CHeartbeatRunner::NewL(TInt aTickInterval, TInt aTotalTicks, TAppRunner& aAppRunner) -00275 { -00276 CHeartbeatRunner* self=new (ELeave) CHeartbeatRunner(aTickInterval, aTotalTicks, aAppRunner); -00277 CleanupStack::PushL(self); -00278 self->ConstructL(); -00279 CleanupStack::Pop(); -00280 return self; -00281 } -00282 -00283 // destruct and give statistics -00284 CHeartbeatRunner::~CHeartbeatRunner() -00285 { -00286 TTimeIntervalMicroSeconds elapsedTime; -00287 TTime currentTime; -00288 currentTime.HomeTime(); // set current time to now -00289 // find and show elapsed time & ticks -00290 elapsedTime = currentTime.MicroSecondsFrom(iStartTime); -00291 -00292 _LIT(KFormat3,"Heartbeat timer %d finished after: %Ld microseonds for %d %dus ticks\n"); -00293 console->Printf(KFormat3,iTimerNumber,elapsedTime.Int64(),iTotalTicks,iTickInterval); -00294 -00295 // cancel any outstanding request; delete owned CPeriodic object -00296 iHeartbeat->Cancel(); -00297 delete iHeartbeat; -00298 // tell app runner we've finished (if last, scheduler will stop) -00299 iAppRunner.NotifyFinished(); -00300 } -00301 -00302 // private -00303 void CHeartbeatRunner::Beat() -00304 { -00305 iTicksLeft--; -00306 if(iTicksLeft<=0) -00307 delete this; -00308 else -00309 RandomDelay(iDelaySeed,iTimerNumber); // a random delay to mess up the timing -00310 } -00311 -00312 // private -00313 void CHeartbeatRunner::Synchronize() -00314 { -00315 TInt ticksMissed = 0; -00316 // what time in microseconds should be for this tick -00317 TTime desiredTime = iStartTime + TTimeIntervalMicroSeconds((iTotalTicks - iTicksLeft) * iTickInterval); -00318 TTime currentTime; // set current time to now -00319 currentTime.HomeTime(); -00320 TTimeIntervalMicroSeconds missedTime = currentTime.MicroSecondsFrom(desiredTime); -00321 // Calculate the ticks missed (quickly!) -00322 TInt64 missedTimeInt = missedTime.Int64(); // convert the missed time interval to an Int64 -00323 -00324 ticksMissed = (missedTimeInt / iTickInterval); -00325 //ticksMissed = (missedTimeInt / iTickInterval).GetTInt(); -00326 -00327 -00328 // The following loop increments the ticks missed by the same amount, but takes much longer -00329 // while (desiredTime < currentTime) -00330 // { -00331 // desiredTime = desiredTime - TTimeIntervalMicroSeconds(iTickInterval); -00332 // ticksMissed++; -00333 // } -00334 _LIT(KFormat4,"Ticks done %d\n"); -00335 console->Printf(KFormat4, (iTotalTicks -iTicksLeft)); -00336 -00337 iTicksLeft = iTicksLeft - ticksMissed; -00338 TTimeIntervalMicroSeconds elapsedTime; -00339 elapsedTime = currentTime.MicroSecondsFrom(iStartTime); // find and show elapsed time & ticks -00340 _LIT(KFormat5,"Elapsed time: %Ld microseconds\n"); -00341 console->Printf(KFormat5, elapsedTime.Int64()); -00342 -00343 _LIT(KFormat6,"Synchronize heartbeat timer %d: ticks missed %d: left %d: done now %d\n"); -00344 console->Printf(KFormat6, -00345 iTimerNumber, -00346 ticksMissed, -00347 iTicksLeft, -00348 ((iTotalTicks - iTicksLeft) <= iTotalTicks) ? iTotalTicks - iTicksLeft : iTotalTicks -00349 ); -00350 // iTicksLeft can be less than zero -00351 if(iTicksLeft<=0) -00352 { -00353 delete this; -00354 } -00355 } -00356 -00357 /* -00358 TAppRunner class -00359 -00360 Encapsulates logic for stopping the active scheduler -00361 */ -00362 -00363 -00364 // do the example -00365 -00366 void doExampleL() -00367 { -00368 // Make and install the active scheduler -00369 CActiveScheduler* scheduler = new (ELeave) CActiveScheduler; -00370 -00371 // Push onto clean-up stack -00372 CleanupStack::PushL(scheduler); -00373 -00374 // Install as active scheduler -00375 CActiveScheduler::Install(scheduler); -00376 -00377 // Controls the stopping of the scheduler -00378 TAppRunner appRunner; -00379 -00380 // Set the tick interval to 1 second. -00381 TInt TickInterval = 1000000; -00382 -00383 // run each kind of timer for increasing numbers of ticks -00384 // was 10/40/10 -00385 -00386 for (TInt total_ticks=4; total_ticks<=6; total_ticks+=2) -00387 { -00388 // Create periodic timer -00389 // -00390 // [nb Comment next line out if you just want to see heart beat runner] -00391 CPeriodicRunner::NewL(TickInterval, total_ticks, appRunner); -00392 -00393 // Create hearbeat -00394 // -00395 // [nb Comment next line out if you just want to see periodic timer] -00396 CHeartbeatRunner::NewL(TickInterval, total_ticks, appRunner); -00397 } -00398 -00399 CActiveScheduler::Start(); -00400 CleanupStack::PopAndDestroy(); // scheduler -00401 } -00402 -