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