mirror of
https://github.com/polserver/polserver
synced 2026-08-13 08:23:08 -04:00
200 lines
4.4 KiB
C++
200 lines
4.4 KiB
C++
/** @file
|
|
*
|
|
* @par History
|
|
*/
|
|
|
|
|
|
#include "schedule.h"
|
|
|
|
#include "../clib/logfacility.h"
|
|
#include "../clib/passert.h"
|
|
#include "../clib/tracebuf.h"
|
|
#include "../plib/systemstate.h"
|
|
#include "globals/state.h"
|
|
#include "globals/uvars.h"
|
|
#include "polclock.h"
|
|
#include "polsig.h"
|
|
#include "profile.h"
|
|
|
|
namespace Pol
|
|
{
|
|
namespace Core
|
|
{
|
|
bool SchComparer::operator()( const ScheduledTask* x, const ScheduledTask* y ) const
|
|
{
|
|
if ( x->next_run_clock_ == y->next_run_clock_ )
|
|
return x > y;
|
|
else
|
|
return x->next_run_clock_ > y->next_run_clock_;
|
|
}
|
|
|
|
bool TaskScheduler::dirty_ = false;
|
|
|
|
static void add_task( ScheduledTask* task )
|
|
{
|
|
TaskScheduler::mark_dirty();
|
|
gamestate.task_queue.push( task );
|
|
}
|
|
|
|
ScheduledTask::ScheduledTask( polclock_t next_run_clock )
|
|
: cancelled( false ), next_run_clock_( next_run_clock ), last_run_clock_( 0 )
|
|
{
|
|
}
|
|
|
|
void ScheduledTask::cancel()
|
|
{
|
|
cancelled = true;
|
|
}
|
|
|
|
inline bool ScheduledTask::ready( polclock_t now_clock )
|
|
{
|
|
return ( now_clock >= next_run_clock_ );
|
|
}
|
|
inline bool ScheduledTask::late( polclock_t now_clock )
|
|
{
|
|
return ( now_clock > next_run_clock_ );
|
|
}
|
|
inline polclock_t ScheduledTask::ticks_late( polclock_t now_clock )
|
|
{
|
|
return ( now_clock - next_run_clock_ );
|
|
}
|
|
|
|
polclock_t ScheduledTask::clocksleft( polclock_t now_clock )
|
|
{
|
|
return next_run_clock_ - now_clock;
|
|
}
|
|
|
|
PeriodicTask::PeriodicTask( void ( *i_f )( void ), int initial_wait_seconds, const char* name )
|
|
: ScheduledTask( 0 ),
|
|
n_initial_clocks( initial_wait_seconds * POLCLOCKS_PER_SEC ),
|
|
n_clocks( initial_wait_seconds * POLCLOCKS_PER_SEC ),
|
|
f( i_f ),
|
|
name_( name )
|
|
{
|
|
}
|
|
|
|
PeriodicTask::PeriodicTask( void ( *i_f )( void ), int initial_wait_seconds, int periodic_seconds,
|
|
const char* name )
|
|
: ScheduledTask( 0 ),
|
|
n_initial_clocks( initial_wait_seconds * POLCLOCKS_PER_SEC ),
|
|
n_clocks( periodic_seconds * POLCLOCKS_PER_SEC ),
|
|
f( i_f ),
|
|
name_( name )
|
|
{
|
|
}
|
|
|
|
|
|
void PeriodicTask::set_secs( int n_secs )
|
|
{
|
|
n_clocks = n_secs * POLCLOCKS_PER_SEC;
|
|
n_initial_clocks = n_secs * POLCLOCKS_PER_SEC;
|
|
}
|
|
void PeriodicTask::start()
|
|
{
|
|
next_run_clock_ = polclock() + n_initial_clocks;
|
|
last_run_clock_ = 0;
|
|
add_task( this );
|
|
}
|
|
|
|
void PeriodicTask::execute( polclock_t now )
|
|
{
|
|
last_run_clock_ = now;
|
|
next_run_clock_ += n_clocks;
|
|
( *f )();
|
|
}
|
|
|
|
OneShotTask::OneShotTask( OneShotTask** handle, polclock_t run_when_clock )
|
|
: ScheduledTask( run_when_clock ), handle( handle )
|
|
{
|
|
if ( handle != nullptr )
|
|
{
|
|
passert( *handle == nullptr );
|
|
*handle = this;
|
|
}
|
|
|
|
add_task( this );
|
|
}
|
|
|
|
OneShotTask::~OneShotTask()
|
|
{
|
|
if ( handle != nullptr )
|
|
*handle = nullptr;
|
|
}
|
|
|
|
void OneShotTask::cancel()
|
|
{
|
|
ScheduledTask::cancel();
|
|
if ( handle != nullptr )
|
|
*handle = nullptr;
|
|
handle = nullptr;
|
|
}
|
|
void OneShotTask::execute( polclock_t /*now_clock*/ )
|
|
{
|
|
if ( !cancelled )
|
|
{
|
|
cancel();
|
|
on_run();
|
|
}
|
|
}
|
|
|
|
void check_scheduled_tasks( polclock_t* clocksleft, bool* pactivity )
|
|
{
|
|
THREAD_CHECKPOINT( tasks, 101 );
|
|
TaskScheduler::cleanse();
|
|
|
|
polclock_t now_clock = polclock();
|
|
TRACEBUF_ADDELEM( "check_scheduled_tasks now_clock", now_clock );
|
|
bool activity = false;
|
|
passert( !gamestate.task_queue.empty() );
|
|
THREAD_CHECKPOINT( tasks, 102 );
|
|
for ( ;; )
|
|
{
|
|
THREAD_CHECKPOINT( tasks, 103 );
|
|
ScheduledTask* task = gamestate.task_queue.top();
|
|
passert_paranoid( task != nullptr );
|
|
TRACEBUF_ADDELEM( "check_scheduled_tasks toptask->nextrun", task->next_run_clock() );
|
|
THREAD_CHECKPOINT( tasks, 104 );
|
|
if ( !task->ready( now_clock ) )
|
|
{
|
|
*clocksleft = task->clocksleft( now_clock );
|
|
*pactivity = activity;
|
|
TRACEBUF_ADDELEM( "check_scheduled_tasks clocksleft", *clocksleft );
|
|
return;
|
|
}
|
|
|
|
THREAD_CHECKPOINT( tasks, 105 );
|
|
if ( !task->late( now_clock ) )
|
|
{
|
|
INC_PROFILEVAR( tasks_ontime );
|
|
}
|
|
else
|
|
{
|
|
INC_PROFILEVAR( tasks_late );
|
|
INC_PROFILEVAR_BY( tasks_late_ticks, task->ticks_late( now_clock ) );
|
|
}
|
|
|
|
THREAD_CHECKPOINT( tasks, 106 );
|
|
gamestate.task_queue.pop();
|
|
|
|
THREAD_CHECKPOINT( tasks, 107 );
|
|
task->execute( now_clock );
|
|
THREAD_CHECKPOINT( tasks, 108 );
|
|
|
|
activity = true;
|
|
|
|
if ( task->cancelled )
|
|
{
|
|
THREAD_CHECKPOINT( tasks, 109 );
|
|
delete task;
|
|
}
|
|
else
|
|
{
|
|
THREAD_CHECKPOINT( tasks, 110 );
|
|
gamestate.task_queue.push( task );
|
|
}
|
|
THREAD_CHECKPOINT( tasks, 111 );
|
|
}
|
|
}
|
|
|
|
} // namespace Core
|
|
} // namespace Pol
|