diff -r 000000000000 -r 4e1aa6a622a0 hwrmhaptics/hapticsclient/src/hwrmhapticsivtdatacache.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hwrmhaptics/hapticsclient/src/hwrmhapticsivtdatacache.cpp Tue Feb 02 00:53:00 2010 +0200 @@ -0,0 +1,377 @@ +/* +* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "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: Implementation of haptics client's IVT-data cache. +* +*/ + + +#include "hwrmhapticsivtdatacache.h" + +// --------------------------------------------------------------------------- +// Two-phase constructor. +// --------------------------------------------------------------------------- +// +CHWRMHapticsIVTDataCache* CHWRMHapticsIVTDataCache::NewL() + { + CHWRMHapticsIVTDataCache* self = CHWRMHapticsIVTDataCache::NewLC(); + CleanupStack::Pop( self ); + + return self; + } + +// --------------------------------------------------------------------------- +// Two-phase asynchronous constructor. +// --------------------------------------------------------------------------- +// +CHWRMHapticsIVTDataCache* CHWRMHapticsIVTDataCache::NewLC() + { + CHWRMHapticsIVTDataCache* self = new ( ELeave ) CHWRMHapticsIVTDataCache(); + CleanupStack::PushL( self ); + + self->ConstructL(); + + return self; + } + +// --------------------------------------------------------------------------- +// Destructor. +// --------------------------------------------------------------------------- +// +CHWRMHapticsIVTDataCache::~CHWRMHapticsIVTDataCache() + { + Reset(); + if ( iIdle ) + { + iIdle->Cancel(); + delete iIdle; + } + iCache.Close(); + } + +// --------------------------------------------------------------------------- +// Adds a new IVT-data item to the cache. +// --------------------------------------------------------------------------- +// +TInt CHWRMHapticsIVTDataCache::AddCacheItem( const TDesC8& aIVTData, + TInt& aFileHandle ) + { + TInt err = KErrNoMemory; + + TCacheItem newItem; + newItem.iIVTData = aIVTData.Alloc(); + newItem.iClientFileHandle = ++iInternalHandle; + newItem.iDeletionRequested = EFalse; + newItem.iLoadObserver = NULL; + + aFileHandle = iInternalHandle; + + if ( newItem.iIVTData ) + { + err = iCache.Append( newItem ); + } + + return err; + } + +// --------------------------------------------------------------------------- +// Adds a new IVT-data item to the cache. This overload is meant for +// asynch calls. +// --------------------------------------------------------------------------- +// +TBool CHWRMHapticsIVTDataCache::UpdateCacheItemListener( + TInt aFileHandle, + TRequestStatus& aClientStatus, + RHWRMHapticsSession* aClientSession, + const TIpcArgs& aArgs ) + { + TBool retVal( EFalse ); + TInt itemIndex = FindItem( aFileHandle ); + + if ( itemIndex >= 0 ) + { + // New load observer listener is only instantiated if there isn't + // already a listener for the cache item. Note that if there already + // were one, this method will return EFalse, and the actual asynch + // call will be made with the original client's status in Impl class. + if ( !iCache[itemIndex].iLoadObserver ) + { + // If the below leaves this method will return EFalse, + // and the actual asynch call will be made with the original + // client's status. + TRAPD(err, + iCache[itemIndex].iLoadObserver = + CHWRMHapticsIVTDataCacheAO::NewL( aFileHandle, + this, + aClientStatus ) ); + if ( !err ) + { + iCache[itemIndex].iLoadObserver->PlayEffectAsynch + ( aClientSession, aArgs ); + retVal = ETrue; + } + } + } + + return retVal; + } + +// --------------------------------------------------------------------------- +// Removes a cache item identified by the given filehandle. +// --------------------------------------------------------------------------- +// +TInt CHWRMHapticsIVTDataCache::RemoveCacheItem( TInt aFileHandle ) + { + TInt err = KErrNotFound; + + // search for the item in the cache + TInt itemIndex = FindItem( aFileHandle ); + + if ( itemIndex >= 0 ) + { + // item was found, either mark it for deletion (if there's active + // load observer active object waiting for response for previous + // play with data request) or otherwise delete and remove it. + if ( iCache[itemIndex].iLoadObserver && + iCache[itemIndex].iLoadObserver->IsActive() ) + { + iCache[itemIndex].iDeletionRequested = ETrue; + } + else + { + delete iCache[itemIndex].iIVTData; + iCache[itemIndex].iIVTData = NULL; + delete iCache[itemIndex].iLoadObserver; + iCache[itemIndex].iLoadObserver = NULL; + iCache.Remove( itemIndex ); + + err = KErrNone; + + // update loaded item index, if needed + if ( iLoadedItem == itemIndex ) + { + iLoadedItem = KErrNotFound; + } + else if ( iLoadedItem > itemIndex ) + { + --iLoadedItem; + } + } + } + + return err; + } + +// --------------------------------------------------------------------------- +// Removes all items from the cache. +// --------------------------------------------------------------------------- +// +void CHWRMHapticsIVTDataCache::Reset() + { + // delete and remove all items + while ( iCache.Count() ) + { + delete iCache[0].iIVTData; + iCache[0].iIVTData = NULL; + delete iCache[0].iLoadObserver; + iCache[0].iLoadObserver = NULL; + iCache.Remove( 0 ); + } + + iLoadedItem = KErrNotFound; + } + +// --------------------------------------------------------------------------- +// Returns a pointer to the IVT-data buffer, which corresponds to +// the given filehandle. +// --------------------------------------------------------------------------- +// +const HBufC8* CHWRMHapticsIVTDataCache::IVTData( TInt aFileHandle ) const + { + HBufC8* ivtData = NULL; + + // search for the item in the cache + TInt itemIndex = FindItem( aFileHandle ); + if ( itemIndex >= 0 ) + { + ivtData = iCache[itemIndex].iIVTData; + } + + return ivtData; + } + +// --------------------------------------------------------------------------- +// Returns whether or not the IVT-data of the given filehandle +// is currently loaded into the haptics system. +// --------------------------------------------------------------------------- +// +TBool CHWRMHapticsIVTDataCache::IsLoaded( TInt aFileHandle ) const + { + TInt ret = EFalse; + TInt index = FindItem( aFileHandle ); + + // if index was found and the index is the loaded item's index, + // this data is already loaded + if ( index >= 0 && index == iLoadedItem ) + { + ret = ETrue; + } + + return ret; + } + +// --------------------------------------------------------------------------- +// Updates server side file handle +// --------------------------------------------------------------------------- +// +void CHWRMHapticsIVTDataCache::UpdateCacheItem( TInt aClientFileHandle, + TBool aSetLoaded ) + { + // find the item from cache with the given filehandle + TInt itemIndex = FindItem( aClientFileHandle ); + if ( itemIndex >= 0 ) + { + if ( aSetLoaded && !iCache[itemIndex].iDeletionRequested ) + { + iLoadedItem = itemIndex; + } + } + } + +// --------------------------------------------------------------------------- +// Returns client side file handle +// --------------------------------------------------------------------------- +// +TInt CHWRMHapticsIVTDataCache::ClientFileHandle( const TDesC8& aIVTData ) + { + // find the item from cache with the given filehandle + TInt clientFileHandle( KErrNotFound ); + TInt count( iCache.Count() ); + for ( TInt i( 0 ); i < count && KErrNotFound == clientFileHandle; ++i ) + { + TPtr8 cachedData = iCache[i].iIVTData->Des(); + if ( cachedData == aIVTData ) + { + clientFileHandle = iCache[i].iClientFileHandle; + } + } + + return clientFileHandle; + } + +// --------------------------------------------------------------------------- +// Method for starting the idle object that then calls garbage collection +// callback. +// --------------------------------------------------------------------------- +// +void CHWRMHapticsIVTDataCache::RequestGarbageCollection() + { + if ( iIdle && !iIdle->IsActive() ) + { + iIdle->Start( TCallBack ( CollectGarbageIdle, this ) ); + } + } + +// --------------------------------------------------------------------------- +// Garbage collection static callback. +// --------------------------------------------------------------------------- +// +TInt CHWRMHapticsIVTDataCache::CollectGarbageIdle( TAny* aObjectPtr ) + { + CHWRMHapticsIVTDataCache* self = + reinterpret_cast( aObjectPtr ); + if ( self ) + { + self->CollectGarbage(); + } + return KErrNone; + } + +// --------------------------------------------------------------------------- +// Garbage collection actual (object specific) callback. Cleans obsolete +// load observers and whole TCacheItems if needed. +// --------------------------------------------------------------------------- +// +void CHWRMHapticsIVTDataCache::CollectGarbage() + { + for ( TInt i = iCache.Count() - 1; i >= 0; --i ) + { + // This garbage collection is only interested in those entries for + // which there has been load observer running, i.e., for which the + // iLoadObserver is non-NULL, and for which the running has stopped, + // i.e., the iLoadObserver.IsActive() check returns EFalse + if ( iCache[i].iLoadObserver && !iCache[i].iLoadObserver->IsActive() ) + { + delete iCache[i].iLoadObserver; + iCache[i].iLoadObserver = NULL; + // If the entry was also marked for deletion, delete the whole + // entry from TCacheItem array + if ( iCache[i].iDeletionRequested ) + { + delete iCache[i].iIVTData; + iCache[i].iIVTData = NULL; + iCache.Remove( i ); + + // update loaded item index, if needed + if ( iLoadedItem == i ) + { + iLoadedItem = KErrNotFound; + } + else if ( iLoadedItem > i ) + { + --iLoadedItem; + } + } + } + } + } + +// --------------------------------------------------------------------------- +// C++ constructor. +// --------------------------------------------------------------------------- +// +CHWRMHapticsIVTDataCache::CHWRMHapticsIVTDataCache() + : iLoadedItem( KErrNotFound ) + { + } + +// --------------------------------------------------------------------------- +// Second phase construction. +// --------------------------------------------------------------------------- +// +void CHWRMHapticsIVTDataCache::ConstructL() + { + iIdle = CIdle::NewL( CActive::EPriorityIdle ); + } + +// --------------------------------------------------------------------------- +// Searches the cache for an item with the given filehandle. +// --------------------------------------------------------------------------- +// +TInt CHWRMHapticsIVTDataCache::FindItem( TInt aClientFileHandle ) const + { + TInt index = KErrNotFound; + + // find the item from cache with the given filehandle + for ( TInt i = 0; i < iCache.Count() && index == KErrNotFound; ++i ) + { + if ( iCache[i].iClientFileHandle == aClientFileHandle ) + { + index = i; + } + } + + return index; + } + +// End of File