Queue.cpp
上传用户:royluo
上传日期:2007-01-05
资源大小:1584k
文件大小:7k
源码类别:

游戏

开发平台:

Visual C++

  1. /*****************************************************************************
  2. *                                                                             
  3. *   Queue.cpp                                                            
  4. *                                                                             
  5. *   Electrical Engineering Faculty - Software Lab                             
  6. *   Spring semester 1998                                                      
  7. *                                                                             
  8. *   Tanks game                                                                
  9. *                                                                             
  10. *   Module description: Implements a multi threaded safe queue, using a linked
  11. *                       list to hold the data. A semaphor is used to signal the
  12. *                       thread for a new incoming data.
  13. *                                                                             
  14. *   Authors: Eran Yariv - 28484475                                           
  15. *            Moshe Zur  - 24070856                                           
  16. *                                                                            
  17. *                                                                            
  18. *   Date: 23/09/98                                                           
  19. *                                                                            
  20. ******************************************************************************/
  21. #include "stdafx.h"
  22. #include "queue.h"
  23. #include "Message.h"
  24. /***************************************************************************
  25.    Function:   CloseQueue
  26.    Purpose:    Empty the queue and delete all it's elements.
  27.    Input:      None.
  28.    Output:     None.
  29. ****************************************************************************/
  30. void CQueue::CloseQueue()
  31. {
  32.     Empty();
  33.     m_bQueueIsDead = TRUE;
  34. }
  35. /***************************************************************************
  36.    Function:   GetQueueSize
  37.    Purpose:    Get the current total number of items in the queue
  38.    Input:      None.
  39.    Output:     Number of items in the queue.
  40. ****************************************************************************/
  41. int CQueue::GetQueueSize()
  42. {
  43.     int nQueueSize;
  44.     if (m_bQueueIsDead) // close Q flag is set
  45.         return 0;   // Size of dead queue is zero
  46.     
  47.     m_QueueCS.Lock(); // Lock the option of accessing the queue
  48.     nQueueSize = m_Queue.GetCount();
  49.     m_QueueCS.Unlock(); // Release the option of accessing the queue
  50.     return nQueueSize;
  51. }
  52. /***************************************************************************
  53.    Function:   Enqueue
  54.    Purpose:    Insert a given element into the queue.
  55.    Input:      Pointer to the new element.
  56.    Output:     TRUE upon success, otherwise - FALSE.
  57. ****************************************************************************/
  58. BOOL CQueue::Enqueue(CObject* pNewElement)
  59. {
  60.     if (m_bQueueIsDead) // close Q flag is set
  61.         return FALSE;   // Cannot add messages to a dead queue
  62. m_QueueCS.Lock(); // Lock the option of accessing the queue
  63.     if (m_bQueueIsDead) // close Q flag is set
  64.         return FALSE;   // Cannot add messages to a dead queue
  65.     if (pNewElement == KILL_Q_MSG)
  66.         m_bQueueIsDead = TRUE;
  67.     else
  68.     {
  69.         m_Queue.AddTail(pNewElement); // Insert the new alement at the tail of the queue
  70.     }
  71.     if(m_bBlocking)  // should wait until there are elements in the queue
  72.     m_DispatchSem.Unlock(); // Update the dispatch semaphore - the queue is not empty
  73.         
  74.     m_QueueCS.Unlock(); // Release the option of accessing the queue
  75.     if (NULL != m_hEnqueueEvent)
  76.     {
  77.         SetEvent (m_hEnqueueEvent);
  78.     }
  79. return TRUE;
  80. }
  81. /***************************************************************************
  82.    Function:   Dequeue
  83.    Purpose:    Get the head object out of the queue.
  84.    Input:      Return object address.
  85.    Output:     BOOL - FALSE if there are no objects in the queue,
  86.                so that no object removed from the list, otherewise - TRUE.
  87.    Remarks:    The head object removed out of the queue but not deleted.
  88. ****************************************************************************/
  89. BOOL CQueue::Dequeue(CObject*& pRes)
  90. {
  91.     if (m_bQueueIsDead) // close Q flag is set
  92.     {
  93.         pRes = KILL_Q_MSG;
  94.         return TRUE;
  95.     }
  96.     if(m_bBlocking) {// should wait until there are elements in the queue
  97.     m_DispatchSem.Lock(); // wait until there are objects in the queue
  98.         if (m_bQueueIsDead) { // close Q flag was set while were sleeping on the locked semaphore
  99.             pRes = KILL_Q_MSG;
  100.             return TRUE;
  101.         }
  102.     }
  103. m_QueueCS.Lock(); // Lock the option of accessing the queue
  104.     if (m_bQueueIsDead) { // Close Q flag was set while were sleeping on the locked semaphore
  105.         pRes = KILL_Q_MSG;
  106.         return TRUE;
  107.     }
  108.     if(m_Queue.IsEmpty()){   // No items in the queue
  109. m_QueueCS.Unlock();
  110.         return FALSE;
  111. }
  112. pRes = m_Queue.RemoveHead (); // Get the queue's head object and remove it
  113. m_QueueCS.Unlock(); // Release the option of accessing the queue
  114.     return TRUE;
  115. }
  116. void 
  117. CQueue::SetNotificationEvent (HANDLE h)
  118. {
  119.     m_hEnqueueEvent = h;
  120. }
  121. void
  122. CQueue::Empty()
  123. {
  124. CObject* pElement;
  125. m_QueueCS.Lock(); // Lock the option of accessing the queue
  126.     for (POSITION pos = m_Queue.GetHeadPosition(); pos != NULL; ) // walk through the queue
  127.     {
  128.         pElement = m_Queue.GetNext(pos);
  129.         
  130.         if(pElement) // not the kill Q message
  131.         {
  132.             delete(pElement); // throw exception
  133.             m_DispatchSem.Unlock ();
  134.         }
  135.     }
  136.     m_Queue.RemoveAll(); 
  137. ASSERT(m_Queue.IsEmpty()); // check if the queue is empty after removing the elements
  138.     
  139. m_QueueCS.Unlock(); // Release the option of accessing the queue
  140. }
  141. BOOL CQueue::Enqueue(CObject* pNewElement, DWORD dwKey)
  142. {
  143.     if (m_bQueueIsDead) // close Q flag is set
  144.         return FALSE;   // Cannot add messages to a dead queue
  145. m_QueueCS.Lock(); // Lock the option of accessing the queue
  146.     if (m_bQueueIsDead) // close Q flag is set
  147.         return FALSE;   // Cannot add messages to a dead queue
  148.     if (pNewElement == KILL_Q_MSG)
  149.         m_bQueueIsDead = TRUE;
  150.     else
  151.     {
  152.         BOOL fInsertDone = FALSE;   // Was an item inserted
  153.         for (POSITION pos = m_Queue.GetHeadPosition(); pos; ) 
  154.         {
  155.             POSITION CurPos = pos;
  156.             if (((CMessage*)m_Queue.GetNext(pos))->GetTime() > dwKey) 
  157.             {
  158.                 m_Queue.InsertBefore(CurPos, pNewElement);
  159.                 fInsertDone = TRUE;
  160.                 break;
  161.             }
  162.         }
  163.         if (! fInsertDone)  // empty loop, or new message has the highest key:
  164.             m_Queue.AddTail(pNewElement); // Insert the new alement at the tail of the queue
  165.     }
  166.     if(m_bBlocking)  // should wait until there are elements in the queue
  167.     m_DispatchSem.Unlock(); // Update the dispatch semaphore - the queue is not empty
  168.         
  169.     m_QueueCS.Unlock(); // Release the option of accessing the queue
  170.     if (NULL != m_hEnqueueEvent)
  171.     {
  172.         SetEvent (m_hEnqueueEvent);
  173.     }
  174. return TRUE;
  175. }