1 /**************************************************************************
2 * event.c -- Flight Gear periodic event scheduler
4 * Written by Curtis Olson, started December 1997.
6 * Copyright (C) 1997 Curtis L. Olson - curt@infoplane.com
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 * (Log is kept at end of this file)
24 **************************************************************************/
38 #if defined( HAVE_WINDOWS_H ) && defined(__MWERKS__)
39 # include <windows.h> /* For Metrowerks environment */
40 # include <winbase.h> /* There is no ANSI/MSL time function that */
41 /* contains milliseconds */
44 #include <Debug/fg_debug.h>
47 #include "fg_time.hxx"
51 #define MAX_EVENTS 100 /* size of event table */
52 #define MAX_RUN_QUEUE 100 /* size of run queue */
56 char description[256];
58 void (*event)( void ); /* pointer to function */
59 int status; /* status flag */
61 long interval; /* interval in ms between each iteration of this event */
63 fg_timestamp last_run;
65 fg_timestamp next_run;
67 long cum_time; /* cumulative processor time of this event */
68 long min_time; /* time of quickest execution */
69 long max_time; /* time of slowest execution */
70 long count; /* number of times executed */
75 struct fgEVENT events[MAX_EVENTS];
80 int queue[MAX_RUN_QUEUE];
85 /* initialize the run queue */
87 queue_front = queue_end = 0;
91 /* return queue empty status */
93 if ( queue_front == queue_end ) {
101 /* return queue full status */
103 if ( (queue_end + 1) % MAX_RUN_QUEUE == queue_front ) {
111 /* add a member to the back of the queue */
114 queue[queue_end] = ptr;
115 events[ptr].status = FG_EVENT_QUEUED;
117 queue_end = (queue_end + 1) % MAX_RUN_QUEUE;
119 printf("RUN QUEUE FULL!!!\n");
122 /* printf("Queued function %d (%d %d)\n", ptr, queue_front, queue_end); */
126 /* remove a member from the front of the queue */
131 printf("PANIC: RUN QUEUE IS EMPTY!!!\n");
134 ptr = queue[queue_front];
135 /* printf("Popped position %d = %d\n", queue_front, ptr); */
136 queue_front = (queue_front + 1) % MAX_RUN_QUEUE;
143 /* run a specified event */
144 void fgEventRun(int ptr) {
150 printf("Running %s\n", e->description);
152 /* record starting time */
153 timestamp(&(e->last_run));
158 /* increment the counter for this event */
161 /* update the event status */
162 e->status = FG_EVENT_READY;
164 /* calculate duration and stats */
165 timestamp(&(e->current));
166 duration = timediff(&(e->last_run), &(e->current));
168 e->cum_time += duration;
170 if ( duration < e->min_time ) {
171 e->min_time = duration;
174 if ( duration > e->max_time ) {
175 e->max_time = duration;
178 /* determine the next absolute run time */
179 timesum(&(e->next_run), &(e->last_run), e->interval);
183 /* Initialize the scheduling subsystem */
184 void fgEventInit( void ) {
185 printf("Initializing event manager\n");
191 /* Register an event with the scheduler, returns a pointer into the
193 int fgEventRegister(char *desc, void (*event)( void ), int status,
198 e = &events[event_ptr];
200 printf("Registering event: %s\n", desc);
202 if ( strlen(desc) < 256 ) {
203 strcpy(e->description, desc);
205 strncpy(e->description, desc, 255);
206 e->description[255] = '\0';
211 e->interval = interval;
214 e->min_time = 100000;
218 /* Actually run the event */
219 fgEventRun(event_ptr);
223 return(event_ptr - 1);
227 /* Update the scheduling parameters for an event */
228 void fgEventUpdate( void ) {
232 /* Delete a scheduled event */
233 void fgEventDelete( void ) {
237 /* Temporarily suspend scheduling of an event */
238 void fgEventSuspend( void ) {
242 /* Resume scheduling and event */
243 void fgEventResume( void ) {
247 /* Dump scheduling stats */
248 void fgEventPrintStats( void ) {
251 if ( event_ptr > 0 ) {
253 printf("Event Stats\n");
254 printf("-----------\n");
256 for ( i = 0; i < event_ptr; i++ ) {
257 printf(" %-20s int=%.2fs cum=%ld min=%ld max=%ld count=%ld ave=%.2f\n",
258 events[i].description,
259 events[i].interval / 1000.0,
261 events[i].min_time, events[i].max_time, events[i].count,
262 events[i].cum_time / (double)events[i].count);
269 /* Add pending jobs to the run queue and run the job at the front of
271 void fgEventProcess( void ) {
272 fg_timestamp current;
275 fgPrintf(FG_EVENT, FG_DEBUG, "Processing events\n");
277 /* get the current time */
280 fgPrintf(FG_EVENT, FG_DEBUG, " Current timestamp = %ld\n", current.seconds);
282 /* printf("Checking if anything is ready to move to the run queue\n"); */
284 /* see if anything else is ready to be placed on the run queue */
285 for ( i = 0; i < event_ptr; i++ ) {
286 if ( events[i].status == FG_EVENT_READY ) {
287 fgPrintf(FG_EVENT, FG_DEBUG,
288 " Item %d, current %d, next run @ %ld\n",
289 i, current.seconds, events[i].next_run.seconds);
290 if ( timediff(¤t, &(events[i].next_run)) <= 0) {
296 /* Checking to see if there is anything on the run queue */
297 /* printf("Checking to see if there is anything on the run queue\n"); */
299 /* printf("Yep, running it\n"); */
307 /* Revision 1.1 1998/04/24 00:52:26 curt
308 /* Wrapped "#include <config.h>" in "#ifdef HAVE_CONFIG_H"
310 /* Separated out lighting calcs into their own file.
312 * Revision 1.13 1998/04/18 04:14:08 curt
313 * Moved fg_debug.c to it's own library.
315 * Revision 1.12 1998/04/09 18:40:13 curt
316 * We had unified some of the platform disparate time handling code, and
317 * there was a bug in timesum() which calculated a new time stamp based on
318 * the current time stamp + offset. This hosed the periodic event processing
319 * logic because you'd never arrive at the time the event was scheduled for.
320 * Sky updates and lighting changes are handled via this event mechanism so
321 * they never changed ... it is fixed now.
323 * Revision 1.11 1998/04/03 22:12:55 curt
324 * Converting to Gnu autoconf system.
325 * Centralized time handling differences.
327 * Revision 1.10 1998/03/14 00:28:34 curt
328 * replaced a printf() with an fgPrintf().
330 * Revision 1.9 1998/01/31 00:43:44 curt
331 * Added MetroWorks patches from Carmen Volpe.
333 * Revision 1.8 1998/01/27 00:48:05 curt
334 * Incorporated Paul Bleisch's <bleisch@chromatic.com> new debug message
335 * system and commandline/config file processing code.
337 * Revision 1.7 1998/01/19 19:27:19 curt
338 * Merged in make system changes from Bob Kuehne <rpk@sgi.com>
339 * This should simplify things tremendously.
341 * Revision 1.6 1998/01/19 18:40:39 curt
342 * Tons of little changes to clean up the code and to remove fatal errors
343 * when building with the c++ compiler.
345 * Revision 1.5 1998/01/06 01:20:27 curt
346 * Tweaks to help building with MSVC++
348 * Revision 1.4 1997/12/31 17:46:50 curt
349 * Tweaked fg_time.c to be able to use ftime() instead of gettimeofday()
351 * Revision 1.3 1997/12/30 22:22:42 curt
352 * Further integration of event manager.
354 * Revision 1.2 1997/12/30 20:47:58 curt
355 * Integrated new event manager with subsystem initializations.
357 * Revision 1.1 1997/12/30 04:19:22 curt