www.pudn.com > rDUNclientBeta1.zip > Timer.cpp


//Timer.cpp - Generic timing engine and basic time/date functions 
//Copyright (C) Robert Merrison 2001 
 
//This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License  
//as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 
//This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied  
//warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 
//You should have received a copy of the GNU General Public License along with this program; if not, write to the  
//Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
 
#include "timer.h" 
 
/*Init: Initialises the timer engine*/ 
bool time_engine::init( debug_engine *debug) 
{ 
		//Set internal debug engine 
	dbg_engine = debug; 
		//Check OS isn't invalid 
	if( OS == OS_OTHER ){ 
		log_timer_message( MSG_CRITICAL, "Unable to start timer engine: Invalid operating system" ); 
		return false; 
	} 
		//Reset the uptime to zero 
	uptime.seconds	= 0; 
	uptime.minutes	= 0; 
	uptime.hours	= 0; 
	uptime.days		= 0; 
 
	first_event		= NULL; 
	last_event		= NULL; 
	event_count		= 0; 
 
	log_timer_message( MSG_NOTICE, "Timer engine started" ); 
	engine_running	= true; 
 
	previous_time	= time( NULL ); 
	return true; 
} 
 
/*Update: Called every frame to adjust timing*/ 
void time_engine::update() 
{ 
	if( OS == OS_WINDOWS ){ 
		update_timers(); 
	} 
	return; 
} 
 
/*Kill: Clean up the engine when we are done*/ 
void time_engine::kill() 
{ 
	if( engine_running == false ){ 
		return; 
	} 
 
	kill_all_timers(); 
	log_timer_message( MSG_NOTICE, "Timer engine killed" ); 
	engine_running	= false; 
 
	return; 
} 
 
/*Log timer message: Acts as an interface between timer object and logger object*/ 
void time_engine::log_timer_message( short msg_type, char* message, ... ) 
{ 
		//Check if we are using the debug engine or not 
//	if( dbg_engine == NULL ){ 
//		return; 
//	} 
		//Read in any paramters that may have been passed 
	va_list	parameters; 
	char	string_to_output[256]; 
	memset( string_to_output, 0, sizeof( string_to_output ) ); 
	va_start( parameters, message ); 
	vsprintf( string_to_output, message, parameters ); 
	va_end( parameters ); 
		//Pass the message on to the logging function 
	dbg_engine->log_message( msg_type, string_to_output ); 
 
	return; 
} 
 
/*Update timers (win32): Update all the timers when running on win32*/ 
void time_engine::update_timers() 
{ 
		//Check to see if another second has passed since last frame 
		time_t	time_since_epoch	= time( NULL ); 
		time_t	time_difference		= time_since_epoch - previous_time; 
		if( time_difference != 0 ){ 
			advance_timer_list( (int)time_difference ); 
		} 
 
		//Update the previous time to equal the current time 
		previous_time	= time_since_epoch; 
		 
	return; 
} 
 
/*Is running: Accessor for engine_running*/ 
bool time_engine::is_running() 
{ 
	return engine_running; 
} 
 
/*Advance timer list: Advances all the timers in the timer list by x seconds*/ 
void time_engine::advance_timer_list( int number_of_seconds ) 
{ 
	event* current_event	= first_event; 
	event* next_event		= NULL; 
		//Loop through the linked list handling timers 
	while( current_event != NULL ){ 
		next_event	= current_event->next_event; 
		decrease_timer( current_event, number_of_seconds ); 
		current_event	= next_event; 
	}	 
	return; 
} 
 
/*Create timer: Adds a timer to the linked list of timers*/ 
event* time_engine::create_timer( void(*target)(void), time_period interval, short repetitions ) 
{ 
		//Create the new event 
	event*	new_event	= new event; 
		//Fill in the details 
	new_event->target	= target; 
	new_event->repetitions	= repetitions; 
	new_event->counter		= time_to_seconds( interval ); 
	new_event->interval		= time_to_seconds( interval ); 
	new_event->next_event	= NULL; 
	new_event->previous_event	= NULL; 
		//If the list is empty 
	if( first_event == NULL ){ 
		first_event		= last_event	= new_event; 
		event_count++; 
		return new_event; 
	} 
		//There is only one entry in the list 
	if( (first_event != NULL) && (first_event == last_event) ){ 
		first_event->next_event	= new_event; 
		last_event	= new_event; 
		new_event->previous_event	= first_event; 
		event_count++; 
		return new_event; 
	} 
		//There are two or more events in the list 
	new_event->previous_event	= last_event; 
	last_event->next_event		= new_event; 
	event_count++; 
	return new_event; 
} 
 
/*Kill timer: Removes a timer from the timer list*/ 
bool time_engine::kill_timer( event* event_to_kill ) 
{ 
		//Make sure the event is actually valid - could be messy otherwise 
	if( event_to_kill == NULL ){ 
		return false; 
	} 
	if( first_event == NULL ){ 
		return false; 
	} 
		//Check if the event to be deleted is the only event 
	if( first_event == event_to_kill && last_event == event_to_kill ){ 
		first_event = NULL; 
		last_event	= NULL; 
		 
		event_count--; 
		delete event_to_kill; 
		return true; 
	} 
		//Event isn't the only event, but it is the first one 
	if( first_event == event_to_kill ){ 
		first_event	= event_to_kill->next_event; 
		event_to_kill->next_event->previous_event = NULL; 
 
		event_count--; 
		delete event_to_kill; 
		return true; 
	} 
		//Event is the last event 
	if( last_event == event_to_kill ){ 
		last_event = event_to_kill->previous_event; 
		last_event->next_event = NULL; 
 
		event_count--; 
		delete event_to_kill; 
		return true; 
	} 
	//Event isn't the first or last event 
	event_to_kill->next_event->previous_event = event_to_kill->previous_event; 
	event_to_kill->previous_event->next_event = event_to_kill->next_event; 
 
	delete event_to_kill; 
	event_count--; 
	return true; 
} 
 
/*Kill all timers: Kills stuff. Specifically, all the timers.*/ 
bool time_engine::kill_all_timers() 
{ 
	int	timers_deleted	= 0; 
	event* current_event	= first_event; 
	event* next_event		= NULL; 
		//Loop through the linked list deleting timers 
	while( current_event != NULL ){ 
		next_event	= current_event->next_event; 
		delete current_event; 
		current_event	= next_event; 
		timers_deleted++; 
		event_count--; 
	} 
		//Clear up the first/last event pointers 
	first_event	= NULL; 
	last_event	= NULL; 
	 
	return true; 
} 
 
/*Decrease timer: Decreases a specified timer's internal counter by x seconds*/ 
void time_engine::decrease_timer( event* event_to_decrease, int number_of_seconds ) 
{ 
	if( event_to_decrease == NULL ){ 
		return; 
	} 
 
	event_to_decrease->counter--; 
	if( event_to_decrease->counter <= 0 ){ 
		event_to_decrease->target(); 
		if( event_to_decrease->repetitions == 1 ){ 
			kill_timer( event_to_decrease ); 
			return; 
		} 
		if( event_to_decrease->repetitions != 0 ){ 
			event_to_decrease->repetitions--; 
		} 
	} 
         
	return; 
} 
 
/*Reset timer: Resets an event's internal timer*/ 
void time_engine::reset_timer( event* event_to_reset ){ 
	if( event_to_reset == NULL ){ 
		return; 
	} 
	event_to_reset->counter	= event_to_reset->interval; 
 
	return; 
} 
 
/*Time to seconds: Converts a time period struct to seconds*/ 
int time_engine::time_to_seconds( time_period time ) 
{ 
	int seconds; 
	seconds	= (time.days * 24 * 60 * 60) + (time.hours * 60 * 60) + (time.minutes * 60) + time.seconds;  
	 
	return seconds; 
} 
 
/*Get time: Gets the current time and date*/ 
tm	time_engine::get_current_time( void ) 
{ 
	time_t time_since_epoch		= time( NULL ); 
	tm *current_time			= localtime( &time_since_epoch ); 
	 
	return (*current_time); 
}