Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

245 lines
7.8 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: innerque.h
  6. * Content: declaration of the CInnerQueue class
  7. *
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 07/16/99 pnewson Created
  12. * 07/27/99 pnewson Overhauled to support new message numbering method
  13. * 08/03/99 pnewson General clean up
  14. * 08/24/99 rodtoll Fixed for release builds -- removed m_wQueueId from debug block
  15. * 10/28/99 pnewson Bug #113933 debug spew too verbose
  16. * implement inner queue pool code
  17. *
  18. ***************************************************************************/
  19. #ifndef _INNERQUEUE_H_
  20. #define _INNERQUEUE_H_
  21. // The inner queue class is used to queue up a single voice message.
  22. // A 'message' in this context means a series of frames that have the
  23. // same message number and are part of the same stream of speech.
  24. // an enum to specify the allowed states of the frame slots
  25. // I appear to have to declare this out here, instead of inside
  26. // the class, otherwise the vector declaration gets confused.
  27. enum ESlotState
  28. {
  29. essEmpty = 1,
  30. essFull,
  31. };
  32. volatile class CInnerQueue
  33. {
  34. public:
  35. // The constructor. bNumSlots must be at least 8, and must be
  36. // a power of 2.
  37. CInnerQueue(BYTE bNumSlots,
  38. WORD wFrameSize,
  39. CFramePool* pfpFramePool,
  40. DNCRITICAL_SECTION* pcsQueue,
  41. BYTE bMsgNum,
  42. BYTE bHighWaterMark = 0,
  43. WORD wQueueId = 0);
  44. HRESULT Init();
  45. // The destructor
  46. ~CInnerQueue();
  47. // An enum used to describe the possible queue states.
  48. enum EState
  49. {
  50. empty = 1, // The queue is currently empty, awaiting the first frame
  51. // Enqueue allowed, Dequeue not allowed.
  52. filling, // The queue is currently filling to the high water mark
  53. // Enqueue allowed. Dequeue not allowed.
  54. ready, // The queue has filled to the high water mark
  55. // Enqueue allowed, Dequeue allowed
  56. finished // The queue has emptied. No new frames accepted
  57. // Enqueue not allowed, Dequeue not allowed.
  58. };
  59. // Get the current state of the queue.
  60. EState GetState() const { return m_eState; }
  61. // Set the current state of the queue.
  62. void SetState(EState eState) { m_eState = eState; }
  63. // Get the current size of the queue
  64. BYTE GetSize() const { return m_bQueueSize; }
  65. // Get the current high water mark
  66. BYTE GetHighWaterMark() const { return m_bHighWaterMark; }
  67. // Set the current high water mark
  68. void SetHighWaterMark(BYTE bHighWaterMark);
  69. // Get, set, and increment the filling dequeue count
  70. BYTE GetFillingDequeueReqs() const { return m_bFillingDequeueReqs; }
  71. void SetFillingDequeueReqs(BYTE bFillingDequeueReqs) { m_bFillingDequeueReqs = bFillingDequeueReqs; }
  72. void IncFillingDequeueReqs() { m_bFillingDequeueReqs++; }
  73. // Get the stats for the current message
  74. WORD GetMissingFrames() const { return m_wMissingFrames; }
  75. WORD GetDuplicateFrames() const { return m_wDuplicateFrames; }
  76. WORD GetOverflowFrames() const { return m_wOverflowFrames; }
  77. WORD GetLateFrames() const { return m_wLateFrames; }
  78. DWORD GetMsgLen() const { return m_dwMsgLen; }
  79. // More stats stuff
  80. void AddToKnownZeroLengthDequeues(WORD w) { m_wKnownZeroLengthDequeues += w; }
  81. WORD GetKnownZeroLengthDequeues() const { return m_wKnownZeroLengthDequeues; }
  82. void IncPossibleZeroLengthDequeues() { m_wPossibleZeroLengthDequeues++; }
  83. void SetPossibleZeroLengthDequeues(WORD w) { m_wPossibleZeroLengthDequeues = w; }
  84. WORD GetPossibleZeroLengthDequeues() const { return m_wPossibleZeroLengthDequeues; }
  85. // Add a frame to the Queue
  86. void Enqueue(const CFrame& frFrame);
  87. // Get a frame from the Queue
  88. CFrame* Dequeue();
  89. // reset the queue to its initial empty state
  90. void Reset();
  91. // reset all the class' stats
  92. void ResetStats();
  93. // get the message number this queue holds
  94. BYTE GetMsgNum() const { return m_bMsgNum; }
  95. void SetMsgNum(BYTE bMsgNum) { m_bMsgNum = bMsgNum; }
  96. void SetQueueId(WORD wQueueId) { m_wQueueId = wQueueId; }
  97. private:
  98. // Has the init function completed successfully?
  99. BOOL m_fInited;
  100. // The current state of the inner queue.
  101. EState m_eState;
  102. // The number of frame slots in the queue. must be a power
  103. // of two, or else things will get bad if the sequence number
  104. // rolls over.
  105. BYTE m_bNumSlots;
  106. // The number of frames required before the queue moves from
  107. // 'filling' to 'ready' state.
  108. BYTE m_bHighWaterMark;
  109. // The current 'size' of the queue. The size of the queue is
  110. // considered to be the number of filled slots, which may not
  111. // be the same as the distance between the first filled slot
  112. // and the last filled slot.
  113. BYTE m_bQueueSize;
  114. // The sequence number of the frame at the head of the queue.
  115. BYTE m_bHeadSeqNum;
  116. // A flag to track the first dequeue action.
  117. bool m_fFirstDequeue;
  118. // an array of slot states
  119. //ESlotState* m_rgeSlotStates;
  120. // An array of pointers to frames. This has to be pointers
  121. // to frames, because CFrame has no default constructor.
  122. CFrame** m_rgpfrSlots;
  123. // This is a little stat that will help us to detect
  124. // when a short message is getting hung up in a queue
  125. // because it's not long enough to trigger the high
  126. // water mark. It counts the number of times an outer dequeue
  127. // operation has been declined because this inner queue
  128. // is in the filling state. This gets reset to 0 when the
  129. // high water mark is hit
  130. BYTE m_bFillingDequeueReqs;
  131. // These vars keep stats on the current message, presumably so
  132. // we can intelligently adjust the high water mark
  133. // A frame is considered missing if it has not arrived by the time
  134. // it is required, but some frames following it have arrived.
  135. WORD m_wMissingFrames;
  136. // This one is pretty obvious. If we get the same frame twice, it's a duplicate
  137. // aarono will bet his car that this can never happen, so if you every see this
  138. // variable above one, call him up and make that bet!
  139. WORD m_wDuplicateFrames;
  140. // Overflow and late frames. If you look at where these are incremented
  141. // you'll see that it is pretty much a judgement call if we're throwing
  142. // away a frame due to an overflow or it being late, so take them with
  143. // a grain of salt. The sum of the two stats is however an accurate count
  144. // of how many frames arrived that we chucked.
  145. WORD m_wOverflowFrames;
  146. WORD m_wLateFrames;
  147. // These are used by the outer queue to remember if it
  148. // needed a frame from this queue when it's size was zero.
  149. WORD m_wPossibleZeroLengthDequeues;
  150. WORD m_wKnownZeroLengthDequeues;
  151. // This is the number of frames that make up the current message
  152. DWORD m_dwMsgLen; // make a dword in case of no voice detection
  153. // The Queue ID is just used for debug messages
  154. WORD m_wQueueId;
  155. // The message number this queue is for
  156. BYTE m_bMsgNum;
  157. // frame pool stuff
  158. CFramePool* m_pfpFramePool;
  159. DNCRITICAL_SECTION* m_pcsQueue;
  160. };
  161. // Inner queues are requested as needed by the CInputQueue2 class.
  162. // This class manages a pool of inner queues so that actual memory
  163. // allocations are few and far between.
  164. class CInnerQueuePool
  165. {
  166. private:
  167. BYTE m_bNumSlots;
  168. WORD m_wFrameSize;
  169. CFramePool* m_pfpFramePool;
  170. DNCRITICAL_SECTION* m_pcsQueue;
  171. std::vector<CInnerQueue *> m_vpiqPool;
  172. DNCRITICAL_SECTION m_lock; // to exclude Get and Return from each other
  173. BOOL m_fCritSecInited;
  174. public:
  175. CInnerQueuePool(
  176. BYTE bNumSlots,
  177. WORD wFrameSize,
  178. CFramePool* pfpFramePool,
  179. DNCRITICAL_SECTION* pcsQueue);
  180. ~CInnerQueuePool();
  181. BOOL Init()
  182. {
  183. if (DNInitializeCriticalSection(&m_lock) )
  184. {
  185. m_fCritSecInited = TRUE;
  186. return TRUE;
  187. }
  188. else
  189. {
  190. return FALSE;
  191. }
  192. }
  193. CInnerQueue* Get(
  194. BYTE bHighWaterMark = 0,
  195. WORD wQueueId = 0,
  196. BYTE bMsgNum = 0);
  197. void Return(CInnerQueue* piq);
  198. };
  199. #endif // _INNERQUEUE_H_