diff -r 000000000000 -r 15bf7259bb7c uiacceltk/hitchcock/Client/src/alfbrusharray.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uiacceltk/hitchcock/Client/src/alfbrusharray.cpp Tue Feb 02 07:56:43 2010 +0200 @@ -0,0 +1,396 @@ +/* +* Copyright (c) 2006 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: Array for brushes +* +*/ + + + +#include "alf/alfbrusharray.h" +#include "alf/alfvisual.h" +#include "alf/alfenv.h" +#include "alfclient.h" +#include "alf/alfbrush.h" +#include "alflogger.h" +#include "alf/alfgencomponent.h" +#include "alf/alfconstants.h" + +#include + +/** + * This watcher is a helper class to detect misusages of the brush arrays. + * + * A classic example is that the user creates a brush which is deleted before + * it is removed from all the arrays where it is added. + * + * This idle-loop is started when the system notices when a brush is deleted which + * is still in this array. This is only acceptable if the owning visual is deleted + * in the same scheduler loop. See the CAlfBrushArrayUsageWatcher::RunL + * for the result if the array is not deleted right away. + */ +NONSHARABLE_CLASS(CAlfBrushArrayUsageWatcher) : public CActive + { +public: + CAlfBrushArrayUsageWatcher(); + ~CAlfBrushArrayUsageWatcher(); +protected: + void RunL(); + void DoCancel(){}; + }; + +// Constructor, which initiates the idle-loop +CAlfBrushArrayUsageWatcher::CAlfBrushArrayUsageWatcher() : CActive( EPriorityIdle ) + { + CActiveScheduler::Add( this ); + + SetActive(); + iStatus = KRequestPending; + TRequestStatus* status = &iStatus; + User::RequestComplete( status, KErrNone ); + } + +// destructor which cancels the loop +CAlfBrushArrayUsageWatcher::~CAlfBrushArrayUsageWatcher() + { + Cancel(); + } + +// RunL is called when the idle-loop is executed. +void CAlfBrushArrayUsageWatcher::RunL() + { + // In normal usage, this code snippet should never ne run. + // This is called, when a user deletes a brush (directly or through a brush array) + // which is still left in this brush array. + + __ALFLOGSTRING( "CAlfBrushArrayUsageWatcher::RunL Incorrect brush deletion!" ) +#ifdef _DEBUG + USER_INVARIANT(); +#endif + User::Leave( KErrGeneral ); + } + + +// Private data structure. +struct CAlfBrushArray::TPrivateData + { + CAlfVisual* iOwner; + RPointerArray iBrushes; + RPointerArray iOwnedBrushes; + CAlfBrushArrayUsageWatcher* iWatcher; + }; + +// ======== MEMBER FUNCTIONS ======== + +// --------------------------------------------------------------------------- +// Constructor. +// --------------------------------------------------------------------------- +// +CAlfBrushArray::CAlfBrushArray() + { + } + + +// --------------------------------------------------------------------------- +// 2nd phase constructor +// --------------------------------------------------------------------------- +// +void CAlfBrushArray::ConstructL(CAlfVisual& aOwner) + { + iData = new (ELeave) TPrivateData; + + iData->iOwner = &aOwner; + iData->iOwnedBrushes.Reset(); + iData->iBrushes.Reset(); + iData->iWatcher = NULL; + } + + +// --------------------------------------------------------------------------- +// Two-phased constructor. +// --------------------------------------------------------------------------- +// +CAlfBrushArray* CAlfBrushArray::NewL(CAlfVisual& aOwner) + { + CAlfBrushArray* self = new( ELeave ) CAlfBrushArray; + CleanupStack::PushL( self ); + self->ConstructL(aOwner); + CleanupStack::Pop( self ); + return self; + } + + +// --------------------------------------------------------------------------- +// Destructor. +// --------------------------------------------------------------------------- +// +CAlfBrushArray::~CAlfBrushArray() + { + if ( iData ) + { + Reset(); + } + delete iData; + iData = NULL; + } + +// --------------------------------------------------------------------------- +// Resets the array. +// --------------------------------------------------------------------------- +// +EXPORT_C void CAlfBrushArray::Reset() + { + for ( TInt i = iData->iBrushes.Count()-1 ; i>= 0; i-- ) + { + iData->iBrushes[i]->RemoveContainingArray( *this ); + } + + iData->iOwnedBrushes.ResetAndDestroy(); + iData->iBrushes.Reset(); + + delete iData->iWatcher; + iData->iWatcher= NULL; + + // Update the server side. + TBuf8<1> dummy; + TInt err = iData->iOwner->Comms()->DoSynchronousCmd(EAlfVisualBrushArrayReset, KNullDesC8(), dummy); + + if ( err ) + { + __ALFLOGSTRING1( "CAlfBrushArray::Reset panic error %d", err ) + USER_INVARIANT(); + } + + } + +// --------------------------------------------------------------------------- +// Add brush onto the array. +// --------------------------------------------------------------------------- +// +EXPORT_C void CAlfBrushArray::AppendL(CAlfBrush* aBrush, TAlfOwnership aOwnership) + { + // Add to iBrushes array. + TInt err = iData->iBrushes.Append( aBrush ); + if ( err != KErrNone ) + { + // on failure, log'n'leave + __ALFLOGSTRING1( "CAlfBrushArray::AppendL leave error %d", err ) + User::Leave( err ); + } + + err = aBrush->AppendContainingArray( *this ); + if ( err != KErrNone ) + { + // on failure remove from iBrushes, log'n'leave + iData->iBrushes.Remove( iData->iBrushes.Count() - 1 ); + iData->iBrushes.Compress(); + __ALFLOGSTRING1( "CAlfBrushArray::AppendL leave error %d", err ) + User::Leave( err ); + } + + // Update the server side. + TInt2 int2(aBrush->Identifier(), aOwnership); + TPckgC buf(int2); + TBuf8<1> dum; + + err = iData->iOwner->Comms()->DoSynchronousCmd(EAlfVisualBrushArrayAppend, buf, dum ); + if ( err != KErrNone ) + { + // On error, remove it from the iBrushes and log'n'leave + RemoveBrush(aBrush, iData->iBrushes.Count() - 1); + + __ALFLOGSTRING1( "CAlfBrushArray::AppendL leave error %d", err ) + User::Leave(err); + } + // append ownership only on success (otherwise double deletion takes place on leave) + if ( aOwnership == EAlfHasOwnership ) + { + err = iData->iOwnedBrushes.Append( aBrush ); + if ( err != KErrNone ) + { + // on failure remove brush (inform server as well) and log'n'leave + Remove( iData->iBrushes.Count() - 1); + __ALFLOGSTRING1( "CAlfBrushArray::AppendL leave error %d", err ) + User::Leave( err ); + } + } + } + +// --------------------------------------------------------------------------- +// Insert +// --------------------------------------------------------------------------- +// +EXPORT_C void CAlfBrushArray::InsertL(TInt aPos, CAlfBrush* aBrush, TAlfOwnership aOwnership) + { + // Add to iBrushes array. + TInt err = iData->iBrushes.Insert( aBrush, aPos ); + if ( err != KErrNone ) + { + // on failure, log'n'leave + __ALFLOGSTRING1( "CAlfBrushArray::InsertL leave error %d", err ) + User::Leave( err ); + } + + err = aBrush->AppendContainingArray( *this ); + if ( err != KErrNone ) + { + // on failure remove from iBrushes, log'n'leave + iData->iBrushes.Remove( aPos ); + iData->iBrushes.Compress(); + __ALFLOGSTRING1( "CAlfBrushArray::InsertL leave error %d", err ) + User::Leave( err ); + } + + // Update the server side. + TInt3 int3(aBrush->Identifier(), aOwnership, aPos); + TPckgC buf(int3); + TBuf8<1> dum; + + err = iData->iOwner->Comms()->DoSynchronousCmd(EAlfVisualBrushArrayInsert, buf, dum ); + if ( err != KErrNone ) + { + // On error, remove it from the iBrushes and log'n'leave + RemoveBrush(aBrush, aPos); + + __ALFLOGSTRING1( "CAlfBrushArray::InsertL leave error %d", err ) + User::Leave(err); + } + + // append ownership only on success (otherwise double deletion takes place on leave) + if ( aOwnership == EAlfHasOwnership ) + { + err = iData->iOwnedBrushes.Append( aBrush ); + if ( err != KErrNone ) + { + // on failure remove brush (inform server as well) and log'n'leave + Remove( aPos ); + __ALFLOGSTRING1( "CAlfBrushArray::InsertL leave error %d", err ) + User::Leave( err ); + } + } + } + +// --------------------------------------------------------------------------- +// Remove +// --------------------------------------------------------------------------- +// +EXPORT_C void CAlfBrushArray::Remove(TInt aPos) + { + // Update the server side. + TPckgC buf(aPos); + TBuf8<1> dum; + + TInt err = iData->iOwner->Comms()->DoSynchronousCmd(EAlfVisualBrushArrayRemove, buf, dum ); + if ( err ) + { + __ALFLOGSTRING1( "CAlfBrushArray::Remove panic error %d", err ) + USER_INVARIANT(); + } + + RemoveBrush(iData->iBrushes[aPos], aPos); + } + +// --------------------------------------------------------------------------- +// Brush count +// --------------------------------------------------------------------------- +// +EXPORT_C TInt CAlfBrushArray::Count() const + { + if ( iData ) + { + return iData->iBrushes.Count(); + } + return 0; + } + +// --------------------------------------------------------------------------- +// [] +// --------------------------------------------------------------------------- +// +EXPORT_C CAlfBrush& CAlfBrushArray::operator [] (TInt aPos) + { + return At(aPos); + } + +// --------------------------------------------------------------------------- +// At +// --------------------------------------------------------------------------- +// +EXPORT_C CAlfBrush& CAlfBrushArray::At(TInt aPos) + { + return *iData->iBrushes[aPos]; + } + + +// --------------------------------------------------------------------------- +// Remove brush and owned brushes if they exist +// --------------------------------------------------------------------------- +// +void CAlfBrushArray::RemoveBrush(CAlfBrush* aBrush, TInt aPosIndex) + { + aBrush->RemoveContainingArray( *this ); + + const TInt ownedIndex = iData->iOwnedBrushes.Find( aBrush ); + if ( ownedIndex != KErrNotFound ) + { + iData->iOwnedBrushes.Remove( ownedIndex ); + iData->iOwnedBrushes.Compress(); + delete aBrush; + } + + if ( aPosIndex != KErrNotFound ) + { + iData->iBrushes.Remove( aPosIndex ); + iData->iBrushes.Compress(); + } + } + +// --------------------------------------------------------------------------- +// Brush is been deleted. Remove it from the array (if exists - might be several times). +// --------------------------------------------------------------------------- +// +void CAlfBrushArray::HandleBrushDestroyed( CAlfBrush& aBrush ) + { + for ( TInt index = Count()-1 ; index>=0 ; index-- ) + { + if ( &At(index) == &aBrush ) + { + // Update the server side. + TPckgC buf(index); + TBuf8<1> dum; + TInt err = iData->iOwner->Comms()->DoSynchronousCmd(EAlfVisualBrushArrayRemove, buf, dum ); + if ( err ) + { + __ALFLOGSTRING1( "CAlfBrushArray::HandleBrushDestroyed panic error %d", err ) + USER_INVARIANT(); + } + + // Check the owned brushes - should never found! + const TInt ownedIndex = iData->iOwnedBrushes.Find( &aBrush ); + __ASSERT_ALWAYS( ownedIndex == KErrNotFound, USER_INVARIANT() ); + + // Remove from iBrushes array + iData->iBrushes.Remove( index ); + iData->iBrushes.Compress(); + + // create watcher + if ( !iData->iWatcher ) + { + // do not mind the OOM + iData->iWatcher = new CAlfBrushArrayUsageWatcher; + } + } + } + } + +