1 // event.cxx -- Flight Gear periodic event scheduler
3 // Written by Curtis Olson, started December 1997.
5 // Copyright (C) 1997 Curtis L. Olson - curt@infoplane.com
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.
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.
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.
30 #include "Include/compiler.h"
32 #include STL_ALGORITHM
33 #include STL_FUNCTIONAL
35 #ifdef FG_HAVE_STD_INCLUDES
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
53 #include <Debug/logstream.hxx>
57 FG_USING_STD(for_each);
58 FG_USING_STD(mem_fun);
60 fgEVENT_MGR global_events;
63 fgEVENT::fgEVENT( const string& desc,
65 EventState evt_status,
70 interval(evt_interval),
79 fgEVENT::fgEVENT( const fgEVENT& evt )
80 : description(evt.description),
81 event_cb(evt.event_cb),
83 interval(evt.interval),
84 last_run(evt.last_run),
86 next_run(evt.next_run),
87 cum_time(evt.cum_time),
88 min_time(evt.min_time),
89 max_time(evt.max_time),
95 fgEVENT::operator= ( const fgEVENT& evt )
99 description = evt.description;
100 event_cb = evt.event_cb;
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;
123 FG_LOG(FG_EVENT, FG_INFO, "Running " << description );
125 // record starting time
129 event_cb->call( (void**)NULL );
131 // increment the counter for this event
134 // update the event status
135 status = FG_EVENT_READY;
137 // calculate duration and stats
139 long duration = current - last_run;
141 cum_time += duration;
143 if ( duration < min_time ) {
147 if ( duration > max_time ) {
151 // determine the next absolute run time
152 next_run = last_run + interval;
156 // Dump scheduling stats
158 fgEVENT::PrintStats() const
160 FG_LOG( FG_EVENT, FG_INFO,
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 );
172 fgEVENT_MGR::fgEVENT_MGR( void ) {
176 // Initialize the scheduling subsystem
177 void fgEVENT_MGR::Init( void ) {
178 FG_LOG(FG_EVENT, FG_INFO, "Initializing event manager" );
180 run_queue.erase( run_queue.begin(), run_queue.end() );
181 event_table.erase( event_table.begin(), event_table.end() );
185 // Register an event with the scheduler.
187 fgEVENT_MGR::Register( const string& desc,
188 const fgCallback& cb,
189 fgEVENT::EventState status,
192 // convert interval specified in milleseconds to usec
193 fgEVENT* e = new fgEVENT( desc, cb, status, interval * 1000 );
195 FG_LOG( FG_EVENT, FG_INFO, "Registering event: " << desc );
197 // Actually run the event
200 // Now add to event_table
201 event_table.push_back(e);
205 // Update the scheduling parameters for an event
206 void fgEVENT_MGR::Update( void ) {
210 // Delete a scheduled event
211 void fgEVENT_MGR::Delete( void ) {
215 // Temporarily suspend scheduling of an event
216 void fgEVENT_MGR::Suspend( void ) {
220 // Resume scheduling and event
221 void fgEVENT_MGR::Resume( void ) {
224 // Dump scheduling stats
226 fgEVENT_MGR::PrintStats()
228 FG_LOG( FG_EVENT, FG_INFO, "" );
229 FG_LOG( FG_EVENT, FG_INFO, "Event Stats" );
230 FG_LOG( FG_EVENT, FG_INFO, "-----------" );
232 ConstEventIterator first = event_table.begin();
233 ConstEventIterator last = event_table.end();
234 while ( first != last )
236 (*first)->PrintStats();
239 #if 0 // msvc++ 6.0 barfs at mem_fun()
240 for_each( event_table.begin(),
242 mem_fun( &fgEVENT::PrintStats ) );
244 FG_LOG( FG_EVENT, FG_INFO, "");
248 // Add pending jobs to the run queue and run the job at the front of
250 void fgEVENT_MGR::Process( void ) {
252 FGTimeStamp cur_time;
253 unsigned int i, size;
255 FG_LOG( FG_EVENT, FG_DEBUG, "Processing events" );
257 // get the current time
260 FG_LOG( FG_EVENT, FG_DEBUG,
261 " Current timestamp = " << cur_time.get_seconds() );
263 // printf("Checking if anything is ready to move to the run queue\n");
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++ ) {
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;
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();
294 fgEVENT_MGR::~fgEVENT_MGR( void ) {
295 EventIterator first = event_table.begin();
296 EventIterator last = event_table.end();
297 for ( ; first != last; ++first )
302 run_queue.erase( run_queue.begin(), run_queue.end() );
303 event_table.erase( event_table.begin(), event_table.end() );