diff -r 29c8f9bc68e1 -r 5960d2d03390 vpnengine/sit/src/taskarrivalobserver.cpp --- 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; - }