📄 timeline.cpp
字号:
}
void Timeline::Done(void)
{
HX_RELEASE(m_pScheduler);
#if defined (_MACINTOSH)
#if defined (_DEBUG) && defined(LOG_MULTIPLE_DEFERRED_TASKS)
BOOL bBetterWaitForCallbacks = FALSE;
if ( m_uiDeferredTaskDepth > 0 )
{
char tmpStr[255]; /* Flawfinder: ignore */
sprintf(tmpStr, "m_uiDeferredTaskDepth = %u;g", m_uiDeferredTaskDepth); /* Flawfinder: ignore */
// DebugStr(c2pstr(tmpStr));
// don't spoil the timing by hitting MacsBug
bBetterWaitForCallbacks = TRUE;
}
#endif
m_bIsQuitting = TRUE;
// sit-n-spin awaiting interrupts to finish.
for ( int i = 0; i < 50; i++ )
{
unsigned long dummyTix;
Delay( 6, &dummyTix );
if ( !m_bAnyCallbackPending )
{
i = 50;
}
}
#if defined(_DEBUG) && defined(LOG_MULTIPLE_DEFERRED_TASKS)
if ( bBetterWaitForCallbacks )
{
if ( m_uiDeferredTaskDepth > 0 )
{
DebugStr( "\pOops! After several seconds the deferred task didn't fire off;g" );
}
else
{
DebugStr( "\pNice... the deferred task fired off and we're good to go;g" );
}
}
#endif
m_bIsQuitting = FALSE;
#endif
}
HX_RESULT Timeline::Resume(void)
{
#if defined(HELIX_CONFIG_NOSTATICS)
TimelineMapType& m_zTimerMap =
GlobalTimelineMapType::Get(&Timeline::m_zTimerMap);
#endif
m_bPaused = FALSE;
if (m_bIsTimerPending)
{
return HXR_OK;
}
m_ulLastCallbackTime = HX_GET_TICKCOUNT();
// Set a timer
#if defined(_WINDOWS) || defined(_SYMBIAN)
m_uiTimerID = HXAsyncTimer::SetTimer(m_ulGranularity, (TIMERPROC)NonMMTimerProc);
if( m_bTimerFixup )
m_uiTimerIDFixup = HXAsyncTimer::SetTimer(m_ulGranularity,
(TIMERPROC)NonMMTimerProc);
// m_uiTimerID = SetTimer( NULL, NULL, (UINT) m_ulGranularity,
// (TIMERPROC) NonMMTimerProc );
// if (m_bTimerFixup)
// m_uiTimerIDFixup = SetTimer( NULL, NULL, (UINT) m_ulGranularity,
// (TIMERPROC) NonMMTimerProc );
#elif defined(_MACINTOSH)
if (m_bUseDeferredTasks)
{
OSErr e = noErr;
if (CLOCKSET(m_tmInfo.tmTask))
{
::RmvTime((QElemPtr) &m_tmInfo);
m_bAnyCallbackPending = 0;
}
m_tmInfo.tmTask.tmAddr = m_uppTask;
m_tmInfo.tmRefCon = (long) this;
m_tmInfo.tmTask.tmWakeUp = 0L;
m_tmInfo.tmTask.tmReserved = 0L;
::InsTime((QElemPtr) &m_tmInfo);
::PrimeTime((QElemPtr) &m_tmInfo, m_ulGranularity);
m_bAnyCallbackPending = 1;
}
#endif
// add this timer to the static timer map
#if defined(_WINDOWS) || defined(_SYMBIAN)
TimerObjects* pTimerObject = new TimerObjects;
if (!pTimerObject)
{
if (!m_bTimerFixup)
// This is the "old code". Execute it just as before the
// timerfixup functionality was introduced.
HXAsyncTimer::KillTimer(m_uiTimerID);
else
{
if (m_uiTimerID)
HXAsyncTimer::KillTimer(m_uiTimerID);
if (m_uiTimerIDFixup)
HXAsyncTimer::KillTimer(m_uiTimerIDFixup);
}
return HXR_OUTOFMEMORY;
}
pTimerObject->m_pTimeline = this;
pTimerObject->m_uiTimer = m_uiTimerID;
m_zTimerMap.SetAt((LONG32) m_uiTimerID, (void*) pTimerObject);
if (m_bTimerFixup)
m_zTimerMap.SetAt((LONG32) m_uiTimerIDFixup, (void*) pTimerObject);
#elif defined(_UNIX) || defined(_MACINTOSH) || defined(__TCS__) || defined(_OPENWAVE)
m_zTimerMap.SetAt(this, this);
#endif
#if defined(_MACINTOSH) && defined(_DEBUG) && defined(LOG_MULTIPLE_DEFERRED_TASKS)
if ( m_bIsTimerPending )
{
DebugStr( "\pTimeLine::Resume -- m_bIsTimerPending already true!;g" );
}
#endif
m_bIsTimerPending = TRUE;
return HXR_OK;
}
HX_RESULT
Timeline::Seek(ULONG32 ulSeekTime)
{
if (!m_bPaused)
{
Pause();
Resume();
}
return HXR_OK;
}
HX_RESULT
Timeline::SetStartTime(ULONG32 ulTime)
{
return HXR_OK;
}
HX_RESULT
Timeline::SetGranularity(ULONG32 ulNumMillisecs)
{
m_ulGranularity = ulNumMillisecs;
return HXR_OK;
}
HX_RESULT
Timeline::OnTimeSync(BOOL bAtInterrupt)
{
#ifdef _MACINTOSH
if ((InterlockedIncrement(&gTIMELINE_MUTEX) > 1) && bAtInterrupt)
{
InterlockedDecrement(&gTIMELINE_MUTEX);
return HXR_OK;
}
#endif
//{FILE* f1 = ::fopen("d:\\temp\\timeline.txt", "a+"); ::fprintf(f1, "%p: %lu \n", this, HX_GET_TICKCOUNT());::fclose(f1);}
if (!m_bPaused)
{
if (m_pScheduler)
{
HXScheduler* pScheduler = m_pScheduler;
pScheduler->AddRef();
pScheduler->OnTimeSync(bAtInterrupt);
pScheduler->Release();
}
}
#ifdef _MACINTOSH
InterlockedDecrement(&gTIMELINE_MUTEX);
#endif
return HXR_OK;
}
/*
* ********* WINDOWS ONLY *****************
*/
#if defined(_WINDOWS) || defined(_SYMBIAN)
/*
* This is a Windows Timer callback proc
*/
void CALLBACK Timeline::NonMMTimerProc(
void* hwnd, // handle of window for timer messages
UINT32 uMsg, // WM_TIMER message
UINT32 idTimer, // timer identifier
ULONG32 dwTime // current system time
)
{
#if defined(HELIX_CONFIG_NOSTATICS)
TimelineMapType& m_zTimerMap =
GlobalTimelineMapType::Get(&Timeline::m_zTimerMap);
#endif
TimerObjects* pTimerObject = NULL;
if (m_zTimerMap.Lookup((LONG32) idTimer, (void*&) pTimerObject))
{
// MUST call this BEFORE OnTimeSync, because OnTimeSync could
// delete the object
KillTimerFixup(idTimer, pTimerObject);
HX_ASSERT( pTimerObject);
HX_ASSERT( pTimerObject->m_pTimeline );
pTimerObject->m_pTimeline->OnTimeSync();
}
return;
}
void Timeline::KillTimerFixup(UINT idTimer, struct TimerObjects* pTimerObject)
{
#if defined(HELIX_CONFIG_NOSTATICS)
TimelineMapType& m_zTimerMap =
GlobalTimelineMapType::Get(&Timeline::m_zTimerMap);
#endif
if (pTimerObject->m_pTimeline->m_bTimerFixup == FALSE)
return;
if (pTimerObject->m_pTimeline->m_uiTimerIDFixup == 0)
return;
if (pTimerObject->m_pTimeline->m_uiTimerID == 0)
return;
if (pTimerObject->m_pTimeline->m_uiTimerID == idTimer)
{
HXAsyncTimer::KillTimer(pTimerObject->m_pTimeline->m_uiTimerIDFixup);
m_zTimerMap.RemoveKey((LONG32) pTimerObject->m_pTimeline->m_uiTimerIDFixup);
pTimerObject->m_pTimeline->m_uiTimerIDFixup = 0;
}
else if (pTimerObject->m_pTimeline->m_uiTimerIDFixup == idTimer)
{
HXAsyncTimer::KillTimer(pTimerObject->m_pTimeline->m_uiTimerID);
m_zTimerMap.RemoveKey((LONG32) pTimerObject->m_pTimeline->m_uiTimerID);
pTimerObject->m_pTimeline->m_uiTimerID = 0;
}
return;
}
#endif
/*
* ********* MAC ONLY *****************
*/
#ifdef _MACINTOSH
/*
* This is the Mac Timer callback proc (deferred task)
*/
pascal void
Timeline::MacTimerProc(TMInfoPtr task)
{
HXMM_INTERRUPTON();
/*
* Setup and then install a deferred task
*/
if (task != NULL && task->tmRefCon != NULL)
{
Timeline* pTheTimeline = (Timeline*)task->tmRefCon;
#if defined(_DEBUG) && defined(LOG_MULTIPLE_DEFERRED_TASKS)
// m_bIsTimerPending better be true right now
if ( !pTheTimeline->m_bIsTimerPending )
{
DebugStr( "\pMacTimerProc -- m_bIsTimerPending is FALSE!;g" );
}
#endif
if (pTheTimeline->m_DeferredTaskStruct.dtAddr != NULL)
{
#if defined (_DEBUG) && defined(LOG_MULTIPLE_DEFERRED_TASKS)
if ( pTheTimeline->m_uiDeferredTaskDepth > 0 )
{
char tmpStr[255]; /* Flawfinder: ignore */
sprintf(tmpStr, "m_uiDeferredTaskDepth = %u;g", pTheTimeline->m_uiDeferredTaskDepth); /* Flawfinder: ignore */
DebugStr(c2pstr(tmpStr));
}
#endif
if ( pTheTimeline->m_bIsQuitting )
{
// short-circuit and don't install deferred task
pTheTimeline->m_bAnyCallbackPending = 0;
#if defined (_DEBUG) && defined(LOG_MULTIPLE_DEFERRED_TASKS)
DebugStr( "\pIt's quitting so we don't install deferred task;g" );
#endif
}
else
{
// now that we're running on OS X, call the "deferred task" immediately.
// Using a deferred thread is an artifact of OS 9: using deferred time
// because it's not quite as nasty as hard interrupt time, plus there were
// things that assumed they could only be interrupted "once". Those should
// now all be THREAD safe (i.e. OS X) and calling deferred time oughtn't
// be necessary.
Timeline::DeferredTaskProc((long)pTheTimeline);
}
}
}
HXMM_INTERRUPTOFF();
}
pascal void Timeline::DeferredTaskProc(long param)
{
HXMM_INTERRUPTON();
Timeline* pTheTimeline = (Timeline*)param;
if (pTheTimeline)
{
#ifdef THREADS_SUPPORTED
if (pTheTimeline->m_pCoreMutex) pTheTimeline->m_pCoreMutex->Lock();
#endif
pTheTimeline->m_bAnyCallbackPending = 0;
if ( !pTheTimeline->m_bIsQuitting )
{
pTheTimeline->InterruptTimeSync();
}
#if defined (_DEBUG) && defined(LOG_MULTIPLE_DEFERRED_TASKS)
else
{
DebugStr( "\pIn DeferredTaskProc, short-circuiting because we're quitting;g" );
}
#endif
#ifdef THREADS_SUPPORTED
if (pTheTimeline->m_pCoreMutex) pTheTimeline->m_pCoreMutex->Unlock();
#endif
}
#if defined (_DEBUG) && defined(LOG_MULTIPLE_DEFERRED_TASKS)
if ( pTheTimeline )
{
if ( pTheTimeline->m_uiDeferredTaskDepth != 0 )
{
char tmpStr[255]; /* Flawfinder: ignore */
sprintf(tmpStr, "m_uiDeferredTaskDepth = %u;g", pTheTimeline->m_uiDeferredTaskDepth); /* Flawfinder: ignore */
DebugStr(c2pstr(tmpStr));
}
}
#endif
HXMM_INTERRUPTOFF();
}
void
Timeline::InterruptTimeSync(void)
{
if (!m_bUseDeferredTasks)
{
ULONG32 ulCurTime = HX_GET_TICKCOUNT();
if ( ulCurTime > (m_ulLastCallbackTime + m_ulGranularity) )
{
OnTimeSync(FALSE);
}
}
else
{
if (m_pInterruptState)
{
m_pInterruptState->EnterInterruptState();
}
OnTimeSync(TRUE);
#if defined (_DEBUG) && defined(LOG_MULTIPLE_DEFERRED_TASKS)
if ( m_bIsQuitting )
{
DebugStr( "\pIn InterruptTimeSync, about to ::PrimeTime, and we're QUITTING!;g" );
}
#endif
if ( !m_bIsQuitting )
{
::PrimeTime((QElemPtr) &m_tmInfo, m_ulGranularity); //restart timer
m_bAnyCallbackPending = 1;
}
if (m_pInterruptState)
{
m_pInterruptState->LeaveInterruptState();
}
}
}
#endif //_MACINTOSH
/*
* ********* MAC & UNIX ONLY *****************
*/
#if defined(_UNIX) || defined(_MACINTOSH) || defined(__TCS__) || defined(_OPENWAVE)
void
Timeline::CallAllTimeSyncs(void)
{
#if defined(HELIX_CONFIG_NOSTATICS)
TimelineMapType& m_zTimerMap =
GlobalTimelineMapType::Get(&Timeline::m_zTimerMap);
#endif
CHXMapPtrToPtr::Iterator ndxTimeline = m_zTimerMap.Begin();
for (; ndxTimeline != m_zTimerMap.End(); ++ndxTimeline)
{
Timeline* pCurrentTimeline = (Timeline*)(*ndxTimeline);
pCurrentTimeline->OnTimeSync();
}
}
#endif /* _UNIX || _MACINTOSH */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -