simgear/screen/Makefile \
simgear/serial/Makefile \
simgear/sound/Makefile \
+ simgear/structure/Makefile \
simgear/threads/Makefile \
simgear/timing/Makefile \
simgear/xgl/Makefile \
serial \
sound \
$(SGTHREAD_DIR) \
+ structure \
timing \
xgl
lib_LIBRARIES = libsgmisc.a
include_HEADERS = \
- commands.hxx \
- exception.hxx \
sg_path.hxx \
sgstream.hxx \
stopwatch.hxx \
zfstream.hxx
libsgmisc_a_SOURCES = \
- commands.cxx \
- exception.cxx \
sg_path.cxx \
sgstream.cxx \
strutils.cxx \
+++ /dev/null
-// commands.cxx - encapsulated commands.
-// Started Spring 2001 by David Megginson, david@megginson.com
-// This code is released into the Public Domain.
-//
-// $Id$
-
-#include <simgear/props/props_io.hxx>
-
-#include "commands.hxx"
-
-
-\f
-////////////////////////////////////////////////////////////////////////
-// Implementation of SGCommandMgr class.
-////////////////////////////////////////////////////////////////////////
-
-
-SGCommandMgr::SGCommandMgr ()
-{
- // no-op
-}
-
-SGCommandMgr::~SGCommandMgr ()
-{
- // no-op
-}
-
-void
-SGCommandMgr::addCommand (const string &name, command_t command)
-{
- _commands[name] = command;
-}
-
-SGCommandMgr::command_t
-SGCommandMgr::getCommand (const string &name) const
-{
- const command_map::const_iterator it = _commands.find(name);
- return (it != _commands.end() ? it->second : 0);
-}
-
-vector<string>
-SGCommandMgr::getCommandNames () const
-{
- vector<string> names;
- command_map::const_iterator it = _commands.begin();
- command_map::const_iterator last = _commands.end();
- while (it != last) {
- names.push_back(it->first);
- it++;
- }
- return names;
-}
-
-bool
-SGCommandMgr::execute (const string &name, const SGPropertyNode * arg) const
-{
- command_t command = getCommand(name);
- if (command == 0)
- return false;
- else
- return (*command)(arg);
-}
-
-// end of commands.cxx
+++ /dev/null
-/**
- * \file commands.hxx
- * Interface definition for encapsulated commands.
- * Started Spring 2001 by David Megginson, david@megginson.com
- * This code is released into the Public Domain.
- *
- * $Id$
- */
-
-#ifndef __COMMANDS_HXX
-#define __COMMANDS_HXX
-
-
-#include <simgear/compiler.h>
-
-#include STL_STRING
-#include <map>
-#include <vector>
-
-#include <simgear/props/props.hxx>
-
-SG_USING_STD(string);
-SG_USING_STD(map);
-SG_USING_STD(vector);
-
-
-/**
- * Manage commands.
- *
- * <p>This class allows the application to register and unregister
- * commands, and provides shortcuts for executing them. Commands are
- * simple functions that take a const pointer to an SGPropertyNode:
- * the function may use the nodes children as parameters.</p>
- *
- * @author David Megginson, david@megginson.com
- */
-class SGCommandMgr
-{
-public:
-
- /**
- * Type for a command function.
- */
- typedef bool (*command_t) (const SGPropertyNode * arg);
-
-
- /**
- * Default constructor.
- */
- SGCommandMgr ();
-
-
- /**
- * Destructor.
- */
- virtual ~SGCommandMgr ();
-
-
- /**
- * Register a new command with the manager.
- *
- * @param name The command name. Any existing command with
- * the same name will silently be overwritten.
- * @param command A pointer to a one-arg function returning
- * a bool result. The argument is always a const pointer to
- * an SGPropertyNode (which may contain multiple values).
- */
- virtual void addCommand (const string &name, command_t command);
-
-
- /**
- * Look up an existing command.
- *
- * @param name The command name.
- * @return A pointer to the command, or 0 if there is no registered
- * command with the name specified.
- */
- virtual command_t getCommand (const string &name) const;
-
-
- /**
- * Get a list of all existing command names.
- *
- * @return A (possibly empty) vector of the names of all registered
- * commands.
- */
- virtual vector<string> getCommandNames () const;
-
-
- /**
- * Execute a command.
- *
- * @param name The name of the command.
- * @param arg A const pointer to an SGPropertyNode. The node
- * may have a value and/or children, etc., so that it is possible
- * to pass an arbitrarily complex data structure to a command.
- * @return true if the command is present and executes successfully,
- * false otherwise.
- */
- virtual bool execute (const string &name, const SGPropertyNode * arg) const;
-
-private:
-
- typedef map<string,command_t> command_map;
- command_map _commands;
-
-};
-
-#endif // __COMMANDS_HXX
-
-// end of commands.hxx
+++ /dev/null
-// exception.cxx - implementation of SimGear base exceptions.
-// Started Summer 2001 by David Megginson, david@megginson.com
-// This code is released into the Public Domain.
-//
-// $Id$
-
-
-#include "exception.hxx"
-#include <stdio.h>
-
-\f
-////////////////////////////////////////////////////////////////////////
-// Implementation of sg_location class.
-////////////////////////////////////////////////////////////////////////
-
-sg_location::sg_location ()
- : _path(""),
- _line(-1),
- _column(-1),
- _byte(-1)
-{
-}
-
-sg_location::sg_location (const string &path, int line, int column)
- : _path(path),
- _line(line),
- _column(column),
- _byte(-1)
-{
-}
-
-sg_location::~sg_location ()
-{
-}
-
-const string &
-sg_location::getPath () const
-{
- return _path;
-}
-
-void
-sg_location::setPath (const string &path)
-{
- _path = path;
-}
-
-int
-sg_location::getLine () const
-{
- return _line;
-}
-
-void
-sg_location::setLine (int line)
-{
- _line = line;
-}
-
-int
-sg_location::getColumn () const
-{
- return _column;
-}
-
-void
-sg_location::setColumn (int column)
-{
- _column = column;
-}
-
-int
-sg_location::getByte () const
-{
- return _byte;
-}
-
-void
-sg_location::setByte (int byte)
-{
- _byte = byte;
-}
-
-string
-sg_location::asString () const
-{
- char buf[128];
- string out = "";
- if (_path != (string)"") {
- out += _path;
- if (_line != -1 || _column != -1)
- out += ",\n";
- }
- if (_line != -1) {
- sprintf(buf, "line %d", _line);
- out += buf;
- if (_column != -1)
- out += ", ";
- }
- if (_column != -1) {
- sprintf(buf, "column %d", _column);
- out += buf;
- }
- return out;
-
-}
-
-
-\f
-////////////////////////////////////////////////////////////////////////
-// Implementation of sg_throwable class.
-////////////////////////////////////////////////////////////////////////
-
-sg_throwable::sg_throwable ()
- : _message(""),
- _origin("")
-{
-}
-
-sg_throwable::sg_throwable (const string &message, const string &origin)
- : _message(message),
- _origin(origin)
-{
-}
-
-sg_throwable::~sg_throwable ()
-{
-}
-
-const string &
-sg_throwable::getMessage () const
-{
- return _message;
-}
-
-const string
-sg_throwable::getFormattedMessage () const
-{
- return getMessage();
-}
-
-void
-sg_throwable::setMessage (const string &message)
-{
- _message = message;
-}
-
-const string &
-sg_throwable::getOrigin () const
-{
- return _origin;
-}
-
-void
-sg_throwable::setOrigin (const string &origin)
-{
- _origin = origin;
-}
-
-
-\f
-////////////////////////////////////////////////////////////////////////
-// Implementation of sg_error class.
-////////////////////////////////////////////////////////////////////////
-
-sg_error::sg_error ()
- : sg_throwable ()
-{
-}
-
-sg_error::sg_error (const string &message, const string &origin)
- : sg_throwable(message, origin)
-{
-}
-
-sg_error::~sg_error ()
-{
-}
-
-
-\f
-////////////////////////////////////////////////////////////////////////
-// Implementation of sg_exception class.
-////////////////////////////////////////////////////////////////////////
-
-sg_exception::sg_exception ()
- : sg_throwable ()
-{
-}
-
-sg_exception::sg_exception (const string &message, const string &origin)
- : sg_throwable(message, origin)
-{
-}
-
-sg_exception::~sg_exception ()
-{
-}
-
-
-\f
-////////////////////////////////////////////////////////////////////////
-// Implementation of sg_io_exception.
-////////////////////////////////////////////////////////////////////////
-
-sg_io_exception::sg_io_exception ()
- : sg_exception()
-{
-}
-
-sg_io_exception::sg_io_exception (const string &message, const string &origin)
- : sg_exception(message, origin)
-{
-}
-
-sg_io_exception::sg_io_exception (const string &message,
- const sg_location &location,
- const string &origin)
- : sg_exception(message, origin),
- _location(location)
-{
-}
-
-sg_io_exception::~sg_io_exception ()
-{
-}
-
-const string
-sg_io_exception::getFormattedMessage () const
-{
- string ret = getMessage();
- ret += "\n at ";
- ret += getLocation().asString();
- return ret;
-}
-
-const sg_location &
-sg_io_exception::getLocation () const
-{
- return _location;
-}
-
-void
-sg_io_exception::setLocation (const sg_location &location)
-{
- _location = location;
-}
-
-
-\f
-////////////////////////////////////////////////////////////////////////
-// Implementation of sg_format_exception.
-////////////////////////////////////////////////////////////////////////
-
-sg_format_exception::sg_format_exception ()
- : sg_exception(),
- _text("")
-{
-}
-
-sg_format_exception::sg_format_exception (const string &message,
- const string &text,
- const string &origin)
- : sg_exception(message, origin),
- _text(text)
-{
-}
-
-sg_format_exception::~sg_format_exception ()
-{
-}
-
-const string &
-sg_format_exception::getText () const
-{
- return _text;
-}
-
-void
-sg_format_exception::setText (const string &text)
-{
- _text = text;
-}
-
-
-\f
-////////////////////////////////////////////////////////////////////////
-// Implementation of sg_range_exception.
-////////////////////////////////////////////////////////////////////////
-
-sg_range_exception::sg_range_exception ()
- : sg_exception()
-{
-}
-
-sg_range_exception::sg_range_exception (const string &message,
- const string &origin)
- : sg_exception(message, origin)
-{
-}
-
-sg_range_exception::~sg_range_exception ()
-{
-}
-
-
-// end of exception.cxx
+++ /dev/null
-/**
- * \file exception.hxx
- * Interface definition for SimGear base exceptions.
- * Started Spring 2001 by David Megginson, david@megginson.com
- * This code is released into the Public Domain.
- *
- * $Id$
- */
-
-#ifndef __SIMGEAR_MISC_EXCEPTION_HXX
-#define __SIMGEAR_MISC_EXCEPTION_HXX 1
-
-#include <simgear/compiler.h>
-#include STL_STRING
-
-SG_USING_STD(string);
-
-
-/**
- * Information encapsulating a single location in an external resource
- *
- * A position in the resource my optionally be provided, either by
- * line number, line number and column number, or byte offset from the
- * beginning of the resource.
- */
-class sg_location
-{
-public:
- sg_location ();
- sg_location (const string &path, int line = -1, int column = -1);
- virtual ~sg_location ();
- virtual const string &getPath () const;
- virtual void setPath (const string &path);
- virtual int getLine () const;
- virtual void setLine (int line);
- virtual int getColumn () const;
- virtual void setColumn (int column);
- virtual int getByte () const;
- virtual void setByte (int byte);
- virtual string asString () const;
-private:
- string _path;
- int _line;
- int _column;
- int _byte;
-};
-
-
-/**
- * Abstract base class for all throwables.
- */
-class sg_throwable
-{
-public:
- sg_throwable ();
- sg_throwable (const string &message, const string &origin = "");
- virtual ~sg_throwable ();
- virtual const string &getMessage () const;
- virtual const string getFormattedMessage () const;
- virtual void setMessage (const string &message);
- virtual const string &getOrigin () const;
- virtual void setOrigin (const string &origin);
-private:
- string _message;
- string _origin;
-};
-
-
-
-/**
- * An unexpected fatal error.
- *
- * Methods and functions show throw this exception when something
- * very bad has happened (such as memory corruption or
- * a totally unexpected internal value). Applications should catch
- * this exception only at the top level if at all, and should
- * normally terminate execution soon afterwards.
- */
-class sg_error : public sg_throwable
-{
-public:
- sg_error ();
- sg_error (const string &message, const string &origin = "");
- virtual ~sg_error ();
-};
-
-
-/**
- * Base class for all SimGear exceptions.
- *
- * SimGear-based code should throw this exception only when no
- * more specific exception applies. It may not be caught until
- * higher up in the application, where it is not possible to
- * resume normal operations if desired.
- *
- * A caller can catch sg_exception by default to ensure that
- * all exceptions are caught. Every SimGear exception can contain
- * a human-readable error message and a human-readable string
- * indicating the part of the application causing the exception
- * (as an aid to debugging, only).
- */
-class sg_exception : public sg_throwable
-{
-public:
- sg_exception ();
- sg_exception (const string &message, const string &origin = "");
- virtual ~sg_exception ();
-};
-
-
-/**
- * An I/O-related SimGear exception.
- *
- * SimGear-based code should throw this exception when it fails
- * to read from or write to an external resource, such as a file,
- * socket, URL, or database.
- *
- * In addition to the functionality of sg_exception, an
- * sg_io_exception may contain location information, such as the name
- * of a file or URL, and possible also a location in that file or URL.
- */
-class sg_io_exception : public sg_exception
-{
-public:
- sg_io_exception ();
- sg_io_exception (const string &message, const string &origin = "");
- sg_io_exception (const string &message, const sg_location &location,
- const string &origin = "");
- virtual ~sg_io_exception ();
- virtual const string getFormattedMessage () const;
- virtual const sg_location &getLocation () const;
- virtual void setLocation (const sg_location &location);
-private:
- sg_location _location;
-};
-
-
-/**
- * A format-related SimGear exception.
- *
- * SimGear-based code should throw this exception when a string
- * does not appear in the expected format (for example, a date
- * string does not conform to ISO 8601).
- *
- * In addition to the functionality of sg_exception, an
- * sg_format_exception can contain a copy of the original malformated
- * text.
- */
-class sg_format_exception : public sg_exception
-{
-public:
- sg_format_exception ();
- sg_format_exception (const string &message, const string &text,
- const string &origin = "");
- virtual ~sg_format_exception ();
- virtual const string &getText () const;
- virtual void setText (const string &text);
-private:
- string _text;
-};
-
-
-/**
- * A range-related SimGear exception.
- *
- * SimGear-based code should throw this exception when a value falls
- * outside the range where it can reasonably be handled; examples
- * include longitude outside the range -180:180, unrealistically high
- * forces or velocities, an illegal airport code, etc. A range
- * exception usually means that something has gone wrong internally.
- */
-class sg_range_exception : public sg_exception
-{
-public:
- sg_range_exception ();
- sg_range_exception (const string &message, const string &origin = "");
- virtual ~sg_range_exception ();
-};
-
-#endif
-
-// end of exception.hxx
// #include STL_IOSTREAM
-#include <simgear/misc/exception.hxx>
+#include <simgear/structure/exception.hxx>
#include "props.hxx"
-
#include "condition.hxx"
SG_USING_STD(istream);
#include <simgear/compiler.h>
#include <simgear/constants.h>
-#include <simgear/misc/exception.hxx>
+#include <simgear/structure/exception.hxx>
#include <string.h>
#include STL_STRING
#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);
--- /dev/null
+.deps
+Makefile
+Makefile.in
--- /dev/null
+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)
+
--- /dev/null
+/**************************************************************************
+ * 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
+
--- /dev/null
+// commands.cxx - encapsulated commands.
+// Started Spring 2001 by David Megginson, david@megginson.com
+// This code is released into the Public Domain.
+//
+// $Id$
+
+#include <simgear/props/props_io.hxx>
+
+#include "commands.hxx"
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// Implementation of SGCommandMgr class.
+////////////////////////////////////////////////////////////////////////
+
+
+SGCommandMgr::SGCommandMgr ()
+{
+ // no-op
+}
+
+SGCommandMgr::~SGCommandMgr ()
+{
+ // no-op
+}
+
+void
+SGCommandMgr::addCommand (const string &name, command_t command)
+{
+ _commands[name] = command;
+}
+
+SGCommandMgr::command_t
+SGCommandMgr::getCommand (const string &name) const
+{
+ const command_map::const_iterator it = _commands.find(name);
+ return (it != _commands.end() ? it->second : 0);
+}
+
+vector<string>
+SGCommandMgr::getCommandNames () const
+{
+ vector<string> names;
+ command_map::const_iterator it = _commands.begin();
+ command_map::const_iterator last = _commands.end();
+ while (it != last) {
+ names.push_back(it->first);
+ it++;
+ }
+ return names;
+}
+
+bool
+SGCommandMgr::execute (const string &name, const SGPropertyNode * arg) const
+{
+ command_t command = getCommand(name);
+ if (command == 0)
+ return false;
+ else
+ return (*command)(arg);
+}
+
+// end of commands.cxx
--- /dev/null
+/**
+ * \file commands.hxx
+ * Interface definition for encapsulated commands.
+ * Started Spring 2001 by David Megginson, david@megginson.com
+ * This code is released into the Public Domain.
+ *
+ * $Id$
+ */
+
+#ifndef __COMMANDS_HXX
+#define __COMMANDS_HXX
+
+
+#include <simgear/compiler.h>
+
+#include STL_STRING
+#include <map>
+#include <vector>
+
+#include <simgear/props/props.hxx>
+
+SG_USING_STD(string);
+SG_USING_STD(map);
+SG_USING_STD(vector);
+
+
+/**
+ * Manage commands.
+ *
+ * <p>This class allows the application to register and unregister
+ * commands, and provides shortcuts for executing them. Commands are
+ * simple functions that take a const pointer to an SGPropertyNode:
+ * the function may use the nodes children as parameters.</p>
+ *
+ * @author David Megginson, david@megginson.com
+ */
+class SGCommandMgr
+{
+public:
+
+ /**
+ * Type for a command function.
+ */
+ typedef bool (*command_t) (const SGPropertyNode * arg);
+
+
+ /**
+ * Default constructor.
+ */
+ SGCommandMgr ();
+
+
+ /**
+ * Destructor.
+ */
+ virtual ~SGCommandMgr ();
+
+
+ /**
+ * Register a new command with the manager.
+ *
+ * @param name The command name. Any existing command with
+ * the same name will silently be overwritten.
+ * @param command A pointer to a one-arg function returning
+ * a bool result. The argument is always a const pointer to
+ * an SGPropertyNode (which may contain multiple values).
+ */
+ virtual void addCommand (const string &name, command_t command);
+
+
+ /**
+ * Look up an existing command.
+ *
+ * @param name The command name.
+ * @return A pointer to the command, or 0 if there is no registered
+ * command with the name specified.
+ */
+ virtual command_t getCommand (const string &name) const;
+
+
+ /**
+ * Get a list of all existing command names.
+ *
+ * @return A (possibly empty) vector of the names of all registered
+ * commands.
+ */
+ virtual vector<string> getCommandNames () const;
+
+
+ /**
+ * Execute a command.
+ *
+ * @param name The name of the command.
+ * @param arg A const pointer to an SGPropertyNode. The node
+ * may have a value and/or children, etc., so that it is possible
+ * to pass an arbitrarily complex data structure to a command.
+ * @return true if the command is present and executes successfully,
+ * false otherwise.
+ */
+ virtual bool execute (const string &name, const SGPropertyNode * arg) const;
+
+private:
+
+ typedef map<string,command_t> command_map;
+ command_map _commands;
+
+};
+
+#endif // __COMMANDS_HXX
+
+// end of commands.hxx
--- /dev/null
+//
+// 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, "" );
+}
--- /dev/null
+// 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
--- /dev/null
+// exception.cxx - implementation of SimGear base exceptions.
+// Started Summer 2001 by David Megginson, david@megginson.com
+// This code is released into the Public Domain.
+//
+// $Id$
+
+
+#include "exception.hxx"
+#include <stdio.h>
+
+\f
+////////////////////////////////////////////////////////////////////////
+// Implementation of sg_location class.
+////////////////////////////////////////////////////////////////////////
+
+sg_location::sg_location ()
+ : _path(""),
+ _line(-1),
+ _column(-1),
+ _byte(-1)
+{
+}
+
+sg_location::sg_location (const string &path, int line, int column)
+ : _path(path),
+ _line(line),
+ _column(column),
+ _byte(-1)
+{
+}
+
+sg_location::~sg_location ()
+{
+}
+
+const string &
+sg_location::getPath () const
+{
+ return _path;
+}
+
+void
+sg_location::setPath (const string &path)
+{
+ _path = path;
+}
+
+int
+sg_location::getLine () const
+{
+ return _line;
+}
+
+void
+sg_location::setLine (int line)
+{
+ _line = line;
+}
+
+int
+sg_location::getColumn () const
+{
+ return _column;
+}
+
+void
+sg_location::setColumn (int column)
+{
+ _column = column;
+}
+
+int
+sg_location::getByte () const
+{
+ return _byte;
+}
+
+void
+sg_location::setByte (int byte)
+{
+ _byte = byte;
+}
+
+string
+sg_location::asString () const
+{
+ char buf[128];
+ string out = "";
+ if (_path != (string)"") {
+ out += _path;
+ if (_line != -1 || _column != -1)
+ out += ",\n";
+ }
+ if (_line != -1) {
+ sprintf(buf, "line %d", _line);
+ out += buf;
+ if (_column != -1)
+ out += ", ";
+ }
+ if (_column != -1) {
+ sprintf(buf, "column %d", _column);
+ out += buf;
+ }
+ return out;
+
+}
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// Implementation of sg_throwable class.
+////////////////////////////////////////////////////////////////////////
+
+sg_throwable::sg_throwable ()
+ : _message(""),
+ _origin("")
+{
+}
+
+sg_throwable::sg_throwable (const string &message, const string &origin)
+ : _message(message),
+ _origin(origin)
+{
+}
+
+sg_throwable::~sg_throwable ()
+{
+}
+
+const string &
+sg_throwable::getMessage () const
+{
+ return _message;
+}
+
+const string
+sg_throwable::getFormattedMessage () const
+{
+ return getMessage();
+}
+
+void
+sg_throwable::setMessage (const string &message)
+{
+ _message = message;
+}
+
+const string &
+sg_throwable::getOrigin () const
+{
+ return _origin;
+}
+
+void
+sg_throwable::setOrigin (const string &origin)
+{
+ _origin = origin;
+}
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// Implementation of sg_error class.
+////////////////////////////////////////////////////////////////////////
+
+sg_error::sg_error ()
+ : sg_throwable ()
+{
+}
+
+sg_error::sg_error (const string &message, const string &origin)
+ : sg_throwable(message, origin)
+{
+}
+
+sg_error::~sg_error ()
+{
+}
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// Implementation of sg_exception class.
+////////////////////////////////////////////////////////////////////////
+
+sg_exception::sg_exception ()
+ : sg_throwable ()
+{
+}
+
+sg_exception::sg_exception (const string &message, const string &origin)
+ : sg_throwable(message, origin)
+{
+}
+
+sg_exception::~sg_exception ()
+{
+}
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// Implementation of sg_io_exception.
+////////////////////////////////////////////////////////////////////////
+
+sg_io_exception::sg_io_exception ()
+ : sg_exception()
+{
+}
+
+sg_io_exception::sg_io_exception (const string &message, const string &origin)
+ : sg_exception(message, origin)
+{
+}
+
+sg_io_exception::sg_io_exception (const string &message,
+ const sg_location &location,
+ const string &origin)
+ : sg_exception(message, origin),
+ _location(location)
+{
+}
+
+sg_io_exception::~sg_io_exception ()
+{
+}
+
+const string
+sg_io_exception::getFormattedMessage () const
+{
+ string ret = getMessage();
+ ret += "\n at ";
+ ret += getLocation().asString();
+ return ret;
+}
+
+const sg_location &
+sg_io_exception::getLocation () const
+{
+ return _location;
+}
+
+void
+sg_io_exception::setLocation (const sg_location &location)
+{
+ _location = location;
+}
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// Implementation of sg_format_exception.
+////////////////////////////////////////////////////////////////////////
+
+sg_format_exception::sg_format_exception ()
+ : sg_exception(),
+ _text("")
+{
+}
+
+sg_format_exception::sg_format_exception (const string &message,
+ const string &text,
+ const string &origin)
+ : sg_exception(message, origin),
+ _text(text)
+{
+}
+
+sg_format_exception::~sg_format_exception ()
+{
+}
+
+const string &
+sg_format_exception::getText () const
+{
+ return _text;
+}
+
+void
+sg_format_exception::setText (const string &text)
+{
+ _text = text;
+}
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// Implementation of sg_range_exception.
+////////////////////////////////////////////////////////////////////////
+
+sg_range_exception::sg_range_exception ()
+ : sg_exception()
+{
+}
+
+sg_range_exception::sg_range_exception (const string &message,
+ const string &origin)
+ : sg_exception(message, origin)
+{
+}
+
+sg_range_exception::~sg_range_exception ()
+{
+}
+
+
+// end of exception.cxx
--- /dev/null
+/**
+ * \file exception.hxx
+ * Interface definition for SimGear base exceptions.
+ * Started Spring 2001 by David Megginson, david@megginson.com
+ * This code is released into the Public Domain.
+ *
+ * $Id$
+ */
+
+#ifndef __SIMGEAR_MISC_EXCEPTION_HXX
+#define __SIMGEAR_MISC_EXCEPTION_HXX 1
+
+#include <simgear/compiler.h>
+#include STL_STRING
+
+SG_USING_STD(string);
+
+
+/**
+ * Information encapsulating a single location in an external resource
+ *
+ * A position in the resource my optionally be provided, either by
+ * line number, line number and column number, or byte offset from the
+ * beginning of the resource.
+ */
+class sg_location
+{
+public:
+ sg_location ();
+ sg_location (const string &path, int line = -1, int column = -1);
+ virtual ~sg_location ();
+ virtual const string &getPath () const;
+ virtual void setPath (const string &path);
+ virtual int getLine () const;
+ virtual void setLine (int line);
+ virtual int getColumn () const;
+ virtual void setColumn (int column);
+ virtual int getByte () const;
+ virtual void setByte (int byte);
+ virtual string asString () const;
+private:
+ string _path;
+ int _line;
+ int _column;
+ int _byte;
+};
+
+
+/**
+ * Abstract base class for all throwables.
+ */
+class sg_throwable
+{
+public:
+ sg_throwable ();
+ sg_throwable (const string &message, const string &origin = "");
+ virtual ~sg_throwable ();
+ virtual const string &getMessage () const;
+ virtual const string getFormattedMessage () const;
+ virtual void setMessage (const string &message);
+ virtual const string &getOrigin () const;
+ virtual void setOrigin (const string &origin);
+private:
+ string _message;
+ string _origin;
+};
+
+
+
+/**
+ * An unexpected fatal error.
+ *
+ * Methods and functions show throw this exception when something
+ * very bad has happened (such as memory corruption or
+ * a totally unexpected internal value). Applications should catch
+ * this exception only at the top level if at all, and should
+ * normally terminate execution soon afterwards.
+ */
+class sg_error : public sg_throwable
+{
+public:
+ sg_error ();
+ sg_error (const string &message, const string &origin = "");
+ virtual ~sg_error ();
+};
+
+
+/**
+ * Base class for all SimGear exceptions.
+ *
+ * SimGear-based code should throw this exception only when no
+ * more specific exception applies. It may not be caught until
+ * higher up in the application, where it is not possible to
+ * resume normal operations if desired.
+ *
+ * A caller can catch sg_exception by default to ensure that
+ * all exceptions are caught. Every SimGear exception can contain
+ * a human-readable error message and a human-readable string
+ * indicating the part of the application causing the exception
+ * (as an aid to debugging, only).
+ */
+class sg_exception : public sg_throwable
+{
+public:
+ sg_exception ();
+ sg_exception (const string &message, const string &origin = "");
+ virtual ~sg_exception ();
+};
+
+
+/**
+ * An I/O-related SimGear exception.
+ *
+ * SimGear-based code should throw this exception when it fails
+ * to read from or write to an external resource, such as a file,
+ * socket, URL, or database.
+ *
+ * In addition to the functionality of sg_exception, an
+ * sg_io_exception may contain location information, such as the name
+ * of a file or URL, and possible also a location in that file or URL.
+ */
+class sg_io_exception : public sg_exception
+{
+public:
+ sg_io_exception ();
+ sg_io_exception (const string &message, const string &origin = "");
+ sg_io_exception (const string &message, const sg_location &location,
+ const string &origin = "");
+ virtual ~sg_io_exception ();
+ virtual const string getFormattedMessage () const;
+ virtual const sg_location &getLocation () const;
+ virtual void setLocation (const sg_location &location);
+private:
+ sg_location _location;
+};
+
+
+/**
+ * A format-related SimGear exception.
+ *
+ * SimGear-based code should throw this exception when a string
+ * does not appear in the expected format (for example, a date
+ * string does not conform to ISO 8601).
+ *
+ * In addition to the functionality of sg_exception, an
+ * sg_format_exception can contain a copy of the original malformated
+ * text.
+ */
+class sg_format_exception : public sg_exception
+{
+public:
+ sg_format_exception ();
+ sg_format_exception (const string &message, const string &text,
+ const string &origin = "");
+ virtual ~sg_format_exception ();
+ virtual const string &getText () const;
+ virtual void setText (const string &text);
+private:
+ string _text;
+};
+
+
+/**
+ * A range-related SimGear exception.
+ *
+ * SimGear-based code should throw this exception when a value falls
+ * outside the range where it can reasonably be handled; examples
+ * include longitude outside the range -180:180, unrealistically high
+ * forces or velocities, an illegal airport code, etc. A range
+ * exception usually means that something has gone wrong internally.
+ */
+class sg_range_exception : public sg_exception
+{
+public:
+ sg_range_exception ();
+ sg_range_exception (const string &message, const string &origin = "");
+ virtual ~sg_range_exception ();
+};
+
+#endif
+
+// end of exception.hxx
--- /dev/null
+
+#include <simgear/debug/logstream.hxx>
+
+#include "exception.hxx"
+#include "subsystem_mgr.hxx"
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// 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;
+}
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// 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;
+ }
+}
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// 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;
+ }
+ }
+}
+
+
+\f
+////////////////////////////////////////////////////////////////////////
+// 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
--- /dev/null
+// 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>
+
+
+\f
+/**
+ * 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;
+
+};
+
+
+\f
+/**
+ * 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;
+};
+
+
+\f
+/**
+ * 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
+
#define __EASYXML_HXX
#include <simgear/compiler.h>
-
-#include <simgear/misc/exception.hxx>
+#include <simgear/structure/exception.hxx>
#include STL_IOSTREAM
#include STL_STRING