]> git.mxchange.org Git - flightgear.git/blob - Time/event.cxx
Convert fgTIMESTAMP to FGTimeStamp which holds usec instead of ms.
[flightgear.git] / Time / event.cxx
1 // event.cxx -- Flight Gear periodic event scheduler
2 //
3 // Written by Curtis Olson, started December 1997.
4 //
5 // Copyright (C) 1997  Curtis L. Olson  - curt@infoplane.com
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 //
21 // $Id$
22 // (Log is kept at end of this file)
23
24
25 #ifdef HAVE_CONFIG_H
26 #  include <config.h>
27 #endif
28
29 #include <string>
30
31 #include "Include/compiler.h"
32
33 #include STL_ALGORITHM
34 #include STL_FUNCTIONAL
35
36 #ifdef FG_HAVE_STD_INCLUDES
37 #  include <cstdio>
38 #  ifdef HAVE_STDLIB_H
39 #    include <cstdlib>
40 #  endif
41 #else
42 #  include <stdio.h>
43 #  ifdef HAVE_STDLIB_H
44 #    include <stdlib.h>
45 #  endif
46 #endif
47
48 #if defined( HAVE_WINDOWS_H ) && defined(__MWERKS__)
49 #  include <windows.h>   // For Metrowerks environment
50 #  include <winbase.h>   // There is no ANSI/MSL time function that
51                          // contains milliseconds
52 #endif
53
54 #include <Debug/logstream.hxx>
55
56 #include "event.hxx"
57
58 FG_USING_STD(for_each);
59 FG_USING_STD(mem_fun);
60
61 fgEVENT_MGR global_events;
62
63
64 fgEVENT::fgEVENT( const string& desc,
65                   const fgCallback& cb,
66                   EventState evt_status,
67                   int evt_interval )
68     : description(desc),
69       event_cb(cb.clone()),
70       status(evt_status),
71       interval(evt_interval),
72       cum_time(0),
73       min_time(100000),
74       max_time(0),
75       count(0)
76 {
77 }
78
79 #if 0
80 fgEVENT::fgEVENT( const fgEVENT& evt )
81     : description(evt.description),
82       event_cb(evt.event_cb),
83       status(evt.status),
84       interval(evt.interval),
85       last_run(evt.last_run),
86       current(evt.current),
87       next_run(evt.next_run),
88       cum_time(evt.cum_time),
89       min_time(evt.min_time),
90       max_time(evt.max_time),
91       count(evt.count)
92 {
93 }
94
95 fgEVENT&
96 fgEVENT::operator= ( const fgEVENT& evt )
97 {
98     if ( this != &evt )
99     {
100         description = evt.description;
101         event_cb = evt.event_cb;
102         status = evt.status;
103         interval = evt.interval;
104         last_run = evt.last_run;
105         current = evt.current;
106         next_run = evt.next_run;
107         cum_time = evt.cum_time;
108         min_time = evt.min_time;
109         max_time = evt.max_time;
110         count = evt.count;
111     }
112     return *this;
113 }
114 #endif
115
116 fgEVENT::~fgEVENT()
117 {
118     delete event_cb;
119 }
120
121 void
122 fgEVENT::run()
123 {
124     FG_LOG(FG_EVENT, FG_INFO, "Running " << description );
125
126     // record starting time
127     last_run.stamp();
128
129     // run the event
130     event_cb->call( (void**)NULL );
131
132     // increment the counter for this event
133     count++;
134
135     // update the event status
136     status = FG_EVENT_READY;
137
138     // calculate duration and stats
139     current.stamp();
140     long duration = current - last_run;
141
142     cum_time += duration;
143
144     if ( duration < min_time ) {
145         min_time = duration;
146     }
147
148     if ( duration > max_time ) {
149         max_time = duration;
150     }
151
152     // determine the next absolute run time
153     next_run =  last_run + interval;
154 }
155
156
157 // Dump scheduling stats
158 int
159 fgEVENT::PrintStats() const
160 {
161     FG_LOG( FG_EVENT, FG_INFO, 
162             "  " << description 
163             << " int=" << interval / 1000.0
164             << " cum=" << cum_time
165             << " min=" << min_time
166             << " max=" <<  max_time
167             << " count=" << count
168             << " ave=" << cum_time / (double)count );
169     return 0;
170 }
171
172 // Constructor
173 fgEVENT_MGR::fgEVENT_MGR( void ) {
174 }
175
176
177 // Initialize the scheduling subsystem
178 void fgEVENT_MGR::Init( void ) {
179     FG_LOG(FG_EVENT, FG_INFO, "Initializing event manager" );
180
181     run_queue.erase( run_queue.begin(), run_queue.end() );
182     event_table.erase( event_table.begin(), event_table.end() );
183 }
184
185
186 // Register an event with the scheduler.
187 void
188 fgEVENT_MGR::Register( const string& desc,
189                        const fgCallback& cb,
190                        fgEVENT::EventState status, 
191                        int interval )
192 {
193     // convert interval specified in milleseconds to usec
194     fgEVENT* e = new fgEVENT( desc, cb, status, interval * 1000 );
195
196     FG_LOG( FG_EVENT, FG_INFO, "Registering event: " << desc );
197
198     // Actually run the event
199     e->run();
200
201     // Now add to event_table
202     event_table.push_back(e);
203 }
204
205
206 // Update the scheduling parameters for an event
207 void fgEVENT_MGR::Update( void ) {
208 }
209
210
211 // Delete a scheduled event
212 void fgEVENT_MGR::Delete( void ) {
213 }
214
215
216 // Temporarily suspend scheduling of an event
217 void fgEVENT_MGR::Suspend( void ) {
218 }
219
220
221 // Resume scheduling and event
222 void fgEVENT_MGR::Resume( void ) {
223 }
224
225 // Dump scheduling stats
226 void
227 fgEVENT_MGR::PrintStats()
228 {
229     FG_LOG( FG_EVENT, FG_INFO, "" );
230     FG_LOG( FG_EVENT, FG_INFO, "Event Stats" );
231     FG_LOG( FG_EVENT, FG_INFO, "-----------" );
232
233     ConstEventIterator first = event_table.begin();
234     ConstEventIterator last = event_table.end();
235     while ( first != last )
236     {
237         (*first)->PrintStats();
238         ++first;
239     }
240 #if 0 // msvc++ 6.0 barfs at mem_fun()
241     for_each( event_table.begin(),
242               event_table.end(),
243               mem_fun( &fgEVENT::PrintStats ) );
244 #endif
245     FG_LOG( FG_EVENT, FG_INFO, "");
246 }
247
248
249 // Add pending jobs to the run queue and run the job at the front of
250 // the queue
251 void fgEVENT_MGR::Process( void ) {
252     fgEVENT *e_ptr;
253     FGTimeStamp cur_time;
254     unsigned int i, size;
255
256     FG_LOG( FG_EVENT, FG_DEBUG, "Processing events" );
257     
258     // get the current time
259     cur_time.stamp();
260
261     FG_LOG( FG_EVENT, FG_DEBUG, 
262             "  Current timestamp = " << cur_time.get_seconds() );
263
264     // printf("Checking if anything is ready to move to the run queue\n");
265
266     // see if anything else is ready to be placed on the run queue
267     size = event_table.size();
268     // while ( current != last ) {
269     for ( i = 0; i < size; i++ ) {
270         // e = *current++;
271         e_ptr = event_table[i];
272         if ( e_ptr->status == fgEVENT::FG_EVENT_READY ) {
273             FG_LOG( FG_EVENT, FG_DEBUG, 
274                     "  Item " << i << " current " << cur_time.get_seconds()
275                     << " next run @ " << e_ptr->next_run.get_seconds() );
276             if ( ( e_ptr->next_run - cur_time ) <= 0 ) {
277                 run_queue.push_back(e_ptr);
278                 e_ptr->status = fgEVENT::FG_EVENT_QUEUED;
279             }
280         }
281     }
282
283     // Checking to see if there is anything on the run queue
284     // printf("Checking to see if there is anything on the run queue\n");
285     if ( run_queue.size() ) {
286         // printf("Yep, running it\n");
287         e_ptr = run_queue.front();
288         run_queue.pop_front();
289         e_ptr->run();
290     }
291 }
292
293
294 // Destructor
295 fgEVENT_MGR::~fgEVENT_MGR( void ) {
296     EventIterator first = event_table.begin();
297     EventIterator last = event_table.end();
298     for ( ; first != last; ++first )
299     {
300         delete (*first);
301     }
302
303     run_queue.erase( run_queue.begin(), run_queue.end() );
304     event_table.erase( event_table.begin(), event_table.end() );
305 }
306
307
308 // $Log$
309 // Revision 1.15  1999/01/09 13:37:42  curt
310 // Convert fgTIMESTAMP to FGTimeStamp which holds usec instead of ms.
311 //
312 // Revision 1.14  1999/01/07 20:25:32  curt
313 // Portability changes and updates from Bernie Bright.
314 //
315 // Revision 1.13  1998/12/04 01:32:46  curt
316 // Converted "struct fg_timestamp" to "class fgTIMESTAMP" and added some
317 // convenience inline operators.
318 //
319 // Revision 1.12  1998/11/23 21:49:07  curt
320 // Borland portability tweaks.
321 //
322 // Revision 1.11  1998/11/09 23:41:51  curt
323 // Log message clean ups.
324 //
325 // Revision 1.10  1998/11/07 19:07:13  curt
326 // Enable release builds using the --without-logging option to the configure
327 // script.  Also a couple log message cleanups, plus some C to C++ comment
328 // conversion.
329 //
330 // Revision 1.9  1998/11/06 21:18:24  curt
331 // Converted to new logstream debugging facility.  This allows release
332 // builds with no messages at all (and no performance impact) by using
333 // the -DFG_NDEBUG flag.
334 //
335 // Revision 1.8  1998/09/15 02:09:29  curt
336 // Include/fg_callback.hxx
337 //   Moved code inline to stop g++ 2.7 from complaining.
338 //
339 // Simulator/Time/event.[ch]xx
340 //   Changed return type of fgEVENT::printStat().  void caused g++ 2.7 to
341 //   complain bitterly.
342 //
343 // Minor bugfix and changes.
344 //
345 // Simulator/Main/GLUTmain.cxx
346 //   Added missing type to idle_state definition - eliminates a warning.
347 //
348 // Simulator/Main/fg_init.cxx
349 //   Changes to airport lookup.
350 //
351 // Simulator/Main/options.cxx
352 //   Uses fg_gzifstream when loading config file.
353 //
354 // Revision 1.7  1998/08/29 13:11:31  curt
355 // Bernie Bright writes:
356 //   I've created some new classes to enable pointers-to-functions and
357 //   pointers-to-class-methods to be treated like objects.  These objects
358 //   can be registered with fgEVENT_MGR.
359 //
360 //   File "Include/fg_callback.hxx" contains the callback class defns.
361 //
362 //   Modified fgEVENT and fgEVENT_MGR to use the callback classes.  Also
363 //   some minor tweaks to STL usage.
364 //
365 //   Added file "Include/fg_stl_config.h" to deal with STL portability
366 //   issues.  I've added an initial config for egcs (and probably gcc-2.8.x).
367 //   I don't have access to Visual C++ so I've left that for someone else.
368 //   This file is influenced by the stl_config.h file delivered with egcs.
369 //
370 //   Added "Include/auto_ptr.hxx" which contains an implementation of the
371 //   STL auto_ptr class which is not provided in all STL implementations
372 //   and is needed to use the callback classes.
373 //
374 //   Deleted fgLightUpdate() which was just a wrapper to call
375 //   fgLIGHT::Update().
376 //
377 //   Modified fg_init.cxx to register two method callbacks in place of the
378 //   old wrapper functions.
379 //
380 // Revision 1.6  1998/08/20 15:12:26  curt
381 // Tweak ...
382 //
383 // Revision 1.5  1998/06/12 00:59:52  curt
384 // Build only static libraries.
385 // Declare memmove/memset for Sloaris.
386 // Rewrote fg_time.c routine to get LST start seconds to better handle
387 //   Solaris, and be easier to port, and understand the GMT vs. local
388 //   timezone issues.
389 //
390 // Revision 1.4  1998/06/05 18:18:12  curt
391 // Incorporated some automake conditionals to try to support mktime() correctly
392 // on a wider variety of platforms.
393 // Added the declaration of memmove needed by the stl which apparently
394 // solaris only defines for cc compilations and not for c++ (__STDC__)
395 //
396 // Revision 1.3  1998/05/22 21:14:53  curt
397 // Rewrote event.cxx in C++ as a class using STL for the internal event list
398 // and run queue this removes the arbitrary list sizes and makes things much
399 // more dynamic.  Because this is C++-classified we can now have multiple
400 // event_tables if we'd ever want them.
401 //
402 // Revision 1.2  1998/04/25 22:06:33  curt
403 // Edited cvs log messages in source files ... bad bad bad!
404 //
405 // Revision 1.1  1998/04/24 00:52:26  curt
406 // Wrapped "#include <config.h>" in "#ifdef HAVE_CONFIG_H"
407 // Fog color fixes.
408 // Separated out lighting calcs into their own file.
409 //
410 // Revision 1.13  1998/04/18 04:14:08  curt
411 // Moved fg_debug.c to it's own library.
412 //
413 // Revision 1.12  1998/04/09 18:40:13  curt
414 // We had unified some of the platform disparate time handling code, and
415 // there was a bug in timesum() which calculated a new time stamp based on
416 // the current time stamp + offset.  This hosed the periodic event processing
417 // logic because you'd never arrive at the time the event was scheduled for.
418 // Sky updates and lighting changes are handled via this event mechanism so
419 // they never changed ... it is fixed now.
420 //
421 // Revision 1.11  1998/04/03 22:12:55  curt
422 // Converting to Gnu autoconf system.
423 // Centralized time handling differences.
424 //
425 // Revision 1.10  1998/03/14 00:28:34  curt
426 // replaced a printf() with an fgPrintf().
427 //
428 // Revision 1.9  1998/01/31 00:43:44  curt
429 // Added MetroWorks patches from Carmen Volpe.
430 //
431 // Revision 1.8  1998/01/27 00:48:05  curt
432 // Incorporated Paul Bleisch's <pbleisch@acm.org> new debug message
433 // system and commandline/config file processing code.
434 //
435 // Revision 1.7  1998/01/19 19:27:19  curt
436 // Merged in make system changes from Bob Kuehne <rpk@sgi.com>
437 // This should simplify things tremendously.
438 //
439 // Revision 1.6  1998/01/19 18:40:39  curt
440 // Tons of little changes to clean up the code and to remove fatal errors
441 // when building with the c++ compiler.
442 //
443 // Revision 1.5  1998/01/06 01:20:27  curt
444 // Tweaks to help building with MSVC++
445 //
446 // Revision 1.4  1997/12/31 17:46:50  curt
447 // Tweaked fg_time.c to be able to use ftime() instead of gettimeofday()
448 //
449 // Revision 1.3  1997/12/30 22:22:42  curt
450 // Further integration of event manager.
451 //
452 // Revision 1.2  1997/12/30 20:47:58  curt
453 // Integrated new event manager with subsystem initializations.
454 //
455 // Revision 1.1  1997/12/30 04:19:22  curt
456 // Initial revision.