os/kernelhwsrv/kernel/eka/euser/cbase/ub_dtim.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of the License "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 // e32\euser\cbase\ub_dtim.cpp
    15 // 
    16 //
    17 
    18 #include "ub_std.h"
    19 
    20 /**
    21 Creates a new timed event queue with the specified active object priority.
    22 
    23 @param aPriority The priority of this active object.
    24 
    25 @return On successful return, a pointer to the queue of timed events.
    26 
    27 @publishedAll
    28 @released
    29 */
    30 EXPORT_C CDeltaTimer* CDeltaTimer::NewL(TInt aPriority)
    31 	{
    32 	TTimeIntervalMicroSeconds32 tickPeriod;
    33 	UserHal::TickPeriod(tickPeriod);
    34 
    35 	CDeltaTimer* timer = new(ELeave) CDeltaTimer(aPriority, tickPeriod.Int());
    36 
    37 	TInt err = timer->iTimer.CreateLocal();
    38 
    39 	if (err)
    40 		{
    41 		delete timer;
    42 		User::Leave(err);
    43 		}
    44 
    45 	CActiveScheduler::Add(timer);
    46 
    47 	return timer;
    48 	}
    49 
    50 /**
    51 Creates a new timed event queue with the specified active object priority, and 
    52 the specified timer granularity.
    53 
    54 @param aPriority    The priority of this active object.
    55 @param aGranularity Ignored.  The resolution of the timer is the tick period.
    56 
    57 @return On successful return, a pointer to the queue of timed events.
    58 
    59 @publishedAll
    60 @deprecated
    61 */
    62 EXPORT_C CDeltaTimer* CDeltaTimer::NewL(TInt aPriority, TTimeIntervalMicroSeconds32 /*aGranularity*/)
    63 	{
    64 	return CDeltaTimer::NewL(aPriority);
    65 	}
    66 
    67 /**
    68 Constructor taking an active object priority value.
    69 
    70 The constructor sets this active object's priority value through a call to 
    71 the base class constructor in its c'tor list.
    72 
    73 @param aPriority    The priority of this active object.
    74 @param aTickPeriod  The period of a tick on the system.
    75 
    76 @internalComponent
    77 @released
    78 */
    79 CDeltaTimer::CDeltaTimer(TInt aPriority, TInt aTickPeriod)
    80 	: CActive(aPriority), iTickPeriod(aTickPeriod)
    81 	{
    82 	}
    83 
    84 /**
    85 Adds a new timed event entry into the timed event queue.
    86 	
    87 @param aTimeInMicroSeconds The interval from the present time when the timed 
    88 	                       event entry is to expire.
    89 @param aEntry              The timed event entry encapsulating the call back that
    90                            is to be called when this timed event entry expires.
    91 
    92 @publishedAll
    93 @released
    94 */
    95 EXPORT_C void CDeltaTimer::Queue(TTimeIntervalMicroSeconds32 aTimeInMicroSeconds, TDeltaTimerEntry& aEntry)
    96 	{
    97 	QueueLong(TTimeIntervalMicroSeconds(MAKE_TINT64(0, aTimeInMicroSeconds.Int())), aEntry);
    98 	}
    99 
   100 /**
   101 Adds a new timed event entry into the timed event queue.
   102 	
   103 @param aTimeInMicroSeconds The interval from the present time when the timed 
   104 	                       event entry is to expire.
   105 @param aEntry              The timed event entry encapsulating the call back that
   106                            is to be called when this timed event entry expires.
   107 
   108 @return KErrNone if sucessful, KErrOverflow if the interval is too great or negative.
   109 
   110 @publishedAll
   111 @released
   112 */
   113 EXPORT_C TInt CDeltaTimer::QueueLong(TTimeIntervalMicroSeconds aTimeInMicroSeconds, TDeltaTimerEntry& aEntry)
   114 	{
   115 	const TInt64 timeInTicks = (aTimeInMicroSeconds.Int64() + iTickPeriod - 1) / iTickPeriod;
   116 
   117 	TInt timeInTicks32 = I64LOW(timeInTicks);
   118 
   119 	// We are using deltas on tick values, hence using maximum signed number of ticks
   120 	if (I64HIGH(timeInTicks) || (timeInTicks32 < 0))
   121 		{
   122 		return KErrOverflow;
   123 		}
   124 
   125 	// Make sure we queue for at least one tick
   126 	if (timeInTicks32 == 0)
   127 		{
   128 		timeInTicks32 = 1;
   129 		}
   130 	
   131 	// Calculate tick count for new entry
   132 	aEntry.iLink.iTickCount = Exec::TickCount() + timeInTicks32;
   133 
   134 	// Add this entry at the right spot
   135 	iQueue.Add(aEntry.iLink);
   136 
   137 	// Queue the timer, re-queuing if we've added to the head of the queue
   138 	Activate(&aEntry.iLink == iQueue.First());
   139 	
   140 	return KErrNone;
   141 	}
   142 
   143 /**
   144 Issues a new RTimer request, if there is no outstanding request and the queue 
   145 is not empty.
   146 
   147 @internalComponent
   148 @released
   149 */
   150 void CDeltaTimer::Activate(TBool aRequeueTimer)
   151 //
   152 // Queue a request on the timer.
   153 //
   154 	{
   155 	if (IsActive())
   156 		{
   157 		if (aRequeueTimer)
   158 			{
   159 			Cancel();
   160 			}
   161 		else
   162 			{
   163 			return;
   164 			}		
   165 		}
   166 
   167 	if (!iQueue.IsEmpty() && !iQueueBusy)
   168 		{
   169 		SetActive();
   170 
   171 		const TInt ticksToWait = iQueue.First()->iTickCount - Exec::TickCount();
   172 
   173 		if (ticksToWait > 0)
   174 			{
   175 			iTimer.AfterTicks(iStatus, ticksToWait);
   176 			}
   177 		else
   178 			{
   179 			TRequestStatus* status = &iStatus;
   180 			User::RequestComplete(status, KErrNone);
   181 			}
   182 		}
   183 	}
   184 
   185 /**
   186 Deals with an RTimer completion event.
   187 
   188 The function inspects the timed event entry at the head of the queue, and 
   189 reduces its timer value by the appropriate amount. If this timed event is 
   190 now found to have expired, the call back function is called, and the timed 
   191 event entry removed from the queue.
   192 
   193 If the timed event entry has not expired, it remains at the head of the queue.
   194 
   195 The function issues a new RTimer request, using the timer granularity value 
   196 as the time interval.
   197 
   198 @see RTimer
   199 @see CActive
   200 
   201 @internalComponent
   202 @released
   203 */
   204 void CDeltaTimer::RunL()
   205 //
   206 // Call all zero delta callbacks
   207 	{
   208 	// Queue busy
   209 	iQueueBusy = ETrue;
   210 
   211 	// Whilst the list of expired timers is being processed, time will pass and
   212 	// the tick count may have increased such that there are now more expired
   213 	// timers.  Loop until we have either emptied the queue or can wait for a
   214 	// timer exipration in the future.
   215 	while (!iQueue.IsEmpty())
   216 		{
   217 		// Calculate how long till first timer expires
   218 		const TUint tickCount = Exec::TickCount();
   219 
   220 		// If the first timer is yet to expire, wait some more
   221 		if (((TInt)(iQueue.First()->iTickCount - tickCount)) > 0)
   222 			{
   223 			break;
   224 			}
   225 
   226 		// Remove entry before callback to prevent re-entrancy issues
   227 		TTickCountQueLink* entry = iQueue.RemoveFirst();
   228 
   229 		// Iterate through the timers we know have expired based on the
   230 		// last calculation of delta
   231 		while (entry)
   232 			{
   233 			// Make callback.  This could go reentrant on Queue[Long]() or Remove().
   234 			reinterpret_cast<TDeltaTimerEntry*>(
   235 				PtrSub(
   236 					entry,
   237 					_FOFF(TDeltaTimerEntry, iLink)
   238 				))
   239 			->iCallBack.CallBack();
   240 
   241 			// Remove the next expired entry, if any
   242 			entry = iQueue.RemoveFirst(tickCount);
   243 			}
   244 		}
   245 
   246 	// Queue idle
   247 	iQueueBusy = EFalse;
   248 
   249 	// Requeue timer
   250 	Activate();
   251 	}
   252 	
   253 /**
   254 Implements cancellation of an oustanding RTimer request.
   255 
   256 @internalComponent
   257 @released
   258 */
   259 void CDeltaTimer::DoCancel()
   260 	{
   261 	iTimer.Cancel();
   262 	}
   263 
   264 /**
   265 Removes the specified timed event entry from the timer queue.
   266 
   267 @param aEntry The timed event entry.
   268 
   269 @publishedAll
   270 @released
   271 */
   272 EXPORT_C void CDeltaTimer::Remove(TDeltaTimerEntry& aEntry)
   273 	{
   274 	// Remove the specified entry from the list
   275 	aEntry.iLink.Deque();
   276 	}
   277 
   278 /**
   279 Destructor.
   280 
   281 Frees all resources before destruction of the object. Specifically, it cancels 
   282 any outstanding timer requests generated by the RTimer object and then deletes 
   283 all timed event entries from the timed event queue.
   284 
   285 @see RTimer
   286 
   287 @publishedAll
   288 @released
   289 */
   290 CDeltaTimer::~CDeltaTimer()
   291 	{
   292 	Cancel();
   293 
   294 	while (!iQueue.IsEmpty())
   295 		{
   296 		iQueue.First()->Deque();
   297 		}
   298 
   299 	iTimer.Close();
   300 	}