diff -r 000000000000 -r 96612d01cf9f videofeeds/utils/inc/mtvobserverutils.inl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/videofeeds/utils/inc/mtvobserverutils.inl Mon Jan 18 20:21:12 2010 +0200 @@ -0,0 +1,214 @@ +/* +* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "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: Helper functions and macros for handling multiple observers.* +*/ + + + + +#ifndef _MTV_OBSERVER_UTILS +#define _MTV_OBSERVER_UTILS + +namespace MtvObserverUtils +{ + +/** + * Struct for holding a bunch of observers and a semaphore for controlling observer removal. + * + * @since Live TV UI v1.0 + */ +template class ContainerType = RPointerArray, class PointerType = ObserverType> +struct RObserverData + { + // constructor for initializing the semaphore + RObserverData() : iSemaphore(0), iShutdown(EFalse) + { + } + /** + * Initializes the container. + * This function is currently just a placeholder, later + * it can be used to add support for CBase-derived containers, + * assuming that all clients call OpenL and Close when using + * this class. + */ + void OpenL() + { + } + /** + * Closes the container. + */ + void Close() + { + iContainer.Close(); + iShutdown = ETrue; + } + // Container can be RPointerArray, RArray.. + // At the moment CBase-derived containers are not supported. + ContainerType iContainer; + // the semaphore is used so that when it has a value greater than zero, observers + // are not removed, but nulled in the container + TInt iSemaphore; + // pointer type member helps code using this object, the using code does not + // need to know the actual observer type + PointerType* iObserver; + // Set to ETrue when the provider of notifications is shut down. + TBool iShutdown; + }; + +/** + * Removes NULL observers from a container. + * @param aExistsNull Tells whether there are any NULL observers. + * Checking this parameter inside this function makes invoking code simpler. + * @param aObserverData Observer data object (usually a RObserverData). + * This data object must contain a container of observers and a semaphore. + */ +template +static void RemoveNullObservers(TBool aExistsNull, ObserverDataType& aObserverData) + { + // semaphore must always be decremented + --aObserverData.iSemaphore; + if ( !aObserverData.iSemaphore && aExistsNull ) + { + for (TInt i = aObserverData.iContainer.Count() - 1; i >= 0; --i) + { + if (aObserverData.iContainer[i] == NULL) + { + aObserverData.iContainer.Remove(i); + } + } + } + } + +/** + * Macro that invokes an observer function for all registered observers. + * @param aNotification Observer function to call. + * @param aObserverData Observer data object (usually a RObserverData). + * This data object must contain a container of observers and a semaphore. + */ +#define RUN_NOTIFY_LOOP(aNotification, aObserverData) \ +do \ + { \ + if ( !aObserverData.iShutdown )\ + {\ + ++aObserverData.iSemaphore; \ + TBool existsNull = EFalse; \ + const TInt count = aObserverData.iContainer.Count(); \ + for ( TInt i = 0; i < count; ++i ) \ + { \ + aObserverData.iObserver = aObserverData.iContainer[ i ]; \ + if ( aObserverData.iObserver ) \ + { \ + TRAP_IGNORE( aObserverData.iObserver->aNotification ); \ + } \ + else \ + { \ + existsNull = ETrue; \ + } \ + } \ + RemoveNullObservers(existsNull, \ + aObserverData); \ + }\ + } while (EFalse) \ + +/** + * Macro that invokes an observer function for all registered observers. + * @param aNotification Observer function to call. + * @param aObserverData Observer data object (usually a RObserverData). + * @param aError On return, contains the possible first error code that happened. + * This data object must contain a container of observers and a semaphore. + */ +#define RUN_NOTIFY_LOOP_L(aNotification, aObserverData, aError) \ +do \ + { \ + aError = KErrNone; \ + TInt ___mtvObserverUtilsNotifyLoopError = KErrNone; \ + if ( !aObserverData.iShutdown )\ + {\ + ++aObserverData.iSemaphore; \ + TBool existsNull = EFalse; \ + const TInt count = aObserverData.iContainer.Count(); \ + for ( TInt i = 0; i < count; ++i ) \ + { \ + aObserverData.iObserver = aObserverData.iContainer[ i ]; \ + if ( aObserverData.iObserver ) \ + { \ + TRAP( ___mtvObserverUtilsNotifyLoopError, aObserverData.iObserver->aNotification ); \ + if ( aError == KErrNone ) \ + { \ + aError = ___mtvObserverUtilsNotifyLoopError; \ + } \ + } \ + else \ + { \ + existsNull = ETrue; \ + } \ + } \ + RemoveNullObservers(existsNull, \ + aObserverData); \ + }\ + } while (EFalse) \ + +/** + * Adds an observer to an observer data object. + * @param aObserverData Data object to which an observer is added. + * @param aObserver Observer to add. + * @param aError Error code to use for Leave if adding fails. + */ +template +static void AddObserverL(ContainerType& aObserverData, ObserverType& aObserver, TInt aError) + { + if (aObserverData.iShutdown) + { + return; + } + TInt pos = aObserverData.iContainer.Find( &aObserver ); + if (KErrNotFound != pos) + { + return; + } + TInt error = aObserverData.iContainer.Append( &aObserver ); + if (KErrNone != error) + { + User::Leave(aError); + } + } + +/** + * Removes an observer from an observer data object. + * @param aObserverData Data object from which an observer is removed. + * @param aObserver Observer to remove. + */ +template +static void RemoveObserver( ContainerType& aObserverData, ObserverType& aObserver ) + { + TInt pos = aObserverData.iContainer.Find( &aObserver ); + if ( KErrNotFound == pos ) + { + return; + } + if ( !aObserverData.iSemaphore ) + { + // NotifyEventL is not part of call stack. Just remove. + aObserverData.iContainer.Remove( pos ); + } + else + { + // Simply set to NULL. NotifyEventL will remove observers. + aObserverData.iContainer[ pos ] = NULL; + } + } + +} // end namespace MtvObserverUtils + +#endif //_MTV_OBSERVER_UTILS