kernel/eka/euser/cbase/ub_dtim.cpp
changeset 0 a41df078684a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kernel/eka/euser/cbase/ub_dtim.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -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<TDeltaTimerEntry*>(
+				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();
+	}