-/**************************************************************************
- * event.c -- Flight Gear periodic event scheduler
- *
- * Written by Curtis Olson, started December 1997.
- *
- * Copyright (C) 1997 Curtis L. Olson - curt@infoplane.com
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id$
- * (Log is kept at end of this file)
- **************************************************************************/
+// event.cxx -- Flight Gear periodic event scheduler
+//
+// Written by Curtis Olson, started December 1997.
+//
+// Copyright (C) 1997 Curtis L. Olson - curt@infoplane.com
+//
+// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+// (Log is kept at end of this file)
#ifdef HAVE_CONFIG_H
#endif
#if defined( HAVE_WINDOWS_H ) && defined(__MWERKS__)
-# include <windows.h> /* For Metrowerks environment */
-# include <winbase.h> /* There is no ANSI/MSL time function that */
- /* contains milliseconds */
+# include <windows.h> // For Metrowerks environment
+# include <winbase.h> // There is no ANSI/MSL time function that
+ // contains milliseconds
#endif
-#include <Debug/fg_debug.h>
+#include "Include/fg_stl_config.h"
+#include STL_ALGORITHM
+#include STL_FUNCTIONAL
-#include "event.hxx"
-#include "fg_time.hxx"
-
-
-
-#define MAX_EVENTS 100 /* size of event table */
-#define MAX_RUN_QUEUE 100 /* size of run queue */
-
-
-struct fgEVENT {
- char description[256];
-
- void (*event)( void ); /* pointer to function */
- int status; /* status flag */
-
- long interval; /* interval in ms between each iteration of this event */
-
- fg_timestamp last_run;
- fg_timestamp current;
- fg_timestamp next_run;
-
- long cum_time; /* cumulative processor time of this event */
- long min_time; /* time of quickest execution */
- long max_time; /* time of slowest execution */
- long count; /* number of times executed */
-};
-
-
-/* Event table */
-struct fgEVENT events[MAX_EVENTS];
-int event_ptr;
-
-
-/* Run Queue */
-int queue[MAX_RUN_QUEUE];
-int queue_front;
-int queue_end;
+#include <Debug/logstream.hxx>
+#include "event.hxx"
-/* initialize the run queue */
-void initq( void ) {
- queue_front = queue_end = 0;
-}
+fgEVENT_MGR global_events;
-/* return queue empty status */
-int emptyq( void ) {
- if ( queue_front == queue_end ) {
- return(1);
- } else {
- return(0);
- }
-}
-
-/* return queue full status */
-int fullq( void ) {
- if ( (queue_end + 1) % MAX_RUN_QUEUE == queue_front ) {
- return(1);
- } else {
- return(0);
- }
+fgEVENT::fgEVENT( const string& desc,
+ const fgCallback& cb,
+ EventState _status,
+ int _interval )
+ : description(desc),
+ event_cb(cb.clone()),
+ status(_status),
+ interval(_interval),
+ cum_time(0),
+ min_time(100000),
+ max_time(0),
+ count(0)
+{
}
-
-/* add a member to the back of the queue */
-void addq(int ptr) {
- if ( !fullq() ) {
- queue[queue_end] = ptr;
- events[ptr].status = FG_EVENT_QUEUED;
-
- queue_end = (queue_end + 1) % MAX_RUN_QUEUE;
- } else {
- printf("RUN QUEUE FULL!!!\n");
- }
-
- /* printf("Queued function %d (%d %d)\n", ptr, queue_front, queue_end); */
+fgEVENT::fgEVENT( const fgEVENT& evt )
+ : description(evt.description),
+#ifdef _FG_NEED_AUTO_PTR
+ // Ugly - cast away const until proper auto_ptr implementation.
+ event_cb((auto_ptr<fgCallback>&)(evt.event_cb)),
+#else
+ event_cb(evt.event_cb),
+#endif
+ status(evt.status),
+ interval(evt.interval),
+ last_run(evt.last_run),
+ current(evt.current),
+ next_run(evt.next_run),
+ cum_time(evt.cum_time),
+ min_time(evt.min_time),
+ max_time(evt.max_time),
+ count(evt.count)
+{
}
-
-/* remove a member from the front of the queue */
-int popq( void ) {
- int ptr;
-
- if ( emptyq() ) {
- printf("PANIC: RUN QUEUE IS EMPTY!!!\n");
- ptr = 0;
- } else {
- ptr = queue[queue_front];
- /* printf("Popped position %d = %d\n", queue_front, ptr); */
- queue_front = (queue_front + 1) % MAX_RUN_QUEUE;
- }
-
- return(ptr);
+fgEVENT::~fgEVENT()
+{
+// cout << "fgEVENT::~fgEVENT" << endl;
}
+void
+fgEVENT::run()
+{
+ printf("Running %s\n", description.c_str() );
-/* run a specified event */
-void fgEventRun(int ptr) {
- struct fgEVENT *e;
- long duration;
-
- e = &events[ptr];
-
- printf("Running %s\n", e->description);
-
- /* record starting time */
- timestamp(&(e->last_run));
+ // record starting time
+ timestamp( &last_run );
- /* run the event */
- (*e->event)();
+ // run the event
+ event_cb->call( (void**)NULL );
- /* increment the counter for this event */
- e->count++;
+ // increment the counter for this event
+ count++;
- /* update the event status */
- e->status = FG_EVENT_READY;
+ // update the event status
+ status = FG_EVENT_READY;
- /* calculate duration and stats */
- timestamp(&(e->current));
- duration = timediff(&(e->last_run), &(e->current));
+ // calculate duration and stats
+ timestamp( ¤t );
+ long duration = timediff( &last_run, ¤t );
- e->cum_time += duration;
+ cum_time += duration;
- if ( duration < e->min_time ) {
- e->min_time = duration;
+ if ( duration < min_time ) {
+ min_time = duration;
}
- if ( duration > e->max_time ) {
- e->max_time = duration;
+ if ( duration > max_time ) {
+ max_time = duration;
}
- /* determine the next absolute run time */
- timesum(&(e->next_run), &(e->last_run), e->interval);
+ // determine the next absolute run time
+ timesum( &next_run, &last_run, interval );
}
-/* Initialize the scheduling subsystem */
-void fgEventInit( void ) {
- printf("Initializing event manager\n");
- event_ptr = 0;
- initq();
+// Dump scheduling stats
+int
+fgEVENT::PrintStats() const
+{
+ printf(" %-30s int=%.2fs cum=%ld min=%ld max=%ld count=%ld ave=%.2f\n",
+ description.c_str(),
+ interval / 1000.0,
+ cum_time, min_time, max_time, count,
+ cum_time / (double)count);
+ return 0;
}
+// Constructor
+fgEVENT_MGR::fgEVENT_MGR( void ) {
+}
-/* Register an event with the scheduler, returns a pointer into the
- * event table */
-int fgEventRegister(char *desc, void (*event)( void ), int status,
- int interval)
-{
- struct fgEVENT *e;
-
- e = &events[event_ptr];
- printf("Registering event: %s\n", desc);
+// Initialize the scheduling subsystem
+void fgEVENT_MGR::Init( void ) {
+ printf("Initializing event manager\n");
- if ( strlen(desc) < 256 ) {
- strcpy(e->description, desc);
- } else {
- strncpy(e->description, desc, 255);
- e->description[255] = '\0';
- }
+ run_queue.erase( run_queue.begin(), run_queue.end() );
+ event_table.erase( event_table.begin(), event_table.end() );
+}
- e->event = event;
- e->status = status;
- e->interval = interval;
- e->cum_time = 0;
- e->min_time = 100000;
- e->max_time = 0;
- e->count = 0;
+// Register an event with the scheduler.
+void
+fgEVENT_MGR::Register( const string& desc,
+ const fgCallback& cb,
+ fgEVENT::EventState status,
+ int interval )
+{
+ fgEVENT e( desc, cb, status, interval );
- /* Actually run the event */
- fgEventRun(event_ptr);
+ printf("Registering event: %s\n", desc.c_str() );
- event_ptr++;
+ // Actually run the event
+ e.run();
- return(event_ptr - 1);
+ // Now add to event_table
+ event_table.push_back(e);
}
-/* Update the scheduling parameters for an event */
-void fgEventUpdate( void ) {
+// Update the scheduling parameters for an event
+void fgEVENT_MGR::Update( void ) {
}
-/* Delete a scheduled event */
-void fgEventDelete( void ) {
+// Delete a scheduled event
+void fgEVENT_MGR::Delete( void ) {
}
-/* Temporarily suspend scheduling of an event */
-void fgEventSuspend( void ) {
+// Temporarily suspend scheduling of an event
+void fgEVENT_MGR::Suspend( void ) {
}
-/* Resume scheduling and event */
-void fgEventResume( void ) {
+// Resume scheduling and event
+void fgEVENT_MGR::Resume( void ) {
}
+// Dump scheduling stats
+void
+fgEVENT_MGR::PrintStats()
+{
+ printf("\n");
+ printf("Event Stats\n");
+ printf("-----------\n");
-/* Dump scheduling stats */
-void fgEventPrintStats( void ) {
- int i;
-
- if ( event_ptr > 0 ) {
- printf("\n");
- printf("Event Stats\n");
- printf("-----------\n");
+ for_each( event_table.begin(),
+ event_table.end(),
+ mem_fun_ref( &fgEVENT::PrintStats ));
- for ( i = 0; i < event_ptr; i++ ) {
- printf(" %-20s int=%.2fs cum=%ld min=%ld max=%ld count=%ld ave=%.2f\n",
- events[i].description,
- events[i].interval / 1000.0,
- events[i].cum_time,
- events[i].min_time, events[i].max_time, events[i].count,
- events[i].cum_time / (double)events[i].count);
- }
- printf("\n");
- }
+ printf("\n");
}
-/* Add pending jobs to the run queue and run the job at the front of
- * the queue */
-void fgEventProcess( void ) {
- fg_timestamp current;
- int i;
+// Add pending jobs to the run queue and run the job at the front of
+// the queue
+void fgEVENT_MGR::Process( void ) {
+ fgEVENT *e_ptr;
+ fg_timestamp cur_time;
+ unsigned int i, size;
- fgPrintf(FG_EVENT, FG_DEBUG, "Processing events\n");
+ FG_LOG( FG_EVENT, FG_DEBUG, "Processing events" );
- /* get the current time */
- timestamp(¤t);
-
- fgPrintf(FG_EVENT, FG_DEBUG, " Current timestamp = %ld\n", current.seconds);
-
- /* printf("Checking if anything is ready to move to the run queue\n"); */
-
- /* see if anything else is ready to be placed on the run queue */
- for ( i = 0; i < event_ptr; i++ ) {
- if ( events[i].status == FG_EVENT_READY ) {
- fgPrintf(FG_EVENT, FG_DEBUG,
- " Item %d, current %d, next run @ %ld\n",
- i, current.seconds, events[i].next_run.seconds);
- if ( timediff(¤t, &(events[i].next_run)) <= 0) {
- addq(i);
+ // get the current time
+ timestamp(&cur_time);
+
+ FG_LOG( FG_EVENT, FG_DEBUG,
+ " Current timestamp = " << cur_time.seconds );
+
+ // printf("Checking if anything is ready to move to the run queue\n");
+
+ // see if anything else is ready to be placed on the run queue
+ size = event_table.size();
+ // while ( current != last ) {
+ for ( i = 0; i < size; i++ ) {
+ // e = *current++;
+ e_ptr = &event_table[i];
+ if ( e_ptr->status == fgEVENT::FG_EVENT_READY ) {
+ FG_LOG( FG_EVENT, FG_DEBUG,
+ " Item " << i << " current " << cur_time.seconds
+ << " next run @ " << e_ptr->next_run.seconds );
+ if ( timediff(&cur_time, &(e_ptr->next_run)) <= 0) {
+ run_queue.push_back(e_ptr);
+ e_ptr->status = fgEVENT::FG_EVENT_QUEUED;
}
}
}
- /* Checking to see if there is anything on the run queue */
- /* printf("Checking to see if there is anything on the run queue\n"); */
- if ( !emptyq() ) {
- /* printf("Yep, running it\n"); */
- i = popq();
- fgEventRun(i);
+ // Checking to see if there is anything on the run queue
+ // printf("Checking to see if there is anything on the run queue\n");
+ if ( run_queue.size() ) {
+ // printf("Yep, running it\n");
+ e_ptr = run_queue.front();
+ run_queue.pop_front();
+ e_ptr->run();
}
}
-/* $Log$
-/* Revision 1.1 1998/04/24 00:52:26 curt
-/* Wrapped "#include <config.h>" in "#ifdef HAVE_CONFIG_H"
-/* Fog color fixes.
-/* Separated out lighting calcs into their own file.
-/*
- * Revision 1.13 1998/04/18 04:14:08 curt
- * Moved fg_debug.c to it's own library.
- *
- * Revision 1.12 1998/04/09 18:40:13 curt
- * We had unified some of the platform disparate time handling code, and
- * there was a bug in timesum() which calculated a new time stamp based on
- * the current time stamp + offset. This hosed the periodic event processing
- * logic because you'd never arrive at the time the event was scheduled for.
- * Sky updates and lighting changes are handled via this event mechanism so
- * they never changed ... it is fixed now.
- *
- * Revision 1.11 1998/04/03 22:12:55 curt
- * Converting to Gnu autoconf system.
- * Centralized time handling differences.
- *
- * Revision 1.10 1998/03/14 00:28:34 curt
- * replaced a printf() with an fgPrintf().
- *
- * Revision 1.9 1998/01/31 00:43:44 curt
- * Added MetroWorks patches from Carmen Volpe.
- *
- * Revision 1.8 1998/01/27 00:48:05 curt
- * Incorporated Paul Bleisch's <bleisch@chromatic.com> new debug message
- * system and commandline/config file processing code.
- *
- * Revision 1.7 1998/01/19 19:27:19 curt
- * Merged in make system changes from Bob Kuehne <rpk@sgi.com>
- * This should simplify things tremendously.
- *
- * Revision 1.6 1998/01/19 18:40:39 curt
- * Tons of little changes to clean up the code and to remove fatal errors
- * when building with the c++ compiler.
- *
- * Revision 1.5 1998/01/06 01:20:27 curt
- * Tweaks to help building with MSVC++
- *
- * Revision 1.4 1997/12/31 17:46:50 curt
- * Tweaked fg_time.c to be able to use ftime() instead of gettimeofday()
- *
- * Revision 1.3 1997/12/30 22:22:42 curt
- * Further integration of event manager.
- *
- * Revision 1.2 1997/12/30 20:47:58 curt
- * Integrated new event manager with subsystem initializations.
- *
- * Revision 1.1 1997/12/30 04:19:22 curt
- * Initial revision.
- *
- */
+// Destructor
+fgEVENT_MGR::~fgEVENT_MGR( void ) {
+}
+
+
+// $Log$
+// Revision 1.9 1998/11/06 21:18:24 curt
+// Converted to new logstream debugging facility. This allows release
+// builds with no messages at all (and no performance impact) by using
+// the -DFG_NDEBUG flag.
+//
+// Revision 1.8 1998/09/15 02:09:29 curt
+// Include/fg_callback.hxx
+// Moved code inline to stop g++ 2.7 from complaining.
+//
+// Simulator/Time/event.[ch]xx
+// Changed return type of fgEVENT::printStat(). void caused g++ 2.7 to
+// complain bitterly.
+//
+// Minor bugfix and changes.
+//
+// Simulator/Main/GLUTmain.cxx
+// Added missing type to idle_state definition - eliminates a warning.
+//
+// Simulator/Main/fg_init.cxx
+// Changes to airport lookup.
+//
+// Simulator/Main/options.cxx
+// Uses fg_gzifstream when loading config file.
+//
+// Revision 1.7 1998/08/29 13:11:31 curt
+// Bernie Bright writes:
+// I've created some new classes to enable pointers-to-functions and
+// pointers-to-class-methods to be treated like objects. These objects
+// can be registered with fgEVENT_MGR.
+//
+// File "Include/fg_callback.hxx" contains the callback class defns.
+//
+// Modified fgEVENT and fgEVENT_MGR to use the callback classes. Also
+// some minor tweaks to STL usage.
+//
+// Added file "Include/fg_stl_config.h" to deal with STL portability
+// issues. I've added an initial config for egcs (and probably gcc-2.8.x).
+// I don't have access to Visual C++ so I've left that for someone else.
+// This file is influenced by the stl_config.h file delivered with egcs.
+//
+// Added "Include/auto_ptr.hxx" which contains an implementation of the
+// STL auto_ptr class which is not provided in all STL implementations
+// and is needed to use the callback classes.
+//
+// Deleted fgLightUpdate() which was just a wrapper to call
+// fgLIGHT::Update().
+//
+// Modified fg_init.cxx to register two method callbacks in place of the
+// old wrapper functions.
+//
+// Revision 1.6 1998/08/20 15:12:26 curt
+// Tweak ...
+//
+// Revision 1.5 1998/06/12 00:59:52 curt
+// Build only static libraries.
+// Declare memmove/memset for Sloaris.
+// Rewrote fg_time.c routine to get LST start seconds to better handle
+// Solaris, and be easier to port, and understand the GMT vs. local
+// timezone issues.
+//
+// Revision 1.4 1998/06/05 18:18:12 curt
+// Incorporated some automake conditionals to try to support mktime() correctly
+// on a wider variety of platforms.
+// Added the declaration of memmove needed by the stl which apparently
+// solaris only defines for cc compilations and not for c++ (__STDC__)
+//
+// Revision 1.3 1998/05/22 21:14:53 curt
+// Rewrote event.cxx in C++ as a class using STL for the internal event list
+// and run queue this removes the arbitrary list sizes and makes things much
+// more dynamic. Because this is C++-classified we can now have multiple
+// event_tables if we'd ever want them.
+//
+// Revision 1.2 1998/04/25 22:06:33 curt
+// Edited cvs log messages in source files ... bad bad bad!
+//
+// Revision 1.1 1998/04/24 00:52:26 curt
+// Wrapped "#include <config.h>" in "#ifdef HAVE_CONFIG_H"
+// Fog color fixes.
+// Separated out lighting calcs into their own file.
+//
+// Revision 1.13 1998/04/18 04:14:08 curt
+// Moved fg_debug.c to it's own library.
+//
+// Revision 1.12 1998/04/09 18:40:13 curt
+// We had unified some of the platform disparate time handling code, and
+// there was a bug in timesum() which calculated a new time stamp based on
+// the current time stamp + offset. This hosed the periodic event processing
+// logic because you'd never arrive at the time the event was scheduled for.
+// Sky updates and lighting changes are handled via this event mechanism so
+// they never changed ... it is fixed now.
+//
+// Revision 1.11 1998/04/03 22:12:55 curt
+// Converting to Gnu autoconf system.
+// Centralized time handling differences.
+//
+// Revision 1.10 1998/03/14 00:28:34 curt
+// replaced a printf() with an fgPrintf().
+//
+// Revision 1.9 1998/01/31 00:43:44 curt
+// Added MetroWorks patches from Carmen Volpe.
+//
+// Revision 1.8 1998/01/27 00:48:05 curt
+// Incorporated Paul Bleisch's <pbleisch@acm.org> new debug message
+// system and commandline/config file processing code.
+//
+// Revision 1.7 1998/01/19 19:27:19 curt
+// Merged in make system changes from Bob Kuehne <rpk@sgi.com>
+// This should simplify things tremendously.
+//
+// Revision 1.6 1998/01/19 18:40:39 curt
+// Tons of little changes to clean up the code and to remove fatal errors
+// when building with the c++ compiler.
+//
+// Revision 1.5 1998/01/06 01:20:27 curt
+// Tweaks to help building with MSVC++
+//
+// Revision 1.4 1997/12/31 17:46:50 curt
+// Tweaked fg_time.c to be able to use ftime() instead of gettimeofday()
+//
+// Revision 1.3 1997/12/30 22:22:42 curt
+// Further integration of event manager.
+//
+// Revision 1.2 1997/12/30 20:47:58 curt
+// Integrated new event manager with subsystem initializations.
+//
+// Revision 1.1 1997/12/30 04:19:22 curt
+// Initial revision.