vpnengine/sit/src/taskarrivalobserver.cpp
branchRCL_3
changeset 49 5960d2d03390
parent 44 735de8341ce4
--- a/vpnengine/sit/src/taskarrivalobserver.cpp	Wed Sep 15 13:20:54 2010 +0300
+++ b/vpnengine/sit/src/taskarrivalobserver.cpp	Wed Oct 13 15:42:16 2010 +0300
@@ -33,6 +33,7 @@
     }
     
 CTaskArrivalObserver::CTaskArrivalObserver()
+    : CAsyncOneShot(EPriorityNormal)
     {
     }
 
@@ -48,9 +49,8 @@
     LOG(Log::Printf(_L("CTaskArrivalObserver::~CTaskArrivalObserver\n")));
     Cancel();
     iEventMediator.Close();
-    
     if (iTaskHandlerList)
-        {    
+        {
         iTaskHandlerList->ResetAndDestroy();
         delete iTaskHandlerList;
         }
@@ -116,25 +116,62 @@
     {
     LOG(Log::Printf(_L("CTaskArrivalObserver::LaunchTaskHandlerL\n")));
     // A new task has arrived so create a task handler for it
+    CTaskHandler* taskHandler = CreateTaskHandlerL(aEventSpec);
 
-    CTaskHandler* taskHandler = TaskHandlerCreator::CreateTaskHandlerL(this, aEventSpec);
+    // Add the handler to the list of active handlers
+    iTaskHandlerList->AppendL(taskHandler);
+
+    // And start performing the task
+    taskHandler->Start();
+    }
+
+CTaskHandler* CTaskArrivalObserver::CreateTaskHandlerL(const TTaskArrivedEventData& aEventSpec)
+    {
+    LOG(Log::Printf(_L("CTaskArrivalObserver::CreateTaskHandlerL\n")));
+    CTaskHandler* taskHandler = NULL;
+
+    taskHandler = TaskHandlerCreator::CreateTaskHandlerL(this, aEventSpec);
+
     if (!taskHandler)
         {
         User::Panic(KSitName, EPanicUnknownEventType);
         }
-        
-    // Add the handler to the list of active handlers
-    iTaskHandlerList->AppendL(taskHandler);
+
+    return taskHandler;
+    }
 
-    //Create the asyncleaner for cleaning the task handler, when the
-    //task is done.
-    CAsyncCleaner* asyncCleaner = new (ELeave) CAsyncCleaner(this, taskHandler);    
-    iAsyncCleanerList->AppendL(asyncCleaner);
-       
-    // And start performing the task
-    taskHandler->Start();
+TInt CTaskArrivalObserver::FindTaskHandler(CTaskHandler* aTaskHandler)
+    {
+    TInt foundIndex = KUnfoundIndex;
+    
+    for (TInt i = 0; i < iTaskHandlerList->Count(); i++)
+        {
+        if (iTaskHandlerList->At(i) == aTaskHandler)
+            {
+            foundIndex = i;
+            break;
+            };
+        }
+
+    return foundIndex;
     }
     
+TInt CTaskArrivalObserver::FindAsyncCleaner(CAsyncCleaner* aAsyncCleaner)
+    {
+    TInt foundIndex = KUnfoundIndex;
+    
+    for (TInt i = 0; i < iAsyncCleanerList->Count(); i++)
+        {
+        if (iAsyncCleanerList->At(i) == aAsyncCleaner)
+            {
+            foundIndex = i;
+            break;
+            };
+        }
+
+    return foundIndex;
+    }
+
 void CTaskArrivalObserver::TaskHandlerComplete(CTaskHandler* aTaskHandler)
     {
     LOG(Log::Printf(_L("CTaskArrivalObserver::TaskHandlerComplete\n")));
@@ -144,73 +181,98 @@
     // Otherwise we'll get panic E32USER-CBase 42 (SetActive called
     // while active object is already active).
     
-    //Find the async cleaner for the task handler:
-    TInt i = 0;
-    for (i = 0; i < iAsyncCleanerList->Count(); ++i)
+    // NOTE. Each asyncCleaner instance will cause itself to be deleted
+    CAsyncCleaner* asyncCleaner = new CAsyncCleaner(this, aTaskHandler);
+    if (asyncCleaner)
+        {
+        // Add the handler to a list of cleaners. This list
+        // is needed to handle some rare cases where the SIT
+        // thread dies before one or more async cleaners get
+        // the chance to delete themselves. Such cleaner
+        // instances get destroyed by the CTaskArrivalObserver
+        // destructor.
+        TRAP_IGNORE(iAsyncCleanerList->AppendL(asyncCleaner));
+        // Initiate the task handler delete operation
+        asyncCleaner->Start();
+        }
+    else
         {
-        if (iAsyncCleanerList->At(i)->IsMatchingCleaner(*aTaskHandler))
-            {
-            iAsyncCleanerList->At(i)->Start();
-            }
+        // Backup - just in case asyncCleaner could not be created
+        AsyncDeleteTaskHandler(aTaskHandler);
         }
-    __ASSERT_DEBUG(i <= iAsyncCleanerList->Count(), User::Invariant());
-    
+    }
+
+void CTaskArrivalObserver::AsyncDeleteTaskHandler(CTaskHandler* aTaskHandler)
+    {
+    LOG(Log::Printf(_L("CTaskArrivalObserver::AsyncDeleteTaskHandler\n")));
+    iTaskHandlerToDelete = aTaskHandler;
+    Call();
+    }
+
+void CTaskArrivalObserver::RunL() // Called as a result of AsyncDeleteTaskHandler
+    {
+    LOG(Log::Printf(_L("CTaskArrivalObserver::RunL\n")));
+
+    DeleteTaskHandler(iTaskHandlerToDelete);
+
+    iTaskHandlerToDelete = NULL;    
     }
 
 void CTaskArrivalObserver::DeleteTaskHandler(CTaskHandler* aTaskHandler)
     {
     LOG(Log::Printf(_L("CTaskArrivalObserver::DeleteTaskHandler\n")));
     
-    __ASSERT_DEBUG(aTaskHandler != NULL, User::Invariant());
-     
     // The specified task handler has done its
     // job succesfully so it can be deleted
-    TInt taskHandlerIndex = KErrNotFound;
-        
-    for (TInt i = 0; i < iTaskHandlerList->Count(); i++)
+    TInt taskHandlerIndex = FindTaskHandler(aTaskHandler);
+    
+    if (taskHandlerIndex != KUnfoundIndex)
         {
-        if (iTaskHandlerList->At(i) == aTaskHandler)
-            {
-            taskHandlerIndex = i;
-            break;
-            };
+        LOG(Log::Printf(_L("CTaskArrivalObserver::DeleteTaskHandler - deleting task handler\n")));
+        // Delete the task handler
+        delete iTaskHandlerList->At(taskHandlerIndex);
+        // Delete the list item
+        iTaskHandlerList->Delete(taskHandlerIndex);
+        // Deleting elements from the array does not cause
+        // the array buffer to be automatically compressed.
+        // Compress it to return excess space to the heap
+        // as task handlers come and go.
+        iTaskHandlerList->Compress();
         }
-    
-    __ASSERT_DEBUG(taskHandlerIndex >= 0, User::Invariant());
-       
-    LOG(Log::Printf(_L("CTaskArrivalObserver::DeleteTaskHandler - deleting task handler\n")));
-    // Delete the task handler
-    delete aTaskHandler;
-    iTaskHandlerList->Delete(taskHandlerIndex);
-    iTaskHandlerList->Compress();
+    else
+        {
+        // 
+        delete aTaskHandler;
+        }
     }
     
 void CTaskArrivalObserver::DeleteAsyncCleaner(CAsyncCleaner* aAsyncCleaner)
     {
     LOG(Log::Printf(_L("CTaskArrivalObserver::DeleteAsyncCleaner\n")));
     
-    __ASSERT_DEBUG(aAsyncCleaner != NULL, User::Invariant());
-    
     // The specified asynchronous cleaner
     // has done its job and be deleted
+    TInt asyncCleanerIndex = FindAsyncCleaner(aAsyncCleaner);
     
-    TInt asyncCleanerIndex = KErrNotFound;
-    for (TInt i = 0; i < iAsyncCleanerList->Count(); i++)
+    if (asyncCleanerIndex != KUnfoundIndex)
         {
-        if (iAsyncCleanerList->At(i) == aAsyncCleaner)
-            {
-            asyncCleanerIndex = i;
-            break;
-            };
+        LOG(Log::Printf(_L("CTaskArrivalObserver::DeleteAsyncCleaner - deleting async cleaner\n")));
+        // Delete the cleaner object
+        delete iAsyncCleanerList->At(asyncCleanerIndex);
+        // Delete the list item
+        iAsyncCleanerList->Delete(asyncCleanerIndex);
+        // Deleting elements from the array does not cause
+        // the array buffer to be automatically compressed.
+        // Compress it to return excess space to the heap
+        // as cleaner objects come and go.
+        iAsyncCleanerList->Compress();
         }
-   
-    __ASSERT_DEBUG(asyncCleanerIndex >= 0, User::Invariant());
-    
-    // Delete the cleaner object
-    delete aAsyncCleaner;
-    iAsyncCleanerList->Delete(asyncCleanerIndex);
-    iAsyncCleanerList->Compress();
-    
+    else
+        {
+        // Always delete the cleaner instance even
+        // though it have not been added to the list
+        delete aAsyncCleaner;
+        }
     }
 
 void CTaskArrivalObserver::TaskHandlerFatalError(CTaskHandler* /*aTaskHandler*/, TInt /*aError*/)
@@ -248,8 +310,3 @@
     // Delete this cleaner object instance as well
     iTaskArrivalObserver->DeleteAsyncCleaner(this);
     }
-
-TBool CAsyncCleaner::IsMatchingCleaner(const CTaskHandler& aTaskHandler) const
-    {
-    return iTaskHandlerToDelete == &aTaskHandler;
-    }