sl@0: // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32\euser\cbase\ub_dtim.cpp sl@0: // sl@0: // sl@0: sl@0: #include "ub_std.h" sl@0: sl@0: /** sl@0: Creates a new timed event queue with the specified active object priority. sl@0: sl@0: @param aPriority The priority of this active object. sl@0: sl@0: @return On successful return, a pointer to the queue of timed events. sl@0: sl@0: @publishedAll sl@0: @released sl@0: */ sl@0: EXPORT_C CDeltaTimer* CDeltaTimer::NewL(TInt aPriority) sl@0: { sl@0: TTimeIntervalMicroSeconds32 tickPeriod; sl@0: UserHal::TickPeriod(tickPeriod); sl@0: sl@0: CDeltaTimer* timer = new(ELeave) CDeltaTimer(aPriority, tickPeriod.Int()); sl@0: sl@0: TInt err = timer->iTimer.CreateLocal(); sl@0: sl@0: if (err) sl@0: { sl@0: delete timer; sl@0: User::Leave(err); sl@0: } sl@0: sl@0: CActiveScheduler::Add(timer); sl@0: sl@0: return timer; sl@0: } sl@0: sl@0: /** sl@0: Creates a new timed event queue with the specified active object priority, and sl@0: the specified timer granularity. sl@0: sl@0: @param aPriority The priority of this active object. sl@0: @param aGranularity Ignored. The resolution of the timer is the tick period. sl@0: sl@0: @return On successful return, a pointer to the queue of timed events. sl@0: sl@0: @publishedAll sl@0: @deprecated sl@0: */ sl@0: EXPORT_C CDeltaTimer* CDeltaTimer::NewL(TInt aPriority, TTimeIntervalMicroSeconds32 /*aGranularity*/) sl@0: { sl@0: return CDeltaTimer::NewL(aPriority); sl@0: } sl@0: sl@0: /** sl@0: Constructor taking an active object priority value. sl@0: sl@0: The constructor sets this active object's priority value through a call to sl@0: the base class constructor in its c'tor list. sl@0: sl@0: @param aPriority The priority of this active object. sl@0: @param aTickPeriod The period of a tick on the system. sl@0: sl@0: @internalComponent sl@0: @released sl@0: */ sl@0: CDeltaTimer::CDeltaTimer(TInt aPriority, TInt aTickPeriod) sl@0: : CActive(aPriority), iTickPeriod(aTickPeriod) sl@0: { sl@0: } sl@0: sl@0: /** sl@0: Adds a new timed event entry into the timed event queue. sl@0: sl@0: @param aTimeInMicroSeconds The interval from the present time when the timed sl@0: event entry is to expire. sl@0: @param aEntry The timed event entry encapsulating the call back that sl@0: is to be called when this timed event entry expires. sl@0: sl@0: @publishedAll sl@0: @released sl@0: */ sl@0: EXPORT_C void CDeltaTimer::Queue(TTimeIntervalMicroSeconds32 aTimeInMicroSeconds, TDeltaTimerEntry& aEntry) sl@0: { sl@0: QueueLong(TTimeIntervalMicroSeconds(MAKE_TINT64(0, aTimeInMicroSeconds.Int())), aEntry); sl@0: } sl@0: sl@0: /** sl@0: Adds a new timed event entry into the timed event queue. sl@0: sl@0: @param aTimeInMicroSeconds The interval from the present time when the timed sl@0: event entry is to expire. sl@0: @param aEntry The timed event entry encapsulating the call back that sl@0: is to be called when this timed event entry expires. sl@0: sl@0: @return KErrNone if sucessful, KErrOverflow if the interval is too great or negative. sl@0: sl@0: @publishedAll sl@0: @released sl@0: */ sl@0: EXPORT_C TInt CDeltaTimer::QueueLong(TTimeIntervalMicroSeconds aTimeInMicroSeconds, TDeltaTimerEntry& aEntry) sl@0: { sl@0: const TInt64 timeInTicks = (aTimeInMicroSeconds.Int64() + iTickPeriod - 1) / iTickPeriod; sl@0: sl@0: TInt timeInTicks32 = I64LOW(timeInTicks); sl@0: sl@0: // We are using deltas on tick values, hence using maximum signed number of ticks sl@0: if (I64HIGH(timeInTicks) || (timeInTicks32 < 0)) sl@0: { sl@0: return KErrOverflow; sl@0: } sl@0: sl@0: // Make sure we queue for at least one tick sl@0: if (timeInTicks32 == 0) sl@0: { sl@0: timeInTicks32 = 1; sl@0: } sl@0: sl@0: // Calculate tick count for new entry sl@0: aEntry.iLink.iTickCount = Exec::TickCount() + timeInTicks32; sl@0: sl@0: // Add this entry at the right spot sl@0: iQueue.Add(aEntry.iLink); sl@0: sl@0: // Queue the timer, re-queuing if we've added to the head of the queue sl@0: Activate(&aEntry.iLink == iQueue.First()); sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: /** sl@0: Issues a new RTimer request, if there is no outstanding request and the queue sl@0: is not empty. sl@0: sl@0: @internalComponent sl@0: @released sl@0: */ sl@0: void CDeltaTimer::Activate(TBool aRequeueTimer) sl@0: // sl@0: // Queue a request on the timer. sl@0: // sl@0: { sl@0: if (IsActive()) sl@0: { sl@0: if (aRequeueTimer) sl@0: { sl@0: Cancel(); sl@0: } sl@0: else sl@0: { sl@0: return; sl@0: } sl@0: } sl@0: sl@0: if (!iQueue.IsEmpty() && !iQueueBusy) sl@0: { sl@0: SetActive(); sl@0: sl@0: const TInt ticksToWait = iQueue.First()->iTickCount - Exec::TickCount(); sl@0: sl@0: if (ticksToWait > 0) sl@0: { sl@0: iTimer.AfterTicks(iStatus, ticksToWait); sl@0: } sl@0: else sl@0: { sl@0: TRequestStatus* status = &iStatus; sl@0: User::RequestComplete(status, KErrNone); sl@0: } sl@0: } sl@0: } sl@0: sl@0: /** sl@0: Deals with an RTimer completion event. sl@0: sl@0: The function inspects the timed event entry at the head of the queue, and sl@0: reduces its timer value by the appropriate amount. If this timed event is sl@0: now found to have expired, the call back function is called, and the timed sl@0: event entry removed from the queue. sl@0: sl@0: If the timed event entry has not expired, it remains at the head of the queue. sl@0: sl@0: The function issues a new RTimer request, using the timer granularity value sl@0: as the time interval. sl@0: sl@0: @see RTimer sl@0: @see CActive sl@0: sl@0: @internalComponent sl@0: @released sl@0: */ sl@0: void CDeltaTimer::RunL() sl@0: // sl@0: // Call all zero delta callbacks sl@0: { sl@0: // Queue busy sl@0: iQueueBusy = ETrue; sl@0: sl@0: // Whilst the list of expired timers is being processed, time will pass and sl@0: // the tick count may have increased such that there are now more expired sl@0: // timers. Loop until we have either emptied the queue or can wait for a sl@0: // timer exipration in the future. sl@0: while (!iQueue.IsEmpty()) sl@0: { sl@0: // Calculate how long till first timer expires sl@0: const TUint tickCount = Exec::TickCount(); sl@0: sl@0: // If the first timer is yet to expire, wait some more sl@0: if (((TInt)(iQueue.First()->iTickCount - tickCount)) > 0) sl@0: { sl@0: break; sl@0: } sl@0: sl@0: // Remove entry before callback to prevent re-entrancy issues sl@0: TTickCountQueLink* entry = iQueue.RemoveFirst(); sl@0: sl@0: // Iterate through the timers we know have expired based on the sl@0: // last calculation of delta sl@0: while (entry) sl@0: { sl@0: // Make callback. This could go reentrant on Queue[Long]() or Remove(). sl@0: reinterpret_cast( sl@0: PtrSub( sl@0: entry, sl@0: _FOFF(TDeltaTimerEntry, iLink) sl@0: )) sl@0: ->iCallBack.CallBack(); sl@0: sl@0: // Remove the next expired entry, if any sl@0: entry = iQueue.RemoveFirst(tickCount); sl@0: } sl@0: } sl@0: sl@0: // Queue idle sl@0: iQueueBusy = EFalse; sl@0: sl@0: // Requeue timer sl@0: Activate(); sl@0: } sl@0: sl@0: /** sl@0: Implements cancellation of an oustanding RTimer request. sl@0: sl@0: @internalComponent sl@0: @released sl@0: */ sl@0: void CDeltaTimer::DoCancel() sl@0: { sl@0: iTimer.Cancel(); sl@0: } sl@0: sl@0: /** sl@0: Removes the specified timed event entry from the timer queue. sl@0: sl@0: @param aEntry The timed event entry. sl@0: sl@0: @publishedAll sl@0: @released sl@0: */ sl@0: EXPORT_C void CDeltaTimer::Remove(TDeltaTimerEntry& aEntry) sl@0: { sl@0: // Remove the specified entry from the list sl@0: aEntry.iLink.Deque(); sl@0: } sl@0: sl@0: /** sl@0: Destructor. sl@0: sl@0: Frees all resources before destruction of the object. Specifically, it cancels sl@0: any outstanding timer requests generated by the RTimer object and then deletes sl@0: all timed event entries from the timed event queue. sl@0: sl@0: @see RTimer sl@0: sl@0: @publishedAll sl@0: @released sl@0: */ sl@0: CDeltaTimer::~CDeltaTimer() sl@0: { sl@0: Cancel(); sl@0: sl@0: while (!iQueue.IsEmpty()) sl@0: { sl@0: iQueue.First()->Deque(); sl@0: } sl@0: sl@0: iTimer.Close(); sl@0: }