]> git.mxchange.org Git - flightgear.git/blob - Simulator/Time/event.cxx
Initial revision.
[flightgear.git] / Simulator / 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
23
24 #ifdef HAVE_CONFIG_H
25 #  include <config.h>
26 #endif
27
28 #include <string>
29
30 #include "Include/compiler.h"
31
32 #include STL_ALGORITHM
33 #include STL_FUNCTIONAL
34
35 #ifdef FG_HAVE_STD_INCLUDES
36 #  include <cstdio>
37 #  ifdef HAVE_STDLIB_H
38 #    include <cstdlib>
39 #  endif
40 #else
41 #  include <stdio.h>
42 #  ifdef HAVE_STDLIB_H
43 #    include <stdlib.h>
44 #  endif
45 #endif
46
47 #if defined( HAVE_WINDOWS_H ) && defined(__MWERKS__)
48 #  include <windows.h>   // For Metrowerks environment
49 #  include <winbase.h>   // There is no ANSI/MSL time function that
50                          // contains milliseconds
51 #endif
52
53 #include <Debug/logstream.hxx>
54
55 #include "event.hxx"
56
57 FG_USING_STD(for_each);
58 FG_USING_STD(mem_fun);
59
60 fgEVENT_MGR global_events;
61
62
63 fgEVENT::fgEVENT( const string& desc,
64                   const fgCallback& cb,
65                   EventState evt_status,
66                   int evt_interval )
67     : description(desc),
68       event_cb(cb.clone()),
69       status(evt_status),
70       interval(evt_interval),
71       cum_time(0),
72       min_time(100000),
73       max_time(0),
74       count(0)
75 {
76 }
77
78 #if 0
79 fgEVENT::fgEVENT( const fgEVENT& evt )
80     : description(evt.description),
81       event_cb(evt.event_cb),
82       status(evt.status),
83       interval(evt.interval),
84       last_run(evt.last_run),
85       current(evt.current),
86       next_run(evt.next_run),
87       cum_time(evt.cum_time),
88       min_time(evt.min_time),
89       max_time(evt.max_time),
90       count(evt.count)
91 {
92 }
93
94 fgEVENT&
95 fgEVENT::operator= ( const fgEVENT& evt )
96 {
97     if ( this != &evt )
98     {
99         description = evt.description;
100         event_cb = evt.event_cb;
101         status = evt.status;
102         interval = evt.interval;
103         last_run = evt.last_run;
104         current = evt.current;
105         next_run = evt.next_run;
106         cum_time = evt.cum_time;
107         min_time = evt.min_time;
108         max_time = evt.max_time;
109         count = evt.count;
110     }
111     return *this;
112 }
113 #endif
114
115 fgEVENT::~fgEVENT()
116 {
117     delete event_cb;
118 }
119
120 void
121 fgEVENT::run()
122 {
123     FG_LOG(FG_EVENT, FG_INFO, "Running " << description );
124
125     // record starting time
126     last_run.stamp();
127
128     // run the event
129     event_cb->call( (void**)NULL );
130
131     // increment the counter for this event
132     count++;
133
134     // update the event status
135     status = FG_EVENT_READY;
136
137     // calculate duration and stats
138     current.stamp();
139     long duration = current - last_run;
140
141     cum_time += duration;
142
143     if ( duration < min_time ) {
144         min_time = duration;
145     }
146
147     if ( duration > max_time ) {
148         max_time = duration;
149     }
150
151     // determine the next absolute run time
152     next_run =  last_run + interval;
153 }
154
155
156 // Dump scheduling stats
157 int
158 fgEVENT::PrintStats() const
159 {
160     FG_LOG( FG_EVENT, FG_INFO, 
161             "  " << description 
162             << " int=" << interval / 1000.0
163             << " cum=" << cum_time
164             << " min=" << min_time
165             << " max=" <<  max_time
166             << " count=" << count
167             << " ave=" << cum_time / (double)count );
168     return 0;
169 }
170
171 // Constructor
172 fgEVENT_MGR::fgEVENT_MGR( void ) {
173 }
174
175
176 // Initialize the scheduling subsystem
177 void fgEVENT_MGR::Init( void ) {
178     FG_LOG(FG_EVENT, FG_INFO, "Initializing event manager" );
179
180     run_queue.erase( run_queue.begin(), run_queue.end() );
181     event_table.erase( event_table.begin(), event_table.end() );
182 }
183
184
185 // Register an event with the scheduler.
186 void
187 fgEVENT_MGR::Register( const string& desc,
188                        const fgCallback& cb,
189                        fgEVENT::EventState status, 
190                        int interval )
191 {
192     // convert interval specified in milleseconds to usec
193     fgEVENT* e = new fgEVENT( desc, cb, status, interval * 1000 );
194
195     FG_LOG( FG_EVENT, FG_INFO, "Registering event: " << desc );
196
197     // Actually run the event
198     e->run();
199
200     // Now add to event_table
201     event_table.push_back(e);
202 }
203
204
205 // Update the scheduling parameters for an event
206 void fgEVENT_MGR::Update( void ) {
207 }
208
209
210 // Delete a scheduled event
211 void fgEVENT_MGR::Delete( void ) {
212 }
213
214
215 // Temporarily suspend scheduling of an event
216 void fgEVENT_MGR::Suspend( void ) {
217 }
218
219
220 // Resume scheduling and event
221 void fgEVENT_MGR::Resume( void ) {
222 }
223
224 // Dump scheduling stats
225 void
226 fgEVENT_MGR::PrintStats()
227 {
228     FG_LOG( FG_EVENT, FG_INFO, "" );
229     FG_LOG( FG_EVENT, FG_INFO, "Event Stats" );
230     FG_LOG( FG_EVENT, FG_INFO, "-----------" );
231
232     ConstEventIterator first = event_table.begin();
233     ConstEventIterator last = event_table.end();
234     while ( first != last )
235     {
236         (*first)->PrintStats();
237         ++first;
238     }
239 #if 0 // msvc++ 6.0 barfs at mem_fun()
240     for_each( event_table.begin(),
241               event_table.end(),
242               mem_fun( &fgEVENT::PrintStats ) );
243 #endif
244     FG_LOG( FG_EVENT, FG_INFO, "");
245 }
246
247
248 // Add pending jobs to the run queue and run the job at the front of
249 // the queue
250 void fgEVENT_MGR::Process( void ) {
251     fgEVENT *e_ptr;
252     FGTimeStamp cur_time;
253     unsigned int i, size;
254
255     FG_LOG( FG_EVENT, FG_DEBUG, "Processing events" );
256     
257     // get the current time
258     cur_time.stamp();
259
260     FG_LOG( FG_EVENT, FG_DEBUG, 
261             "  Current timestamp = " << cur_time.get_seconds() );
262
263     // printf("Checking if anything is ready to move to the run queue\n");
264
265     // see if anything else is ready to be placed on the run queue
266     size = event_table.size();
267     // while ( current != last ) {
268     for ( i = 0; i < size; i++ ) {
269         // e = *current++;
270         e_ptr = event_table[i];
271         if ( e_ptr->status == fgEVENT::FG_EVENT_READY ) {
272             FG_LOG( FG_EVENT, FG_DEBUG, 
273                     "  Item " << i << " current " << cur_time.get_seconds()
274                     << " next run @ " << e_ptr->next_run.get_seconds() );
275             if ( ( e_ptr->next_run - cur_time ) <= 0 ) {
276                 run_queue.push_back(e_ptr);
277                 e_ptr->status = fgEVENT::FG_EVENT_QUEUED;
278             }
279         }
280     }
281
282     // Checking to see if there is anything on the run queue
283     // printf("Checking to see if there is anything on the run queue\n");
284     if ( run_queue.size() ) {
285         // printf("Yep, running it\n");
286         e_ptr = run_queue.front();
287         run_queue.pop_front();
288         e_ptr->run();
289     }
290 }
291
292
293 // Destructor
294 fgEVENT_MGR::~fgEVENT_MGR( void ) {
295     EventIterator first = event_table.begin();
296     EventIterator last = event_table.end();
297     for ( ; first != last; ++first )
298     {
299         delete (*first);
300     }
301
302     run_queue.erase( run_queue.begin(), run_queue.end() );
303     event_table.erase( event_table.begin(), event_table.end() );
304 }
305
306