00001 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). 00002 // All rights reserved. 00003 // This component and the accompanying materials are made available 00004 // under the terms of "Eclipse Public License v1.0" 00005 // which accompanies this distribution, and is available 00006 // at the URL "http://www.eclipse.org/legal/epl-v10.html". 00007 // 00008 // Initial Contributors: 00009 // Nokia Corporation - initial contribution. 00010 // 00011 // Contributors: 00012 // 00013 // Description: 00014 // Contains the definition of member functions of the CQueue class. 00015 // 00016 00017 00018 00023 #include "queue.h" 00024 00029 CQueue* CQueue::NewL() 00030 { 00031 CQueue* self = new (ELeave)CQueue; 00032 CleanupStack::PushL(self); 00033 self->ConstructL(); 00034 CleanupStack::Pop(self); 00035 return self; 00036 } 00037 00043 void CQueue::ConstructL() 00044 { 00045 // Create the local RMutex variable. 00046 User::LeaveIfError(iMutex.CreateLocal()); 00047 // Create the local RCondVar variable. 00048 User::LeaveIfError(iCondVar.CreateLocal()); 00049 } 00050 00054 CQueue::CQueue() 00055 { 00056 } 00057 00062 void CQueue::Insert() 00063 { 00064 // Wait for the mutex. 00065 // The mutex is required to ensure that only one thread updates iArray at a time. 00066 iMutex.Wait(); 00067 // Insertion operation. 00068 // Insert some random number as a token into the queue. 00069 iArray.Append(Math::Random()%10); 00070 // Signal the local condition variable to indicate that queue has new data. 00071 iCondVar.Signal(); 00072 // release the mutex so that the other thread has access to iArray. 00073 iMutex.Signal(); 00074 // RCondVar::Broadcast() can be used as an alternative to the RCondVar::Signal() function. 00075 // It is more relevant to use Broadcast() when more than two threads are blocking on single condition variable. 00076 // The following code block illustrates the use of the Broadcast() function. 00077 // 00078 //if(!IsEmpty()) 00079 // { 00080 // iCondVar.Broadcast(); 00081 // iMutex.Signal(); 00082 // } 00083 // 00084 } 00085 00090 void CQueue::Remove() 00091 { 00092 // Ensures that mutex is held by the current thread. 00093 iMutex.Wait(); 00094 // Test to see whether there is anything in the queue before attempting to remove an item. 00095 // If the queue is empty wait for a signal on the Condition Variable before proceeding 00096 while(!IsEmpty()) 00097 { 00098 // The following call blocks this thread and releases the mutex so that the other thread can update the shared data. 00099 // When the other thread signals iCondVar and releases the mutex this thread continues. 00100 iCondVar.Wait(iMutex); 00101 // If there were more than one consumer waiting for the same signal 00102 // it would be essential to test IsEmpty() again because another thread, or threads, 00103 // might have got the mutex before this one and emptied the array. 00104 // For this reason if is good practise to use while( IsEmpty() ) instead of if( IsEmpty() ). 00105 } 00106 // Deletion operation. 00107 iArray.Remove(0); 00108 // Release the mutex. 00109 iMutex.Signal(); 00110 } 00111 00116 TBool CQueue::IsEmpty() 00117 { 00118 if(iArray.Count() > 0) 00119 { 00120 return ETrue; 00121 } 00122 return EFalse; 00123 } 00124 00129 void CQueue::GetTokens(RArray<TInt>& aArray) 00130 { 00131 for(TInt ix = 0; ix < iArray.Count(); ix++) 00132 { 00133 aArray.Append(iArray[ix]); 00134 } 00135 } 00136 00140 CQueue::~CQueue() 00141 { 00142 iMutex.Close(); 00143 iCondVar.Close(); 00144 }