hwrmhaptics/hapticsclient/src/hwrmhapticsivtdatacache.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 17 Sep 2010 08:36:42 +0300
changeset 69 dc67b94625c5
parent 0 4e1aa6a622a0
permissions -rw-r--r--
Revision: 201037 Kit: 201037

/*
* 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