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.
28 #include "Include/compiler.h"
30 #ifdef FG_MATH_EXCEPTION_CLASH
34 #include STL_ALGORITHM
35 #include STL_FUNCTIONAL
38 #ifdef FG_HAVE_STD_INCLUDES
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
56 #include <Debug/logstream.hxx>
60 FG_USING_STD(for_each);
61 FG_USING_STD(mem_fun);
64 fgEVENT_MGR global_events;
67 fgEVENT::fgEVENT( const string& desc,
69 EventState evt_status,
74 interval(evt_interval),
83 fgEVENT::fgEVENT( const fgEVENT& evt )
84 : description(evt.description),
85 event_cb(evt.event_cb),
87 interval(evt.interval),
88 last_run(evt.last_run),
90 next_run(evt.next_run),
91 cum_time(evt.cum_time),
92 min_time(evt.min_time),
93 max_time(evt.max_time),
99 fgEVENT::operator= ( const fgEVENT& evt )
103 description = evt.description;
104 event_cb = evt.event_cb;
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;
127 FG_LOG(FG_EVENT, FG_INFO, "Running " << description );
129 // record starting time
133 event_cb->call( (void**)NULL );
135 // increment the counter for this event
138 // update the event status
139 status = FG_EVENT_READY;
141 // calculate duration and stats
143 long duration = current - last_run;
145 cum_time += duration;
147 if ( duration < min_time ) {
151 if ( duration > max_time ) {
155 // determine the next absolute run time
156 next_run = last_run + interval;
160 // Dump scheduling stats
162 fgEVENT::PrintStats() const
164 FG_LOG( FG_EVENT, FG_INFO,
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 );
176 fgEVENT_MGR::fgEVENT_MGR( void ) {
180 // Initialize the scheduling subsystem
181 void fgEVENT_MGR::Init( void ) {
182 FG_LOG(FG_EVENT, FG_INFO, "Initializing event manager" );
184 run_queue.erase( run_queue.begin(), run_queue.end() );
185 event_table.erase( event_table.begin(), event_table.end() );
189 // Register an event with the scheduler.
191 fgEVENT_MGR::Register( const string& desc,
192 const fgCallback& cb,
193 fgEVENT::EventState status,
196 // convert interval specified in milleseconds to usec
197 fgEVENT* e = new fgEVENT( desc, cb, status, interval * 1000 );
199 FG_LOG( FG_EVENT, FG_INFO, "Registering event: " << desc );
201 // Actually run the event
204 // Now add to event_table
205 event_table.push_back(e);
209 // Update the scheduling parameters for an event
210 void fgEVENT_MGR::Update( void ) {
214 // Delete a scheduled event
215 void fgEVENT_MGR::Delete( void ) {
219 // Temporarily suspend scheduling of an event
220 void fgEVENT_MGR::Suspend( void ) {
224 // Resume scheduling and event
225 void fgEVENT_MGR::Resume( void ) {
228 // Dump scheduling stats
230 fgEVENT_MGR::PrintStats()
232 FG_LOG( FG_EVENT, FG_INFO, "" );
233 FG_LOG( FG_EVENT, FG_INFO, "Event Stats" );
234 FG_LOG( FG_EVENT, FG_INFO, "-----------" );
236 ConstEventIterator first = event_table.begin();
237 ConstEventIterator last = event_table.end();
238 while ( first != last )
240 (*first)->PrintStats();
243 #if 0 // msvc++ 6.0 barfs at mem_fun()
244 for_each( event_table.begin(),
246 mem_fun( &fgEVENT::PrintStats ) );
248 FG_LOG( FG_EVENT, FG_INFO, "");
252 // Add pending jobs to the run queue and run the job at the front of
254 void fgEVENT_MGR::Process( void ) {
256 FGTimeStamp cur_time;
257 unsigned int i, size;
259 FG_LOG( FG_EVENT, FG_DEBUG, "Processing events" );
261 // get the current time
264 FG_LOG( FG_EVENT, FG_DEBUG,
265 " Current timestamp = " << cur_time.get_seconds() );
267 // printf("Checking if anything is ready to move to the run queue\n");
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++ ) {
274 e_ptr = event_table[i];
275 if ( e_ptr->status == fgEVENT::FG_EVENT_READY ) {
276 FG_LOG( FG_EVENT, FG_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;
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();
298 fgEVENT_MGR::~fgEVENT_MGR( void ) {
299 EventIterator first = event_table.begin();
300 EventIterator last = event_table.end();
301 for ( ; first != last; ++first )
306 run_queue.erase( run_queue.begin(), run_queue.end() );
307 event_table.erase( event_table.begin(), event_table.end() );