📄 hxsched.cpp
字号:
{
m_pCoreMutex->Unlock();
}
return theErr;
}
HX_RESULT HXScheduler::ExecuteCurrentFunctions(BOOL bAtInterrupt)
{
BOOL bShouldServiceSystem = FALSE;
BOOL bShouldServiceInterrupt = FALSE;
BOOL bImmediatesPending = FALSE;
BOOL bInterruptImmediatesPending = FALSE;
if (FALSE == UpdateCurrentTime(bAtInterrupt, bShouldServiceSystem, bShouldServiceInterrupt))
{
return HXR_OK;
}
/* if not at interrupt time, execute interrupt safe &
* non-interrupt safe tasks
*/
if( bShouldServiceInterrupt && !m_pInterruptTimeScheduler->empty() )
{
m_pInterruptTimeScheduler->execute(m_CurrentTimeVal);
/*
* Don't execute more then 100 immediate elements. We don't wanna
* hold on too long and spin here.
*/
int count = 0;
// Keep executing until there are no more zero time elements
while ((bInterruptImmediatesPending = m_pInterruptTimeScheduler->immediate()) &&
(count < 100))
{
count += m_pInterruptTimeScheduler->execute(m_CurrentTimeVal);
}
}
if (bShouldServiceSystem && !m_pScheduler->empty())
{
m_pScheduler->execute(m_CurrentTimeVal);
/*
* Don't execute more then 100 immediate elements. We don't wanna
* hold on too long and spin here.
*/
int count = 0;
// Keep executing until there are no more zero time elements
while ((bImmediatesPending = m_pScheduler->immediate()) &&
(count < 100))
{
count += m_pScheduler->execute(m_CurrentTimeVal);
}
#if defined(_WIN32) || defined(THREADS_SUPPORTED)
BOOL bChange = FALSE;
if (m_pScheduler->empty())
{
if (m_ulCurrentGranularity < MINIMUM_GRANULARITY &&
(MINIMUM_GRANULARITY - m_ulCurrentGranularity >=
MINIMUM_DIFFERENCE))
{
bChange = TRUE;
m_ulCurrentGranularity = MINIMUM_GRANULARITY;
}
}
else if (m_ulCurrentGranularity > MINIMUM_DIFFERENCE)
{
Timeval timeout = m_pScheduler->head_time() - m_CurrentTimeVal;
INT32 lTimeoutInMs;
if (timeout.tv_sec >= 0)
{
lTimeoutInMs = timeout.tv_sec * 1000 +
timeout.tv_usec / 1000;
}
else
{
lTimeoutInMs = 0;
}
if (lTimeoutInMs > 0 &&
(UINT32) lTimeoutInMs < m_ulCurrentGranularity &&
(m_ulCurrentGranularity - (UINT32) lTimeoutInMs >=
MINIMUM_DIFFERENCE))
{
bChange = TRUE;
m_ulCurrentGranularity = (UINT32) ((lTimeoutInMs >= MINIMUM_DIFFERENCE ?
lTimeoutInMs: MINIMUM_DIFFERENCE));
}
}
if (bChange)
{
m_pTimeline->Pause();
/* Reset the granularity */
m_pTimeline->SetGranularity(m_ulCurrentGranularity);
/* Resume */
m_pTimeline->Resume();
}
#endif /*_WIN32*/
}
m_bImmediatesPending = bImmediatesPending || bInterruptImmediatesPending;
Timeval timeout;
if (!m_pScheduler->empty())
{
timeout = m_pScheduler->head_time() - m_CurrentTimeVal;
if (timeout.tv_sec >= 0)
{
m_ulSystemNextDueTime = (UINT32) (timeout.tv_sec*1000+timeout.tv_usec/1000);
}
else
{
m_ulSystemNextDueTime = 0;
}
}
else
{
m_ulSystemNextDueTime = m_ulCurrentGranularity;
}
if (!m_pInterruptTimeScheduler->empty())
{
timeout = m_pInterruptTimeScheduler->head_time() - m_CurrentTimeVal;
if (timeout.tv_sec >= 0)
{
m_ulInterruptNextDueTime = (UINT32) (timeout.tv_sec*1000+timeout.tv_usec/1000);
}
else
{
m_ulInterruptNextDueTime = 0;
}
}
else
{
m_ulInterruptNextDueTime = m_ulCurrentGranularity;
}
return HXR_OK;
}
BOOL HXScheduler::IsEmpty()
{
return (m_pScheduler->empty() && m_pInterruptTimeScheduler->empty());
}
BOOL HXScheduler::GetNextEventDueTimeDiff(ULONG32 &ulEarliestDueTimeDiff)
{
if (m_pScheduler->empty() && m_pInterruptTimeScheduler->empty())
return FALSE;
Timeval nextDueTime;
Timeval now;
now.tv_sec = m_CurrentTimeVal.tv_sec;
now.tv_usec = m_CurrentTimeVal.tv_usec;
if (m_pScheduler->empty())
{
nextDueTime = m_pInterruptTimeScheduler->head_time();
}
else if (m_pInterruptTimeScheduler->empty())
{
nextDueTime = m_pScheduler->head_time();
}
else
{
if (m_pInterruptTimeScheduler->head_time() < m_pScheduler->head_time())
{
nextDueTime = m_pInterruptTimeScheduler->head_time();
}
else
{
nextDueTime = m_pScheduler->head_time();
}
}
if (nextDueTime > now)
{
nextDueTime -= now;
}
else
{
nextDueTime = 0.0;
}
ulEarliestDueTimeDiff = (ULONG32) ( nextDueTime.tv_sec*1000 +
nextDueTime.tv_usec/1000);
return TRUE;
}
HX_RESULT HXScheduler::StartScheduler()
{
return StartSchedulerImplementation(FALSE);
}
HX_RESULT HXScheduler::StartSchedulerTimerFixup()
{
return StartSchedulerImplementation(TRUE);
}
HX_RESULT HXScheduler::StartSchedulerImplementation(BOOL TimerFixup)
{
HX_RESULT theErr = HXR_OK;
/* Stop any already running scheduler*/
StopScheduler();
(void) gettimeofday((Timeval*)&m_CurrentTimeVal, 0);
m_ulLastUpdateTime = HX_GET_TICKCOUNT();
#if defined(_WIN32) || defined(THREADS_SUPPORTED)
if (m_bIsInterruptEnabled)
{
if (!m_pAsyncTimer)
{
m_pAsyncTimer = new CAsyncTimer(this);
}
if (!m_pAsyncTimer)
{
return HXR_OUTOFMEMORY;
}
m_pAsyncTimer->SetGranularity(MINIMUM_GRANULARITY);
theErr = m_pAsyncTimer->StartTimer();
}
#endif // _WIN32 || THREADS_SUPPORTED
if (!m_pTimeline)
{
m_pTimeline = new Timeline;
}
if (m_pTimeline)
{
m_pTimeline->Init( (IUnknown*) (IHXScheduler*) this, m_bUseDeferredTask);
#if defined(_MACINTOSH) && defined(THREADS_SUPPORTED)
m_pTimeline->SetCoreMutex(m_pCoreMutex);
#endif
m_pTimeline->SetStartTime(0);
m_ulCurrentGranularity = MINIMUM_GRANULARITY;
m_pTimeline->SetGranularity(m_ulCurrentGranularity);
if (TimerFixup)
m_pTimeline->SetTimerFixup(TRUE);
m_pTimeline->Resume();
}
else
{
theErr = HXR_OUTOFMEMORY;
}
return theErr;
}
void HXScheduler::StopScheduler()
{
#if defined(_WIN32) || defined(THREADS_SUPPORTED)
if (m_pAsyncTimer)
{
m_pAsyncTimer->StopTimer();
}
#endif
if (m_pTimeline)
{
m_pTimeline->Pause();
m_pTimeline->Done();
}
}
BOOL HXScheduler::IsAtInterruptTime(void)
{
#ifdef _MACINTOSH
return !IsMacInCooperativeThread();
#elif defined (_WIN32) || defined(THREADS_SUPPORTED)
return (m_bIsInterruptEnabled &&
m_pAsyncTimer->InTimerThread());
#endif
return FALSE;
}
BOOL HXScheduler::UpdateCurrentTime(BOOL bAtInterrupt, BOOL& bShouldServiceSystem,
BOOL& bShouldServiceInterrupt)
{
BOOL bResult = TRUE;
#if defined(_WINDOWS) || defined(_WIN32) || defined (_MACINTOSH) || defined(THREADS_SUPPORTED)
UINT32 ulCurrentTime = HX_GET_TICKCOUNT();
UINT32 ulElapsedTime = CALCULATE_ELAPSED_TICKS(m_ulLastUpdateTime, ulCurrentTime);
// UINT32 ulCurrentTimeBetter = HX_GET_BETTERTICKCOUNT();
//{FILE* f1 = ::fopen("d:\\temp\\better.txt", "a+"); ::fprintf(f1, "Diff %lu %lu %lu %lu\n", ulCurrentTime, ulCurrentTimeBetter, ulElapsedTime, CALCULATE_ELAPSED_TICKS(ulCurrentTimeBetter, ulCurrentTime));::fclose(f1);}
if (ulElapsedTime >= m_ulInterruptNextDueTime)
{
bShouldServiceInterrupt = TRUE;
}
if (!bAtInterrupt &&
ulElapsedTime >= m_ulSystemNextDueTime)
{
bShouldServiceSystem = TRUE;
}
//{FILE* f1 = ::fopen("d:\\temp\\pq.txt", "a+"); ::fprintf(f1, "\nUpdateCurrentTime %d %lu", m_ulCoreThreadID == GetCurrentThreadId(), CALCULATE_ELAPSED_TICKS(m_ulLastUpdateTime, ulCurrentTime));::fclose(f1);}
if (bShouldServiceSystem || bShouldServiceInterrupt)
{
m_CurrentTimeVal += (1000 * ulElapsedTime);
m_ulLastUpdateTime = ulCurrentTime;
}
#else
if (!bAtInterrupt)
{
bShouldServiceSystem = TRUE;
}
bShouldServiceInterrupt = TRUE;
(void) gettimeofday(&m_CurrentTimeVal, 0);
#endif
if (!(bShouldServiceSystem || bShouldServiceInterrupt))
{
bResult = FALSE;
if (!m_pScheduler->empty() &&
m_pScheduler->head_time() != m_headTime)
{
m_headTime = m_pScheduler->head_time();
bResult = TRUE;
}
if (!m_pInterruptTimeScheduler->empty() &&
m_pInterruptTimeScheduler->head_time() != m_interruptHeadTime)
{
m_interruptHeadTime = m_pInterruptTimeScheduler->head_time();
bResult = TRUE;
}
}
return bResult;
}
void HXScheduler::NotifyPlayState(BOOL bInPlayingState)
{
#if defined(_WIN32) || defined(THREADS_SUPPORTED)
if (m_pAsyncTimer)
{
m_pAsyncTimer->NotifyPlayState(bInPlayingState);
}
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -