kernel/eka/euser/cbase/ub_dtim.cpp
changeset 9 96e5fb8b040d
equal deleted inserted replaced
-1:000000000000 9:96e5fb8b040d
       
     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 	}