1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kernel/eka/euser/cbase/ub_dtim.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,300 @@
1.4 +// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32\euser\cbase\ub_dtim.cpp
1.18 +//
1.19 +//
1.20 +
1.21 +#include "ub_std.h"
1.22 +
1.23 +/**
1.24 +Creates a new timed event queue with the specified active object priority.
1.25 +
1.26 +@param aPriority The priority of this active object.
1.27 +
1.28 +@return On successful return, a pointer to the queue of timed events.
1.29 +
1.30 +@publishedAll
1.31 +@released
1.32 +*/
1.33 +EXPORT_C CDeltaTimer* CDeltaTimer::NewL(TInt aPriority)
1.34 + {
1.35 + TTimeIntervalMicroSeconds32 tickPeriod;
1.36 + UserHal::TickPeriod(tickPeriod);
1.37 +
1.38 + CDeltaTimer* timer = new(ELeave) CDeltaTimer(aPriority, tickPeriod.Int());
1.39 +
1.40 + TInt err = timer->iTimer.CreateLocal();
1.41 +
1.42 + if (err)
1.43 + {
1.44 + delete timer;
1.45 + User::Leave(err);
1.46 + }
1.47 +
1.48 + CActiveScheduler::Add(timer);
1.49 +
1.50 + return timer;
1.51 + }
1.52 +
1.53 +/**
1.54 +Creates a new timed event queue with the specified active object priority, and
1.55 +the specified timer granularity.
1.56 +
1.57 +@param aPriority The priority of this active object.
1.58 +@param aGranularity Ignored. The resolution of the timer is the tick period.
1.59 +
1.60 +@return On successful return, a pointer to the queue of timed events.
1.61 +
1.62 +@publishedAll
1.63 +@deprecated
1.64 +*/
1.65 +EXPORT_C CDeltaTimer* CDeltaTimer::NewL(TInt aPriority, TTimeIntervalMicroSeconds32 /*aGranularity*/)
1.66 + {
1.67 + return CDeltaTimer::NewL(aPriority);
1.68 + }
1.69 +
1.70 +/**
1.71 +Constructor taking an active object priority value.
1.72 +
1.73 +The constructor sets this active object's priority value through a call to
1.74 +the base class constructor in its c'tor list.
1.75 +
1.76 +@param aPriority The priority of this active object.
1.77 +@param aTickPeriod The period of a tick on the system.
1.78 +
1.79 +@internalComponent
1.80 +@released
1.81 +*/
1.82 +CDeltaTimer::CDeltaTimer(TInt aPriority, TInt aTickPeriod)
1.83 + : CActive(aPriority), iTickPeriod(aTickPeriod)
1.84 + {
1.85 + }
1.86 +
1.87 +/**
1.88 +Adds a new timed event entry into the timed event queue.
1.89 +
1.90 +@param aTimeInMicroSeconds The interval from the present time when the timed
1.91 + event entry is to expire.
1.92 +@param aEntry The timed event entry encapsulating the call back that
1.93 + is to be called when this timed event entry expires.
1.94 +
1.95 +@publishedAll
1.96 +@released
1.97 +*/
1.98 +EXPORT_C void CDeltaTimer::Queue(TTimeIntervalMicroSeconds32 aTimeInMicroSeconds, TDeltaTimerEntry& aEntry)
1.99 + {
1.100 + QueueLong(TTimeIntervalMicroSeconds(MAKE_TINT64(0, aTimeInMicroSeconds.Int())), aEntry);
1.101 + }
1.102 +
1.103 +/**
1.104 +Adds a new timed event entry into the timed event queue.
1.105 +
1.106 +@param aTimeInMicroSeconds The interval from the present time when the timed
1.107 + event entry is to expire.
1.108 +@param aEntry The timed event entry encapsulating the call back that
1.109 + is to be called when this timed event entry expires.
1.110 +
1.111 +@return KErrNone if sucessful, KErrOverflow if the interval is too great or negative.
1.112 +
1.113 +@publishedAll
1.114 +@released
1.115 +*/
1.116 +EXPORT_C TInt CDeltaTimer::QueueLong(TTimeIntervalMicroSeconds aTimeInMicroSeconds, TDeltaTimerEntry& aEntry)
1.117 + {
1.118 + const TInt64 timeInTicks = (aTimeInMicroSeconds.Int64() + iTickPeriod - 1) / iTickPeriod;
1.119 +
1.120 + TInt timeInTicks32 = I64LOW(timeInTicks);
1.121 +
1.122 + // We are using deltas on tick values, hence using maximum signed number of ticks
1.123 + if (I64HIGH(timeInTicks) || (timeInTicks32 < 0))
1.124 + {
1.125 + return KErrOverflow;
1.126 + }
1.127 +
1.128 + // Make sure we queue for at least one tick
1.129 + if (timeInTicks32 == 0)
1.130 + {
1.131 + timeInTicks32 = 1;
1.132 + }
1.133 +
1.134 + // Calculate tick count for new entry
1.135 + aEntry.iLink.iTickCount = Exec::TickCount() + timeInTicks32;
1.136 +
1.137 + // Add this entry at the right spot
1.138 + iQueue.Add(aEntry.iLink);
1.139 +
1.140 + // Queue the timer, re-queuing if we've added to the head of the queue
1.141 + Activate(&aEntry.iLink == iQueue.First());
1.142 +
1.143 + return KErrNone;
1.144 + }
1.145 +
1.146 +/**
1.147 +Issues a new RTimer request, if there is no outstanding request and the queue
1.148 +is not empty.
1.149 +
1.150 +@internalComponent
1.151 +@released
1.152 +*/
1.153 +void CDeltaTimer::Activate(TBool aRequeueTimer)
1.154 +//
1.155 +// Queue a request on the timer.
1.156 +//
1.157 + {
1.158 + if (IsActive())
1.159 + {
1.160 + if (aRequeueTimer)
1.161 + {
1.162 + Cancel();
1.163 + }
1.164 + else
1.165 + {
1.166 + return;
1.167 + }
1.168 + }
1.169 +
1.170 + if (!iQueue.IsEmpty() && !iQueueBusy)
1.171 + {
1.172 + SetActive();
1.173 +
1.174 + const TInt ticksToWait = iQueue.First()->iTickCount - Exec::TickCount();
1.175 +
1.176 + if (ticksToWait > 0)
1.177 + {
1.178 + iTimer.AfterTicks(iStatus, ticksToWait);
1.179 + }
1.180 + else
1.181 + {
1.182 + TRequestStatus* status = &iStatus;
1.183 + User::RequestComplete(status, KErrNone);
1.184 + }
1.185 + }
1.186 + }
1.187 +
1.188 +/**
1.189 +Deals with an RTimer completion event.
1.190 +
1.191 +The function inspects the timed event entry at the head of the queue, and
1.192 +reduces its timer value by the appropriate amount. If this timed event is
1.193 +now found to have expired, the call back function is called, and the timed
1.194 +event entry removed from the queue.
1.195 +
1.196 +If the timed event entry has not expired, it remains at the head of the queue.
1.197 +
1.198 +The function issues a new RTimer request, using the timer granularity value
1.199 +as the time interval.
1.200 +
1.201 +@see RTimer
1.202 +@see CActive
1.203 +
1.204 +@internalComponent
1.205 +@released
1.206 +*/
1.207 +void CDeltaTimer::RunL()
1.208 +//
1.209 +// Call all zero delta callbacks
1.210 + {
1.211 + // Queue busy
1.212 + iQueueBusy = ETrue;
1.213 +
1.214 + // Whilst the list of expired timers is being processed, time will pass and
1.215 + // the tick count may have increased such that there are now more expired
1.216 + // timers. Loop until we have either emptied the queue or can wait for a
1.217 + // timer exipration in the future.
1.218 + while (!iQueue.IsEmpty())
1.219 + {
1.220 + // Calculate how long till first timer expires
1.221 + const TUint tickCount = Exec::TickCount();
1.222 +
1.223 + // If the first timer is yet to expire, wait some more
1.224 + if (((TInt)(iQueue.First()->iTickCount - tickCount)) > 0)
1.225 + {
1.226 + break;
1.227 + }
1.228 +
1.229 + // Remove entry before callback to prevent re-entrancy issues
1.230 + TTickCountQueLink* entry = iQueue.RemoveFirst();
1.231 +
1.232 + // Iterate through the timers we know have expired based on the
1.233 + // last calculation of delta
1.234 + while (entry)
1.235 + {
1.236 + // Make callback. This could go reentrant on Queue[Long]() or Remove().
1.237 + reinterpret_cast<TDeltaTimerEntry*>(
1.238 + PtrSub(
1.239 + entry,
1.240 + _FOFF(TDeltaTimerEntry, iLink)
1.241 + ))
1.242 + ->iCallBack.CallBack();
1.243 +
1.244 + // Remove the next expired entry, if any
1.245 + entry = iQueue.RemoveFirst(tickCount);
1.246 + }
1.247 + }
1.248 +
1.249 + // Queue idle
1.250 + iQueueBusy = EFalse;
1.251 +
1.252 + // Requeue timer
1.253 + Activate();
1.254 + }
1.255 +
1.256 +/**
1.257 +Implements cancellation of an oustanding RTimer request.
1.258 +
1.259 +@internalComponent
1.260 +@released
1.261 +*/
1.262 +void CDeltaTimer::DoCancel()
1.263 + {
1.264 + iTimer.Cancel();
1.265 + }
1.266 +
1.267 +/**
1.268 +Removes the specified timed event entry from the timer queue.
1.269 +
1.270 +@param aEntry The timed event entry.
1.271 +
1.272 +@publishedAll
1.273 +@released
1.274 +*/
1.275 +EXPORT_C void CDeltaTimer::Remove(TDeltaTimerEntry& aEntry)
1.276 + {
1.277 + // Remove the specified entry from the list
1.278 + aEntry.iLink.Deque();
1.279 + }
1.280 +
1.281 +/**
1.282 +Destructor.
1.283 +
1.284 +Frees all resources before destruction of the object. Specifically, it cancels
1.285 +any outstanding timer requests generated by the RTimer object and then deletes
1.286 +all timed event entries from the timed event queue.
1.287 +
1.288 +@see RTimer
1.289 +
1.290 +@publishedAll
1.291 +@released
1.292 +*/
1.293 +CDeltaTimer::~CDeltaTimer()
1.294 + {
1.295 + Cancel();
1.296 +
1.297 + while (!iQueue.IsEmpty())
1.298 + {
1.299 + iQueue.First()->Deque();
1.300 + }
1.301 +
1.302 + iTimer.Close();
1.303 + }