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.

621 lines
17 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: innerque.cpp
  6. * Content:
  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. * 10/29/99 rodtoll Bug #113726 - Integrate Voxware Codecs. Plugged memory leak
  18. * caused as a result of new architecture.
  19. * 01/14/2000 rodtoll Updated to use new Frame SetEqual function
  20. * 01/31/2000 pnewson replace SAssert with DNASSERT
  21. * 06/28/2000 rodtoll Prefix Bug #38022
  22. *
  23. ***************************************************************************/
  24. #include "dxvutilspch.h"
  25. #undef DPF_SUBCOMP
  26. #define DPF_SUBCOMP DN_SUBCOMP_VOICE
  27. #define MODULE_ID INNERQUEUE
  28. // the number of slots reseved to account for
  29. // out of order startup frames. For example, if the first
  30. // three frames of a message arrive in the order 3, 2, 1, instead
  31. // of 1, 2, 3, we must reserve 2 slots in front of the "first"
  32. // frame (3) so we'll have a place to put the tardy 1 and 2.
  33. const BYTE c_bNumStartSlots = 2;
  34. #undef DPF_MODNAME
  35. #define DPF_MODNAME "CInnerQueue::CInnerQueue"
  36. CInnerQueue::CInnerQueue(
  37. BYTE bNumSlots,
  38. WORD wFrameSize,
  39. CFramePool* pfpFramePool,
  40. DNCRITICAL_SECTION* pcsQueue,
  41. BYTE bMsgNum,
  42. BYTE bHighWaterMark,
  43. WORD wQueueId
  44. )
  45. : m_bNumSlots(bNumSlots)
  46. , m_eState(CInnerQueue::empty)
  47. , m_bHighWaterMark(bHighWaterMark)
  48. , m_bQueueSize(0)
  49. , m_bHeadSeqNum(0)
  50. , m_fFirstDequeue(true)
  51. //, m_rgeSlotStates(NULL)
  52. , m_rgpfrSlots(NULL)
  53. , m_bFillingDequeueReqs(0)
  54. , m_wMissingFrames(0)
  55. , m_wDuplicateFrames(0)
  56. , m_wOverflowFrames(0)
  57. , m_wLateFrames(0)
  58. , m_wPossibleZeroLengthDequeues(0)
  59. , m_wKnownZeroLengthDequeues(0)
  60. , m_dwMsgLen(0)
  61. , m_wQueueId(wQueueId)
  62. , m_bMsgNum(bMsgNum)
  63. , m_pfpFramePool(pfpFramePool)
  64. , m_pcsQueue(pcsQueue)
  65. , m_fInited(FALSE)
  66. {
  67. #if defined(DPVOICE_QUEUE_DEBUG)
  68. DPFX(DPFPREP, DVF_INFOLEVEL, "** QUEUE ** %i:%i ** CInnerQueue::CInnerQueue() CFramePool: %p", m_wQueueId, m_bMsgNum, m_pfpFramePool);
  69. #endif
  70. // verify that bNumSlots is at least 8, and is a
  71. // power of 2.
  72. DNASSERT(bNumSlots == 0x08 ||
  73. bNumSlots == 0x10 ||
  74. bNumSlots == 0x20 ||
  75. bNumSlots == 0x40 ||
  76. bNumSlots == 0x80);
  77. // Check to make sure the watermark is not larger
  78. // than the number of slots. It should really be
  79. // significantly less than bNumSlots, but oh well.
  80. //
  81. DNASSERT(bHighWaterMark < bNumSlots - c_bNumStartSlots);
  82. }
  83. #undef DPF_MODNAME
  84. #define DPF_MODNAME "CInnerQueue::Init"
  85. HRESULT CInnerQueue::Init()
  86. {
  87. int i;
  88. /*
  89. // allocate the slot state array
  90. m_rgeSlotStates = new ESlotState[m_bNumSlots];
  91. if (m_rgeSlotStates == NULL)
  92. {
  93. goto error;
  94. }
  95. */
  96. // allocate the slot array
  97. m_rgpfrSlots = new CFrame*[m_bNumSlots];
  98. if (m_rgpfrSlots == NULL)
  99. {
  100. goto error;
  101. }
  102. // Initialize the slot states and the slots
  103. for (i = 0; i < m_bNumSlots; ++i)
  104. {
  105. //m_rgeSlotStates[i] = essEmpty;
  106. m_rgpfrSlots[i] = NULL;
  107. }
  108. m_fInited = TRUE;
  109. return S_OK;
  110. error:
  111. /*
  112. if (m_rgeSlotStates != NULL)
  113. {
  114. delete [] m_rgeSlotStates;
  115. m_rgeSlotStates = NULL;
  116. }
  117. */
  118. if (m_rgpfrSlots != NULL)
  119. {
  120. delete [] m_rgpfrSlots;
  121. m_rgpfrSlots = NULL;
  122. }
  123. m_fInited = FALSE;
  124. return E_FAIL;
  125. }
  126. #undef DPF_MODNAME
  127. #define DPF_MODNAME "CInnerQueue::~CInnerQueue"
  128. CInnerQueue::~CInnerQueue()
  129. {
  130. if (m_fInited)
  131. {
  132. /*
  133. if (m_rgeSlotStates != NULL)
  134. {
  135. delete [] m_rgeSlotStates;
  136. m_rgeSlotStates = NULL;
  137. }
  138. */
  139. if (m_rgpfrSlots != NULL)
  140. {
  141. // check to ensure that no frames are in use
  142. for (int i = 0; i < m_bNumSlots; ++i)
  143. {
  144. if( m_rgpfrSlots[i] != NULL )
  145. m_rgpfrSlots[i]->Return();
  146. }
  147. delete [] m_rgpfrSlots;
  148. m_rgpfrSlots = NULL;
  149. }
  150. }
  151. }
  152. #undef DPF_MODNAME
  153. #define DPF_MODNAME "CInnerQueue::Reset"
  154. void CInnerQueue::Reset()
  155. {
  156. if (!m_fInited)
  157. {
  158. return;
  159. }
  160. // loop through and make sure none of the frames are currently locked and clear the slot states
  161. for (int i = 0; i < m_bNumSlots; ++i)
  162. {
  163. if (m_rgpfrSlots[i] != NULL)
  164. {
  165. m_rgpfrSlots[i]->Return();
  166. }
  167. //m_rgeSlotStates[i] = essEmpty;
  168. }
  169. m_eState = CInnerQueue::empty;
  170. m_bQueueSize = 0;
  171. m_bHeadSeqNum = 0;
  172. m_fFirstDequeue = true;
  173. m_bFillingDequeueReqs = 0;
  174. ResetStats();
  175. }
  176. #undef DPF_MODNAME
  177. #define DPF_MODNAME "CInnerQueue::ResetStats"
  178. void CInnerQueue::ResetStats()
  179. {
  180. if (!m_fInited)
  181. {
  182. return;
  183. }
  184. m_wMissingFrames = 0;
  185. m_wDuplicateFrames = 0;
  186. m_wOverflowFrames = 0;
  187. m_wLateFrames = 0;
  188. m_dwMsgLen = 0;
  189. m_wPossibleZeroLengthDequeues = 0;
  190. m_wKnownZeroLengthDequeues = 0;
  191. }
  192. // This function is not inline because it needs the module id, sigh.
  193. #undef DPF_MODNAME
  194. #define DPF_MODNAME "CInnerQueue::SetHighWaterMark"
  195. void CInnerQueue::SetHighWaterMark(BYTE bHighWaterMark)
  196. {
  197. if (!m_fInited)
  198. {
  199. return;
  200. }
  201. DNASSERT(bHighWaterMark < m_bNumSlots);
  202. m_bHighWaterMark = bHighWaterMark;
  203. }
  204. // Note: this class does not have it's own critical
  205. // section. The caller must ensure that enqueue and
  206. // dequeue are not called at the same time. It is
  207. // intended that this class is used only within
  208. // the InputQueue2 class, which does have a critical
  209. // section.
  210. #undef DPF_MODNAME
  211. #define DPF_MODNAME "CInnerQueue::Enqueue"
  212. void CInnerQueue::Enqueue(const CFrame& frFrame)
  213. {
  214. if (!m_fInited)
  215. {
  216. return;
  217. }
  218. #if defined(DPVOICE_QUEUE_DEBUG)
  219. DPFX(DPFPREP, DVF_INFOLEVEL, "** QUEUE ** %i:%i ** CInnerQueue::Enqueue() MsgNum[%i] SeqNum[%i]", m_wQueueId, m_bMsgNum, frFrame.GetMsgNum(), frFrame.GetSeqNum());
  220. #endif
  221. DNASSERT(m_eState != finished);
  222. if (m_eState == empty)
  223. {
  224. // This is the first frame, so set the head of the queue.
  225. // NOTE: It may seem strange to set the head of the
  226. // queue to 2 frames before the first one we receive,
  227. // but this covers the case where the first frame
  228. // we receive is not the first frame of the message.
  229. // By using this logic, if any of the first, second
  230. // or third frames arrive first, we will not chop
  231. // off the start of the message. When the user
  232. // asks for the first dequeue, it will skip the
  233. // empty slots at the head of the queue, assuming
  234. // they haven't been filled in.
  235. m_bHeadSeqNum = (frFrame.GetSeqNum() - c_bNumStartSlots);
  236. #if defined(DPVOICE_QUEUE_DEBUG)
  237. DPFX(DPFPREP, DVF_INFOLEVEL, "** QUEUE ** %i:%i ** CInnerQueue::Enqueue() new message - m_bHeadSeqNum[%i]", m_wQueueId, m_bMsgNum, m_bHeadSeqNum);
  238. DPFX(DPFPREP, DVF_INFOLEVEL, "** QUEUE ** %i:%i ** CInnerQueue::Enqueue() state changed to filling", m_wQueueId, m_bMsgNum);
  239. #endif
  240. m_eState = filling;
  241. }
  242. // Check to see if we should put this frame into the queue.
  243. //
  244. // NOTE: The logic below implicitly checks for queue overflows.
  245. // if the sequence number is out of the allowable range, one
  246. // of two things may have happened.
  247. // 1) queue overflow
  248. // 2) frame arrived too late
  249. //
  250. // First we need to know if we are dealing with a wraparound
  251. // problem.
  252. bool fKeepFrame = false;
  253. if ((BYTE)(m_bHeadSeqNum + m_bNumSlots) < m_bHeadSeqNum)
  254. {
  255. // we've got a wraparound problem, so use this alternate logic
  256. if (frFrame.GetSeqNum() >= m_bHeadSeqNum
  257. || frFrame.GetSeqNum() < (BYTE)(m_bHeadSeqNum + m_bNumSlots))
  258. {
  259. fKeepFrame = true;
  260. }
  261. }
  262. else
  263. {
  264. // no wraparound problem, so use the straightforward logic
  265. if (frFrame.GetSeqNum() >= m_bHeadSeqNum
  266. && frFrame.GetSeqNum() < m_bHeadSeqNum + m_bNumSlots)
  267. {
  268. fKeepFrame = true;
  269. }
  270. }
  271. // if we're supposed to keep this frame, copy it into the
  272. // appropriate slot
  273. if (fKeepFrame)
  274. {
  275. BYTE bSlot = frFrame.GetSeqNum() % m_bNumSlots;
  276. // check to see if this slot is full
  277. //if (m_rgeSlotStates[bSlot] == essFull)
  278. if (m_rgpfrSlots[bSlot] != NULL)
  279. {
  280. // This is a duplicate frame, so don't do anything
  281. // with it, but tell the debugger about it, and
  282. // update our stats.
  283. //
  284. // NOTE: We know that this a duplicate frame and
  285. // not a queue overflow because we have already
  286. // checked for queue overflow above.
  287. #if defined(DPVOICE_QUEUE_DEBUG)
  288. DPFX(DPFPREP, DVF_INFOLEVEL, "** QUEUE ** %i:%i ** CInnerQueue::Enqueue() Ignoring duplicate frame, sequence number[%i], slot[%i]",
  289. m_wQueueId, m_bMsgNum, frFrame.GetSeqNum(), bSlot);
  290. #endif
  291. m_wDuplicateFrames++;
  292. }
  293. else
  294. {
  295. #if defined(DPVOICE_QUEUE_DEBUG)
  296. DPFX(DPFPREP, DVF_INFOLEVEL, "** QUEUE ** %i:%i ** CInnerQueue::Enqueue() putting frame in slot[%i]", m_wQueueId, m_bMsgNum, bSlot);
  297. #endif
  298. // if the frame previously occupying this slot has not
  299. // yet been released, this slot will not have a null pointer.
  300. DNASSERT(m_rgpfrSlots[bSlot] == NULL);
  301. // get a frame from the pool
  302. //m_rgpfrSlots[bSlot] = m_pfpFramePool->Get(m_pcsQueue, &m_rgpfrSlots[bSlot]);
  303. m_rgpfrSlots[bSlot] = m_pfpFramePool->Get(m_pcsQueue, NULL);
  304. #if defined(DPVOICE_QUEUE_DEBUG)
  305. DPFX(DPFPREP, DVF_INFOLEVEL, "** QUEUE ** %i:%i ** CInnerQueue::Enqueue() got frame from pool, Addr:%p", m_wQueueId, m_bMsgNum, m_rgpfrSlots[bSlot]);
  306. #endif
  307. /* RMT -- Added new func to copy frames directly.
  308. // the client number is the same
  309. m_rgpfrSlots[bSlot]->SetClientId(frFrame.GetClientId());
  310. // copy the target
  311. m_rgpfrSlots[bSlot]->SetTarget(frFrame.GetTarget());
  312. // No one but this function should be using
  313. // the sequence number, so just zero it out.
  314. m_rgpfrSlots[bSlot]->SetSeqNum(0);
  315. // copy the frame's data, also sets the frame length
  316. m_rgpfrSlots[bSlot]->CopyData(frFrame);
  317. // set the silence flag
  318. m_rgpfrSlots[bSlot]->SetIsSilence(frFrame.GetIsSilence()); */
  319. HRESULT hr;
  320. hr = m_rgpfrSlots[bSlot]->SetEqual(frFrame);
  321. if( FAILED( hr ) )
  322. {
  323. DNASSERT( FALSE );
  324. DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to copy frame in innerque" );
  325. }
  326. // this buffer is now full
  327. //m_rgeSlotStates[bSlot] = essFull;
  328. // increment the queue size
  329. ++m_bQueueSize;
  330. #if defined(DPVOICE_QUEUE_DEBUG)
  331. DPFX(DPFPREP, DVF_INFOLEVEL, "** QUEUE ** %i:%i ** CInnerQueue::Enqueue() new queue size[%i]", m_wQueueId, m_bMsgNum, m_bQueueSize);
  332. #endif
  333. // if the queue is currently filling, check to see if we've
  334. // passed the high water mark.
  335. if (m_eState == filling && m_bQueueSize > m_bHighWaterMark)
  336. {
  337. #if defined(DPVOICE_QUEUE_DEBUG)
  338. DPFX(DPFPREP, DVF_INFOLEVEL, "** QUEUE ** %i:%i ** CInnerQueue::Enqueue() High Water Mark hit, now in ready state", m_wQueueId, m_bMsgNum);
  339. #endif
  340. m_bFillingDequeueReqs = 0;
  341. m_eState = ready;
  342. }
  343. }
  344. }
  345. else
  346. {
  347. // Make a guess as to what caused this: overflow or late frame
  348. // Sequence numbers are allowed to be in the range 0 to 255.
  349. // if a sequence number is somewhere in the range 127 prior
  350. // to the current queue head (accounting for wraparound) then
  351. // assume it's a late frame. Otherwise, assume it's an overflow frame.
  352. if ((frFrame.GetSeqNum() < m_bHeadSeqNum
  353. && frFrame.GetSeqNum() > (int)m_bHeadSeqNum - 127)
  354. || (frFrame.GetSeqNum() > (128 + m_bHeadSeqNum)))
  355. {
  356. #if defined(DPVOICE_QUEUE_DEBUG)
  357. DPFX(DPFPREP, DVF_INFOLEVEL, "** QUEUE ** %i:%i ** CInnerQueue::Enqueue() Late frame, discarded", m_wQueueId, m_bMsgNum);
  358. #endif
  359. m_wLateFrames++;
  360. }
  361. else
  362. {
  363. #if defined(DPVOICE_QUEUE_DEBUG)
  364. DPFX(DPFPREP, DVF_INFOLEVEL, "** QUEUE ** %i:%i ** CInnerQueue::Enqueue() Overflow frame, discarded", m_wQueueId, m_bMsgNum);
  365. #endif
  366. m_wOverflowFrames++;
  367. }
  368. }
  369. return;
  370. }
  371. // Note: this class does not have it's own critical
  372. // section. The caller must ensure that enqueue and
  373. // dequeue are not called at the same time. It is
  374. // intended that this class is used only within
  375. // the InputQueue2 class, which does have a critical
  376. // section.
  377. #undef DPF_MODNAME
  378. #define DPF_MODNAME "CInnerQueue::Dequeue"
  379. CFrame* CInnerQueue::Dequeue()
  380. {
  381. CFrame* pfrReturn;
  382. if (!m_fInited)
  383. {
  384. return NULL;
  385. }
  386. // make sure that we're in the ready state
  387. DNASSERT(m_eState == ready);
  388. // The only class that should be using this one should
  389. // never call dequeue when there's nothing to get, so assert
  390. DNASSERT(m_bQueueSize != 0);
  391. // If we get here, there is at least one frame in the queue, somewhere.
  392. // increment the length of the message
  393. ++m_dwMsgLen;
  394. // find the index of the oldest frame, starting with the frame at the
  395. // head of the queue.
  396. BYTE bSlot = m_bHeadSeqNum % m_bNumSlots;
  397. int i = 0;
  398. #if defined(DPVOICE_QUEUE_DEBUG)
  399. DPFX(DPFPREP, DVF_INFOLEVEL, "** QUEUE ** %i:%i ** CInnerQueue::Dequeue() Checking slot[%i]", m_wQueueId, m_bMsgNum, bSlot);
  400. #endif
  401. //while (m_rgeSlotStates[bSlot] != essFull)
  402. while (m_rgpfrSlots[bSlot] == NULL)
  403. {
  404. // if this is the first dequeue, then we want to skip any empty
  405. // slots to find the first frame in the message. Otherwise, this
  406. // is a lost frame, and should be treated accordingly.
  407. if (m_fFirstDequeue == true)
  408. {
  409. // The current slot does not have a frame, try the
  410. // next. Put in a little sanity check for infinite
  411. // looping.
  412. DNASSERT(i++ < m_bNumSlots);
  413. ++bSlot;
  414. bSlot %= m_bNumSlots;
  415. #if defined(DPVOICE_QUEUE_DEBUG)
  416. DPFX(DPFPREP, DVF_INFOLEVEL, "** QUEUE ** %i:%i ** CInnerQueue::Dequeue() slot empty, checking slot[%i]", m_wQueueId, m_bMsgNum, bSlot);
  417. #endif
  418. // increment the head sequence number
  419. ++m_bHeadSeqNum;
  420. }
  421. else
  422. {
  423. // This is a lost frame
  424. #if defined(DPVOICE_QUEUE_DEBUG)
  425. DPFX(DPFPREP, DVF_INFOLEVEL, "** QUEUE ** %i:%i ** CInnerQueue::Dequeue() Frame Missing", m_wQueueId, m_bMsgNum);
  426. #endif
  427. ++m_wMissingFrames;
  428. // this missing frame is part of the message too, so
  429. // increment the total message size
  430. ++m_dwMsgLen;
  431. // increment the head sequence number
  432. ++m_bHeadSeqNum;
  433. // this is no longer the first dequeue
  434. m_fFirstDequeue = false;
  435. // return a silent frame marked as lost
  436. CFrame* pfr = m_pfpFramePool->Get(m_pcsQueue, NULL);
  437. pfr->SetIsSilence(true);
  438. pfr->SetIsLost(true);
  439. return pfr;
  440. }
  441. }
  442. m_fFirstDequeue = false;
  443. // By now, bSlot points to a valid, useful frame, which
  444. // we should return.
  445. // mark the slot we are about to return as empty
  446. //m_rgeSlotStates[bSlot] = essEmpty;
  447. // decrement the queue size
  448. --m_bQueueSize;
  449. #if defined(DPVOICE_QUEUE_DEBUG)
  450. DPFX(DPFPREP, DVF_INFOLEVEL, "** QUEUE ** %i:%i ** CInnerQueue::Dequeue() Returning frame in slot[%i]; New queue size[%i]", m_wQueueId, m_bMsgNum, bSlot, m_bQueueSize);
  451. #endif
  452. // increment the head sequence number
  453. ++m_bHeadSeqNum;
  454. // this is not a lost frame
  455. //m_rgpfrSlots[bSlot]->SetIsLost(false);
  456. pfrReturn = m_rgpfrSlots[bSlot];
  457. pfrReturn->SetIsLost(false);
  458. m_rgpfrSlots[bSlot] = NULL;
  459. //return(m_rgpfrSlots[bSlot]);
  460. return(pfrReturn);
  461. }
  462. #undef DPF_MODNAME
  463. #define DPF_MODNAME "CInnerQueuePool::CInnerQueuePool"
  464. CInnerQueuePool::CInnerQueuePool(
  465. BYTE bNumSlots,
  466. WORD wFrameSize,
  467. CFramePool* pfpFramePool,
  468. DNCRITICAL_SECTION* pcsQueue)
  469. : m_bNumSlots(bNumSlots)
  470. , m_wFrameSize(wFrameSize)
  471. , m_pfpFramePool(pfpFramePool)
  472. , m_pcsQueue(pcsQueue)
  473. , m_fCritSecInited(FALSE)
  474. {
  475. }
  476. #undef DPF_MODNAME
  477. #define DPF_MODNAME "CInnerQueuePool::~CInnerQueuePool"
  478. CInnerQueuePool::~CInnerQueuePool()
  479. {
  480. for (std::vector<CInnerQueue *>::iterator iter1 = m_vpiqPool.begin(); iter1 < m_vpiqPool.end(); ++iter1)
  481. {
  482. delete *iter1;
  483. }
  484. if (m_fCritSecInited)
  485. {
  486. DNDeleteCriticalSection(&m_lock);
  487. }
  488. }
  489. #undef DPF_MODNAME
  490. #define DPF_MODNAME "CInnerQueuePool::Get"
  491. CInnerQueue* CInnerQueuePool::Get(
  492. BYTE bHighWaterMark,
  493. WORD wQueueId,
  494. BYTE bMsgNum
  495. )
  496. {
  497. HRESULT hr;
  498. BFCSingleLock csl(&m_lock);
  499. csl.Lock();
  500. CInnerQueue* piq;
  501. if (m_vpiqPool.empty())
  502. {
  503. // the pool is empty, return a new inner queue
  504. piq = new CInnerQueue(
  505. m_bNumSlots,
  506. m_wFrameSize,
  507. m_pfpFramePool,
  508. m_pcsQueue,
  509. bMsgNum,
  510. bHighWaterMark,
  511. wQueueId);
  512. if( piq == NULL )
  513. return NULL;
  514. hr = piq->Init();
  515. if (FAILED(hr))
  516. {
  517. delete piq;
  518. return NULL;
  519. }
  520. }
  521. else
  522. {
  523. // there are some inner queues in the pool, pop
  524. // the last one off the back of the vector
  525. piq = m_vpiqPool.back();
  526. m_vpiqPool.pop_back();
  527. piq->SetMsgNum(bMsgNum);
  528. piq->SetQueueId(wQueueId);
  529. piq->SetHighWaterMark(bHighWaterMark);
  530. piq->Reset();
  531. }
  532. return piq;
  533. }
  534. #undef DPF_MODNAME
  535. #define DPF_MODNAME "CInnerQueuePool::Return"
  536. void CInnerQueuePool::Return(CInnerQueue* piq)
  537. {
  538. BFCSingleLock csl(&m_lock);
  539. csl.Lock();
  540. // drop this inner queue on the back for reuse
  541. m_vpiqPool.push_back(piq);
  542. }