From: <mk...@us...> - 2003-09-03 03:09:07
|
Update of /cvsroot/csp/APPLICATIONS/CSPSim/Source In directory sc8-pr-cvs1:/tmp/cvs-serv7663 Modified Files: Bus.cpp Log Message: Index: Bus.cpp =================================================================== RCS file: /cvsroot/csp/APPLICATIONS/CSPSim/Source/Bus.cpp,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** Bus.cpp 2 Sep 2003 20:39:25 -0000 1.1 --- Bus.cpp 3 Sep 2003 03:09:04 -0000 1.2 *************** *** 1,3 **** ! #include <SimData/Ref.h> #include <SimData/Key.h> #include <map> --- 1,28 ---- ! // Combat Simulator Project - FlightSim Demo ! // Copyright (C) 2003 The Combat Simulator Project ! // http://csp.sourceforge.net ! // ! // 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ! ! ! /** ! * @file Bus.cpp ! * ! **/ ! ! ! #include <SimData/Object.h> #include <SimData/Key.h> #include <map> *************** *** 14,21 **** direct comments to the csp developer's forum. ! The code compiles with gcc-3.3 under Linux, but has not been ! tested at all under Windows. To build an executable you will ! need to install libsigc++ (Google: libsigc++). The following ! command works for me but may need tweaking on other systems: g++-3.3 -I/usr/include/python2.2 --- 39,47 ---- direct comments to the csp developer's forum. ! The code builds with gcc-3.2 and gcc-3.3 under Linux, but has ! not been tested at all under Windows. To build an executable ! you will need to install libsigc++ (Google: libsigc++). The ! following command works for me but may need tweaking on other ! systems: g++-3.3 -I/usr/include/python2.2 *************** *** 24,32 **** -L/usr/lib/python2.2/site-packages/SimData -g -O2 ! bus.cpp -lSimData -lsigc -lpthread */ class Bus; --- 50,60 ---- -L/usr/lib/python2.2/site-packages/SimData -g -O2 ! Bus.cpp ! -o BusTest -lSimData -lsigc -lpthread */ class Bus; + class Model; *************** *** 42,48 **** * by other systems over the bus. */ ! class System: public simdata::Referenced, public SigC::Object { friend class Bus; protected: /** Register channels for access to internal data by other * systems on the bus. --- 70,115 ---- * by other systems over the bus. */ ! class System: public simdata::Object, public SigC::Object { friend class Bus; + friend class Model; + protected: + + typedef SigC::Signal1<void,double> UpdateSignal; + + private: + + Model* m_Model; + std::string m_Name; + + struct TimedUpdate: public simdata::Referenced { + UpdateSignal _signal; + double _interval; + double _lapse; + void update(double dt) { + _lapse += dt; + if (_lapse > _interval) { + _signal.emit(_lapse); + _lapse = 0.0; + } + } + TimedUpdate(double interval): _interval(interval), _lapse(0.0) {} + }; + + struct TimedUpdater { + double dt; + TimedUpdater(double dt_): dt(dt_) {} + void operator()(simdata::Ref<TimedUpdate> &tu) { tu->update(dt); } + }; + + std::vector< simdata::Ref<TimedUpdate> > m_TimedUpdates; + + protected: + UpdateSignal &addTimedUpdate(double interval) { + simdata::Ref<TimedUpdate> tu = new TimedUpdate(interval); + m_TimedUpdates.push_back(tu); + return tu->_signal; + } + /** Register channels for access to internal data by other * systems on the bus. *************** *** 51,55 **** * if the system may be attached to more than one bus. */ ! virtual void registerChannels(Bus *bus) {} /** Bind to channels provided by other systems on the bus. --- 118,122 ---- * if the system may be attached to more than one bus. */ ! virtual void registerChannels() {} /** Bind to channels provided by other systems on the bus. *************** *** 60,73 **** * system member variables for later use. */ ! virtual void bind(Bus *bus) {} ! public: ! /** System reference (convenience) type. ! */ ! typedef simdata::Ref< System > Ref; /** Destructor. */ virtual ~System() {} }; --- 127,159 ---- * system member variables for later use. */ ! virtual void bind() {} ! inline void setModel(Model *model); ! ! // XXX use raw pointers here to prevent circular references ! // that keep the model alive. the model pointer is only ! // for internal use by the system instance, which will be ! // destroyed when the model goes out of scope. ! inline Model* getModel() const; /** Destructor. */ virtual ~System() {} + public: + + System(std::string const &name): m_Name(name) {} + + std::string const &getName() const { return m_Name; } + + virtual void onUpdate(double dt) { + std::for_each(m_TimedUpdates.begin(), + m_TimedUpdates.end(), + TimedUpdater(dt)); + } + + /** System reference (convenience) type. + */ + typedef simdata::Ref<System> Ref; + }; *************** *** 316,328 **** class Bus: public simdata::Referenced { - /// Key to system map type - typedef std::map<simdata::Key, System::Ref> SystemMap; - /// Key to channl map type typedef std::map<simdata::Key, ChannelBase::Ref> ChannelMap; - /// Map of all systems connected to the bus - SystemMap m_Systems; - /// Map of all channels connected to the bus ChannelMap m_Channels; --- 402,408 ---- *************** *** 344,368 **** typedef simdata::Ref<Bus> Ref; - /** Attach a system to this bus. - * - * Any number of systems may be attached to the bus prior - * to calling bind(). Systems are identified internally by - * a hash key generated from their name. These keys must be - * unique and an assertion will be raised if a system with - * the same hash key has already been added to the bus. - * - * This method calls the system's registerChannels() method. - * - * @param system The system to attach. - * @param name The string identifier of the system. - */ - void attachSystem(System::Ref system, std::string const &name) { - assert(!m_Bound); - assert(!hasSystem(name)); - simdata::Key key(name); - m_Systems[key] = system; - system->registerChannels(this); - } - /** Test if a particular data channel is available. */ --- 424,427 ---- *************** *** 371,380 **** } - /** Test if a particular system is connected. - */ - bool hasSystem(std::string const &name) { - return getSystem(name).valid(); - } - /** Register a new channel. * --- 430,433 ---- *************** *** 391,419 **** } - /** Bind all connected systems to data channels on the bus. - * - * Bus construction is a two step process. First systems are - * added using attachSystem(). This method in turn calls each - * system's registerChannels method to declare all the channels - * that the system exports. Once all systems are attached, - * bindSystems() calls each system's bind() method to allow it to - * obtain references to data channels provided by other systems. - * This is only done once, and subsequent calls to bindSystems() - * have no effect. - * - * It is currently an (assertion) error to call attachSystem() - * after bindSystems() has been called. If the need arises - * to provide greater flexibility for dynamically attaching - * systems to the bus, this requirement can be relaxed. - */ - void bindSystems() { - if (m_Bound) return; - for (SystemMap::iterator iter = m_Systems.begin(); - iter != m_Systems.end(); ++iter) { - iter->second->bind(this); - } - m_Bound = true; - } - /** Get the name of this bus. */ --- 444,447 ---- *************** *** 460,475 **** } - /** Get a system by name. - * - * @returns A reference to the system or a null reference if the - * system is not connected to the bus. - */ - System::Ref getSystem(std::string const &name) { - simdata::Key key(name); - SystemMap::iterator iter = m_Systems.find(key); - if (iter == m_Systems.end()) return 0; - return iter->second; - } - /** Get the bus status value. */ --- 488,491 ---- *************** *** 515,518 **** --- 531,612 ---- + class Model: public simdata::Object { + + typedef std::map<std::string, Bus::Ref> BusMap; + + typedef std::map<std::string, System::Ref> SystemMap; + + BusMap m_Buses; + + SystemMap m_Systems; + + protected: + + Bus* addBus(std::string const &name) { + assert(m_Buses.find(name) == m_Buses.end()); + Bus *bus = new Bus(name); + m_Buses[name] = bus; + return bus; + } + + System* addSystem(System *system) { + assert(system); + std::string name = system->getName(); + assert(m_Systems.find(name) == m_Systems.end()); + m_Systems[system->getName()] = system; + system->setModel(this); + system->registerChannels(); + return system; + } + + void bindSystems() { + for (SystemMap::iterator iter = m_Systems.begin(); + iter != m_Systems.end(); ++iter) { + iter->second->bind(); + } + } + + virtual ~Model() { + } + + public: + + Bus::Ref getBus(std::string const &name, bool required = true) const { + BusMap::const_iterator iter = m_Buses.find(name); + if (iter == m_Buses.end()) { + assert(!required); + return 0; + } + return iter->second; + } + + System::Ref getSystem(std::string const &name, bool required = true) const { + SystemMap::const_iterator iter = m_Systems.find(name); + if (iter == m_Systems.end()) { + assert(!required); + return 0; + } + return iter->second; + } + + Model(): simdata::Object() {} + + virtual void onUpdate(double dt) { + SystemMap::iterator iter = m_Systems.begin(); + for (; iter != m_Systems.end(); ++iter) { + iter->second->onUpdate(dt); + } + } + + }; + + + void System::setModel(Model *model) { + assert(m_Model == 0); + m_Model = model; + } + + Model* System::getModel() const { return m_Model; } + *************** *** 526,530 **** struct MFD: public System { ! void registerChannels(Bus *bus); Channel<int>::Ref m_MasterMode; Channel<int>::Ref m_Submode; --- 620,625 ---- struct MFD: public System { ! MFD(std::string const &name = "MFD"): System(name) {} ! void registerChannels(); Channel<int>::Ref m_MasterMode; Channel<int>::Ref m_Submode; *************** *** 532,546 **** }; ! void MFD::registerChannels(Bus *bus) { ! if (bus->getName()=="A") { ! m_MasterMode = bus->registerChannel(new Channel<int>("MasterMode", 0)); ! m_Submode = bus->registerChannel(new Channel<int>("Submode", 1)); ! m_Submode->connect(this, &MFD::getSubMode, false); ! } m_MasterMode->set(1); } struct FCS: public System { ! void bind(Bus *bus); void onMasterMode(); Channel<int>::CRef m_MasterMode; --- 627,641 ---- }; ! void MFD::registerChannels() { ! Bus::Ref bus = getModel()->getBus("A"); ! m_MasterMode = bus->registerChannel(new Channel<int>("MasterMode", 0)); ! m_Submode = bus->registerChannel(new Channel<int>("Submode", 1)); ! m_Submode->connect(this, &MFD::getSubMode, false); m_MasterMode->set(1); } struct FCS: public System { ! FCS(std::string const &name = "FCS"): System(name) {} ! void bind(); void onMasterMode(); Channel<int>::CRef m_MasterMode; *************** *** 548,559 **** }; ! void FCS::bind(Bus *bus) { ! if (bus->getName()=="A") { ! m_MasterMode = bus->getChannel("MasterMode"); ! m_MasterMode->connect(this, &FCS::onMasterMode); ! m_Submode = bus->getChannel("Submode"); ! std::cout << m_Submode->get() << " is the answer?\n"; ! ! } } --- 643,653 ---- }; ! void FCS::bind() { ! Bus::Ref bus = getModel()->getBus("A"); ! assert(bus.valid()); ! m_MasterMode = bus->getChannel("MasterMode"); ! m_MasterMode->connect(this, &FCS::onMasterMode); ! m_Submode = bus->getChannel("Submode"); ! std::cout << m_Submode->get() << " is the answer?\n"; } *************** *** 571,603 **** } ! void AvionicsSuite() { ! std::cout << "avionics suite\n"; ! Bus::Ref busA = new Bus("A"); ! System::Ref m_FCS = new FCS(); ! System::Ref m_MFD = new MFD(); ! busA->attachSystem(m_FCS, "FCS"); ! busA->attachSystem(m_MFD, "MFD"); ! busA->bindSystems(); ! Channel<int>::Ref mm = busA->getSharedChannel("MasterMode"); ! Channel<int>::Ref sm = busA->getSharedChannel("Submode"); ! std::cout << sizeof(*mm) << " bytes\n"; ! simdata::SimTime t0, t1; ! t0 = simdata::SimDate::getSystemTime(); ! for (int i = 0; i < 1000000; i++) { ! mm->set(i); } ! t1 = simdata::SimDate::getSystemTime(); ! std::cout << (t1-t0) << " us\n"; ! t0 = simdata::SimDate::getSystemTime(); ! for (int i = 0; i < 1000000; i++) { ! sm->set(i); } - t1 = simdata::SimDate::getSystemTime(); - std::cout << (t1-t0) << " us\n"; }; int main() { ! AvionicsSuite(); return 0; } ! --- 665,710 ---- } ! struct Avionics: public Model { ! void init() { ! addBus("A"); ! addSystem(new MFD("MFD")); ! addSystem(new FCS("FCS")); ! bindSystems(); } ! ! void test() { ! std::cout << "avionics suite\n"; ! System::Ref m_FCS = getSystem("FCS"); ! System::Ref m_MFD = getSystem("MFD"); ! Bus::Ref busA = getBus("A"); ! Channel<int>::Ref mm = busA->getSharedChannel("MasterMode"); ! Channel<int>::Ref sm = busA->getSharedChannel("Submode"); ! std::cout << sizeof(*mm) << " bytes\n"; ! simdata::SimTime t0, t1; ! t0 = simdata::SimDate::getSystemTime(); ! for (int i = 0; i < 1000000; i++) { ! mm->set(i); ! } ! t1 = simdata::SimDate::getSystemTime(); ! std::cout << (t1-t0) << " us\n"; ! t0 = simdata::SimDate::getSystemTime(); ! for (int i = 0; i < 1000000; i++) { ! sm->set(i); ! } ! t1 = simdata::SimDate::getSystemTime(); ! std::cout << (t1-t0) << " us\n"; ! } ! ! ~Avionics() { ! std::cout << "~Avionics\n"; } }; + /* int main() { ! Avionics a; ! a.init(); ! a.test(); return 0; } ! */ |