mpx/commonframework/common/src/mpxmessagequeue.cpp
author Simon Howkins <simonh@symbian.org>
Thu, 18 Nov 2010 13:26:55 +0000
branchRCL_3
changeset 69 71775bb0f6c0
parent 9 bee149131e4b
permissions -rw-r--r--
Adjusted to avoid exports, etc, from a top-level bld.inf

/*
* Copyright (c) 2007 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:  Queue the message
*
*/

#include <mpxlog.h>
#ifdef _DEBUG
#include <mpxmessagegeneraldefs.h>
#endif
#include "mpxmessagequeue.h"

// ============================ PRIVATE CLASSES ==============================
NONSHARABLE_CLASS(CMPXMessageItem) : public CBase
    {
public:
    static CMPXMessageItem* NewL(const CMPXMessage* aMsg, TInt aError);
    ~CMPXMessageItem();
    /**
     *  message object
     *
     *  @return message object
     */
    CMPXMessage* Message()
        {
        return iMsg;
        }
    /**
     *  Error code associated with the message
     *
     *  @return the error code
     */
    TInt Error()
        {
        return iError;
        }
    /**
     *  Offset to the task queue
     *
     *  @return the offset
     */
     static TInt Offset()
         {
         return _FOFF(CMPXMessageItem,iLink);
         }
private:
    CMPXMessageItem(TInt aError);
    void ConstructL(const CMPXMessage* aMsg);
private:
    TSglQueLink iLink;
    CMPXMessage* iMsg;
    TInt iError;
    };

CMPXMessageItem* CMPXMessageItem::NewL(const CMPXMessage* aMsg, TInt aError)
    {
    CMPXMessageItem* self = new ( ELeave ) CMPXMessageItem(aError);
    CleanupStack::PushL( self );
    self->ConstructL(aMsg);
    CleanupStack::Pop(self);
    return self;
    }

CMPXMessageItem::CMPXMessageItem(TInt aError)
:   iError(aError)
    {
    }

CMPXMessageItem::~CMPXMessageItem()
    {
    MPX_DEBUG2("-->CMPXMessageItem::~CMPXMessageItem 0x%08x", this);
    if (iMsg)
        {
        MPX_DEBUG3("CMPXMessageItem::~CMPXMessageItem msg 0x%08x, msgHandle 0x%08x",
                   iMsg, iMsg->Data());

        delete iMsg;
        iMsg = NULL;
        }
    MPX_DEBUG2("<--CMPXMessageItem::~CMPXMessageItem 0x%08x", this);
    }

void CMPXMessageItem::ConstructL(const CMPXMessage* aMsg)
    {
    MPX_FUNC_EX("CMPXMessageItem::ConstructL");
    iMsg = aMsg ? CMPXMessage::NewL(*aMsg) : NULL;
    }

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

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

// ----------------------------------------------------------------------------
// C++ constructor.
// ----------------------------------------------------------------------------
//
CMPXMessageQueue::CMPXMessageQueue()
:   iMsgs(CMPXMessageItem::Offset()),
    iFailure(KErrNone)
    {
    }

// ----------------------------------------------------------------------------
// Second-phase constructor.
// ----------------------------------------------------------------------------
//
void CMPXMessageQueue::ConstructL()
    {
    MPX_FUNC_EX("CMPXMessageQueue::ConstructL");
    }

// ----------------------------------------------------------------------------
// Destructor
// ----------------------------------------------------------------------------
//
EXPORT_C CMPXMessageQueue::~CMPXMessageQueue()
    {
    MPX_FUNC_EX("CMPXMessageQueue::~CMPXMessageQueue()");
    Reset();
    }

// ----------------------------------------------------------------------------
// Send next message request from client
// ----------------------------------------------------------------------------
//
EXPORT_C void CMPXMessageQueue::SendNext(const RMessage2& aMsgRequest)
    {
    MPX_FUNC_EX("CMPXMessageQueue::SendNext()");
    MPX_ASSERT(iMsgRequest.IsNull());
    iMsgRequest = aMsgRequest;
    if (!iMsgs.IsEmpty())
        {
        Send();
        }
    }

// ----------------------------------------------------------------------------
// Adds a message into the queue and sends the message if slot is available
// ----------------------------------------------------------------------------
//
EXPORT_C void CMPXMessageQueue::Add(const CMPXMessage* aMessage, TInt aError)
    {
    // aMessage should not be NULL and aError is KErrNone
    MPX_ASSERT(aMessage || aError);
    MPX_FUNC_EX("CMPXMessageQueue::Add()");
    CMPXMessageItem* item(NULL);
    TRAPD(err, item = CMPXMessageItem::NewL(aMessage, aError));
    if (KErrNone==err)
        {
        iMsgs.AddLast(*item);
#ifdef _DEBUG
        MPX_DEBUG3("CMPXMessageQueue::Add 0x%08x, items %d", this, ++iCount);
#endif
        }//else failed to create message item.
    else
        {
        MPX_DEBUG2("CMPXMessageQueue::Add Failed to create message item %d", err);
        }

    if (KErrNone!=err && KErrNone==iFailure)
        { // Set the failure code
        iFailure = err;
        }

    if (!iMsgRequest.IsNull())
        { // outstanding request
        Send();
        } // else client has not finished current message yet
    }

// ----------------------------------------------------------------------------
// Reset message queue
// ----------------------------------------------------------------------------
//
EXPORT_C void CMPXMessageQueue::Reset()
    {
    MPX_FUNC_EX("CMPXMessageQueue::Reset()");
    if (!iMsgRequest.IsNull())
        {
        iMsgRequest.Complete(KErrCancel);
        }
    delete iMsgSent;
    iMsgSent = NULL;
    TSglQueIter<CMPXMessageItem> iter(iMsgs);
    CMPXMessageItem* msgItem=NULL;
    while ((msgItem=iter++) != NULL) // Compiler on warning while(msgItem==iter++)
        {
        delete msgItem;
        }
    iMsgs.Reset();
    }

// ----------------------------------------------------------------------------
// Send a message
// ----------------------------------------------------------------------------
//
void CMPXMessageQueue::Send()
    {
    MPX_DEBUG3("-->CMPXMessageQueue::Send() 0x%08x, iMsgSent 0x%08x",
              this, iMsgSent);
    delete iMsgSent;
    iMsgSent = NULL;
    TInt data(0);
    TInt err(KErrNone);
    if (iFailure)
        {
        err=iFailure;
        iFailure = KErrNone; // Reset failure code
        }
    else
        {
        MPX_ASSERT(!iMsgs.IsEmpty());
        iMsgSent = iMsgs.First();
        iMsgs.Remove(*iMsgSent);
#ifdef _DEBUG
        MPX_DEBUG4("CMPXMessageQueue::Send 0x%08x, msg 0x%08x, items %d",
                    this, iMsgSent->Message(), --iCount);
#endif
        if (iMsgSent->Message())
            {
            data = iMsgSent->Message()->Data();
            MPX_ASSERT(data>0);
#ifdef _DEBUG
            CMPXMessage* msg = iMsgSent->Message();
            TMPXMessageId* pId = msg->Value<TMPXMessageId>(KMPXMessageGeneralId);
            if (pId)
                {
                TInt id = static_cast<TInt>(*pId);
                MPX_DEBUG5("CMPXMessageQueue::Send msg item 0x%08x, msg 0x%08x, msgHandle 0x%08x, msgId 0x%08x",
                        iMsgSent, iMsgSent->Message(), data, id);
                if (id==KMPXMessageGeneral)
                    {
                    MPX_ASSERT(msg->IsSupported(KMPXMessageGeneralEvent));
                    TInt* pEvent = msg->Value<TInt>(KMPXMessageGeneralEvent);
                    MPX_ASSERT(msg->IsSupported(KMPXMessageGeneralType));
                    TInt* pType = msg->Value<TInt>(KMPXMessageGeneralType);
                    MPX_ASSERT(msg->IsSupported(KMPXMessageGeneralData));
                    TInt* pData = msg->Value<TInt>(KMPXMessageGeneralData);
                    if (pEvent && pType && pData)
                        {
                        MPX_DEBUG5("CMPXMessageQueue::Send general msg item 0x%08x, event %d, type %d, data %d",
                                    iMsgSent, *pEvent, *pType, *pData);
                        }
                    else
                        {
                        MPX_DEBUG1("CMPXMessageQueue::Send OOM");
                        }
                    }
                }
            else
                {
                MPX_DEBUG1("CMPXMessageQueue::Send OOM");
                }
#endif
            } // else NULL message
        else // else NULL message
            {
            MPX_ASSERT(iMsgSent->Error());
            MPX_DEBUG3("CMPXMessageQueue::Send NULL message 0x%08x, err %d",
                       this, iMsgSent->Error());
            }
        err = iMsgSent->Error();
        }

    TPckgC<TInt> dataPkg(data);
    TPckgC<TInt> errPkg(err);
    TInt ret = (iMsgRequest.Write(0, dataPkg));
    if (!ret)
        {
        ret = iMsgRequest.Write(1, errPkg);
        }
#ifdef _DEBUG
    if (ret)
        {
        MPX_DEBUG1("CMPXMessageQueue::Send Failed to write data");
        }
#endif
    iMsgRequest.Complete(ret);
    MPX_DEBUG5("<--CMPXMessageQueue::Send() 0x%08x, sentMsgHandle 0x%08x, sentError %d,  sentRet %d",
               this, data, err, ret);
    }

// ----------------------------------------------------------------------------
// Adds a message into the top of the queue and sends the message if slot is available
// ----------------------------------------------------------------------------
//
EXPORT_C TInt CMPXMessageQueue::AddFirst(const CMPXMessage* aMessage, TInt aError)
    {
    // aMessage should not be NULL and aError is KErrNone
    MPX_ASSERT(aMessage || aError);
    MPX_FUNC_EX("CMPXMessageQueue::AddFirst()");
    CMPXMessageItem* item(NULL);
    TRAPD(err, item = CMPXMessageItem::NewL(aMessage, aError));
    if (KErrNone==err)
        {
        iMsgs.AddFirst(*item);
#ifdef _DEBUG
        MPX_DEBUG3("CMPXMessageQueue::AddFirst 0x%08x, items %d", this, ++iCount);
#endif
        }//else failed to create message item.
    else
        {
        MPX_DEBUG2("CMPXMessageQueue::AddFirst Failed to create message item %d", err);
        }
    if (KErrNone!=err && KErrNone==iFailure)
        { // Set the failure code
        iFailure = err;
        }
    if (!iMsgRequest.IsNull())
        { // outstanding request
        Send();
        } // else client has not finished current message yet
    return err;
    }
// End of file