hwrmhaptics/hapticsclient/src/hwrmhapticsivtdatacache.cpp
changeset 0 4e1aa6a622a0
--- /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<CHWRMHapticsIVTDataCache*>( 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