+//
+// FGEventMgr.cxx -- Event Manager
+//
+// Written by Bernie Bright, started April 2002.
+//
+// Copyright (C) 2002 Curtis L. Olson - curt@me.umn.edu
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//
+// $Id$
+
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <simgear/compiler.h>
#include <simgear/debug/logstream.hxx>
-// #include <functional>
-// #include <algorithm>
#include "FGEventMgr.hxx"
FGEventMgr::FGEvent::FGEvent()
: name_(""),
callback_(0),
- status_(FG_EVENT_SUSP),
- ms_(0),
+ repeat_value_(0),
+ initial_value_(0),
ms_to_go_(0),
cum_time(0),
min_time(100000),
FGEventMgr::FGEvent::FGEvent( const char* name,
fgCallback* cb,
- EventState status,
- interval_type ms )
+ interval_type repeat_value,
+ interval_type initial_value )
: name_(name),
callback_(cb),
- status_(status),
- ms_(ms),
- ms_to_go_(ms),
+ repeat_value_(repeat_value),
+ initial_value_(initial_value),
+ //ms_to_go_(repeat_value_),
cum_time(0),
min_time(100000),
max_time(0),
count(0)
{
- if (status == FG_EVENT_READY)
+ if (initial_value_ < 0)
+ {
this->run();
+ ms_to_go_ = repeat_value_;
+ }
+ else
+ {
+ ms_to_go_ = initial_value_;
+ }
}
start_time.stamp();
// run the event
- callback_->call(0);
+ (*callback_)();
finish_time.stamp();
if ( duration > max_time ) {
max_time = duration;
}
-
- reset();
}
void
{
SG_LOG( SG_EVENT, SG_INFO,
" " << name_
- << " int=" << ms_ / 1000.0
+ << " int=" << repeat_value_ / 1000.0
<< " cum=" << cum_time
<< " min=" << min_time
<< " max=" << max_time
void
FGEventMgr::update( int dt )
{
- // Scan all events. Execute any whose interval has expired.
+ if (dt < 0)
+ {
+ SG_LOG( SG_GENERAL, SG_ALERT,
+ "FGEventMgr::update() called with negative delta T" );
+ return;
+ }
+
+ int min_value = 0;
event_container_type::iterator first = event_table.begin();
event_container_type::iterator last = event_table.end();
- for(; first != last; ++first)
+ event_container_type::iterator event = event_table.end();
+
+ // Scan all events. Run one whose interval has expired.
+ while (first != last)
{
if (first->update( dt ))
{
- first->run();
+ if (first->value() < min_value)
+ {
+ // Select event with largest negative value.
+ // Its been waiting longest.
+ min_value = first->value();
+ event = first;
+ }
+ }
+ ++first;
+ }
+
+ if (event != last)
+ {
+ event->run();
+
+ if (event->repeat_value() > 0)
+ {
+ event->reset();
+ }
+ else
+ {
+ SG_LOG( SG_GENERAL, SG_DEBUG, "Deleting event " << event->name() );
+ event_table.erase( event );
}
}
}
event_table.push_back( event );
SG_LOG( SG_EVENT, SG_INFO, "Registered event " << event.name()
- << " to run every " << event.interval() << "ms" );
+ << " to run every " << event.repeat_value() << "ms" );
}
void
SG_LOG( SG_EVENT, SG_INFO, "Event Stats" );
SG_LOG( SG_EVENT, SG_INFO, "-----------" );
-#if 1
event_container_type::const_iterator first = event_table.begin();
event_container_type::const_iterator last = event_table.end();
for (; first != last; ++first)
{
first->print_stats();
}
-#else
- // #@!$ MSVC can't handle const member functions.
- std::for_each( event_table.begin(), event_table.end(),
- std::mem_fun_ref( &FGEvent::print_stats ) );
-#endif
+
SG_LOG( SG_EVENT, SG_INFO, "" );
}
{
public:
- /**
- *
- */
- enum EventState {
- FG_EVENT_SUSP = 0,
- FG_EVENT_READY = 1,
- FG_EVENT_QUEUED = 2
- };
-
typedef int interval_type;
private:
FGEvent( const char* desc,
fgCallback* cb,
- EventState status,
- interval_type ms );
+ interval_type repeat_value,
+ interval_type initial_value );
/**
*
*/
void reset()
{
- status_ = FG_EVENT_READY;
- ms_to_go_ = ms_;
+ ms_to_go_ = repeat_value_;
}
/**
*/
void run();
- bool is_ready() const { return status_ == FG_EVENT_READY; }
-
string name() const { return name_; }
- interval_type interval() const { return ms_; }
+ interval_type repeat_value() const { return repeat_value_; }
+ int value() const { return ms_to_go_; }
/**
* Display event statistics.
*/
bool update( int dt_ms )
{
- if (status_ != FG_EVENT_READY)
- return false;
-
ms_to_go_ -= dt_ms;
return ms_to_go_ <= 0;
}
private:
string name_;
fgCallback* callback_;
- EventState status_;
- interval_type ms_;
+ interval_type repeat_value_;
+ interval_type initial_value_;
int ms_to_go_;
unsigned long cum_time; // cumulative processor time of this event
void update( int dt );
/**
- * Register a function to be executed every 'interval' milliseconds.
+ * Register a free standing function to be executed some time in the future.
* @param desc A brief description of this callback for logging.
* @param cb The callback function to be executed.
- * @param state
- * @param interval Callback repetition rate in milliseconds.
+ * @param repeat_value repetition rate in milliseconds.
+ * @param initial_value initial delay value in milliseconds. A value of
+ * -1 means run immediately.
*/
+ template< typename Fun >
void Register( const char* name,
- void (*cb)(),
- interval_type interval_ms,
- EventState state = FG_EVENT_READY )
- {
- this->Register( FGEvent( name, new fgFunctionCallback(cb), state, interval_ms ) );
- }
-
- template< class Obj >
- void Register( const char* name,
- Obj* obj, void (Obj::*pmf)() const,
- interval_type interval_ms,
- EventState state = FG_EVENT_READY )
+ const Fun& f,
+ interval_type repeat_value,
+ interval_type initial_value = -1 )
{
- this->Register( FGEvent( name, new fgMethodCallback<Obj>(obj,pmf), state, interval_ms ) );
+ this->Register( FGEvent( name,
+ make_callback(f),
+ repeat_value,
+ initial_value ) );
}
- template< class Obj >
+ template< class ObjPtr, typename MemFn >
void Register( const char* name,
- Obj* obj, void (Obj::*pmf)(),
- interval_type interval_ms,
- EventState state = FG_EVENT_READY )
+ const ObjPtr& p,
+ MemFn pmf,
+ interval_type repeat_value,
+ interval_type initial_value = -1 )
{
- this->Register( FGEvent( name, new fgMethodCallback<Obj>(obj,pmf), state, interval_ms ) );
+ this->Register( FGEvent( name,
+ make_callback(p,pmf),
+ repeat_value,
+ initial_value ) );
}
/**
// if the 4th field is 0.0, this specifies a direction ...
GLfloat white[4] = { 1.0, 1.0, 1.0, 1.0 };
// base sky color
- GLfloat base_sky_color[4] = {0.60, 0.60, 0.90, 1.0};
+ GLfloat base_sky_color[4] = { 0.60, 0.60, 0.90, 1.0 };
// base fog color
- GLfloat base_fog_color[4] = {0.90, 0.90, 1.00, 1.0};
+ GLfloat base_fog_color[4] = { 0.90, 0.90, 1.00, 1.0 };
double deg, ambient, diffuse, sky_brightness;
f = current_aircraft.fdm_state;