Update contrib.
1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
22 NONSHARABLE_CLASS(RDbCache::CCache) : private CBase
25 static CCache* OpenL( TInt aSize, TBool aUseTimer );
29 void Hold( CBase* aObject, TUint aMicroSeconds );
30 void Release ( const CBase& aObject );
38 enum { ETimerPriority = -10 };
39 enum { ETimerPeriod = 0x100000 }; // ~1.0s
41 static inline TInt TlsHandle();
45 static CCache* NewL( TInt aSize, TBool aUseTimer );
47 void Expire( TInt aElapsedTime );
48 void Remove( TEntry*& aRef );
50 static void DoFlush( TAny* aPtr );
54 TTimeIntervalMicroSeconds32 iTickPeriod;
58 TEntry iEntries[1]; // or maybe more
61 // Class CDbObjectCache
63 //inline TInt RDbCache::CCache::TlsHandle()
64 //// use the address of a static function for the handle
65 // { return TInt( NewL ); }
69 RDbCache::CCache::CCache( TInt aSize )
71 // Initialise the free entry list
74 TEntry* entry = iEntries;
75 while ( --aSize != 0 )
77 entry[1].iNext = entry;
83 RDbCache::CCache::~CCache()
86 // empty the cache (destory the items now)
88 __ASSERT( iCache == 0 );
93 const TInt KTickPeriod = 10000000;
94 const TTimeIntervalMicroSeconds32 gTickPeriod(KTickPeriod);
95 RDbCache::CCache* RDbCache::CCache::NewL( TInt aSize, TBool aUseTimer )
97 // Construct a cache with aSize slots and one referee
100 //#warning !! RDbCache::CCache::NewL not implemented (uses UserHal/UserSvr) !!
101 CCache* cache = new( ELeave, sizeof( TEntry ) * ( aSize - 1 ) ) CCache( aSize ); // get the extra size for the cache entries, leaves on error
102 CleanupClosePushL( *cache );
103 cache->iTickPeriod = gTickPeriod;
104 //User::LeaveIfError( UserHal::TickPeriod( cache->iTickPeriod ) );
105 //User::LeaveIfError( UserSvr::DllSetTls( TlsHandle(), cache ) );
108 // cache->iTimer = CPeriodic::NewL( ETimerPriority );
113 inline void RDbCache::CCache::Open()
117 void RDbCache::CCache::Close()
119 // remove a referee and delete as required
122 __ASSERT( iRef >= 0 );
127 RDbCache::CCache* RDbCache::CCache::OpenL( TInt aSize, TBool aUseTimer )
129 // Grab a reference to the cache, constructing it if required
132 // CCache* cache = ( CCache* )UserSvr::DllTls( TlsHandle() );
133 CCache* cache = ( CCache* )gCachePtr;
135 return NewL( aSize, aUseTimer );
140 void RDbCache::CCache::Hold( CBase* aObject, TUint aMicroSeconds )
142 // Hold aObject in the cache or destroy it
145 Flush(); // Destroy expired entries and re-assess Zero-time
146 TInt ticks = aMicroSeconds / TUint( iTickPeriod.Int() );
147 TEntry* entry = iFree;
149 { // no free slots: check the first cache entry
151 if ( iCache->iDelta > ticks )
152 { // aObject expires first
156 ExpireFirst(); // remove the first entry and use it
159 iFree = entry->iNext; // move the free list pointer to the next entry
161 // find the insertion point in the cache delta-list
162 TEntry** pcache = &iCache;
166 __ASSERT( ticks >= 0 );
170 TInt t = ticks - cache->iDelta;
172 { // add to the list here
173 cache->iDelta = -t; // reduce the following delta
176 ticks = t; // reduce the entry delta
177 pcache = &cache->iNext;
179 *pcache = entry; // set up the entry
180 entry->iDelta = ticks;
181 entry->iNext = cache;
182 entry->iObject = aObject;
183 // // kick the timer if we need to
184 // if ( iTimer && !iTimer->IsActive() )
185 // iTimer->Start( ETimerPeriod, ETimerPeriod, TCallBack( ( TInt (*)(TAny*) )DoFlush, this ) );
188 void RDbCache::CCache::Remove( RDbCache::CCache::TEntry*& aRef )
190 // Remove the entry at aRef from the cache
193 TEntry& entry = *aRef;
194 TEntry* next = entry.iNext;
199 next->iDelta += entry.iDelta;
200 // else if ( iTimer ) // the cache is now empty, so stop the timer if we have one
204 void RDbCache::CCache::ExpireFirst()
206 // Expire the first entry in the cache
209 __ASSERT( iCache != 0 );
210 // the ordering here is important. Removing the entry first allows the
211 // object d'tor to call Release() without causing re-entrancy problems.
212 CBase* object = iCache->iObject;
217 void RDbCache::CCache::Release( const CBase& aObject )
219 // Remove the cache entry for aObject, if it is in the cache
222 TEntry** pcache = &iCache;
225 TEntry* entry = *pcache;
228 if ( entry->iObject == &aObject )
233 pcache = &entry->iNext;
237 void RDbCache::CCache::Expire( TInt aElapsedTime )
239 // Destroy entries which expire with aElapsedTime
242 __ASSERT( aElapsedTime > 0 );
243 if ( iCache && ( iCache->iDelta -= aElapsedTime ) < 0 )
245 Open(); // This allows the cache to be owned by an object in the cache
247 while ( iCache && iCache->iDelta < 0 );
248 Close(); // The cache may be destroyed now
252 void RDbCache::CCache::Flush()
254 // Check the execution clock and destroy any expired entries
256 // Care has to be taken to handle the 32-bit wraparound of the tick-count
257 // e.g. iZeroTime = 0xffffffffu, now = 0
260 TUint now = User::TickCount();
261 TUint elapsed = now - iZeroTime;
264 Expire( elapsed <= TUint( KMaxTInt ) ? elapsed : TUint( KMaxTInt ) );
267 void RDbCache::CCache::DoFlush( TAny* aPtr )
269 // Callback for the timer
272 static_cast<CCache*>( aPtr )->Flush();
278 TInt RDbCache::Open( TInt aSize, TBool aUseTimer )
280 // Get a handle on the cache
283 __ASSERT( aSize > 0 );
284 TRAPD( r, iCache = CCache::OpenL( aSize, aUseTimer ) );
288 void RDbCache::Close()
290 // Close this handle on the cache
293 CCache* cache = iCache;
301 void RDbCache::Hold( CBase* aObject, TUint aMicroSeconds )
303 // Hold aObject on the cache, if open
304 // We are now responsible for deleting the object
308 iCache->Hold( aObject, aMicroSeconds );
310 delete aObject; // no cache available
313 void RDbCache::Release( const CBase& aObject ) const
315 // Retrieve aObject from the cache
319 iCache->Release( aObject );
322 void RDbCache::Flush()
324 // Destroy any cached objects which have expired