Timer optimizations.
Made the list of pendinig timers ordered. Added a free list of used timer structures. git-svn-id: https://svn.code.sf.net/p/freeglut/code/trunk@372 7f0cb862-5218-0410-a997-914c9d46530a
This commit is contained in:
parent
e6de6c2e6f
commit
e7a19a5546
@ -76,6 +76,7 @@ SFG_State fgState = { { -1, -1, GL_FALSE }, /* Position */
|
|||||||
{ { 0, 0 }, GL_FALSE },
|
{ { 0, 0 }, GL_FALSE },
|
||||||
#endif
|
#endif
|
||||||
{ NULL, NULL }, /* Timers */
|
{ NULL, NULL }, /* Timers */
|
||||||
|
{ NULL, NULL }, /* FreeTimers */
|
||||||
NULL, /* IdleCallback */
|
NULL, /* IdleCallback */
|
||||||
0, /* ActiveMenus */
|
0, /* ActiveMenus */
|
||||||
NULL, /* MenuStateCallback */
|
NULL, /* MenuStateCallback */
|
||||||
@ -235,9 +236,15 @@ void fgDeinitialize( void )
|
|||||||
|
|
||||||
fgDestroyStructure( );
|
fgDestroyStructure( );
|
||||||
|
|
||||||
while( timer = ( SFG_Timer * )fgState.Timers.First )
|
while( (timer = fgState.Timers.First) )
|
||||||
{
|
{
|
||||||
fgListRemove ( &fgState.Timers, &timer->Node );
|
fgListRemove( &fgState.Timers, &timer->Node );
|
||||||
|
free( timer );
|
||||||
|
}
|
||||||
|
|
||||||
|
while( (timer = fgState.FreeTimers.First) )
|
||||||
|
{
|
||||||
|
fgListRemove( &fgState.FreeTimers, &timer->Node );
|
||||||
free( timer );
|
free( timer );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,7 +281,9 @@ void fgDeinitialize( void )
|
|||||||
|
|
||||||
fgState.Time.Set = GL_FALSE;
|
fgState.Time.Set = GL_FALSE;
|
||||||
|
|
||||||
fgState.Timers.First = fgState.Timers.Last = NULL;
|
fgListInit( &fgState.Timers );
|
||||||
|
fgListInit( &fgState.FreeTimers );
|
||||||
|
|
||||||
fgState.IdleCallback = NULL;
|
fgState.IdleCallback = NULL;
|
||||||
fgState.MenuStateCallback = ( FGCBMenuState )NULL;
|
fgState.MenuStateCallback = ( FGCBMenuState )NULL;
|
||||||
fgState.MenuStatusCallback = ( FGCBMenuStatus )NULL;
|
fgState.MenuStatusCallback = ( FGCBMenuStatus )NULL;
|
||||||
|
@ -239,6 +239,7 @@ struct tagSFG_State
|
|||||||
|
|
||||||
SFG_Time Time; /* Time that glutInit was called */
|
SFG_Time Time; /* Time that glutInit was called */
|
||||||
SFG_List Timers; /* The freeglut timer hooks */
|
SFG_List Timers; /* The freeglut timer hooks */
|
||||||
|
SFG_List FreeTimers; /* The unused timer hooks */
|
||||||
|
|
||||||
FGCBIdle IdleCallback; /* The global idle callback */
|
FGCBIdle IdleCallback; /* The global idle callback */
|
||||||
|
|
||||||
|
@ -277,38 +277,20 @@ static void fghCheckJoystickPolls( void )
|
|||||||
static void fghCheckTimers( void )
|
static void fghCheckTimers( void )
|
||||||
{
|
{
|
||||||
long checkTime = fgElapsedTime( );
|
long checkTime = fgElapsedTime( );
|
||||||
SFG_Timer *timer, *next;
|
SFG_Timer *timer;
|
||||||
SFG_List timedOut;
|
|
||||||
|
|
||||||
fgListInit(&timedOut);
|
while( timer = fgState.Timers.First )
|
||||||
|
|
||||||
for( timer = (SFG_Timer *)fgState.Timers.First;
|
|
||||||
timer;
|
|
||||||
timer = (SFG_Timer *)next )
|
|
||||||
{
|
{
|
||||||
next = (SFG_Timer *)timer->Node.Next;
|
if( timer->TriggerTime > checkTime )
|
||||||
|
break;
|
||||||
|
|
||||||
if( timer->TriggerTime <= checkTime )
|
fgListRemove( &fgState.Timers, &timer->Node );
|
||||||
{
|
fgListAppend( &fgState.FreeTimers, &timer->Node );
|
||||||
fgListRemove( &fgState.Timers, &timer->Node );
|
|
||||||
fgListAppend( &timedOut, &timer->Node );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
timer->Callback( timer->ID );
|
||||||
* Now feel free to execute all the hooked and timed out timer callbacks
|
|
||||||
* And delete the timed out timers...
|
|
||||||
*/
|
|
||||||
while ( (timer = (SFG_Timer *)timedOut.First) )
|
|
||||||
{
|
|
||||||
if( timer->Callback != NULL )
|
|
||||||
timer->Callback( timer->ID );
|
|
||||||
fgListRemove( &timedOut, &timer->Node );
|
|
||||||
free( timer );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Elapsed Time
|
* Elapsed Time
|
||||||
*/
|
*/
|
||||||
@ -319,12 +301,12 @@ long fgElapsedTime( void )
|
|||||||
#if TARGET_HOST_UNIX_X11
|
#if TARGET_HOST_UNIX_X11
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
long elapsed;
|
long elapsed;
|
||||||
|
|
||||||
gettimeofday( &now, NULL );
|
gettimeofday( &now, NULL );
|
||||||
|
|
||||||
elapsed = (now.tv_usec - fgState.Time.Value.tv_usec) / 1000;
|
elapsed = (now.tv_usec - fgState.Time.Value.tv_usec) / 1000;
|
||||||
elapsed += (now.tv_sec - fgState.Time.Value.tv_sec) * 1000;
|
elapsed += (now.tv_sec - fgState.Time.Value.tv_sec) * 1000;
|
||||||
|
|
||||||
return elapsed;
|
return elapsed;
|
||||||
#elif TARGET_HOST_WIN32
|
#elif TARGET_HOST_WIN32
|
||||||
return timeGetTime() - fgState.Time.Value;
|
return timeGetTime() - fgState.Time.Value;
|
||||||
@ -435,28 +417,16 @@ static int fgHavePendingRedisplays (void)
|
|||||||
fgEnumWindows( fgHavePendingRedisplaysCallback, &enumerator );
|
fgEnumWindows( fgHavePendingRedisplaysCallback, &enumerator );
|
||||||
return !!enumerator.data;
|
return !!enumerator.data;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* Indicates whether there are any outstanding timers.
|
|
||||||
*/
|
|
||||||
#if 0 /* Not used */
|
|
||||||
static int fgHaveTimers( void )
|
|
||||||
{
|
|
||||||
return !!fgState.Timers.First;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/*
|
/*
|
||||||
* Returns the number of GLUT ticks (milliseconds) till the next timer event.
|
* Returns the number of GLUT ticks (milliseconds) till the next timer event.
|
||||||
*/
|
*/
|
||||||
static long fgNextTimer( void )
|
static long fgNextTimer( void )
|
||||||
{
|
{
|
||||||
long now = fgElapsedTime();
|
|
||||||
long ret = INT_MAX;
|
long ret = INT_MAX;
|
||||||
SFG_Timer *timer;
|
SFG_Timer *timer;
|
||||||
|
|
||||||
for( timer = (SFG_Timer *)fgState.Timers.First;
|
if( (timer = fgState.Timers.First) )
|
||||||
timer;
|
ret = timer->TriggerTime - fgElapsedTime();
|
||||||
timer = (SFG_Timer *)timer->Node.Next )
|
|
||||||
ret = MIN( ret, MAX( 0, timer->TriggerTime - now ) );
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1011,7 +981,8 @@ void FGAPIENTRY glutMainLoopEvent( void )
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
fghCheckTimers( );
|
if( fgState.Timers.First )
|
||||||
|
fghCheckTimers( );
|
||||||
fghCheckJoystickPolls( );
|
fghCheckJoystickPolls( );
|
||||||
fghDisplayAll( );
|
fghDisplayAll( );
|
||||||
|
|
||||||
|
@ -643,4 +643,26 @@ int fgListLength(SFG_List *list)
|
|||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void fgListInsert(SFG_List *list, SFG_Node *next, SFG_Node *node)
|
||||||
|
{
|
||||||
|
SFG_Node *prev;
|
||||||
|
|
||||||
|
if( (node->Next = next) )
|
||||||
|
{
|
||||||
|
prev = next->Prev;
|
||||||
|
next->Prev = node;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
prev = list->Last;
|
||||||
|
list->Last = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( (node->Prev = prev) )
|
||||||
|
prev->Next = node;
|
||||||
|
else
|
||||||
|
list->First = node;
|
||||||
|
}
|
||||||
|
|
||||||
/*** END OF FILE ***/
|
/*** END OF FILE ***/
|
||||||
|
Reference in New Issue
Block a user