mpx/commonframework/common/src/mpxtaskqueue.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 17 Dec 2009 08:55:47 +0200
changeset 0 a2952bb97e68
permissions -rw-r--r--
Revision: 200949 Kit: 200951

/*
* Copyright (c) 2006 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:  Serializing the task
*
*/

#include <mpxlog.h>
#include "mpxtaskqueueobserver.h"
#include "mpxtaskqueue.h"

// ============================ PRIVATE CLASS =================================
NONSHARABLE_CLASS(CTask) : public CBase
    {
public:
    /**
    *  C++ constructor
    *
    *  @param aTask task id
    *  @param aCallback callback
    *  @param aHandler task handler
    *  @param aParamData data
    *  @param aBuf, extra data in buffer, ownership transferred.
    *  @param aPtrData, extra pointer data
    *  @param aAlive1, pointer to CBased object, ownership transferred
    *  @param aCObject2, pointer to CBased object, ownership transferred
    */
    CTask(TInt aTask,
          TAny* aCallback,
          MMPXTaskQueueObserver* aHandler,
          TInt aParamData=0,
          CBufBase* aBuf=NULL,
          TAny* aPtrData=NULL,
          CBase* aCObject1=NULL,
          CBase* aCObject2=NULL
          );

    /**
    * destructor
    */
    ~CTask();

    /**
    *  Offset to the task queue
    *
    *  @return the offset
    */
    static TInt Offset();

public:
    TInt iTask;
    TAny* iCallback; // call back when task completed
    MMPXTaskQueueObserver* iHandler; // task handler which will execute the task
    TInt iParamData; // Integer data
    CBufBase* iBuf;  // owned. deleted when task is removed
    TAny* iPtrData;  // ojbect data, Not owned.
    CBase* iCObject1;  // owned
    CBase* iCObject2;  // owned

    TPtrC8 iPtr;     // Descriptor to iBuf
    TSglQueLink iLink;
    };

// ----------------------------------------------------------------------------
// Task contructor
// ----------------------------------------------------------------------------
//
CTask::CTask(
    TInt aTask,
    TAny* aCallback,
    MMPXTaskQueueObserver* aHandler,
    TInt aParamData/*=0*/,
    CBufBase* aBuf/*=NULL*/,
    TAny* aPtrData/*=NULL*/,
    CBase* aCObject1/*=NULL*/,
    CBase* aCObject2/*=NULL*/)
:   iTask(aTask), iCallback(aCallback), iHandler(aHandler),
    iParamData(aParamData),iBuf(aBuf), iPtrData(aPtrData),
    iCObject1(aCObject1),iCObject2(aCObject2)
    {
    if (iBuf)
        {
        iPtr.Set(iBuf->Ptr(0));
        }
    else
        {
        iPtr.Set(KNullDesC8);
        }
    }

// ----------------------------------------------------------------------------
// Task destructor
// ----------------------------------------------------------------------------
//
CTask::~CTask()
    {
    delete iBuf;
    delete iCObject1;
    delete iCObject2;
    }

// ----------------------------------------------------------------------------
// Offset of the task queue
// ----------------------------------------------------------------------------
//
TInt CTask::Offset()
    {
    return _FOFF(CTask,iLink);
    }

// ============================ PRIVATE CLASS =================================
NONSHARABLE_CLASS(CMPXTaskQueueScheduler) : public CActive
    {
    public:
        /**
        * Two-phased constructor
        * @param aObserver the observer
        * @return object of constructed
        */
        static CMPXTaskQueueScheduler* NewL(TSglQue<CTask>& aTaskQueue);

        /**
        *  Destructor
        */
        ~CMPXTaskQueueScheduler();

        /**
        *  Schedule to execute next task
        */
        void ScheduleNextTask();

        /**
        *  Complete current task
        */
        void CompleteTask();

    public: // From base classes

        /**
        * From CActive
        * Handles an active object's request completion event
        */
        void RunL();

        /**
        * From CActive
        * Implements cancellation of an outstanding request.
        */
        void DoCancel();

    private:
        /**
        *  C++ constructor
        *
        *  @param aObserver observer
        */
        CMPXTaskQueueScheduler(TSglQue<CTask>& aTaskQueue);

        /**
        *  2nd phase contructor
        *
        */
        void ConstructL();

    private:
        TSglQue<CTask>& iTaskQueue;
        TBool iTaskProcessing;
    };

// ----------------------------------------------------------------------------
// Two-phased constructor
// ----------------------------------------------------------------------------
//
CMPXTaskQueueScheduler* CMPXTaskQueueScheduler::NewL(TSglQue<CTask>& aTaskQueue)
    {
    CMPXTaskQueueScheduler* s = new(ELeave)CMPXTaskQueueScheduler(aTaskQueue);
    CleanupStack::PushL(s);
    s->ConstructL();
    CleanupStack::Pop(s);
    return s;
    }

// ----------------------------------------------------------------------------
// Constructor.
// ----------------------------------------------------------------------------
//
CMPXTaskQueueScheduler::CMPXTaskQueueScheduler(TSglQue<CTask>& aTaskQueue)
    :CActive(EPriorityStandard),
    iTaskQueue(aTaskQueue),
    iTaskProcessing(EFalse)
    {
    CActiveScheduler::Add(this);
    }

// ----------------------------------------------------------------------------
// Constructor.
// ----------------------------------------------------------------------------
//
void CMPXTaskQueueScheduler::ConstructL()
    {
    }

// ----------------------------------------------------------------------------
// Destructor
// ----------------------------------------------------------------------------
//
CMPXTaskQueueScheduler::~CMPXTaskQueueScheduler()
    {
    Cancel();
    }

// ----------------------------------------------------------------------------
// Schedule to execute next task
// ----------------------------------------------------------------------------
//
void CMPXTaskQueueScheduler::ScheduleNextTask()
    {
    if (!IsActive() && !iTaskProcessing)
        {
        SetActive();
        TRequestStatus* status = &iStatus;
        User::RequestComplete(status, KErrNone);
        }
    }

// ----------------------------------------------------------------------------
// Complete current task
// ----------------------------------------------------------------------------
//
void CMPXTaskQueueScheduler::CompleteTask()
    {
    iTaskProcessing = EFalse;
    }

// ----------------------------------------------------------------------------
// Plugin has completed the request
// ----------------------------------------------------------------------------
//
void CMPXTaskQueueScheduler::RunL()
    {
    MPX_FUNC_EX("CMPXTaskQueueScheduler::RunL");
    if (!iTaskQueue.IsEmpty())
        {
        CTask* task=iTaskQueue.First();
        if (task->iHandler)
            {
            iTaskProcessing = ETrue;
            MPX_DEBUG3("CMPXTaskQueueScheduler::RunL %d cb 0x%08x",
                       task->iTask, task->iCallback);
            task->iHandler->ExecuteTask(task->iTask,
                                        task->iParamData,
                                        task->iPtrData,
                                        *(task->iBuf),
                                        task->iCallback,
                                        task->iCObject1,
                                        task->iCObject2);
            }
        }
    }

// ----------------------------------------------------------------------------
// Canceling has to be done by plugin
// ----------------------------------------------------------------------------
//
void CMPXTaskQueueScheduler::DoCancel()
    {
    iTaskProcessing = EFalse;
    }


// ============================ MEMBER FUNCTIONS ==============================

// ----------------------------------------------------------------------------
// Two-phased constructor
// ----------------------------------------------------------------------------
//
EXPORT_C CMPXTaskQueue* CMPXTaskQueue::NewL()
    {
    CMPXTaskQueue* s = new(ELeave)CMPXTaskQueue();
    CleanupStack::PushL(s);
    s->ConstructL();
    CleanupStack::Pop(s);
    return s;
    }

// ----------------------------------------------------------------------------
// Constructor.
// ----------------------------------------------------------------------------
//
CMPXTaskQueue::CMPXTaskQueue()
   :iTaskList(CTask::Offset())
    {
    }

// ----------------------------------------------------------------------------
// Destructor
// ----------------------------------------------------------------------------
//
EXPORT_C CMPXTaskQueue::~CMPXTaskQueue()
    {
    Reset();
    }

// ----------------------------------------------------------------------------
// Constructor.
// ----------------------------------------------------------------------------
//
void CMPXTaskQueue::ConstructL()
    {
    }


// ----------------------------------------------------------------------------
// Add a task
// ----------------------------------------------------------------------------
//
EXPORT_C  void CMPXTaskQueue::AddTaskL(
    TInt aTask,
    TAny* aCallback,
    TInt aParamData/*=0*/,
    CBufBase* aBuf/*=NULL*/,
    TAny* aPtrData/*=NULL*/,
    CBase* aCObject1/*=NULL*/,
    CBase* aCObject2/*=NULL*/)
    {
    MPX_FUNC_EX("CMPXTaskQueue::AddTaskL");
    CTask* t=new(ELeave)CTask(aTask,aCallback,NULL, aParamData,
                              aBuf, aPtrData,aCObject1,aCObject2);
    iTaskList.AddLast(*t);
    }

// ----------------------------------------------------------------------------
// Remove a task
// ----------------------------------------------------------------------------
//
EXPORT_C TAny* CMPXTaskQueue::RemoveTask()
    {
    MPX_FUNC_EX("CMPXTaskQueue::RemoveTask()");
    // Remove current task from queque
    if (iTaskList.IsEmpty())
        {
        return NULL;
        }
    CTask* task=iTaskList.First();
    TAny* cb=task->iCallback;
    iTaskList.Remove(*task);
    MPX_DEBUG3("CMPXTaskQueue::RemoveTask %d cb 0x%08x", task->iTask, cb);
    delete task;
    return cb;
    }

// ----------------------------------------------------------------------------
// Remove task from a client
// ----------------------------------------------------------------------------
//
EXPORT_C void CMPXTaskQueue::RemoveTask(TAny* aCallback)
    {
    MPX_FUNC_EX("CMPXTaskQueue::RemoveTask(TAny* aCallback)");
    // Remove current task from queque
    TSglQueIter<CTask> iter(iTaskList);
    CTask* t=NULL;
    while ((t=iter++) != NULL) // Compiler warning on while (t=iter++)
        {
        if (t->iCallback == aCallback)
            {
            iTaskList.Remove(*t);
            MPX_DEBUG3("CMPXTaskQueue::RemoveTask %d cb 0x%08x",
                       t->iTask, aCallback);
            delete t;
            }
        }
    }

// ----------------------------------------------------------------------------
// Reutrn if the task queue empty
// ----------------------------------------------------------------------------
//
EXPORT_C TBool CMPXTaskQueue::IsEmpty()
    {
    return iTaskList.IsEmpty();
    }

// ----------------------------------------------------------------------------
// Reset task queue
// ----------------------------------------------------------------------------
//
EXPORT_C void CMPXTaskQueue::Reset()
    {
    TSglQueIter<CTask> iter(iTaskList);
    CTask* t=NULL;
    while ((t=iter++) != NULL) // Compiler warning on while (t=iter++)
        {
        delete t;
        }
    iTaskList.Reset();
    }

// ----------------------------------------------------------------------------
// Return current task
// ----------------------------------------------------------------------------
//
EXPORT_C TInt CMPXTaskQueue::Param()
    {
    return iTaskList.IsEmpty() ? KErrNotFound :  iTaskList.First()->iParamData;
    }

// ----------------------------------------------------------------------------
// Return current parameter data
// ----------------------------------------------------------------------------
//
EXPORT_C TInt CMPXTaskQueue::Task()
    {
    return iTaskList.IsEmpty() ? KErrNotFound :  iTaskList.First()->iTask;
    }

// ----------------------------------------------------------------------------
// Return current call back
// ----------------------------------------------------------------------------
//
EXPORT_C TAny* CMPXTaskQueue::Callback()
    {
    return iTaskList.IsEmpty() ? NULL :  iTaskList.First()->iCallback;
    }

// ----------------------------------------------------------------------------
// Return pointer data
// ----------------------------------------------------------------------------
//
EXPORT_C TAny* CMPXTaskQueue::PtrData()
    {
    return iTaskList.IsEmpty() ? NULL :  iTaskList.First()->iPtrData;
    }

// ----------------------------------------------------------------------------
// Return buffer data
// ----------------------------------------------------------------------------
//
EXPORT_C const TDesC8& CMPXTaskQueue::BufData()
    {
    if (iTaskList.IsEmpty())
        {
        return KNullDesC8;
        }
    else
        {
        return iTaskList.First()->iPtr;
        }
    }

// ----------------------------------------------------------------------------
// Two-phased constructor
// ----------------------------------------------------------------------------
//
EXPORT_C CMPXActiveTaskQueue* CMPXActiveTaskQueue::NewL()
    {
    CMPXActiveTaskQueue* s = new(ELeave)CMPXActiveTaskQueue();
    CleanupStack::PushL(s);
    s->ConstructL();
    CleanupStack::Pop(s);
    return s;
    }

// ----------------------------------------------------------------------------
// Constructor.
// ----------------------------------------------------------------------------
//
CMPXActiveTaskQueue::CMPXActiveTaskQueue()
    {
    }

// ----------------------------------------------------------------------------
// Constructor.
// ----------------------------------------------------------------------------
//
void CMPXActiveTaskQueue::ConstructL()
    {
    iScheduler = CMPXTaskQueueScheduler::NewL(iTaskList);
    }


// ----------------------------------------------------------------------------
// Destructor
// ----------------------------------------------------------------------------
//
EXPORT_C CMPXActiveTaskQueue::~CMPXActiveTaskQueue()
    {
    MPX_FUNC_EX("CMPXActiveTaskQueue::~CMPXActiveTaskQueue");
    if (iScheduler)
        {
        delete iScheduler;
        }
    }

// ----------------------------------------------------------------------------
// Add a task
// ----------------------------------------------------------------------------
//
EXPORT_C  void CMPXActiveTaskQueue::AddTaskL(
    TInt aTask,
    TAny* aCallback,
    MMPXTaskQueueObserver* aHandler,
    TInt aParamData/*=0*/,
    CBufBase* aBuf/*=NULL*/,
    TAny* aPtrData/*=NULL*/,
    CBase* aCObject1/*=NULL*/,
    CBase* aCObject2/*=NULL*/)
    {
    MPX_FUNC_EX("CMPXActiveTaskQueue::AddTaskL");
    CTask* t=new(ELeave)CTask(aTask,aCallback,aHandler,aParamData,
                              aBuf,aPtrData,aCObject1,aCObject2);
    iTaskList.AddLast(*t);
    ScheduleNextTask();
    }

// ----------------------------------------------------------------------------
// Schedule to execute next task
// ----------------------------------------------------------------------------
//
EXPORT_C void CMPXActiveTaskQueue::ScheduleNextTask()
    {
    iScheduler->ScheduleNextTask();
    }

// ----------------------------------------------------------------------------
// Complete current task
// ----------------------------------------------------------------------------
//
EXPORT_C void CMPXActiveTaskQueue::CompleteTask()
    {
    MPX_FUNC_EX("CMPXActiveTaskQueue::CompleteTask()");
    (void)RemoveTask();
    iScheduler->CompleteTask();
    ScheduleNextTask();
    }

// ----------------------------------------------------------------------------
// Cancels all outsatnding tasks
// ----------------------------------------------------------------------------
//
EXPORT_C void CMPXActiveTaskQueue::CancelRequests()
    {
    MPX_FUNC_EX("CMPXActiveTaskQueue::CancelRequests");
    iScheduler->Cancel();
    CMPXTaskQueue::Reset();
    }

// ----------------------------------------------------------------------------
// CMPXActiveTaskQueue::CompleteAllTasks
// ----------------------------------------------------------------------------
//
EXPORT_C void CMPXActiveTaskQueue::CompleteAllTasks(
    TInt aError)
    {
    MPX_FUNC_EX("CMPXActiveTaskQueue::CompleteAllTasks");
    iScheduler->Cancel();

    TSglQueIter<CTask> iter(iTaskList);
    CTask* task(NULL);
    while ((task = iter++) != NULL) // Compiler warning on while (t=iter++)
        {
        task->iHandler->HandleTaskError(task->iTask, task->iPtrData,
                                        task->iCallback, aError);
        delete task;
        }
    iTaskList.Reset();
    }