diff -r f7f0874bfe7d -r 74c9f037fd5d engine/collectionframework/thumbnailcreator/src/glxtntaskmanager.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/engine/collectionframework/thumbnailcreator/src/glxtntaskmanager.cpp Fri Mar 19 09:28:59 2010 +0200 @@ -0,0 +1,345 @@ +/* +* Copyright (c) 2008-2009 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: Task manager for multiple tasks. Allows asynchronosity and +* tracking/callback for long running tasks. +* +*/ + + + +/** + * @internal reviewed 31/07/2007 by Simon Brooks + */ + +#include "glxtntaskmanager.h" + +#include + +#include "glxtnbackgroundgenerationtask.h" +#include "glxtntask.h" + +const TInt KGlxTMMaxTasksToRunInOneRound = 4; +// ----------------------------------------------------------------------------- +// Static Constructor +// ----------------------------------------------------------------------------- +// +CGlxtnTaskManager* CGlxtnTaskManager::NewL() + { + TRACER("CGlxtnTaskManager::NewL()"); + CGlxtnTaskManager* self = new (ELeave) CGlxtnTaskManager(); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +// ----------------------------------------------------------------------------- +// Constructor +// ----------------------------------------------------------------------------- +// +CGlxtnTaskManager::CGlxtnTaskManager() + : CActive(EPriorityStandard) + { + TRACER("CGlxtnTaskManager::CGlxtnTaskManager()"); + } + +// ----------------------------------------------------------------------------- +// ConstructL +// ----------------------------------------------------------------------------- +// +void CGlxtnTaskManager::ConstructL() + { + TRACER("void CGlxtnTaskManager::ConstructL()"); + CActiveScheduler::Add(this); + } + +// ----------------------------------------------------------------------------- +// Destructor +// ----------------------------------------------------------------------------- +// +CGlxtnTaskManager::~CGlxtnTaskManager() + { + TRACER("CGlxtnTaskManager::~CGlxtnTaskManager()"); + Cancel(); + iTasks.ResetAndDestroy(); + } + +// ----------------------------------------------------------------------------- +// Task by id +// ----------------------------------------------------------------------------- +// +CGlxtnTask* CGlxtnTaskManager::Task(const TGlxtnTaskId& aId) const + { + TRACER("CGlxtnTaskManager::Task(const TGlxtnTaskId& aId)"); + TInt count = iTasks.Count(); + for (TInt i = 0; i < count; i++) + { + CGlxtnTask* task = iTasks[i]; + if (task->Id() == aId) + { + return task; + } + } + + // Not found + return NULL; + } + +// ----------------------------------------------------------------------------- +// AddTaskL +// ----------------------------------------------------------------------------- +// +void CGlxtnTaskManager::AddTaskL(CGlxtnTask* aTask, TExecutionOrder aExecutionOrder) + { + TRACER("CGlxtnTaskManager::AddTaskL()"); + __ASSERT_DEBUG(aTask, Panic(EGlxPanicNullPointer)); + __ASSERT_DEBUG(iTasks.Find(aTask) == KErrNotFound, Panic(EGlxPanicIllegalArgument)); // Task already added + CleanupStack::PushL(aTask); + + // Order manually to allow full control over placement of tasks when + // priorities are the same + TInt priority = aTask->Priority(); + TInt count = iTasks.Count(); + + TInt pos = 0; + while ( pos < count ) + { + TInt compPriority = iTasks[pos]->Priority(); + if ( compPriority < priority + || (compPriority == priority && EFirstOut == aExecutionOrder) ) + { + break; + } + + pos++; + } + + iTasks.InsertL(aTask, pos); + CleanupStack::Pop(aTask); + + aTask->SetManager(this); + + // Start processing the task if this active object is not already doing something else + if ( !iCurrentTask ) + { + AsyncRun(); + } + else if( dynamic_cast(iCurrentTask) && (!dynamic_cast(aTask)) ) + { + iCurrentTask->Cancel(); + } + } + +// ----------------------------------------------------------------------------- +// CancelTasks +// Cancel all tasks relating to a given media item. +// ----------------------------------------------------------------------------- +// +void CGlxtnTaskManager::CancelTasks(const TGlxMediaId& aItemId) + { + TRACER("CGlxtnTaskManager::CancelTasks()"); + TInt count = iTasks.Count(); + + if( aItemId == TGlxMediaId(0) ) + { + if( dynamic_cast(iCurrentTask) ) + { + iCurrentTask->Cancel(); + } + } + + for ( TInt i = 0; i < count; i++ ) + { + CGlxtnTask* task = iTasks[i]; + + if ( task->ItemId() == aItemId ) + { + task->Cancel(); + } + } + } + +// ----------------------------------------------------------------------------- +// CancelTasks +// Cancel all tasks using a given storage. +// ----------------------------------------------------------------------------- +// +void CGlxtnTaskManager::CancelTasks(MGlxtnThumbnailStorage* aStorage) + { + TRACER("void CGlxtnTaskManager::CancelTasks()"); + TInt count = iTasks.Count(); + + for ( TInt i = 0; i < count; i++ ) + { + CGlxtnTask* task = iTasks[i]; + + if ( task->Storage() == aStorage ) + { + task->Cancel(); + } + } + } + +// ----------------------------------------------------------------------------- +// RunL +// ----------------------------------------------------------------------------- +// +void CGlxtnTaskManager::RunL() + { + TRACER("void CGlxtnTaskManager::RunL()"); + TInt taskIndex = 0; + TInt tasksRun = 0; + while ( taskIndex < iTasks.Count() ) + { + if ( iCurrentTask ) + { + if ( CGlxtnTask::EStarting == iCurrentTask->State() ) + { + // Start the task + iCurrentTask->StartL(iStatus); + } + else if ( CGlxtnTask::ERunning == iCurrentTask->State() ) + { + // Let the task run + iCurrentTask->RunL(iStatus); + } + + if ( CGlxtnTask::ERunning == iCurrentTask->State() ) + { + SetActive(); + return; + } + + // Task completed or cancelled, delete the task immediately + __ASSERT_DEBUG(iStatus != KRequestPending, Panic(EGlxPanicIllegalState)); + __ASSERT_DEBUG(CGlxtnTask::EComplete == iCurrentTask->State() + || CGlxtnTask::ECanceled == iCurrentTask->State(), Panic(EGlxPanicIllegalState)); + + // Search for the task again, since the processing of the task might have added new tasks to the queue + TInt index = iTasks.Find(iCurrentTask); + __ASSERT_DEBUG(index != KErrNotFound, Panic(EGlxPanicLogicError)); + iTasks.Remove(index); + delete iCurrentTask; + iCurrentTask = NULL; + + // Start from top, since the task might have added another task + taskIndex = 0; + } + else + { + CGlxtnTask* task = iTasks[taskIndex]; + CGlxtnTask::TState state = task->State(); + + switch ( state ) + { + case CGlxtnTask::EIdle: + // Task not started. Ignore and try next task + taskIndex++; // Skip + break; + case CGlxtnTask::EStarting: + { + // Start the task + iCurrentTask = task; + + // Update active object priority to match task priority + TInt priority = task->Priority(); + if ( priority != Priority() ) + { + SetPriority(priority); + } + + // Check if too many tasks have been run during this call to RunL. + // This check exist to make sure a blocking loop does not occur, in which + // a task creates another task which completes immediately, which creates + // another task, which also completes immediately. (Task don't have to + // be asynchronous.) + tasksRun++; + if ( tasksRun >= KGlxTMMaxTasksToRunInOneRound ) + { + AsyncRun(); + return; + } + } + break; + case CGlxtnTask::ECanceled: + // Task is canceled, remove from queue + delete task; + iTasks.Remove(taskIndex); + break; + default: + Panic(EGlxPanicIllegalState); // Unknown or wrong state + break; + } + } + } + } + +// ----------------------------------------------------------------------------- +// DoCancel +// ----------------------------------------------------------------------------- +// +void CGlxtnTaskManager::DoCancel() + { + TRACER("CGlxtnTaskManager::DoCancel()"); + TInt count = iTasks.Count(); + for (TInt i = 0; i < count; i++) + { + CGlxtnTask* task = iTasks[i]; + CGlxtnTask::TState state = task->State(); + if (state == CGlxtnTask::ERunning) + { + task->Cancel(); + } + } + } + +// ----------------------------------------------------------------------------- +// RunError +// ----------------------------------------------------------------------------- +// +TInt CGlxtnTaskManager::RunError(TInt aError) + { + TRACER("CGlxtnTaskManager::RunError()"); + if ( iCurrentTask ) + { + iCurrentTask->RunError(aError); + + if ( CGlxtnTask::ERunning == iCurrentTask->State() ) + { + SetActive(); + } + else + { + AsyncRun(); + } + + return KErrNone; + } + + return aError; + } + +// ----------------------------------------------------------------------------- +// AsyncRun +// ----------------------------------------------------------------------------- +// +void CGlxtnTaskManager::AsyncRun() + { + TRACER("CGlxtnTaskManager::AsyncRun()"); + // Issue a self-completing request. + iStatus = KRequestPending; + SetActive(); + TRequestStatus* status = &iStatus; + User::RequestComplete(status, KErrNone); + }