photosgallery/collectionframework/thumbnailcreator/src/glxtntaskmanager.cpp
changeset 0 4e91876724a2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/photosgallery/collectionframework/thumbnailcreator/src/glxtntaskmanager.cpp	Thu Dec 17 08:45:44 2009 +0200
@@ -0,0 +1,346 @@
+/*
+* 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 <glxtracer.h>
+
+#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 &&  !IsActive() ) 
+		{
+        AsyncRun();
+		}
+    else if( dynamic_cast<CGlxtnBackgroundGenerationTask*>(iCurrentTask) && (!dynamic_cast<CGlxtnBackgroundGenerationTask*>(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<CGlxtnBackgroundGenerationTask*>(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);
+    }