Move FGEventMgr and FGSubsystemMgr over to SimGear, add SGEventMgr to FlightGear's globals structre and some small code cleanups
This commit is contained in:
parent
f3eeeb760f
commit
d22640ef4e
@ -367,6 +367,7 @@ AC_CONFIG_FILES([ \
|
||||
simgear/screen/Makefile \
|
||||
simgear/serial/Makefile \
|
||||
simgear/sound/Makefile \
|
||||
simgear/structure/Makefile \
|
||||
simgear/threads/Makefile \
|
||||
simgear/timing/Makefile \
|
||||
simgear/xgl/Makefile \
|
||||
|
@ -30,6 +30,7 @@ SUBDIRS = \
|
||||
serial \
|
||||
sound \
|
||||
$(SGTHREAD_DIR) \
|
||||
structure \
|
||||
timing \
|
||||
xgl
|
||||
|
||||
|
@ -3,8 +3,6 @@ includedir = @includedir@/misc
|
||||
lib_LIBRARIES = libsgmisc.a
|
||||
|
||||
include_HEADERS = \
|
||||
commands.hxx \
|
||||
exception.hxx \
|
||||
sg_path.hxx \
|
||||
sgstream.hxx \
|
||||
stopwatch.hxx \
|
||||
@ -14,8 +12,6 @@ include_HEADERS = \
|
||||
zfstream.hxx
|
||||
|
||||
libsgmisc_a_SOURCES = \
|
||||
commands.cxx \
|
||||
exception.cxx \
|
||||
sg_path.cxx \
|
||||
sgstream.cxx \
|
||||
strutils.cxx \
|
||||
|
@ -13,10 +13,9 @@
|
||||
|
||||
// #include STL_IOSTREAM
|
||||
|
||||
#include <simgear/misc/exception.hxx>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
|
||||
#include "props.hxx"
|
||||
|
||||
#include "condition.hxx"
|
||||
|
||||
SG_USING_STD(istream);
|
||||
|
@ -37,7 +37,7 @@
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/constants.h>
|
||||
#include <simgear/misc/exception.hxx>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
|
||||
#include <string.h>
|
||||
#include STL_STRING
|
||||
|
@ -17,13 +17,12 @@
|
||||
#include <plib/ssg.h>
|
||||
#include <plib/ul.h>
|
||||
|
||||
#include <simgear/misc/exception.hxx>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/props/props_io.hxx>
|
||||
|
||||
#include "animation.hxx"
|
||||
|
||||
#include "model.hxx"
|
||||
|
||||
SG_USING_STD(vector);
|
||||
|
3
simgear/structure/.cvsignore
Normal file
3
simgear/structure/.cvsignore
Normal file
@ -0,0 +1,3 @@
|
||||
.deps
|
||||
Makefile
|
||||
Makefile.in
|
20
simgear/structure/Makefile.am
Normal file
20
simgear/structure/Makefile.am
Normal file
@ -0,0 +1,20 @@
|
||||
includedir = @includedir@/structure
|
||||
|
||||
lib_LIBRARIES = libsgstructure.a
|
||||
|
||||
include_HEADERS = \
|
||||
callback.hxx \
|
||||
commands.hxx \
|
||||
exception.hxx \
|
||||
event_mgr.hxx \
|
||||
subsystem_mgr.hxx
|
||||
|
||||
libsgstructure_a_SOURCES = \
|
||||
commands.cxx \
|
||||
exception.cxx \
|
||||
event_mgr.cxx\
|
||||
subsystem_mgr.cxx
|
||||
|
||||
|
||||
INCLUDES = -I$(top_srcdir)
|
||||
|
148
simgear/structure/callback.hxx
Normal file
148
simgear/structure/callback.hxx
Normal file
@ -0,0 +1,148 @@
|
||||
/**************************************************************************
|
||||
* callback.hxx -- Wrapper classes to treat function and method pointers
|
||||
* as objects.
|
||||
*
|
||||
* 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$
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef _SG_CALLBACK_HXX
|
||||
#define _SG_CALLBACK_HXX
|
||||
|
||||
/**
|
||||
* Abstract base class for all callbacks.
|
||||
*/
|
||||
class SGCallback
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
virtual ~SGCallback() {}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
virtual SGCallback* clone() const = 0;
|
||||
|
||||
/**
|
||||
* Execute the callback function.
|
||||
*/
|
||||
virtual void operator()() = 0;
|
||||
|
||||
protected:
|
||||
/**
|
||||
*
|
||||
*/
|
||||
SGCallback() {}
|
||||
|
||||
private:
|
||||
// Not implemented.
|
||||
void operator=( const SGCallback& );
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback for invoking a file scope function.
|
||||
*/
|
||||
template< typename Fun >
|
||||
class SGFunctionCallback : public SGCallback
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*
|
||||
*/
|
||||
SGFunctionCallback( const Fun& fun )
|
||||
: SGCallback(), f_(fun) {}
|
||||
|
||||
SGCallback* clone() const
|
||||
{
|
||||
return new SGFunctionCallback( *this );
|
||||
}
|
||||
|
||||
void operator()() { f_(); }
|
||||
|
||||
private:
|
||||
// Not defined.
|
||||
SGFunctionCallback();
|
||||
|
||||
private:
|
||||
Fun f_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback for invoking a member function.
|
||||
*/
|
||||
template< class ObjPtr, typename MemFn >
|
||||
class SGMethodCallback : public SGCallback
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
SGMethodCallback( const ObjPtr& pObj, MemFn pMemFn )
|
||||
: SGCallback(),
|
||||
pObj_(pObj),
|
||||
pMemFn_(pMemFn)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
SGCallback* clone() const
|
||||
{
|
||||
return new SGMethodCallback( *this );
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void operator()()
|
||||
{
|
||||
((*pObj_).*pMemFn_)();
|
||||
}
|
||||
|
||||
private:
|
||||
// Not defined.
|
||||
SGMethodCallback();
|
||||
|
||||
private:
|
||||
ObjPtr pObj_;
|
||||
MemFn pMemFn_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper template functions.
|
||||
*/
|
||||
|
||||
template< typename Fun >
|
||||
SGCallback*
|
||||
make_callback( const Fun& fun )
|
||||
{
|
||||
return new SGFunctionCallback<Fun>(fun);
|
||||
}
|
||||
|
||||
template< class ObjPtr, typename MemFn >
|
||||
SGCallback*
|
||||
make_callback( const ObjPtr& pObj, MemFn pMemFn )
|
||||
{
|
||||
return new SGMethodCallback<ObjPtr,MemFn>(pObj, pMemFn );
|
||||
}
|
||||
|
||||
#endif // _SG_CALLBACK_HXX
|
||||
|
258
simgear/structure/event_mgr.cxx
Normal file
258
simgear/structure/event_mgr.cxx
Normal file
@ -0,0 +1,258 @@
|
||||
//
|
||||
// SGEventMgr.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 <simgear_config.h>
|
||||
#endif
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
|
||||
#include "event_mgr.hxx"
|
||||
|
||||
SGEvent::SGEvent()
|
||||
: _name(""),
|
||||
_callback(0),
|
||||
_subsystem(0),
|
||||
_repeat_value(0),
|
||||
_initial_value(0),
|
||||
_ms_to_go(0),
|
||||
_cum_time(0),
|
||||
_min_time(100000),
|
||||
_max_time(0),
|
||||
_count(0)
|
||||
{
|
||||
}
|
||||
|
||||
SGEvent::SGEvent( const char* name,
|
||||
SGCallback* cb,
|
||||
interval_type repeat_value,
|
||||
interval_type initial_value )
|
||||
: _name(name),
|
||||
_callback(cb),
|
||||
_subsystem(NULL),
|
||||
_repeat_value(repeat_value),
|
||||
_initial_value(initial_value),
|
||||
_cum_time(0),
|
||||
_min_time(100000),
|
||||
_max_time(0),
|
||||
_count(0)
|
||||
{
|
||||
if (_initial_value < 0)
|
||||
{
|
||||
this->run();
|
||||
_ms_to_go = _repeat_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
_ms_to_go = _initial_value;
|
||||
}
|
||||
}
|
||||
|
||||
SGEvent::SGEvent( const char* name,
|
||||
const SGSubsystem* subsystem,
|
||||
interval_type repeat_value,
|
||||
interval_type initial_value )
|
||||
: _name(name),
|
||||
_callback(NULL),
|
||||
_subsystem((SGSubsystem*)&subsystem),
|
||||
_repeat_value(repeat_value),
|
||||
_initial_value(initial_value),
|
||||
_cum_time(0),
|
||||
_min_time(100000),
|
||||
_max_time(0),
|
||||
_count(0)
|
||||
{
|
||||
if (_initial_value < 0)
|
||||
{
|
||||
this->run();
|
||||
_ms_to_go = _repeat_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
_ms_to_go = _initial_value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SGEvent::~SGEvent()
|
||||
{
|
||||
//delete callback_;
|
||||
}
|
||||
|
||||
void
|
||||
SGEvent::run()
|
||||
{
|
||||
SGTimeStamp start_time;
|
||||
SGTimeStamp finish_time;
|
||||
|
||||
start_time.stamp();
|
||||
|
||||
// run the event
|
||||
if (_callback)
|
||||
{
|
||||
(*_callback)();
|
||||
} else if (_subsystem)
|
||||
{
|
||||
_subsystem->update(_repeat_value);
|
||||
}
|
||||
|
||||
finish_time.stamp();
|
||||
|
||||
++_count;
|
||||
|
||||
unsigned long duration = finish_time - start_time;
|
||||
|
||||
_cum_time += duration;
|
||||
|
||||
if ( duration < _min_time ) {
|
||||
_min_time = duration;
|
||||
}
|
||||
|
||||
if ( duration > _max_time ) {
|
||||
_max_time = duration;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SGEvent::print_stats() const
|
||||
{
|
||||
SG_LOG( SG_EVENT, SG_INFO,
|
||||
" " << _name
|
||||
<< " int=" << _repeat_value / 1000.0
|
||||
<< " cum=" << _cum_time
|
||||
<< " min=" << _min_time
|
||||
<< " max=" << _max_time
|
||||
<< " count=" << _count
|
||||
<< " ave=" << _cum_time / (double)_count );
|
||||
}
|
||||
|
||||
|
||||
|
||||
SGEventMgr::SGEventMgr()
|
||||
{
|
||||
}
|
||||
|
||||
SGEventMgr::~SGEventMgr()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SGEventMgr::init()
|
||||
{
|
||||
SG_LOG( SG_EVENT, SG_INFO, "Initializing event manager" );
|
||||
|
||||
event_table.clear();
|
||||
}
|
||||
|
||||
void
|
||||
SGEventMgr::reinit()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SGEventMgr::bind()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SGEventMgr::unbind()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SGEventMgr::update( double dt )
|
||||
{
|
||||
int dt_ms = int(dt * 1000);
|
||||
|
||||
if (dt_ms < 0)
|
||||
{
|
||||
SG_LOG( SG_GENERAL, SG_ALERT,
|
||||
"SGEventMgr::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();
|
||||
event_container_type::iterator event = event_table.end();
|
||||
|
||||
// Scan all events. Run one whose interval has expired.
|
||||
while (first != last)
|
||||
{
|
||||
if (first->update( dt_ms ))
|
||||
{
|
||||
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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SGEventMgr::add( const SGEvent& event )
|
||||
{
|
||||
event_table.push_back( event );
|
||||
|
||||
SG_LOG( SG_EVENT, SG_INFO, "registered event " << event.name()
|
||||
<< " to run every " << event.repeat_value() << "ms" );
|
||||
}
|
||||
|
||||
void
|
||||
SGEventMgr::print_stats() const
|
||||
{
|
||||
SG_LOG( SG_EVENT, SG_INFO, "" );
|
||||
SG_LOG( SG_EVENT, SG_INFO, "Event Stats" );
|
||||
SG_LOG( SG_EVENT, SG_INFO, "-----------" );
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
SG_LOG( SG_EVENT, SG_INFO, "" );
|
||||
}
|
209
simgear/structure/event_mgr.hxx
Normal file
209
simgear/structure/event_mgr.hxx
Normal file
@ -0,0 +1,209 @@
|
||||
// eventmMgr.hxx -- periodic event scheduler
|
||||
//
|
||||
// Written by Curtis Olson, started December 1997.
|
||||
// Modified by Bernie Bright, April 2002.
|
||||
//
|
||||
// Copyright (C) 1997 Curtis L. Olson - curt@infoplane.com
|
||||
//
|
||||
// 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$
|
||||
|
||||
#ifndef SG_EVENT_MGR_HXX
|
||||
#define SG_EVENT_MGR_HXX 1
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include <simgear/structure/callback.hxx>
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
#include <simgear/timing/timestamp.hxx>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
SG_USING_STD(vector);
|
||||
SG_USING_STD(string);
|
||||
|
||||
|
||||
class SGEvent
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
typedef int interval_type;
|
||||
|
||||
private:
|
||||
|
||||
string _name;
|
||||
SGCallback* _callback;
|
||||
SGSubsystem* _subsystem;
|
||||
interval_type _repeat_value;
|
||||
interval_type _initial_value;
|
||||
int _ms_to_go;
|
||||
|
||||
unsigned long _cum_time; // cumulative processor time of this event
|
||||
unsigned long _min_time; // time of quickest execution
|
||||
unsigned long _max_time; // time of slowest execution
|
||||
unsigned long _count; // number of times executed
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
SGEvent();
|
||||
|
||||
SGEvent( const char* desc,
|
||||
SGCallback* cb,
|
||||
interval_type repeat_value,
|
||||
interval_type initial_value );
|
||||
|
||||
SGEvent( const char* desc,
|
||||
const SGSubsystem* subsystem,
|
||||
interval_type repeat_value,
|
||||
interval_type initial_value );
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
~SGEvent();
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
inline void reset()
|
||||
{
|
||||
_ms_to_go = _repeat_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute this event's callback.
|
||||
*/
|
||||
void run();
|
||||
|
||||
inline string name() const { return _name; }
|
||||
inline interval_type repeat_value() const { return _repeat_value; }
|
||||
inline int value() const { return _ms_to_go; }
|
||||
|
||||
/**
|
||||
* Display event statistics.
|
||||
*/
|
||||
void print_stats() const;
|
||||
|
||||
/**
|
||||
* Update the elapsed time for this event.
|
||||
* @param dt_ms elapsed time in milliseconds.
|
||||
* @return true if elapsed time has expired.
|
||||
*/
|
||||
inline bool update( int dt_ms )
|
||||
{
|
||||
return (_ms_to_go -= dt_ms) <= 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class SGEventMgr : public SGSubsystem
|
||||
{
|
||||
private:
|
||||
|
||||
typedef SGEvent::interval_type interval_type;
|
||||
typedef vector< SGEvent > event_container_type;
|
||||
|
||||
void add( const SGEvent& event );
|
||||
|
||||
// registered events.
|
||||
event_container_type event_table;
|
||||
|
||||
|
||||
public:
|
||||
SGEventMgr();
|
||||
~SGEventMgr();
|
||||
|
||||
/**
|
||||
* Initialize the scheduling subsystem.
|
||||
*/
|
||||
void init();
|
||||
void reinit();
|
||||
void bind();
|
||||
void unbind();
|
||||
|
||||
/*
|
||||
* Update the elapsed time for all events.
|
||||
* @param dt elapsed time in seconds.
|
||||
*/
|
||||
void update( double dt );
|
||||
|
||||
/**
|
||||
* 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 repeat_value repetition rate in milliseconds.
|
||||
* @param initial_value initial delay value in milliseconds. A value of
|
||||
* -1 means run immediately.
|
||||
*/
|
||||
template< typename Fun >
|
||||
inline void add( const char* name,
|
||||
const Fun& f,
|
||||
interval_type repeat_value,
|
||||
interval_type initial_value = -1 )
|
||||
{
|
||||
this->add( SGEvent( name,
|
||||
make_callback(f),
|
||||
repeat_value,
|
||||
initial_value ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* register a subsystem of which the update function will be executed some
|
||||
* time in the future.
|
||||
* @param desc A brief description of this callback for logging.
|
||||
* @param subsystem The subsystem of which the update function will be
|
||||
* executed.
|
||||
* @param repeat_value repetition rate in milliseconds.
|
||||
* @param initial_value initial delay value in milliseconds. A value of
|
||||
* -1 means run immediately.
|
||||
*/
|
||||
inline void add( const char* name,
|
||||
const SGSubsystem* subsystem,
|
||||
interval_type repeat_value,
|
||||
interval_type initial_value = -1 )
|
||||
{
|
||||
this->add( SGEvent( name,
|
||||
subsystem,
|
||||
repeat_value,
|
||||
initial_value ) );
|
||||
}
|
||||
|
||||
template< class ObjPtr, typename MemFn >
|
||||
inline void add( const char* name,
|
||||
const ObjPtr& p,
|
||||
MemFn pmf,
|
||||
interval_type repeat_value,
|
||||
interval_type initial_value = -1 )
|
||||
{
|
||||
this->add( SGEvent( name,
|
||||
make_callback(p,pmf),
|
||||
repeat_value,
|
||||
initial_value ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Display statistics for all registered events.
|
||||
*/
|
||||
void print_stats() const;
|
||||
};
|
||||
|
||||
|
||||
#endif //SG_EVENT_MGR_HXX
|
333
simgear/structure/subsystem_mgr.cxx
Normal file
333
simgear/structure/subsystem_mgr.cxx
Normal file
@ -0,0 +1,333 @@
|
||||
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
|
||||
#include "exception.hxx"
|
||||
#include "subsystem_mgr.hxx"
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of SGSubsystem
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
SGSubsystem::SGSubsystem ()
|
||||
: _suspended(false)
|
||||
{
|
||||
}
|
||||
|
||||
SGSubsystem::~SGSubsystem ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SGSubsystem::init ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SGSubsystem::reinit ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SGSubsystem::bind ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SGSubsystem::unbind ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SGSubsystem::suspend ()
|
||||
{
|
||||
_suspended = true;
|
||||
}
|
||||
|
||||
void
|
||||
SGSubsystem::suspend (bool suspended)
|
||||
{
|
||||
_suspended = suspended;
|
||||
}
|
||||
|
||||
void
|
||||
SGSubsystem::resume ()
|
||||
{
|
||||
_suspended = false;
|
||||
}
|
||||
|
||||
bool
|
||||
SGSubsystem::is_suspended () const
|
||||
{
|
||||
return _suspended;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of SGSubsystemGroup.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SGSubsystemGroup::SGSubsystemGroup ()
|
||||
{
|
||||
}
|
||||
|
||||
SGSubsystemGroup::~SGSubsystemGroup ()
|
||||
{
|
||||
for (unsigned int i = 0; i < _members.size(); i++)
|
||||
delete _members[i];
|
||||
}
|
||||
|
||||
void
|
||||
SGSubsystemGroup::init ()
|
||||
{
|
||||
for (unsigned int i = 0; i < _members.size(); i++)
|
||||
_members[i]->subsystem->init();
|
||||
}
|
||||
|
||||
void
|
||||
SGSubsystemGroup::reinit ()
|
||||
{
|
||||
for (unsigned int i = 0; i < _members.size(); i++)
|
||||
_members[i]->subsystem->reinit();
|
||||
}
|
||||
|
||||
void
|
||||
SGSubsystemGroup::bind ()
|
||||
{
|
||||
for (unsigned int i = 0; i < _members.size(); i++)
|
||||
_members[i]->subsystem->bind();
|
||||
}
|
||||
|
||||
void
|
||||
SGSubsystemGroup::unbind ()
|
||||
{
|
||||
for (unsigned int i = 0; i < _members.size(); i++)
|
||||
_members[i]->subsystem->unbind();
|
||||
}
|
||||
|
||||
void
|
||||
SGSubsystemGroup::update (double delta_time_sec)
|
||||
{
|
||||
for (unsigned int i = 0; i < _members.size(); i++)
|
||||
_members[i]->update(delta_time_sec); // indirect call
|
||||
}
|
||||
|
||||
void
|
||||
SGSubsystemGroup::suspend ()
|
||||
{
|
||||
for (unsigned int i = 0; i < _members.size(); i++)
|
||||
_members[i]->subsystem->suspend();
|
||||
}
|
||||
|
||||
void
|
||||
SGSubsystemGroup::resume ()
|
||||
{
|
||||
for (unsigned int i = 0; i < _members.size(); i++)
|
||||
_members[i]->subsystem->resume();
|
||||
}
|
||||
|
||||
bool
|
||||
SGSubsystemGroup::is_suspended () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
SGSubsystemGroup::set_subsystem (const string &name, SGSubsystem * subsystem,
|
||||
double min_step_sec)
|
||||
{
|
||||
Member * member = get_member(name, true);
|
||||
if (member->subsystem != 0)
|
||||
delete member->subsystem;
|
||||
member->name = name;
|
||||
member->subsystem = subsystem;
|
||||
member->min_step_sec = min_step_sec;
|
||||
}
|
||||
|
||||
SGSubsystem *
|
||||
SGSubsystemGroup::get_subsystem (const string &name)
|
||||
{
|
||||
Member * member = get_member(name);
|
||||
if (member != 0)
|
||||
return member->subsystem;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
SGSubsystemGroup::remove_subsystem (const string &name)
|
||||
{
|
||||
for (unsigned int i = 0; i < _members.size(); i++) {
|
||||
if (name == _members[i]->name) {
|
||||
_members.erase(_members.begin() + i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
SGSubsystemGroup::has_subsystem (const string &name) const
|
||||
{
|
||||
return (((SGSubsystemGroup *)this)->get_member(name) != 0);
|
||||
}
|
||||
|
||||
SGSubsystemGroup::Member *
|
||||
SGSubsystemGroup::get_member (const string &name, bool create)
|
||||
{
|
||||
for (unsigned int i = 0; i < _members.size(); i++) {
|
||||
if (_members[i]->name == name)
|
||||
return _members[i];
|
||||
}
|
||||
if (create) {
|
||||
Member * member = new Member;
|
||||
_members.push_back(member);
|
||||
return member;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of SGSubsystemGroup::Member
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
SGSubsystemGroup::Member::Member ()
|
||||
: name(""),
|
||||
subsystem(0),
|
||||
min_step_sec(0),
|
||||
elapsed_sec(0)
|
||||
{
|
||||
}
|
||||
|
||||
SGSubsystemGroup::Member::Member (const Member &)
|
||||
{
|
||||
Member();
|
||||
}
|
||||
|
||||
SGSubsystemGroup::Member::~Member ()
|
||||
{
|
||||
// FIXME: causes a crash
|
||||
// delete subsystem;
|
||||
}
|
||||
|
||||
void
|
||||
SGSubsystemGroup::Member::update (double delta_time_sec)
|
||||
{
|
||||
elapsed_sec += delta_time_sec;
|
||||
if (elapsed_sec >= min_step_sec) {
|
||||
if (!subsystem->is_suspended()) {
|
||||
subsystem->update(elapsed_sec);
|
||||
elapsed_sec = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of SGSubsystemMgr.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
SGSubsystemMgr::SGSubsystemMgr ()
|
||||
{
|
||||
}
|
||||
|
||||
SGSubsystemMgr::~SGSubsystemMgr ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
SGSubsystemMgr::init ()
|
||||
{
|
||||
for (int i = 0; i < MAX_GROUPS; i++)
|
||||
_groups[i].init();
|
||||
}
|
||||
|
||||
void
|
||||
SGSubsystemMgr::reinit ()
|
||||
{
|
||||
for (int i = 0; i < MAX_GROUPS; i++)
|
||||
_groups[i].reinit();
|
||||
}
|
||||
|
||||
void
|
||||
SGSubsystemMgr::bind ()
|
||||
{
|
||||
for (int i = 0; i < MAX_GROUPS; i++)
|
||||
_groups[i].bind();
|
||||
}
|
||||
|
||||
void
|
||||
SGSubsystemMgr::unbind ()
|
||||
{
|
||||
for (int i = 0; i < MAX_GROUPS; i++)
|
||||
_groups[i].unbind();
|
||||
}
|
||||
|
||||
void
|
||||
SGSubsystemMgr::update (double delta_time_sec)
|
||||
{
|
||||
for (int i = 0; i < MAX_GROUPS; i++) {
|
||||
_groups[i].update(delta_time_sec);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SGSubsystemMgr::suspend ()
|
||||
{
|
||||
for (int i = 0; i < MAX_GROUPS; i++)
|
||||
_groups[i].suspend();
|
||||
}
|
||||
|
||||
void
|
||||
SGSubsystemMgr::resume ()
|
||||
{
|
||||
for (int i = 0; i < MAX_GROUPS; i++)
|
||||
_groups[i].resume();
|
||||
}
|
||||
|
||||
bool
|
||||
SGSubsystemMgr::is_suspended () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
SGSubsystemMgr::add (const char * name, SGSubsystem * subsystem,
|
||||
GroupType group, double min_time_sec)
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Adding subsystem " << name);
|
||||
get_group(group)->set_subsystem(name, subsystem, min_time_sec);
|
||||
|
||||
if (_subsystem_map.find(name) != _subsystem_map.end()) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Adding duplicate subsystem " << name);
|
||||
throw sg_exception("duplicate subsystem");
|
||||
}
|
||||
_subsystem_map[name] = subsystem;
|
||||
}
|
||||
|
||||
SGSubsystemGroup *
|
||||
SGSubsystemMgr::get_group (GroupType group)
|
||||
{
|
||||
return &(_groups[group]);
|
||||
}
|
||||
|
||||
SGSubsystem *
|
||||
SGSubsystemMgr::get_subsystem (const string &name)
|
||||
{
|
||||
map<string,SGSubsystem *>::iterator s =_subsystem_map.find(name);
|
||||
|
||||
if (s == _subsystem_map.end())
|
||||
return 0;
|
||||
else
|
||||
return s->second;
|
||||
}
|
||||
|
||||
// end of fgfs.cxx
|
345
simgear/structure/subsystem_mgr.hxx
Normal file
345
simgear/structure/subsystem_mgr.hxx
Normal file
@ -0,0 +1,345 @@
|
||||
// Written by David Megginson, started 2000-12
|
||||
//
|
||||
// Copyright (C) 2000 David Megginson, david@megginson.com
|
||||
//
|
||||
// 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$
|
||||
|
||||
|
||||
#ifndef __SUBSYSTEM_MGR_HXX
|
||||
#define __SUBSYSTEM_MGR_HXX 1
|
||||
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#if 0
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
# include <windows.h>
|
||||
# include <float.h>
|
||||
#endif
|
||||
|
||||
#include STL_STRING
|
||||
SG_USING_STD(string);
|
||||
|
||||
#include <vector>
|
||||
SG_USING_STD(vector);
|
||||
#endif
|
||||
|
||||
#include <map>
|
||||
SG_USING_STD(map);
|
||||
|
||||
#include <simgear/props/props.hxx>
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Basic interface for all FlightGear subsystems.
|
||||
*
|
||||
* <p>This is an abstract interface that all FlightGear subsystems
|
||||
* will eventually implement. It defines the basic operations for
|
||||
* each subsystem: initialization, property binding and unbinding, and
|
||||
* updating. Interfaces may define additional methods, but the
|
||||
* preferred way of exchanging information with other subsystems is
|
||||
* through the property tree.</p>
|
||||
*
|
||||
* <p>To publish information through a property, a subsystem should
|
||||
* bind it to a variable or (if necessary) a getter/setter pair in the
|
||||
* bind() method, and release the property in the unbind() method:</p>
|
||||
*
|
||||
* <pre>
|
||||
* void MySubsystem::bind ()
|
||||
* {
|
||||
* fgTie("/controls/flight/elevator", &_elevator);
|
||||
* fgSetArchivable("/controls/flight/elevator");
|
||||
* }
|
||||
*
|
||||
* void MySubsystem::unbind ()
|
||||
* {
|
||||
* fgUntie("/controls/flight/elevator");
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>To reference a property (possibly) from another subsystem, there
|
||||
* are two alternatives. If the property will be referenced only
|
||||
* infrequently (say, in the init() method), then the fgGet* methods
|
||||
* declared in fg_props.hxx are the simplest:</p>
|
||||
*
|
||||
* <pre>
|
||||
* void MySubsystem::init ()
|
||||
* {
|
||||
* _errorMargin = fgGetFloat("/display/error-margin-pct");
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>On the other hand, if the property will be referenced frequently
|
||||
* (say, in the update() method), then the hash-table lookup required
|
||||
* by the fgGet* methods might be too expensive; instead, the
|
||||
* subsystem should obtain a reference to the actual property node in
|
||||
* its init() function and use that reference in the main loop:</p>
|
||||
*
|
||||
* <pre>
|
||||
* void MySubsystem::init ()
|
||||
* {
|
||||
* _errorNode = fgGetNode("/display/error-margin-pct", true);
|
||||
* }
|
||||
*
|
||||
* void MySubsystem::update (double delta_time_sec)
|
||||
* {
|
||||
* do_something(_errorNode.getFloatValue());
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>The node returned will always be a pointer to SGPropertyNode,
|
||||
* and the subsystem should <em>not</em> delete it in its destructor
|
||||
* (the pointer belongs to the property tree, not the subsystem).</p>
|
||||
*
|
||||
* <p>The program may ask the subsystem to suspend or resume
|
||||
* sim-time-dependent operations; by default, the suspend() and
|
||||
* resume() methods set the protected variable <var>_suspended</var>,
|
||||
* which the subsystem can reference in its update() method, but
|
||||
* subsystems may also override the suspend() and resume() methods to
|
||||
* take different actions.</p>
|
||||
*/
|
||||
class SGSubsystem
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
SGSubsystem ();
|
||||
|
||||
/**
|
||||
* Virtual destructor to ensure that subclass destructors are called.
|
||||
*/
|
||||
virtual ~SGSubsystem ();
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the subsystem.
|
||||
*
|
||||
* <p>This method should set up the state of the subsystem, but
|
||||
* should not bind any properties. Note that any dependencies on
|
||||
* the state of other subsystems should be placed here rather than
|
||||
* in the constructor, so that FlightGear can control the
|
||||
* initialization order.</p>
|
||||
*/
|
||||
virtual void init ();
|
||||
|
||||
|
||||
/**
|
||||
* Reinitialize the subsystem.
|
||||
*
|
||||
* <p>This method should cause the subsystem to reinitialize itself,
|
||||
* and (normally) to reload any configuration files.</p>
|
||||
*/
|
||||
virtual void reinit ();
|
||||
|
||||
|
||||
/**
|
||||
* Acquire the subsystem's property bindings.
|
||||
*
|
||||
* <p>This method should bind all properties that the subsystem
|
||||
* publishes. It will be invoked after init, but before any
|
||||
* invocations of update.</p>
|
||||
*/
|
||||
virtual void bind ();
|
||||
|
||||
|
||||
/**
|
||||
* Release the subsystem's property bindings.
|
||||
*
|
||||
* <p>This method should release all properties that the subsystem
|
||||
* publishes. It will be invoked by FlightGear (not the destructor)
|
||||
* just before the subsystem is removed.</p>
|
||||
*/
|
||||
virtual void unbind ();
|
||||
|
||||
|
||||
/**
|
||||
* Update the subsystem.
|
||||
*
|
||||
* <p>FlightGear invokes this method every time the subsystem should
|
||||
* update its state.</p>
|
||||
*
|
||||
* @param delta_time_sec The delta time, in seconds, since the last
|
||||
* update. On first update, delta time will be 0.
|
||||
*/
|
||||
virtual void update (double delta_time_sec) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Suspend operation of this subsystem.
|
||||
*
|
||||
* <p>This method instructs the subsystem to suspend
|
||||
* sim-time-dependent operations until asked to resume. The update
|
||||
* method will still be invoked so that the subsystem can take any
|
||||
* non-time-dependent actions, such as updating the display.</p>
|
||||
*
|
||||
* <p>It is not an error for the suspend method to be invoked when
|
||||
* the subsystem is already suspended; the invocation should simply
|
||||
* be ignored.</p>
|
||||
*/
|
||||
virtual void suspend ();
|
||||
|
||||
|
||||
/**
|
||||
* Suspend or resum operation of this subsystem.
|
||||
*
|
||||
* @param suspended true if the subsystem should be suspended, false
|
||||
* otherwise.
|
||||
*/
|
||||
virtual void suspend (bool suspended);
|
||||
|
||||
|
||||
/**
|
||||
* Resume operation of this subsystem.
|
||||
*
|
||||
* <p>This method instructs the subsystem to resume
|
||||
* sim-time-depended operations. It is not an error for the resume
|
||||
* method to be invoked when the subsystem is not suspended; the
|
||||
* invocation should simply be ignored.</p>
|
||||
*/
|
||||
virtual void resume ();
|
||||
|
||||
|
||||
/**
|
||||
* Test whether this subsystem is suspended.
|
||||
*
|
||||
* @return true if the subsystem is suspended, false if it is not.
|
||||
*/
|
||||
virtual bool is_suspended () const;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
bool _suspended;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A group of FlightGear subsystems.
|
||||
*/
|
||||
class SGSubsystemGroup : public SGSubsystem
|
||||
{
|
||||
public:
|
||||
|
||||
SGSubsystemGroup ();
|
||||
virtual ~SGSubsystemGroup ();
|
||||
|
||||
virtual void init ();
|
||||
virtual void reinit ();
|
||||
virtual void bind ();
|
||||
virtual void unbind ();
|
||||
virtual void update (double delta_time_sec);
|
||||
virtual void suspend ();
|
||||
virtual void resume ();
|
||||
virtual bool is_suspended () const;
|
||||
|
||||
virtual void set_subsystem (const string &name,
|
||||
SGSubsystem * subsystem,
|
||||
double min_step_sec = 0);
|
||||
virtual SGSubsystem * get_subsystem (const string &name);
|
||||
virtual void remove_subsystem (const string &name);
|
||||
virtual bool has_subsystem (const string &name) const;
|
||||
|
||||
private:
|
||||
|
||||
struct Member {
|
||||
|
||||
Member ();
|
||||
Member (const Member &member);
|
||||
virtual ~Member ();
|
||||
|
||||
virtual void update (double delta_time_sec);
|
||||
|
||||
string name;
|
||||
SGSubsystem * subsystem;
|
||||
double min_step_sec;
|
||||
double elapsed_sec;
|
||||
};
|
||||
|
||||
Member * get_member (const string &name, bool create = false);
|
||||
|
||||
vector<Member *> _members;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Manage subsystems for FlightGear.
|
||||
*
|
||||
* This top-level subsystem will eventually manage all of the
|
||||
* subsystems in FlightGear: it broadcasts its life-cycle events
|
||||
* (init, bind, etc.) to all of the subsystems it manages. Subsystems
|
||||
* are grouped to guarantee order of initialization and execution --
|
||||
* currently, the only two groups are INIT and GENERAL, but others
|
||||
* will appear in the future.
|
||||
*
|
||||
* All subsystems are named as well as grouped, and subsystems can be
|
||||
* looked up by name and cast to the appropriate subtype when another
|
||||
* subsystem needs to invoke specialized methods.
|
||||
*
|
||||
* The subsystem manager owns the pointers to all the subsystems in
|
||||
* it.
|
||||
*/
|
||||
class SGSubsystemMgr : public SGSubsystem
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Types of subsystem groups.
|
||||
*/
|
||||
enum GroupType {
|
||||
INIT = 0,
|
||||
GENERAL,
|
||||
MAX_GROUPS
|
||||
};
|
||||
|
||||
SGSubsystemMgr ();
|
||||
virtual ~SGSubsystemMgr ();
|
||||
|
||||
virtual void init ();
|
||||
virtual void reinit ();
|
||||
virtual void bind ();
|
||||
virtual void unbind ();
|
||||
virtual void update (double delta_time_sec);
|
||||
virtual void suspend ();
|
||||
virtual void resume ();
|
||||
virtual bool is_suspended () const;
|
||||
|
||||
virtual void add (const char * name,
|
||||
SGSubsystem * subsystem,
|
||||
GroupType group = GENERAL,
|
||||
double min_time_sec = 0);
|
||||
|
||||
virtual SGSubsystemGroup * get_group (GroupType group);
|
||||
|
||||
virtual SGSubsystem * get_subsystem(const string &name);
|
||||
|
||||
private:
|
||||
|
||||
SGSubsystemGroup _groups[MAX_GROUPS];
|
||||
map<string,SGSubsystem *> _subsystem_map;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // __SUBSYSTEM_MGR_HXX
|
||||
|
@ -9,8 +9,7 @@
|
||||
#define __EASYXML_HXX
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include <simgear/misc/exception.hxx>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
|
||||
#include STL_IOSTREAM
|
||||
#include STL_STRING
|
||||
|
Loading…
Reference in New Issue
Block a user