sl@0: // Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). sl@0: // sl@0: // Permission is hereby granted, free of charge, to any person obtaining a sl@0: // copy of this software and/or associated documentation files (the sl@0: // "Materials"), to deal in the Materials without restriction, including sl@0: // without limitation the rights to use, copy, modify, merge, publish, sl@0: // distribute, sublicense, and/or sell copies of the Materials, and to sl@0: // permit persons to whom the Materials are furnished to do so, subject to sl@0: // the following conditions: sl@0: // sl@0: // The above copyright notice and this permission notice shall be included sl@0: // in all copies or substantial portions of the Materials. sl@0: // sl@0: // THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, sl@0: // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF sl@0: // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. sl@0: // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY sl@0: // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, sl@0: // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE sl@0: // MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. sl@0: // sl@0: // Description: sl@0: // sl@0: // sl@0: // sl@0: sl@0: #define KInitialIndexValue (-1) sl@0: sl@0: #include "owfmessagequeue.h" sl@0: #include "owfdebug.h" sl@0: #include sl@0: sl@0: class CMessageQueue: public CBase sl@0: { sl@0: public: sl@0: virtual ~CMessageQueue(); sl@0: static CMessageQueue* NewL(); sl@0: static CMessageQueue* NewLC(); sl@0: void Send(TInt msg, void* data); sl@0: TInt Fetch(OWF_MESSAGE* msg, TInt timeout); sl@0: TInt Fetch(OWF_MESSAGE* msg); sl@0: sl@0: private: sl@0: CMessageQueue(); sl@0: void ConstructL(); sl@0: sl@0: private: sl@0: const static TInt iQueueSize = 16; sl@0: OWF_MESSAGE iMessageArray[iQueueSize]; sl@0: RSemaphore iFetchSeamaphore; sl@0: RSemaphore iSendSemaphore; sl@0: RFastLock iProtectionMutex; sl@0: TInt iSendIndex; sl@0: TInt iFetchIndex; sl@0: }; sl@0: sl@0: CMessageQueue::CMessageQueue(): sl@0: iSendIndex(KInitialIndexValue), sl@0: iFetchIndex(KInitialIndexValue) sl@0: { sl@0: sl@0: } sl@0: sl@0: CMessageQueue::~CMessageQueue() sl@0: { sl@0: iFetchSeamaphore.Close(); sl@0: iSendSemaphore.Close(); sl@0: iProtectionMutex.Close(); sl@0: } sl@0: sl@0: void CMessageQueue::ConstructL() sl@0: { sl@0: User::LeaveIfError(iFetchSeamaphore.CreateLocal(0)); sl@0: User::LeaveIfError(iSendSemaphore.CreateLocal(iQueueSize)); sl@0: User::LeaveIfError(iProtectionMutex.CreateLocal()); sl@0: } sl@0: sl@0: CMessageQueue* CMessageQueue::NewLC() sl@0: { sl@0: CMessageQueue* self = new(ELeave) CMessageQueue(); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: return(self); sl@0: } sl@0: sl@0: CMessageQueue* CMessageQueue::NewL() sl@0: { sl@0: CMessageQueue* self = CMessageQueue::NewLC(); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: void CMessageQueue::Send(TInt msg, void* data) sl@0: { sl@0: iSendSemaphore.Wait(); sl@0: iProtectionMutex.Wait(); sl@0: iSendIndex = (iSendIndex + 1) % iQueueSize; sl@0: iMessageArray[iSendIndex].id = msg; sl@0: iMessageArray[iSendIndex].data = data; sl@0: iProtectionMutex.Signal(); sl@0: iFetchSeamaphore.Signal(); sl@0: } sl@0: sl@0: TInt CMessageQueue::Fetch(OWF_MESSAGE* msg, TInt timeout) sl@0: { sl@0: TInt ret = KErrNone; sl@0: if (!msg) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: sl@0: if ((ret = iFetchSeamaphore.Wait(timeout)) == KErrNone) sl@0: { sl@0: iProtectionMutex.Wait(); sl@0: if (iSendIndex == iFetchIndex) sl@0: { sl@0: iProtectionMutex.Signal(); sl@0: return KErrTimedOut; sl@0: } sl@0: else sl@0: { sl@0: iFetchIndex = (iFetchIndex + 1) % iQueueSize; sl@0: *msg = iMessageArray[iFetchIndex]; sl@0: iProtectionMutex.Signal(); sl@0: iSendSemaphore.Signal(); sl@0: return KErrNone; sl@0: } sl@0: } sl@0: return ret; sl@0: } sl@0: sl@0: TInt CMessageQueue::Fetch(OWF_MESSAGE* msg) sl@0: { sl@0: if (!msg) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: sl@0: iFetchSeamaphore.Wait(); sl@0: iProtectionMutex.Wait(); sl@0: iFetchIndex = (iFetchIndex + 1) % iQueueSize; sl@0: *msg = iMessageArray[iFetchIndex]; sl@0: iProtectionMutex.Signal(); sl@0: iSendSemaphore.Signal(); sl@0: return KErrNone; sl@0: } sl@0: sl@0: OWF_API_CALL void sl@0: OWF_MessageQueue_Destroy(OWF_MESSAGE_QUEUE* queue) sl@0: { sl@0: if (!queue) sl@0: { sl@0: return; sl@0: } sl@0: delete (CMessageQueue*)queue->queuePtr; sl@0: queue->queuePtr = NULL; sl@0: } sl@0: sl@0: OWF_API_CALL OWFint sl@0: OWF_MessageQueue_Init(OWF_MESSAGE_QUEUE* queue) sl@0: { sl@0: if (!queue) sl@0: { sl@0: return MSG_QUEUE_INIT_ERR; sl@0: } sl@0: sl@0: TRAPD(err, queue->queuePtr = CMessageQueue::NewL()); sl@0: return (err || !queue->queuePtr) ? MSG_QUEUE_INIT_ERR : MSG_QUEUE_INIT_OK; sl@0: } sl@0: sl@0: OWF_API_CALL void sl@0: OWF_Message_Send(OWF_MESSAGE_QUEUE* queue, sl@0: OWFuint msg, sl@0: void* data) sl@0: { sl@0: OWF_ASSERT(queue); sl@0: OWF_ASSERT(queue->queuePtr); sl@0: sl@0: ((CMessageQueue*)(queue->queuePtr))->Send(msg, data); sl@0: } sl@0: sl@0: OWF_API_CALL OWFint sl@0: OWF_Message_Wait(OWF_MESSAGE_QUEUE* queue, sl@0: OWF_MESSAGE* msg, sl@0: OWFint timeout) sl@0: { sl@0: OWF_ASSERT(queue); sl@0: OWF_ASSERT(queue->queuePtr); sl@0: OWF_ASSERT(msg); sl@0: sl@0: OWFint ret = 0; sl@0: sl@0: if (WAIT_FOREVER == timeout) sl@0: { sl@0: ret = ((CMessageQueue*)(queue->queuePtr))->Fetch(msg); sl@0: } sl@0: else sl@0: { sl@0: ret = ((CMessageQueue*)(queue->queuePtr))->Fetch(msg, timeout); sl@0: } sl@0: switch (ret) sl@0: { sl@0: case KErrNone: sl@0: return MSG_QUEUE_WAIT_MSG_FETCHED; sl@0: case KErrTimedOut: sl@0: return MSG_QUEUE_WAIT_MSG_TIMEDOUT; sl@0: default: sl@0: return MSG_QUEUE_WAIT_MSG_ERR; sl@0: } sl@0: } sl@0: