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

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: hxsched.cpp,v 1.6.20.1 2004/07/09 02:06:33 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 "hxcom.h"
  50. #include "hxtypes.h"
  51. #include "hxresult.h"
  52. #ifdef _WINDOWS
  53. #include <windows.h>
  54. #endif
  55. #include "timeval.h"
  56. #include "clientpq.h"
  57. #include "ihxpckts.h"
  58. #include "hxfiles.h"
  59. #include "hxengin.h"
  60. #include "hxcore.h"
  61. #include "hxprefs.h"
  62. #include "timeline.h"
  63. #include "hxtick.h"
  64. #ifdef _MACINTOSH
  65. #include "hx_moreprocesses.h"
  66. #endif
  67. #if defined(_WIN32) || defined(THREADS_SUPPORTED)
  68. #include "casyntim.h"
  69. #endif /*_WIN32*/
  70. #include "hxthread.h"
  71. #include "hxsched.h"
  72. #include "hxheap.h"
  73. #ifdef _DEBUG
  74. #undef HX_THIS_FILE
  75. static const char HX_THIS_FILE[] = __FILE__;
  76. #endif
  77. #if defined(_WINDOWS) && !defined(_WIN32)   /* WIN16 */
  78. #define MINIMUM_GRANULARITY   55
  79. #elif defined (_MACINTOSH)     /* MACINTOSH */
  80. #define MINIMUM_GRANULARITY   20
  81. #elif defined (_UNIX)
  82. #define MINIMUM_GRANULARITY   20
  83. #else     /* ELSE */
  84. #define MINIMUM_GRANULARITY   20
  85. #endif 
  86. #define MINIMUM_DIFFERENCE    5
  87. // HXScheduler...
  88. HXScheduler::HXScheduler(IUnknown* pContext) :
  89.      m_lRefCount (0)
  90.     ,m_pScheduler(0)
  91.     ,m_pInterruptTimeScheduler(0)
  92.     ,m_pID(0)
  93.     ,m_pContext(pContext)
  94.     ,m_bLocked(FALSE)
  95.     ,m_bUseDeferredTask(TRUE)
  96. #if defined(_WIN32) || defined(THREADS_SUPPORTED)
  97.     ,m_pAsyncTimer(0)
  98. #endif 
  99.     ,m_pTimeline(0)
  100.     ,m_ulCurrentGranularity(0)
  101.     ,m_pCoreMutex(NULL)
  102.     ,m_ulLastUpdateTime(0)
  103.     ,m_bIsInterruptEnabled(FALSE)
  104.     ,m_ulSystemNextDueTime(0)
  105.     ,m_ulInterruptNextDueTime(0)
  106.     ,m_headTime(0)
  107.     ,m_interruptHeadTime(0)
  108.     ,m_bImmediatesPending(0)
  109. {
  110.     m_pID = new CHXID(100);
  111.     m_pScheduler = new ClientPQ(m_pID);
  112.     m_pInterruptTimeScheduler = new ClientPQ(m_pID);
  113.     (void) gettimeofday(&m_CurrentTimeVal, 0);
  114.     m_ulLastUpdateTime = HX_GET_TICKCOUNT();
  115. }
  116. HXScheduler::~HXScheduler()
  117. {
  118.     StopScheduler();
  119.     HX_DELETE(m_pScheduler);
  120.     HX_DELETE(m_pInterruptTimeScheduler);
  121.     HX_DELETE(m_pID);
  122. #if defined(_WIN32) || defined(THREADS_SUPPORTED)
  123.     HX_DELETE(m_pAsyncTimer);
  124. #endif 
  125.     HX_DELETE(m_pTimeline);
  126. }
  127. /*
  128.  * IUnknown methods
  129.  */
  130. /////////////////////////////////////////////////////////////////////////
  131. // Method:
  132. // IUnknown::QueryInterface
  133. // Purpose:
  134. // Implement this to export the interfaces supported by your 
  135. // object.
  136. //
  137. STDMETHODIMP HXScheduler::QueryInterface(REFIID riid, void** ppvObj)
  138. {
  139. #ifdef _MACINTOSH
  140.     if (IsEqualIID(riid, IID_IHXInterruptState) && m_pContext)
  141.     {
  142. return m_pContext->QueryInterface(riid, ppvObj);
  143.     }
  144. #endif
  145.     QInterfaceList qiList[] =
  146.         {
  147.             { GET_IIDHANDLE(IID_IHXScheduler), (IHXScheduler*)this },
  148.             { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXScheduler*)this },
  149.         };
  150.     
  151.     return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  152. }
  153. /////////////////////////////////////////////////////////////////////////
  154. // Method:
  155. // IUnknown::AddRef
  156. // Purpose:
  157. // Everyone usually implements this the same... feel free to use
  158. // this implementation.
  159. //
  160. STDMETHODIMP_(ULONG32) HXScheduler::AddRef()
  161. {
  162.     return InterlockedIncrement(&m_lRefCount);
  163. }
  164. /////////////////////////////////////////////////////////////////////////
  165. // Method:
  166. // IUnknown::Release
  167. // Purpose:
  168. // Everyone usually implements this the same... feel free to use
  169. // this implementation.
  170. //
  171. STDMETHODIMP_(ULONG32) HXScheduler::Release()
  172. {
  173.     if (InterlockedDecrement(&m_lRefCount) > 0)
  174.     {
  175. return m_lRefCount;
  176.     }
  177.     delete this;
  178.     return 0;
  179. }
  180. /*
  181.  * HXScheduler methods
  182.  */
  183. /************************************************************************
  184.  * Method:
  185.  * IHXScheduler::Enter
  186.  * Purpose:
  187.  * enter objects in the service queue
  188.  */
  189. STDMETHODIMP_(CallbackHandle)
  190. HXScheduler::RelativeEnter(IHXCallback* pCallback, ULONG32 ulTime)
  191. {
  192.     /*
  193.      * A RelativeEnter() of 0 ms is a special case that needs to be
  194.      * AbsoluteEnter() of 0
  195.      */
  196.     if (ulTime == 0)
  197.     {
  198. HXTimeval rVal;
  199. rVal.tv_sec = rVal.tv_usec = 0;
  200. return AbsoluteEnter(pCallback, rVal);
  201.     }
  202.     UINT32  usecs = 0;
  203.     UINT32  secs = 0;
  204.     Timeval lTime;
  205.     // handle the possible overflow of UINT32 when
  206.     // converting from milli-second to micro-second
  207.     if (ulTime > 4000000)
  208.     {
  209. secs = ulTime / 1000;
  210. usecs = (ulTime % 1000) * 1000;
  211.     }
  212.     else
  213.     {
  214. secs = 0;
  215. usecs = ulTime * 1000;
  216. if (usecs >= 1000000)
  217. {
  218.     secs = usecs / 1000000;
  219.     usecs = usecs % 1000000;
  220. }
  221.     }
  222.     lTime.tv_sec    = secs;
  223.     lTime.tv_usec   = usecs;
  224.     Timeval now;
  225.     now.tv_sec = m_CurrentTimeVal.tv_sec;
  226.     now.tv_usec = m_CurrentTimeVal.tv_usec;
  227.     now += lTime;
  228.     
  229.     if (pCallback)
  230.     {
  231. IHXInterruptSafe* pInterruptSafeCB = NULL;
  232. if(HXR_OK == pCallback->QueryInterface(IID_IHXInterruptSafe, 
  233. (void**) &pInterruptSafeCB))
  234. {
  235.     if (pInterruptSafeCB && pInterruptSafeCB->IsInterruptSafe())
  236.     {
  237.      CallbackHandle hCallback = (CallbackHandle) m_pInterruptTimeScheduler->
  238.      enter(now, pCallback);
  239.         pInterruptSafeCB->Release();
  240.         return hCallback;
  241.     }
  242.     pInterruptSafeCB->Release();
  243. }
  244.     }
  245.     
  246.     return (CallbackHandle) m_pScheduler->enter(now, pCallback);
  247. }
  248. /************************************************************************
  249.  * Method:
  250.  *     IHXScheduler::AbsoluteEnter
  251.  * Purpose:
  252.  *     enter objects in the service queue at absolute time
  253.  */
  254. STDMETHODIMP_(CallbackHandle)
  255. HXScheduler::AbsoluteEnter(IHXCallback* pCallback, HXTimeval tVal)
  256. {
  257.     Timeval lTime;
  258.     lTime.tv_sec    = tVal.tv_sec;
  259.     lTime.tv_usec   = tVal.tv_usec;
  260.     if (pCallback)
  261.     {
  262. IHXInterruptSafe* pInterruptSafeCB = NULL;
  263. if(HXR_OK == pCallback->QueryInterface(IID_IHXInterruptSafe, 
  264. (void**) &pInterruptSafeCB))
  265. {
  266.     if (pInterruptSafeCB && pInterruptSafeCB->IsInterruptSafe())
  267.     {
  268.      CallbackHandle hCallback = (CallbackHandle) m_pInterruptTimeScheduler->
  269.      enter(lTime, pCallback);
  270.         pInterruptSafeCB->Release();
  271.         return hCallback;
  272.     }
  273.     pInterruptSafeCB->Release();
  274. }
  275.     }
  276.     return (CallbackHandle) m_pScheduler->enter(lTime, pCallback);
  277. }
  278. /************************************************************************
  279.  * Method:
  280.  * IHXScheduler::Remove
  281.  * Purpose:
  282.  * remove objects from the service queue
  283.  */
  284. STDMETHODIMP HXScheduler::Remove(CallbackHandle Handle)
  285. {
  286.     if (m_pInterruptTimeScheduler->removeifexists(Handle))
  287.     {
  288.      return HXR_OK;
  289.     }
  290.     m_pScheduler->remove(Handle);
  291.     return HXR_OK;
  292. }
  293. /************************************************************************
  294.  * Method:
  295.  *     IHXScheduler::GetCurrentSchedulerTime
  296.  * Purpose:
  297.  *     gives the current time in the timeline of the scheduler...
  298.  */
  299. STDMETHODIMP_(HXTimeval) HXScheduler::GetCurrentSchedulerTime(void)
  300. {
  301.     HXTimeval hxTimeval;
  302.     hxTimeval.tv_sec = m_CurrentTimeVal.tv_sec;
  303.     hxTimeval.tv_usec = m_CurrentTimeVal.tv_usec;
  304.     return hxTimeval;
  305. }
  306. /************************************************************************
  307.  * Method:
  308.  * OnTimeSync
  309.  * Purpose:
  310.  * TBD
  311.  *
  312.  */
  313. HX_RESULT HXScheduler::OnTimeSync(BOOL bAtInterrupt)
  314. {
  315.     HX_RESULT theErr = HXR_OK;
  316.     
  317.     if (m_pCoreMutex)
  318.     {
  319. m_pCoreMutex->Lock();
  320.     }
  321.     if (!m_bLocked)
  322.     {
  323. m_bLocked = TRUE;
  324. theErr = ExecuteCurrentFunctions (bAtInterrupt);
  325. m_bLocked = FALSE;
  326.     }
  327.     if (m_pCoreMutex)
  328.     {
  329. m_pCoreMutex->Unlock();
  330.     }
  331.     return theErr;
  332. }
  333. HX_RESULT HXScheduler::ExecuteCurrentFunctions(BOOL bAtInterrupt)
  334. {
  335.     BOOL bShouldServiceSystem     = FALSE;
  336.     BOOL bShouldServiceInterrupt    = FALSE;
  337.     BOOL bImmediatesPending     = FALSE;
  338.     BOOL bInterruptImmediatesPending = FALSE;
  339.     if (FALSE == UpdateCurrentTime(bAtInterrupt, bShouldServiceSystem, bShouldServiceInterrupt))
  340.     {
  341.         return HXR_OK;
  342.     }
  343.     /* if not at interrupt time, execute interrupt safe & 
  344.      * non-interrupt safe tasks 
  345.      */
  346.     if( bShouldServiceInterrupt && !m_pInterruptTimeScheduler->empty() )
  347.     {
  348. m_pInterruptTimeScheduler->execute(m_CurrentTimeVal);
  349. /*
  350.  * Don't execute more then 100 immediate elements.  We don't wanna
  351.  * hold on too long and spin here.
  352.  */
  353. int count = 0;
  354. // Keep executing until there are no more zero time elements
  355. while ((bInterruptImmediatesPending = m_pInterruptTimeScheduler->immediate()) && 
  356.        (count < 100))
  357. {
  358.             count += m_pInterruptTimeScheduler->execute(m_CurrentTimeVal);
  359. }
  360.     }
  361.     if (bShouldServiceSystem && !m_pScheduler->empty())
  362.     {
  363. m_pScheduler->execute(m_CurrentTimeVal);
  364. /*
  365.  * Don't execute more then 100 immediate elements.  We don't wanna
  366.  * hold on too long and spin here.
  367.  */
  368. int count = 0;
  369. // Keep executing until there are no more zero time elements
  370. while ((bImmediatesPending = m_pScheduler->immediate()) && 
  371.        (count < 100))
  372. {
  373.     count += m_pScheduler->execute(m_CurrentTimeVal);
  374. }
  375. #if defined(_WIN32) || defined(THREADS_SUPPORTED)
  376. BOOL bChange = FALSE;
  377. if (m_pScheduler->empty())
  378.         {
  379.             if (m_ulCurrentGranularity < MINIMUM_GRANULARITY &&
  380. (MINIMUM_GRANULARITY - m_ulCurrentGranularity >= 
  381. MINIMUM_DIFFERENCE))
  382.     {
  383. bChange = TRUE;
  384. m_ulCurrentGranularity = MINIMUM_GRANULARITY;
  385.     }
  386.         }
  387.         else if (m_ulCurrentGranularity > MINIMUM_DIFFERENCE)
  388.         {
  389.     Timeval timeout   = m_pScheduler->head_time() - m_CurrentTimeVal;
  390.     INT32  lTimeoutInMs;
  391.     
  392.     if (timeout.tv_sec >= 0)
  393.     {
  394. lTimeoutInMs = timeout.tv_sec * 1000 + 
  395.        timeout.tv_usec / 1000;
  396.     }
  397.     else
  398.     {
  399. lTimeoutInMs = 0;
  400.     }
  401.     if (lTimeoutInMs > 0 &&
  402. (UINT32) lTimeoutInMs < m_ulCurrentGranularity &&
  403. (m_ulCurrentGranularity - (UINT32) lTimeoutInMs >= 
  404.     MINIMUM_DIFFERENCE))
  405.     {
  406. bChange = TRUE;
  407. m_ulCurrentGranularity = (UINT32) ((lTimeoutInMs >= MINIMUM_DIFFERENCE ? 
  408. lTimeoutInMs: MINIMUM_DIFFERENCE));
  409.     }
  410. }
  411. if (bChange)
  412. {
  413. m_pTimeline->Pause();
  414. /* Reset the granularity */
  415. m_pTimeline->SetGranularity(m_ulCurrentGranularity);
  416. /* Resume */
  417. m_pTimeline->Resume();
  418. }
  419. #endif /*_WIN32*/
  420.     }
  421.     m_bImmediatesPending = bImmediatesPending || bInterruptImmediatesPending;
  422.     Timeval timeout;
  423.     if (!m_pScheduler->empty())
  424.     {
  425. timeout = m_pScheduler->head_time() - m_CurrentTimeVal;
  426. if (timeout.tv_sec >= 0)
  427. {
  428.     m_ulSystemNextDueTime = (UINT32) (timeout.tv_sec*1000+timeout.tv_usec/1000);
  429. }
  430. else
  431. {
  432.     m_ulSystemNextDueTime = 0;
  433. }
  434.     }
  435.     else
  436.     {
  437. m_ulSystemNextDueTime = m_ulCurrentGranularity;
  438.     }
  439.     if (!m_pInterruptTimeScheduler->empty())
  440.     {
  441. timeout = m_pInterruptTimeScheduler->head_time() - m_CurrentTimeVal;
  442. if (timeout.tv_sec >= 0)
  443. {
  444.     m_ulInterruptNextDueTime = (UINT32) (timeout.tv_sec*1000+timeout.tv_usec/1000);
  445. }
  446. else
  447. {
  448.     m_ulInterruptNextDueTime = 0;
  449. }
  450.     }
  451.     else
  452.     {
  453. m_ulInterruptNextDueTime = m_ulCurrentGranularity;
  454.     }
  455.     return HXR_OK;
  456. }
  457. BOOL HXScheduler::IsEmpty() 
  458. {
  459.     return (m_pScheduler->empty() && m_pInterruptTimeScheduler->empty());
  460. }
  461. BOOL HXScheduler::GetNextEventDueTimeDiff(ULONG32 &ulEarliestDueTimeDiff)
  462. {
  463.     if (m_pScheduler->empty() && m_pInterruptTimeScheduler->empty())
  464. return FALSE;
  465.     Timeval nextDueTime;
  466.     Timeval now;
  467.     now.tv_sec = m_CurrentTimeVal.tv_sec;
  468.     now.tv_usec = m_CurrentTimeVal.tv_usec;
  469.     if (m_pScheduler->empty())
  470.     {
  471. nextDueTime = m_pInterruptTimeScheduler->head_time();
  472.     }
  473.     else if (m_pInterruptTimeScheduler->empty())
  474.     {
  475. nextDueTime = m_pScheduler->head_time();
  476.     }
  477.     else
  478.     {
  479. if (m_pInterruptTimeScheduler->head_time() < m_pScheduler->head_time())
  480. {
  481.     nextDueTime = m_pInterruptTimeScheduler->head_time();
  482. }
  483. else
  484. {
  485.     nextDueTime = m_pScheduler->head_time();
  486. }
  487.     }
  488.     if (nextDueTime > now)
  489.     {
  490. nextDueTime -= now;
  491.     }
  492.     else
  493.     {
  494. nextDueTime = 0.0;
  495.     }
  496.     ulEarliestDueTimeDiff = (ULONG32) ( nextDueTime.tv_sec*1000 + 
  497. nextDueTime.tv_usec/1000);
  498.     return TRUE;
  499. }
  500. HX_RESULT    HXScheduler::StartScheduler()
  501. {
  502.     return StartSchedulerImplementation(FALSE);
  503. }
  504. HX_RESULT    HXScheduler::StartSchedulerTimerFixup()
  505. {
  506.     return StartSchedulerImplementation(TRUE);
  507. }
  508. HX_RESULT    HXScheduler::StartSchedulerImplementation(BOOL TimerFixup)
  509. {
  510.     HX_RESULT theErr = HXR_OK;
  511.     /* Stop any already running scheduler*/
  512.     StopScheduler();
  513.     (void) gettimeofday((Timeval*)&m_CurrentTimeVal, 0);
  514.     m_ulLastUpdateTime = HX_GET_TICKCOUNT();
  515. #if defined(_WIN32) || defined(THREADS_SUPPORTED)
  516.     if (m_bIsInterruptEnabled)
  517.     {
  518. if (!m_pAsyncTimer)
  519. {
  520.     m_pAsyncTimer = new CAsyncTimer(this);
  521. }
  522. if (!m_pAsyncTimer)
  523. {
  524.     return HXR_OUTOFMEMORY;
  525. }
  526. m_pAsyncTimer->SetGranularity(MINIMUM_GRANULARITY);
  527.         theErr = m_pAsyncTimer->StartTimer();
  528.     }
  529. #endif // _WIN32 || THREADS_SUPPORTED
  530.     if (!m_pTimeline)
  531.     {
  532. m_pTimeline = new Timeline;
  533.     }
  534.     if (m_pTimeline)
  535.     {
  536. m_pTimeline->Init( (IUnknown*) (IHXScheduler*) this, m_bUseDeferredTask);
  537. #if defined(_MACINTOSH) && defined(THREADS_SUPPORTED)
  538. m_pTimeline->SetCoreMutex(m_pCoreMutex);
  539. #endif
  540. m_pTimeline->SetStartTime(0);
  541. m_ulCurrentGranularity = MINIMUM_GRANULARITY;
  542. m_pTimeline->SetGranularity(m_ulCurrentGranularity);
  543. if (TimerFixup)
  544.     m_pTimeline->SetTimerFixup(TRUE);
  545. m_pTimeline->Resume();
  546.     }
  547.     else
  548.     {
  549. theErr = HXR_OUTOFMEMORY;
  550.     }
  551.     return theErr;
  552. }
  553. void HXScheduler::StopScheduler()
  554. {
  555. #if defined(_WIN32) || defined(THREADS_SUPPORTED)
  556.     if (m_pAsyncTimer)
  557.     {
  558. m_pAsyncTimer->StopTimer();
  559.     }
  560. #endif    
  561.     if (m_pTimeline)
  562.     {
  563. m_pTimeline->Pause();
  564. m_pTimeline->Done();
  565.     }
  566. }
  567. BOOL HXScheduler::IsAtInterruptTime(void)
  568. {
  569. #ifdef _MACINTOSH
  570.     return !IsMacInCooperativeThread();
  571. #elif defined (_WIN32)  || defined(THREADS_SUPPORTED)
  572.     return (m_bIsInterruptEnabled &&
  573.     m_pAsyncTimer->InTimerThread());
  574. #endif
  575.     return FALSE;
  576. }
  577. BOOL HXScheduler::UpdateCurrentTime(BOOL bAtInterrupt, BOOL& bShouldServiceSystem, 
  578.                                      BOOL& bShouldServiceInterrupt)
  579. {
  580.     BOOL    bResult = TRUE;
  581. #if defined(_WINDOWS) || defined(_WIN32) || defined (_MACINTOSH) || defined(THREADS_SUPPORTED)
  582.     UINT32 ulCurrentTime = HX_GET_TICKCOUNT();
  583.     UINT32 ulElapsedTime = CALCULATE_ELAPSED_TICKS(m_ulLastUpdateTime, ulCurrentTime);
  584. //    UINT32 ulCurrentTimeBetter = HX_GET_BETTERTICKCOUNT();
  585. //{FILE* f1 = ::fopen("d:\temp\better.txt", "a+"); ::fprintf(f1, "Diff %lu %lu %lu %lun", ulCurrentTime, ulCurrentTimeBetter, ulElapsedTime, CALCULATE_ELAPSED_TICKS(ulCurrentTimeBetter, ulCurrentTime));::fclose(f1);}
  586.     if (ulElapsedTime >= m_ulInterruptNextDueTime)
  587.     {
  588. bShouldServiceInterrupt = TRUE;
  589.     }
  590.     if (!bAtInterrupt &&
  591. ulElapsedTime >= m_ulSystemNextDueTime)
  592.     {
  593. bShouldServiceSystem = TRUE;
  594.     }
  595. //{FILE* f1 = ::fopen("d:\temp\pq.txt", "a+"); ::fprintf(f1, "nUpdateCurrentTime %d %lu", m_ulCoreThreadID == GetCurrentThreadId(), CALCULATE_ELAPSED_TICKS(m_ulLastUpdateTime, ulCurrentTime));::fclose(f1);}
  596.     if (bShouldServiceSystem || bShouldServiceInterrupt)
  597.     {
  598. m_CurrentTimeVal    += (1000 * ulElapsedTime);
  599. m_ulLastUpdateTime  = ulCurrentTime;
  600.     }
  601. #else
  602.     if (!bAtInterrupt)
  603.     {
  604. bShouldServiceSystem    = TRUE;
  605.     }
  606.     bShouldServiceInterrupt = TRUE;
  607.     (void) gettimeofday(&m_CurrentTimeVal, 0);
  608. #endif
  609.     if (!(bShouldServiceSystem || bShouldServiceInterrupt))
  610.     {
  611. bResult = FALSE;
  612. if (!m_pScheduler->empty() &&
  613.     m_pScheduler->head_time() != m_headTime)
  614. {
  615.     m_headTime = m_pScheduler->head_time();
  616.     bResult = TRUE;
  617. }
  618.     
  619. if (!m_pInterruptTimeScheduler->empty() &&
  620.     m_pInterruptTimeScheduler->head_time() != m_interruptHeadTime)
  621. {
  622.     m_interruptHeadTime = m_pInterruptTimeScheduler->head_time();
  623.     bResult = TRUE;
  624. }
  625.     }
  626.     return bResult;
  627. }
  628. void HXScheduler::NotifyPlayState(BOOL bInPlayingState)
  629. {
  630. #if defined(_WIN32) || defined(THREADS_SUPPORTED)
  631.     if (m_pAsyncTimer)
  632.     {
  633. m_pAsyncTimer->NotifyPlayState(bInPlayingState);
  634.     }
  635. #endif
  636. }