pq.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:11k
源码类别:

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: pq.cpp,v 1.4.22.3 2004/07/09 01:44:03 hubbe Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. #include "hxtypes.h"
  50. #include "hxassert.h"
  51. #include "debug.h"
  52. #include "timeval.h"
  53. #include "hxcom.h"
  54. #include "hxengin.h"
  55. #include "ihxpckts.h"
  56. #include "hxfiles.h"
  57. #include "id.h"
  58. #include "pq.h"
  59. #include "hxheap.h"
  60. #ifdef _DEBUG
  61. #undef HX_THIS_FILE
  62. static const char HX_THIS_FILE[] = __FILE__;
  63. #endif
  64. #ifdef WIN32
  65. /*
  66.  * XXX This is the 3.0 bug that Glenn found. 
  67.  * We need to fix this correctly!
  68.  */
  69. #define float double
  70. #endif
  71. PQ::PQ(CHXID* pIds)
  72. {
  73. //    int i;
  74.     m_pHead = 0;
  75.     m_pNextZeroInsertion = 0;
  76.     m_lElementCount = 0;
  77.     m_HeadTime.tv_sec = PQ_UNINITIALIZED;
  78.     gettimeofday(&m_Bucket0Time, 0);
  79.     m_Bucket0Time.tv_usec = 0;
  80.     memset (m_pBuckets, 0, NUM_BUCKETS * sizeof (PQElem*));
  81.     if (pIds)
  82.     {
  83. m_pIds = pIds;
  84. m_bOwnID = FALSE;
  85.     }
  86.     else
  87.     {
  88. m_pIds = new CHXID;
  89. m_bOwnID = TRUE;
  90.     }
  91. }
  92. PQ::~PQ()
  93. {
  94.     Timeval now;
  95.     now.tv_sec = 0x7fffffff;
  96.     now.tv_usec = 0x7fffffff;
  97.     PQElem* pElem = _remove_head(now);
  98.     while (pElem) 
  99.     {
  100. PQElem* pElemNext = pElem->m_pNext;
  101. m_pIds->destroy(pElem->m_Id);
  102. if (!pElem->m_bDefunct)
  103.     free_callback(pElem->m_pCallback);
  104. free_elem(pElem);
  105. if (!pElemNext)
  106.     break;
  107. pElem = pElemNext; 
  108.     }
  109.     for (int i = 0; i < NUM_BUCKETS; i++)
  110.     {
  111. PQElem* pElem = m_pBuckets[i];
  112. while (pElem) 
  113. {
  114.     PQElem* pElemNext = pElem->m_pNext;
  115.     m_pIds->destroy(pElem->m_Id);
  116.     if (!pElem->m_bDefunct)
  117. free_callback(pElem->m_pCallback);
  118.     free_elem(pElem);
  119.     if (!pElemNext)
  120. break;
  121.     pElem = pElemNext; 
  122. }
  123.     }
  124.     if (m_bOwnID)
  125.     {
  126. HX_DELETE(m_pIds);
  127.     }
  128. }
  129. UINT32
  130. PQ::enter(Timeval t, IHXCallback* pCallback)
  131. {
  132. #ifdef WIN32
  133.     /*
  134.      * Normalize t for NT
  135.      */
  136.     t.tv_usec = (t.tv_usec / 1000) * 1000;
  137. #endif
  138.     PQElem** pq;
  139.     PQElem* q;
  140.     PQElem* i = new_elem();
  141.     HX_ASSERT (i);
  142.     pCallback->AddRef();
  143.     i->m_pCallback  = pCallback;
  144.     i->m_bRemoved = 0;
  145. #ifdef SMP_PQ_DEBUG
  146.     if (pCallback < 0x8000)
  147.     {
  148. printf ("Bad Callback!! BAD BAD BAD!n");
  149. volatile int* pCrashMe = 0;
  150. *pCrashMe = 5;
  151.     }
  152. #endif
  153.     int bucket = (int)((t.tv_sec  - m_Bucket0Time.tv_sec)  * RESOLUTION +
  154.            (t.tv_usec - m_Bucket0Time.tv_usec) / (float)USEC_PER_BUCKET);
  155.     if ((bucket < NUM_BUCKETS) && (bucket >= 0))
  156.     {
  157. i->m_pNext = m_pBuckets[bucket];
  158.      i->m_Time = t;
  159.      m_pBuckets[bucket] = i;
  160.     }
  161.     else
  162.     {
  163. if (t.tv_sec == 0)
  164. {
  165.     if (m_pNextZeroInsertion)
  166.     {
  167. i->m_pNext = m_pNextZeroInsertion->m_pNext;
  168. m_pNextZeroInsertion->m_pNext = i;
  169. m_pNextZeroInsertion = i;
  170. i->m_Time = t;
  171. goto inserted;
  172.     }
  173.     else
  174.     {
  175. m_pNextZeroInsertion = i;
  176.     }
  177. }
  178. for (pq = &m_pHead; (q = *pq) != 0; pq = &q->m_pNext)
  179. {
  180.     if (q->m_Time >= t)
  181. break;
  182. }
  183. *pq = i;
  184. i->m_pNext = q;
  185. i->m_Time = t;
  186.     }
  187. inserted:
  188.     if ((m_HeadTime.tv_sec == PQ_UNINITIALIZED) || (m_HeadTime > t))
  189.      m_HeadTime = t;
  190.     m_lElementCount++;
  191.     i->m_Id = m_pIds->create((void *)i);
  192. //{FILE* f1 = ::fopen("c:\temp\pq.txt", "a+"); ::fprintf(f1, "enter: %lun", i->m_Id);::fclose(f1);}
  193.     return i->m_Id;
  194. }
  195. void
  196. PQ::remove(UINT32 id)
  197. {
  198. //{FILE* f1 = ::fopen("c:\temp\pq.txt", "a+"); ::fprintf(f1, "remove: %lun", id);::fclose(f1);}
  199.     PQElem* i = (PQElem*)m_pIds->get(id);
  200.     HX_ASSERT(i);
  201.     if (i)
  202.     {
  203. i->m_bDefunct = 1;
  204. free_callback(i->m_pCallback);
  205.     }
  206. }
  207. BOOL
  208. PQ::removeifexists(UINT32 id)
  209. {
  210.     PQElem* i = (PQElem*)m_pIds->get(id);
  211.     
  212.     if (i)
  213.     {
  214. //{FILE* f1 = ::fopen("c:\temp\pq.txt", "a+"); ::fprintf(f1, "removeifexists: %lun", id);::fclose(f1);}
  215. i->m_bDefunct = 1;
  216. free_callback(i->m_pCallback);
  217. return TRUE;
  218.     }
  219.     return FALSE;
  220. }
  221. BOOL
  222. PQ::exists(UINT32 id)
  223. {
  224.     return ((PQElem*)m_pIds->get(id) != 0);
  225. }
  226. int
  227. PQ::execute(Timeval now)
  228. {
  229.     PQElem* pElem = _remove_head(now);
  230.     int ulCount = 0;
  231.     /* Make sure head time is uninitialized ONLY if element count is zero */
  232.     HX_ASSERT(m_HeadTime.tv_sec != PQ_UNINITIALIZED || m_lElementCount == 0);
  233.     while (pElem) 
  234.     {
  235.         PQElem* pElemNext = dispatch_element(pElem);
  236.         if (!pElem->m_bDefunct)
  237.             ulCount++;
  238.         destroy_element(pElem);
  239.         if (!pElemNext)
  240.             break;
  241.         pElem = pElemNext; 
  242.     }
  243.     return ulCount;
  244. }
  245. PQElem*
  246. PQ::get_execute_list(Timeval now)
  247. {
  248.     return _remove_head(now);
  249. }
  250. PQElem*
  251. PQ::execute_element(PQElem* pElem)
  252. {
  253.     PQElem* pElemNext = dispatch_element(pElem);
  254.     destroy_element(pElem);
  255.     return pElemNext;
  256. }
  257. PQElem*
  258. PQ::_remove_head(Timeval now)
  259. {
  260.     int i;
  261.     PQElem* out_list = 0;
  262.     PQElem* current = 0;
  263.     m_pNextZeroInsertion = NULL;
  264.     int bucket = (int)((now.tv_sec  - m_Bucket0Time.tv_sec)  * RESOLUTION +
  265.            (now.tv_usec - m_Bucket0Time.tv_usec) / (float)USEC_PER_BUCKET);
  266.     // We are not yet ready to empty the first bucket
  267.     if (bucket < 0)
  268.     {
  269.      m_HeadTime.tv_sec = PQ_UNINITIALIZED;
  270.      for (i = 0; i < NUM_BUCKETS; i++)
  271.          if (m_pBuckets[i])
  272.          {
  273.           m_HeadTime = m_pBuckets[i]->m_Time;
  274.           break;
  275.          }
  276.     }
  277.     else
  278.     {
  279.      if (bucket >= NUM_BUCKETS)
  280.          bucket = NUM_BUCKETS - 1;
  281.      for (i = 0; i <= bucket; i++)
  282.      {
  283.          if (!m_pBuckets[i])
  284.           continue;
  285.          if (!out_list)
  286.           out_list = m_pBuckets[i];
  287.          if (current)
  288.          {
  289.           // Concatenate with previous bucket's list
  290.           current->m_pNext = m_pBuckets[i];
  291.          }
  292.          current = m_pBuckets[i];
  293.          while (current->m_pNext)
  294.          {
  295. current = current->m_pNext;
  296.           m_lElementCount--;
  297.          }
  298.     m_lElementCount--;
  299.      }
  300.      // Update the first bucket's time stamp.
  301.      Timeval t;
  302.      t.tv_sec = 0;
  303.      t.tv_usec = (int)((float)USEC_PER_BUCKET * (bucket + 1));
  304.      m_Bucket0Time += t;
  305. #ifdef WIN32
  306. /*
  307.  * Adjust Bucket0Time.tv_usec for NT
  308.  */
  309. m_Bucket0Time.tv_usec = (m_Bucket0Time.tv_usec / 1000) * 1000;
  310. #endif
  311.      // Move the buckets up
  312. memmove (m_pBuckets, &m_pBuckets[bucket + 1], (NUM_BUCKETS - bucket - 1) *
  313.          sizeof (void *));
  314.      // Zero all new buckets
  315. for (i = NUM_BUCKETS - 1;; i--, bucket--)
  316.      {
  317.          m_pBuckets[i] = 0;
  318.          if (!bucket)
  319.           break;
  320.      }
  321.      // Recalculate the m_HeadTime
  322.      m_HeadTime.tv_sec = PQ_UNINITIALIZED;
  323.      for (i = 0; i < NUM_BUCKETS; i++)
  324.          if (m_pBuckets[i])
  325.          {
  326.           m_HeadTime = m_pBuckets[i]->m_Time;
  327.           break;
  328.          }
  329.     }
  330.     PQElem* h;
  331.     if (!m_pHead)
  332. return out_list;
  333.     h = m_pHead;
  334.     /*
  335.      * Keep track of the head time from the buckets
  336.      */
  337.     Timeval TempHeadTime = m_HeadTime;
  338.     
  339.     if ((m_HeadTime.tv_sec == PQ_UNINITIALIZED) || (h->m_Time < m_HeadTime))
  340.      m_HeadTime = h->m_Time;
  341.     if (h->m_Time != (LONG32)0 && now < h->m_Time)
  342. return out_list;
  343.     PQElem* last;
  344.     for (;;)
  345.     {
  346. last = m_pHead;
  347. m_lElementCount--;
  348. m_pHead = last->m_pNext;
  349. if (!m_pHead)
  350.     break;
  351. if (m_pHead->m_Time != (LONG32)0 && now < m_pHead->m_Time)
  352. {
  353.     last->m_pNext = 0;
  354.     break;
  355. }
  356.     }
  357.     /*
  358.      * If the head time from the alternate queue is earlier than the head
  359.      * time from the buckets, keep the head time from the alternate queue
  360.      */
  361.     if (m_pHead &&
  362.         (TempHeadTime.tv_sec == PQ_UNINITIALIZED || m_pHead->m_Time < TempHeadTime))
  363. TempHeadTime = m_pHead->m_Time;
  364.     /*
  365.      * Now reset m_HeadTime to the time of the queue which will be ready
  366.      * first
  367.      */
  368.     if (m_HeadTime == (LONG32)0 || TempHeadTime < m_HeadTime)
  369.      m_HeadTime = TempHeadTime;
  370.     if (current)
  371.     {
  372. last->m_pNext = out_list;
  373. out_list = h;
  374.     }
  375.     else
  376.      return h;
  377.     return out_list;
  378. }
  379. PQElem* PQ::dispatch_element(PQElem* pElem)
  380. {
  381.     PQElem* pRet = NULL;
  382.     
  383.     if (pElem)
  384.     {
  385.         pRet = pElem->m_pNext;
  386.         if (!pElem->m_bDefunct && pElem->m_pCallback)
  387.         {
  388.             pElem->m_pCallback->Func();
  389.             free_callback(pElem->m_pCallback);
  390.         }
  391.     }
  392.     
  393.     return pRet;
  394. }
  395. void PQ::destroy_element(PQElem* pElem)
  396. {
  397.     if (pElem && m_pIds)
  398.     {
  399.         m_pIds->destroy(pElem->m_Id);
  400.         free_elem(pElem);
  401.     }
  402. }