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