32
|
1 |
/*
|
|
2 |
* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
|
3 |
* All rights reserved.
|
|
4 |
* This component and the accompanying materials are made available
|
|
5 |
* under the terms of "Eclipse Public License v1.0"
|
|
6 |
* which accompanies this distribution, and is available
|
|
7 |
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
|
|
8 |
*
|
|
9 |
* Initial Contributors:
|
|
10 |
* Nokia Corporation - Initial contribution
|
|
11 |
*
|
|
12 |
* Description:
|
|
13 |
* This class contains implementation of CFlexTimerContainer.
|
|
14 |
*
|
|
15 |
*/
|
|
16 |
|
|
17 |
// System include files
|
|
18 |
#include <hal.h>
|
|
19 |
|
|
20 |
// User include files
|
|
21 |
#include "flextimercommon.h"
|
|
22 |
#include "flextimercontainer.h"
|
|
23 |
#include "flextimeritem.h"
|
|
24 |
#include "mflextimerservicecb.h"
|
|
25 |
#include "OstTraceDefinitions.h"
|
|
26 |
#ifdef OST_TRACE_COMPILER_IN_USE
|
|
27 |
#include "flextimercontainerTraces.h"
|
|
28 |
#endif
|
|
29 |
|
|
30 |
|
|
31 |
|
|
32 |
// This literal is only used by __ASSERT_DEBUG macro. Therefore, to prevent
|
|
33 |
// unnacessary warnings, it is not compiled into release builds.
|
|
34 |
#ifdef _DEBUG
|
|
35 |
static const TInt KCBNullPointer = 1;
|
|
36 |
_LIT( KCBNullPointerDescriptor, "FlexTimerService CB is NULL." );
|
|
37 |
#endif
|
|
38 |
|
|
39 |
// ---------------------------------------------------------------------------
|
|
40 |
// NewL
|
|
41 |
// ---------------------------------------------------------------------------
|
|
42 |
//
|
|
43 |
CFlexTimerContainer* CFlexTimerContainer::NewL()
|
|
44 |
{
|
|
45 |
CFlexTimerContainer* self = new (ELeave) CFlexTimerContainer();
|
|
46 |
|
|
47 |
OstTrace1( TRACE_INTERNAL,
|
|
48 |
CFLEXTIMERCONTAINER_NEWL,
|
|
49 |
"CFlexTimerContainer::NewL;this=%x",
|
|
50 |
( TUint )self );
|
|
51 |
|
|
52 |
return self;
|
|
53 |
}
|
|
54 |
|
|
55 |
// ---------------------------------------------------------------------------
|
|
56 |
// destructor
|
|
57 |
// If the list is not empty when coming here something has already gone wrong.
|
|
58 |
// Lets just delete the timers and forget Timeout() calling
|
|
59 |
// ---------------------------------------------------------------------------
|
|
60 |
//
|
|
61 |
CFlexTimerContainer::~CFlexTimerContainer()
|
|
62 |
{
|
|
63 |
CFlexTimerItem* item = NULL;
|
|
64 |
|
|
65 |
OstTrace1(
|
|
66 |
TRACE_INTERNAL,
|
|
67 |
DUP1_CFLEXTIMERCONTAINER_CFLEXTIMERCONTAINER,
|
|
68 |
"CFlexTimerContainer::~CFlexTimerContainer;this=%x",
|
|
69 |
( TUint )this );
|
|
70 |
|
|
71 |
while ( !iTimerList.IsEmpty() )
|
|
72 |
{
|
|
73 |
item = iTimerList.First();
|
|
74 |
iTimerList.Remove( *item );
|
|
75 |
delete item;
|
|
76 |
}
|
|
77 |
}
|
|
78 |
// ---------------------------------------------------------------------------
|
|
79 |
// Make new timer and add it to list. On purpose do not make sanity checks.
|
|
80 |
// Invalid(in the past) timers are found later.
|
|
81 |
// ---------------------------------------------------------------------------
|
|
82 |
//
|
|
83 |
void CFlexTimerContainer::AddTimerL(
|
|
84 |
const TTimeIntervalMicroSeconds& aWinStartInterval,
|
|
85 |
const TTimeIntervalMicroSeconds& aWinEndInterval,
|
|
86 |
TBool aCancelAtSystemTimeChange,
|
|
87 |
const MFlexTimerServiceCB* aFlexTimerServiceCB )
|
|
88 |
{
|
|
89 |
OstTraceExt5( TRACE_INTERNAL,
|
|
90 |
CFLEXTIMERCONTAINER_ADDTIMERL,
|
|
91 |
"CFlexTimerContainer::AddTimerL;this=%x;"
|
|
92 |
"aWinStartInterval=%Ld;"
|
|
93 |
"aWinEndInterval=%Ld;"
|
|
94 |
"aCancelAtSystemTimeChange=%u;"
|
|
95 |
"aFlexTimerServiceCB=%x",
|
|
96 |
( TUint )this,
|
|
97 |
aWinStartInterval.Int64(),
|
|
98 |
aWinEndInterval.Int64(),
|
|
99 |
aCancelAtSystemTimeChange,
|
|
100 |
( TUint )aFlexTimerServiceCB );
|
|
101 |
|
|
102 |
__ASSERT_DEBUG( aFlexTimerServiceCB,
|
|
103 |
User::Panic( KCBNullPointerDescriptor, KCBNullPointer ) );
|
|
104 |
|
|
105 |
// Before creating new flextimer timeout item, the interval times are
|
|
106 |
// converted to absolute tick based time used by the engine.
|
|
107 |
TTime winAbsStart( IntervalToAbsoluteTime( aWinStartInterval ) );
|
|
108 |
TTime winAbsEnd( IntervalToAbsoluteTime( aWinEndInterval ) );
|
|
109 |
|
|
110 |
CFlexTimerItem* newItem = CFlexTimerItem::NewL( winAbsStart,
|
|
111 |
winAbsEnd,
|
|
112 |
aCancelAtSystemTimeChange,
|
|
113 |
aFlexTimerServiceCB );
|
|
114 |
|
|
115 |
iTimerList.AddLast( *newItem );
|
|
116 |
}
|
|
117 |
// ---------------------------------------------------------------------------
|
|
118 |
// Loop through list and if timer containing same CB that is given as a
|
|
119 |
// parameter is found, remove timer. If no timer found just return error code.
|
|
120 |
// ---------------------------------------------------------------------------
|
|
121 |
//
|
|
122 |
TInt CFlexTimerContainer::RemoveTimer(
|
|
123 |
const MFlexTimerServiceCB* aFlexTimerServiceCB )
|
|
124 |
{
|
|
125 |
OstTraceExt2( TRACE_INTERNAL,
|
|
126 |
CFLEXTIMERCONTAINER_REMOVETIMER,
|
|
127 |
"CFlexTimerContainer::RemoveTimer;this=%x;aFlexTimerServiceCB=%x",
|
|
128 |
( TUint )this,
|
|
129 |
( TUint )aFlexTimerServiceCB );
|
|
130 |
|
|
131 |
__ASSERT_DEBUG( aFlexTimerServiceCB,
|
|
132 |
User::Panic( KCBNullPointerDescriptor, KCBNullPointer ) );
|
|
133 |
|
|
134 |
TSglQueIter<CFlexTimerItem> listIter( iTimerList );
|
|
135 |
CFlexTimerItem* item = NULL;
|
|
136 |
|
|
137 |
listIter.SetToFirst();
|
|
138 |
// Iter++ makes iterator to point to next element if one exists.
|
|
139 |
// Otherwise NULL.
|
|
140 |
while ( (item = listIter++) != NULL )
|
|
141 |
{
|
|
142 |
if ( item->GetCB() == aFlexTimerServiceCB )
|
|
143 |
{
|
|
144 |
iTimerList.Remove( *item );
|
|
145 |
delete item;
|
|
146 |
return KErrNone;
|
|
147 |
}
|
|
148 |
}
|
|
149 |
return KErrNotFound;
|
|
150 |
}
|
|
151 |
// ---------------------------------------------------------------------------
|
|
152 |
// Loop through timers and find time/timer that must expire next
|
|
153 |
// Calculate time left to that moment and return it.
|
|
154 |
// ---------------------------------------------------------------------------
|
|
155 |
//
|
|
156 |
TBool CFlexTimerContainer::GetNextTimeout(
|
|
157 |
TTimeIntervalMicroSeconds& aNextTimeoutDelay )
|
|
158 |
{
|
|
159 |
TSglQueIter<CFlexTimerItem> listIter( iTimerList );
|
|
160 |
TTime currentAbsoluteTime( 0 );
|
|
161 |
CFlexTimerItem* item = NULL;
|
|
162 |
TTime tempTime( 0 );
|
|
163 |
TTime nextTimeout( 0 );
|
|
164 |
|
|
165 |
GetCurrentTime( currentAbsoluteTime );
|
|
166 |
// Take first item as a reference value.
|
|
167 |
listIter.SetToFirst();
|
|
168 |
item = listIter++;
|
|
169 |
if ( item )
|
|
170 |
{
|
|
171 |
item->GetMaxAbsoluteTime( nextTimeout );
|
|
172 |
}
|
|
173 |
|
|
174 |
// Find the timer that needs to expire next, and set nextTimeout to the
|
|
175 |
// time, when the timer needs to expire.
|
|
176 |
while ( (item = listIter++) != NULL )
|
|
177 |
{
|
|
178 |
item->GetMaxAbsoluteTime( tempTime );
|
|
179 |
if ( tempTime < nextTimeout )
|
|
180 |
{
|
|
181 |
nextTimeout = tempTime;
|
|
182 |
}
|
|
183 |
}
|
|
184 |
// Calculate difference between now -> min timeout time. If in past,
|
|
185 |
// return zero interval
|
|
186 |
aNextTimeoutDelay = nextTimeout.MicroSecondsFrom( currentAbsoluteTime );
|
|
187 |
if ( aNextTimeoutDelay < TTimeIntervalMicroSeconds( 0 ) )
|
|
188 |
{
|
|
189 |
aNextTimeoutDelay = 0;
|
|
190 |
}
|
|
191 |
|
|
192 |
OstTraceExt2( TRACE_INTERNAL,
|
|
193 |
CFLEXTIMERCONTAINER_GETNEXTTIMEOUT,
|
|
194 |
"CFlexTimerContainer::GetNextTimeout;this=%x;aNextTimeoutDelay=%Ld",
|
|
195 |
( TUint )this,
|
|
196 |
aNextTimeoutDelay.Int64() );
|
|
197 |
|
|
198 |
return !iTimerList.IsEmpty();
|
|
199 |
}
|
|
200 |
// ---------------------------------------------------------------------------
|
|
201 |
// Excecute selected algorithms and finally fire all timers in candidate list.
|
|
202 |
// ---------------------------------------------------------------------------
|
|
203 |
//
|
|
204 |
void CFlexTimerContainer::FireTimers( TFlexTimerAlgorithm aAlgorithmToBeUsed )
|
|
205 |
{
|
|
206 |
OstTraceExt2( TRACE_INTERNAL,
|
|
207 |
CFLEXTIMERCONTAINER_FIRETIMERS,
|
|
208 |
"CFlexTimerContainer::FireTimers;this=%x;aAlgorithmToBeUsed=%x",
|
|
209 |
( TUint )this,
|
|
210 |
( TUint )aAlgorithmToBeUsed );
|
|
211 |
|
|
212 |
TSglQue<CFlexTimerItem> candidateList( _FOFF( CFlexTimerItem, iLink ) );
|
|
213 |
|
|
214 |
TTime currentAbsoluteTime( 0 );
|
|
215 |
|
|
216 |
GetCurrentTime( currentAbsoluteTime );
|
|
217 |
|
|
218 |
// Simple algorithm is always executed
|
|
219 |
SimpleAlgorithm( candidateList, currentAbsoluteTime );
|
|
220 |
|
|
221 |
if ( EFlexTimerAlgorithmLatestPossible == aAlgorithmToBeUsed )
|
|
222 |
{
|
|
223 |
LatestPossibleAlgorithm( candidateList );
|
|
224 |
}
|
|
225 |
ExpireTimers( candidateList );
|
|
226 |
}
|
|
227 |
|
|
228 |
//
|
|
229 |
// ---------------------------------------------------------------------------
|
|
230 |
// Loop through timer list, call abort to timer if it is abortable.
|
|
231 |
// Then remove timer from list and delete it.
|
|
232 |
// ---------------------------------------------------------------------------
|
|
233 |
//
|
|
234 |
void CFlexTimerContainer::AbortTimersDueToTimeChange( TInt aReason )
|
|
235 |
{
|
|
236 |
OstTraceExt2( TRACE_INTERNAL,
|
|
237 |
CFLEXTIMERCONTAINER_ABORTTIMERSDUETOTIMECHANGE,
|
|
238 |
"CFlexTimerContainer::AbortTimersDueToTimeChange;this=%x;aReason=%d",
|
|
239 |
( TUint )this,
|
|
240 |
aReason );
|
|
241 |
|
|
242 |
TSglQueIter<CFlexTimerItem> listIter( iTimerList );
|
|
243 |
CFlexTimerItem* item = NULL;
|
|
244 |
listIter.SetToFirst();
|
|
245 |
|
|
246 |
// Go through all timers and check if the timer has
|
|
247 |
// AbortAtSystemTimeChange flag set, if so, abort the timer.
|
|
248 |
while ( (item = listIter++) != NULL )
|
|
249 |
{
|
|
250 |
if ( item->IsAbortedAtSystemTimeChange() )
|
|
251 |
{
|
|
252 |
item->GetCB()->Abort( aReason );
|
|
253 |
iTimerList.Remove( *item );
|
|
254 |
delete item;
|
|
255 |
}
|
|
256 |
}
|
|
257 |
}
|
|
258 |
// ---------------------------------------------------------------------------
|
|
259 |
// Constructor for CFlexTimerContainer
|
|
260 |
// ---------------------------------------------------------------------------
|
|
261 |
//
|
|
262 |
CFlexTimerContainer::CFlexTimerContainer() :
|
|
263 |
iTimerList( _FOFF( CFlexTimerItem, iLink ) ),
|
|
264 |
iLastTicks( 0 ),
|
|
265 |
iCurrentAbsoluteTime( 0 )
|
|
266 |
{
|
|
267 |
OstTrace1( TRACE_INTERNAL,
|
|
268 |
CFLEXTIMERCONTAINER_CFLEXTIMERCONTAINER,
|
|
269 |
"CFlexTimerContainer::CFlexTimerContainer;this=%x",
|
|
270 |
( TUint )this );
|
|
271 |
TInt err;
|
|
272 |
|
|
273 |
// Get system tick length for converting tics to microseconds.
|
|
274 |
err = HAL::Get( HAL::ESystemTickPeriod, iTickPeriod );
|
|
275 |
|
|
276 |
__ASSERT_ALWAYS(
|
|
277 |
err == KErrNone,
|
|
278 |
User::Panic(
|
|
279 |
KFlexTimerContainerPanicCat,
|
|
280 |
static_cast <TInt> ( EFlexTimerContainerNoTickPeriod ) ) );
|
|
281 |
}
|
|
282 |
// ---------------------------------------------------------------------------
|
|
283 |
// Loops through timer list and moves all timers that can be fired to
|
|
284 |
// candidate list. Can be fired means that minimum time is reached. Note that
|
|
285 |
// if we are late for some reason (very likely if someone has win size zero),
|
|
286 |
// candidate list can now contain timers that are late (max time passed).
|
|
287 |
// ---------------------------------------------------------------------------
|
|
288 |
//
|
|
289 |
void CFlexTimerContainer::SimpleAlgorithm(
|
|
290 |
TSglQue<CFlexTimerItem>& aCandidateList,
|
|
291 |
TTime& aCurrentTime )
|
|
292 |
{
|
|
293 |
OstTraceExt3( TRACE_INTERNAL,
|
|
294 |
CFLEXTIMERCONTAINER_SIMPLEALGORITHM,
|
|
295 |
"CFlexTimerContainer::SimpleAlgorithm;"
|
|
296 |
"this=%x;aCandidateList=%x;aCurrentTime=%Ld;",
|
|
297 |
( TUint )this,
|
|
298 |
( TUint )&aCandidateList,
|
|
299 |
aCurrentTime.Int64() );
|
|
300 |
|
|
301 |
TSglQueIter<CFlexTimerItem> listIter( iTimerList );
|
|
302 |
CFlexTimerItem* item = NULL;
|
|
303 |
TTime minTime( 0 );
|
|
304 |
|
|
305 |
listIter.SetToFirst();
|
|
306 |
// Iter++ makes iterator to point to next element if one exists.
|
|
307 |
// Otherwise NULL.
|
|
308 |
while ( (item = listIter++) != NULL )
|
|
309 |
{
|
|
310 |
item->GetMinAbsoluteTime( minTime );
|
|
311 |
if ( minTime <= aCurrentTime )
|
|
312 |
{
|
|
313 |
OstTraceExt2( TRACE_INTERNAL,
|
|
314 |
DUP1_CFLEXTIMERCONTAINER_SIMPLEALGORITHM,
|
|
315 |
"CFlexTimerContainer::SimpleAlgorithm - Adding item;"
|
|
316 |
"this=%x;item=%x",
|
|
317 |
( TUint )this,
|
|
318 |
( TUint )item );
|
|
319 |
// Remove from candidate list needs to be done before the
|
|
320 |
// item is added to back to iTimerList, because the lists
|
|
321 |
// use the same iLink member.
|
|
322 |
iTimerList.Remove( *item );
|
|
323 |
|
|
324 |
// This timer can be timeouted, add it to timeout candidate list.
|
|
325 |
// The list is called candidate list, because the content of the
|
|
326 |
// list may be pruned by passing it to other algorithms for furher
|
|
327 |
// prosessing.
|
|
328 |
aCandidateList.AddLast( *item );
|
|
329 |
}
|
|
330 |
}
|
|
331 |
}
|
|
332 |
|
|
333 |
//
|
|
334 |
// ---------------------------------------------------------------------------
|
|
335 |
// Loops through dropped list and candidate list and find timers where:
|
|
336 |
// dropped timers right side of the window is earlier than candidate timers
|
|
337 |
// right side of the window i.e. Candidate can be fired later with dropped
|
|
338 |
// timer, without additional timer firings
|
|
339 |
// ---------------------------------------------------------------------------
|
|
340 |
//
|
|
341 |
void CFlexTimerContainer::LatestPossibleAlgorithm(
|
|
342 |
TSglQue<CFlexTimerItem>& aCandidateList )
|
|
343 |
{
|
|
344 |
TSglQueIter<CFlexTimerItem> listIter( iTimerList );
|
|
345 |
TSglQueIter<CFlexTimerItem> candidateListIter( aCandidateList );
|
|
346 |
CFlexTimerItem* droppedItem = NULL;
|
|
347 |
CFlexTimerItem* candidateItem = NULL;
|
|
348 |
TTime droppedMaxTime( 0 );
|
|
349 |
TTime candidateMaxTime( 0 );
|
|
350 |
|
|
351 |
OstTraceExt2( TRACE_INTERNAL,
|
|
352 |
CFLEXTIMERCONTAINER_LATESTPOSSIBLEALGORITHM,
|
|
353 |
"CFlexTimerContainer::LatestPossibleAlgorithm;"
|
|
354 |
"this=%x;aCandidateList=%x",
|
|
355 |
( TUint )this,
|
|
356 |
( TUint )&aCandidateList );
|
|
357 |
|
|
358 |
listIter.SetToFirst();
|
|
359 |
candidateListIter.SetToFirst();
|
|
360 |
|
|
361 |
droppedItem = listIter++;
|
|
362 |
|
|
363 |
if ( droppedItem != NULL )
|
|
364 |
{
|
|
365 |
// Initiliaze next dropped timeout time to some value.
|
|
366 |
droppedItem->GetMaxAbsoluteTime( droppedMaxTime );
|
|
367 |
|
|
368 |
// Loop through dropped timers and find the dropped timer that will have
|
|
369 |
// shortest time to its timeout.
|
|
370 |
while ( (droppedItem = listIter++) != NULL )
|
|
371 |
{
|
|
372 |
droppedItem->GetMaxAbsoluteTime( candidateMaxTime );
|
|
373 |
if ( droppedMaxTime > candidateMaxTime )
|
|
374 |
{
|
|
375 |
droppedMaxTime = candidateMaxTime;
|
|
376 |
}
|
|
377 |
}
|
|
378 |
|
|
379 |
// Loop through candidate timers
|
|
380 |
while ( (candidateItem = candidateListIter++) != NULL )
|
|
381 |
{
|
|
382 |
candidateItem->GetMaxAbsoluteTime( candidateMaxTime );
|
|
383 |
// If candidate can be fired together with dropped timer ->
|
|
384 |
// don't fire candidate yet.
|
|
385 |
if ( droppedMaxTime <= candidateMaxTime )
|
|
386 |
{
|
|
387 |
OstTraceExt2( TRACE_INTERNAL,
|
|
388 |
DUP1_CFLEXTIMERCONTAINER_LATESTPOSSIBLEALGORITHM,
|
|
389 |
"CFlexTimerContainer::LatestPossibleAlgorithm -"
|
|
390 |
" Removing item;this=%x;candidateItem=%x",
|
|
391 |
( TUint )this,
|
|
392 |
( TUint )candidateItem );
|
|
393 |
|
|
394 |
// Remove from candidate list needs to be done before the
|
|
395 |
// item is added to back to iTimerList, because the lists
|
|
396 |
// use the same iLink member.
|
|
397 |
aCandidateList.Remove( *candidateItem );
|
|
398 |
// Add to first so we don't handle this again.
|
|
399 |
iTimerList.AddFirst( *candidateItem );
|
|
400 |
}
|
|
401 |
}
|
|
402 |
}
|
|
403 |
}
|
|
404 |
// ---------------------------------------------------------------------------
|
|
405 |
// Loops through candidate list and calls timeout to all timers.
|
|
406 |
// Then removes timer from list and deletes it.
|
|
407 |
// ---------------------------------------------------------------------------
|
|
408 |
//
|
|
409 |
void CFlexTimerContainer::ExpireTimers(
|
|
410 |
TSglQue<CFlexTimerItem>& aCandidateList )
|
|
411 |
{
|
|
412 |
OstTraceExt2( TRACE_INTERNAL,
|
|
413 |
CFLEXTIMERCONTAINER_EXPIRETIMERS,
|
|
414 |
"CFlexTimerContainer::ExpireTimers;this=%x;candidateList=%x",
|
|
415 |
( TUint )this,
|
|
416 |
( TUint )&aCandidateList );
|
|
417 |
|
|
418 |
TSglQueIter<CFlexTimerItem> candidateListIter( aCandidateList );
|
|
419 |
CFlexTimerItem* item = NULL;
|
|
420 |
|
|
421 |
candidateListIter.SetToFirst();
|
|
422 |
// Iter++ makes iterator to point to next element if one exists.
|
|
423 |
// Otherwise NULL.
|
|
424 |
while ( (item = candidateListIter++) != NULL )
|
|
425 |
{
|
|
426 |
item->GetCB()->Timeout();
|
|
427 |
aCandidateList.Remove( *item );
|
|
428 |
delete item;
|
|
429 |
}
|
|
430 |
}
|
|
431 |
// ---------------------------------------------------------------------------
|
|
432 |
// Get current time return current time in FlexTimer engine time base. This
|
|
433 |
// time base is begins from the first call to GetCurrentTime and it is base on
|
|
434 |
// system ticks.
|
|
435 |
// ---------------------------------------------------------------------------
|
|
436 |
//
|
|
437 |
void CFlexTimerContainer::GetCurrentTime( TTime& aAbsoluteTime )
|
|
438 |
{
|
|
439 |
TUint32 currentTicks = User::TickCount();
|
|
440 |
|
|
441 |
// Accumulate current absolute time with the time passed since last
|
|
442 |
// update. Both currentTicks and iLastTicks are unsigned int types, thus
|
|
443 |
// "currentTicks - iLastTicks" will handle also the case currentTicks
|
|
444 |
// overflows.
|
|
445 |
iCurrentAbsoluteTime += TicksToAbsoluteTime( currentTicks
|
|
446 |
- iLastTicks );
|
|
447 |
|
|
448 |
iLastTicks = currentTicks;
|
|
449 |
|
|
450 |
// N.B. Even though the time is is returned as TTime, this time has own
|
|
451 |
// time base. (See function description)
|
|
452 |
aAbsoluteTime = iCurrentAbsoluteTime;
|
|
453 |
}
|
|
454 |
|
|
455 |
|
|
456 |
|
|
457 |
|
|
458 |
|
|
459 |
|