emailuis/emailui/src/FreestyleEmailDownloadInformationMediator.cpp
changeset 2 5253a20d2a1e
parent 1 12c456ceeff2
child 3 a4d6f1ea0416
--- a/emailuis/emailui/src/FreestyleEmailDownloadInformationMediator.cpp	Thu Jan 07 12:38:38 2010 +0200
+++ b/emailuis/emailui/src/FreestyleEmailDownloadInformationMediator.cpp	Mon Jan 18 20:08:26 2010 +0200
@@ -44,7 +44,8 @@
 //
 CFSEmailDownloadInfoMediator::CFSEmailDownloadInfoMediator( CFSMailClient& aMailClient )
     : CActive( EPriorityNormal ), iMailClient(aMailClient),
-    iDownloadArray( KArrayGranularity, _FOFF(TDownload, iRequestId) ), iDownloadsStarted ( EFalse )
+    iDownloadArray( KArrayGranularity, _FOFF(TDownload, iRequestId) ), iDownloadsStarted ( EFalse ),
+    iNotificationsInProgress( 0 ), iObserverDeleted( EFalse )
 	{
     FUNC_LOG;
 	CActiveScheduler::Add( this );
@@ -383,11 +384,11 @@
 void CFSEmailDownloadInfoMediator::StopObserving( MFSEmailDownloadInformationObserver* aObserver, TFSMailMsgId aMessageId )
 	{
 	FUNC_LOG;
-    for (TInt i=0; i<iObserverArray.Count(); i++)
+    for (TInt i=iObserverArray.Count()-1; i>=0; i--)
     	{
    		if ( iObserverArray[i].iObserver == aObserver && iObserverArray[i].iMessageId == aMessageId )
    			{
-   			iObserverArray.Remove(i);
+            RemoveObserver(i);
    			}
     	}
 	}
@@ -395,14 +396,14 @@
 void CFSEmailDownloadInfoMediator::StopObserving( MFSEmailDownloadInformationObserver* aObserver )
 	{
 	FUNC_LOG;
-    for (TInt i=0; i<iObserverArray.Count(); i++)
+    for ( TInt i=iObserverArray.Count()-1; i>=0; i-- )
     	{
    		if ( iObserverArray[i].iObserver == aObserver )
    			{
-   			iObserverArray.Remove(i);
+   			RemoveObserver(i);
    			}
     	}
-    for (TInt i=0; i<iAllObserverArray.Count(); i++)
+    for ( TInt i=iAllObserverArray.Count()-1; i>=0; i-- )
     	{
 		if ( iAllObserverArray[i] == aObserver )
    			{
@@ -411,6 +412,23 @@
     	}
 	}
 
+void CFSEmailDownloadInfoMediator::RemoveObserver( TInt aIdx )
+    {
+    if ( iNotificationsInProgress == 0 )
+        {
+        // If we're not currently iterating over the array, remove the entry
+        // immediately.
+        iObserverArray.Remove( aIdx );
+        }
+    else
+        {
+        // We're currently iterating over the array: mark the entry as
+        // deleted and flag that we've done so.
+        iObserverArray[aIdx].iDeleted = ETrue;
+        iObserverDeleted = ETrue;
+        }
+    }
+
 void CFSEmailDownloadInfoMediator::DownloadL( TPartData aPart, TBool aCompleteNote )
 	{
 	FUNC_LOG;
@@ -725,25 +743,61 @@
 		
 	SetActive();
     }
-	
+
 void CFSEmailDownloadInfoMediator::NotifyObserversL( const TFSProgress& aEvent, const TPartData& aPart )
     {
 	FUNC_LOG;
+
+	// notify observers of this particular message part
+    iNotificationsInProgress++;
+    TRAPD( error, NotifyPartObserversL( aEvent, aPart ) );
+    if ( --iNotificationsInProgress == 0 )
+        {
+        CleanUpObservers();
+        }
+    if ( error )
+        {
+        User::Leave( error );
+        }
+
+    // send response to every 'all observer'
+    for ( TInt i=iAllObserverArray.Count()-1; i>=0; i-- )
+        {
+        iAllObserverArray[i]->RequestResponseL( aEvent, aPart );
+        }
+    }
+
+void CFSEmailDownloadInfoMediator::NotifyPartObserversL( const TFSProgress& aEvent, const TPartData& aPart )
+    {
+	FUNC_LOG;
 	// go through all observers
-    for ( TInt j=iObserverArray.Count()-1; j>=0; j--)
+    for ( TInt j=iObserverArray.Count()-1; j>=0; j-- )
 		{
 		// if observer is observing this message
-		if ( iObserverArray[j].iMessageId == aPart.iMessageId )
+		if ( !iObserverArray[j].iDeleted && iObserverArray[j].iMessageId == aPart.iMessageId )
 			{
 			// send response to observer
 			iObserverArray[j].iObserver->RequestResponseL( aEvent, aPart );
 			}
 		}
-	// send response to every 'all observer'
-	for (TInt i=0; i<iAllObserverArray.Count(); i++)
-		{
-		iAllObserverArray[i]->RequestResponseL( aEvent, aPart );
-		}
+    }
+
+void CFSEmailDownloadInfoMediator::CleanUpObservers()
+    {
+    FUNC_LOG;
+    // If one or more observers have been marked for deletion, go through
+    // the observer array and remove them.
+    if ( iObserverDeleted )
+        {
+        for ( TInt j=iObserverArray.Count()-1; j>=0; j-- )
+            {
+            if ( iObserverArray[j].iDeleted )
+                {
+                iObserverArray.Remove(j);
+                }
+            }
+        iObserverDeleted = EFalse;
+        }
     }
 
 void CFSEmailDownloadInfoMediator::RunL()