diff -r f345bda72bc4 -r 43e37759235e Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/_periodic_8cpp_source.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/_periodic_8cpp_source.html Tue Mar 30 16:16:55 2010 +0100 @@ -0,0 +1,418 @@ + + + + +TB9.2 Example Applications: examples/Base/Timers/Periodic/Periodic.cpp Source File + + + + + +

examples/Base/Timers/Periodic/Periodic.cpp

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 
+
+
Generated by  + +doxygen 1.6.2
+ +