From: Mathias Froehlich Date: Sun, 26 Feb 2012 11:04:12 +0000 (+0100) Subject: hla: Rework toplevel HLA classes. X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=92f7445bb90442832005f4ffd6273e590ac9e059;p=simgear.git hla: Rework toplevel HLA classes. Better seperation between the rti and the hla level of classes. Decouple object model setup from the need to connect at a federate. Fix alignment computations for the standard hla data types. Work towards an interaction class abstraction. Add more flexibility in deriving from the base classes and adding callbacks. --- diff --git a/simgear/hla/CMakeLists.txt b/simgear/hla/CMakeLists.txt index b575c4ce..cd91a81e 100644 --- a/simgear/hla/CMakeLists.txt +++ b/simgear/hla/CMakeLists.txt @@ -40,6 +40,7 @@ set(HLA_SOURCES HLAEnumeratedDataElement.cxx HLAEnumeratedDataType.cxx HLAFederate.cxx + HLAInteractionClass.cxx HLAFixedRecordDataElement.cxx HLAFixedRecordDataType.cxx HLAObjectClass.cxx @@ -54,6 +55,7 @@ simgear_component(hla hla "${HLA_SOURCES}" "${HLA_HEADERS}") if(RTI_FOUND) set(RTI13_SOURCES + RTI13InteractionClass.cxx RTI13ObjectClass.cxx RTI13ObjectInstance.cxx RTI13Federate.cxx @@ -64,6 +66,7 @@ if(RTI_FOUND) endif() set(RTI_SOURCES + RTIInteractionClass.cxx RTIObjectClass.cxx RTIObjectInstance.cxx RTIFederate.cxx diff --git a/simgear/hla/HLAArrayDataType.cxx b/simgear/hla/HLAArrayDataType.cxx index f52da283..8f6435b6 100644 --- a/simgear/hla/HLAArrayDataType.cxx +++ b/simgear/hla/HLAArrayDataType.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2009 - 2011 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public @@ -44,12 +44,16 @@ HLAArrayDataType::toArrayDataType() const return this; } +void +HLAArrayDataType::releaseDataTypeReferences() +{ + _elementDataType = 0; + HLADataType::releaseDataTypeReferences(); +} + void HLAArrayDataType::setElementDataType(const HLADataType* elementDataType) { - // FIXME this only works if we do not reset the alignment to something smaller - if (getAlignment() < elementDataType->getAlignment()) - setAlignment(elementDataType->getAlignment()); _elementDataType = elementDataType; } @@ -65,6 +69,15 @@ HLAArrayDataType::setIsString(bool isString) _isString = isString; } +void +HLAArrayDataType::_recomputeAlignmentImplementation() +{ + unsigned alignment = 1; + if (const HLADataType* dataType = getElementDataType()) + alignment = std::max(alignment, dataType->getAlignment()); + setAlignment(alignment); +} + /////////////////////////////////////////////////////////////////////////////////// HLAFixedArrayDataType::HLAFixedArrayDataType(const std::string& name) : @@ -160,13 +173,20 @@ HLAVariableArrayDataType::encode(HLAEncodeStream& stream, const HLAAbstractArray } void -HLAVariableArrayDataType::setSizeDataType(const HLADataType* sizeDataType) +HLAVariableArrayDataType::setSizeDataType(const HLABasicDataType* sizeDataType) { - // FIXME this only works if we do not reset the alignment to something smaller - if (getAlignment() < sizeDataType->getAlignment()) - setAlignment(sizeDataType->getAlignment()); _sizeDataType = sizeDataType; - // setAlignment(SGMisc::max(_sizeDataType->getAlignment(), _elementDataType->getAlignment()); +} + +void +HLAVariableArrayDataType::_recomputeAlignmentImplementation() +{ + unsigned alignment = 1; + if (const HLADataType* dataType = getElementDataType()) + alignment = std::max(alignment, dataType->getAlignment()); + if (const HLADataType* dataType = getSizeDataType()) + alignment = std::max(alignment, dataType->getAlignment()); + setAlignment(alignment); } } // namespace simgear diff --git a/simgear/hla/HLAArrayDataType.hxx b/simgear/hla/HLAArrayDataType.hxx index a38f05bc..87be3851 100644 --- a/simgear/hla/HLAArrayDataType.hxx +++ b/simgear/hla/HLAArrayDataType.hxx @@ -1,4 +1,4 @@ -// Copyright (C) 2009 - 2011 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public @@ -35,6 +35,8 @@ public: virtual const HLAArrayDataType* toArrayDataType() const; + virtual void releaseDataTypeReferences(); + virtual bool decode(HLADecodeStream& stream, HLAAbstractArrayDataElement& value) const = 0; virtual bool encode(HLAEncodeStream& stream, const HLAAbstractArrayDataElement& value) const = 0; @@ -50,6 +52,9 @@ public: bool getIsString() const { return _isString; } +protected: + virtual void _recomputeAlignmentImplementation(); + private: SGSharedPtr _elementDataType; bool _isOpaque; @@ -85,12 +90,15 @@ public: virtual bool decode(HLADecodeStream& stream, HLAAbstractArrayDataElement& value) const; virtual bool encode(HLAEncodeStream& stream, const HLAAbstractArrayDataElement& value) const; - void setSizeDataType(const HLADataType* sizeDataType); - const HLADataType* getSizeDataType() const + void setSizeDataType(const HLABasicDataType* sizeDataType); + const HLABasicDataType* getSizeDataType() const { return _sizeDataType.get(); } +protected: + virtual void _recomputeAlignmentImplementation(); + private: - SGSharedPtr _sizeDataType; + SGSharedPtr _sizeDataType; }; } // namespace simgear diff --git a/simgear/hla/HLABasicDataType.cxx b/simgear/hla/HLABasicDataType.cxx index 106e8158..63b8b872 100644 --- a/simgear/hla/HLABasicDataType.cxx +++ b/simgear/hla/HLABasicDataType.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public diff --git a/simgear/hla/HLABasicDataType.hxx b/simgear/hla/HLABasicDataType.hxx index 60f1ba7d..2f298122 100644 --- a/simgear/hla/HLABasicDataType.hxx +++ b/simgear/hla/HLABasicDataType.hxx @@ -1,4 +1,4 @@ -// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public diff --git a/simgear/hla/HLADataType.cxx b/simgear/hla/HLADataType.cxx index 73198534..3addcb83 100644 --- a/simgear/hla/HLADataType.cxx +++ b/simgear/hla/HLADataType.cxx @@ -39,12 +39,6 @@ HLADataType::accept(HLADataTypeVisitor& visitor) const visitor.apply(*this); } -const HLADataTypeReference* -HLADataType::toDataTypeReference() const -{ - return 0; -} - const HLABasicDataType* HLADataType::toBasicDataType() const { @@ -75,6 +69,19 @@ HLADataType::toVariantRecordDataType() const return 0; } +bool +HLADataType::recomputeAlignment() +{ + unsigned alignment = getAlignment(); + _recomputeAlignmentImplementation(); + return alignment != getAlignment(); +} + +void +HLADataType::releaseDataTypeReferences() +{ +} + void HLADataType::setAlignment(unsigned alignment) { @@ -85,20 +92,9 @@ HLADataType::setAlignment(unsigned alignment) _alignment = alignment; } -HLADataTypeReference::~HLADataTypeReference() -{ -} - void -HLADataTypeReference::accept(HLADataTypeVisitor& visitor) const -{ - visitor.apply(*this); -} - -const HLADataTypeReference* -HLADataTypeReference::toDataTypeReference() const +HLADataType::_recomputeAlignmentImplementation() { - return this; } } diff --git a/simgear/hla/HLADataType.hxx b/simgear/hla/HLADataType.hxx index c792edd2..e728fa8c 100644 --- a/simgear/hla/HLADataType.hxx +++ b/simgear/hla/HLADataType.hxx @@ -1,4 +1,4 @@ -// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public @@ -27,7 +27,6 @@ namespace simgear { class HLADataTypeVisitor; -class HLADataTypeReference; class HLABasicDataType; class HLAArrayDataType; class HLAEnumeratedDataType; @@ -51,7 +50,6 @@ public: virtual void accept(HLADataTypeVisitor& visitor) const; - virtual const HLADataTypeReference* toDataTypeReference() const; virtual const HLABasicDataType* toBasicDataType() const; virtual const HLAArrayDataType* toArrayDataType() const; virtual const HLAEnumeratedDataType* toEnumeratedDataType() const; @@ -60,35 +58,25 @@ public: const HLAVariantRecordDataType* toVariantDataType() const { return toVariantRecordDataType(); } virtual const HLAVariantRecordDataType* toVariantRecordDataType() const; + /// Recompute the alignment value of this data type. + /// Return true if the alignment changed, false otherwise. + bool recomputeAlignment(); + /// Release references to other data types. Since we can have cycles this is + /// required for propper feeing of memory. + virtual void releaseDataTypeReferences(); + protected: HLADataType(const std::string& name, unsigned alignment = 1); void setAlignment(unsigned alignment); + virtual void _recomputeAlignmentImplementation(); + private: std::string _name; std::string _semantics; unsigned _alignment; }; -// Weak reference to a data type. Used to implement self referencing data types -class HLADataTypeReference : public HLADataType { -public: - HLADataTypeReference(const SGSharedPtr& dataType) : - HLADataType(dataType->getName(), dataType->getAlignment()), - _dataType(dataType) - { } - virtual ~HLADataTypeReference(); - - SGSharedPtr getDataType() const - { return _dataType.lock(); } - - virtual void accept(HLADataTypeVisitor& visitor) const; - virtual const HLADataTypeReference* toDataTypeReference() const; - -private: - SGWeakPtr _dataType; -}; - } // namespace simgear #endif diff --git a/simgear/hla/HLADataTypeVisitor.hxx b/simgear/hla/HLADataTypeVisitor.hxx index 824b22a3..a73488af 100644 --- a/simgear/hla/HLADataTypeVisitor.hxx +++ b/simgear/hla/HLADataTypeVisitor.hxx @@ -38,16 +38,6 @@ public: virtual void apply(const HLADataType& dataType) { } - virtual void apply(const HLADataTypeReference& dataType) - { - SGSharedPtr dataTypeReference = dataType.getDataType(); - if (!dataTypeReference.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "HLADataTypeReference weak reference vanished!"); - return; - } - dataTypeReference->accept(*this); - } - virtual void apply(const HLABasicDataType& dataType) { apply(static_cast(dataType)); } virtual void apply(const HLAInt8DataType& dataType) diff --git a/simgear/hla/HLAEnumeratedDataType.cxx b/simgear/hla/HLAEnumeratedDataType.cxx index 56fd34dd..d7cc2a9f 100644 --- a/simgear/hla/HLAEnumeratedDataType.cxx +++ b/simgear/hla/HLAEnumeratedDataType.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public @@ -176,5 +176,14 @@ HLAEnumeratedDataType::setRepresentation(HLABasicDataType* representation) _map.swap(representationVisitor._map); } +void +HLAEnumeratedDataType::_recomputeAlignmentImplementation() +{ + unsigned alignment = 1; + if (const HLADataType* dataType = getRepresentation()) + alignment = std::max(alignment, dataType->getAlignment()); + setAlignment(alignment); +} + } // namespace simgear diff --git a/simgear/hla/HLAEnumeratedDataType.hxx b/simgear/hla/HLAEnumeratedDataType.hxx index 7066adba..973b2c5a 100644 --- a/simgear/hla/HLAEnumeratedDataType.hxx +++ b/simgear/hla/HLAEnumeratedDataType.hxx @@ -1,4 +1,4 @@ -// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public @@ -70,6 +70,9 @@ public: return _map->getDataType(); } +protected: + virtual void _recomputeAlignmentImplementation(); + private: class AbstractMap : public SGReferenced { public: diff --git a/simgear/hla/HLAFederate.cxx b/simgear/hla/HLAFederate.cxx index 4a9d93d4..141cbc8e 100644 --- a/simgear/hla/HLAFederate.cxx +++ b/simgear/hla/HLAFederate.cxx @@ -17,6 +17,8 @@ #include "HLAFederate.hxx" +#include + #include "simgear/debug/logstream.hxx" #include "RTIFederate.hxx" @@ -44,6 +46,13 @@ HLAFederate::HLAFederate() : HLAFederate::~HLAFederate() { + _clearRTI(); + + // Remove the data type references from the data types. + // This is to remove the cycles from the data types that might happen if a data type references itself + for (DataTypeMap::iterator i = _dataTypeMap.begin(); i != _dataTypeMap.end(); ++i) { + i->second->releaseDataTypeReferences(); + } } HLAFederate::Version @@ -206,7 +215,8 @@ HLAFederate::disconnect() SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!"); return false; } - _rtiFederate = 0; + + _clearRTI(); return true; } @@ -739,11 +749,6 @@ bool HLAFederate::readObjectModelTemplate(const std::string& objectModel, HLAFederate::ObjectModelFactory& objectModelFactory) { - if (!_rtiFederate.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!"); - return false; - } - // The XML version of the federate object model. // This one covers the generic attributes, parameters and data types. HLAOMTXmlVisitor omtXmlVisitor; @@ -758,6 +763,8 @@ HLAFederate::readObjectModelTemplate(const std::string& objectModel, return false; } + omtXmlVisitor.setDataTypesToFederate(*this); + unsigned numObjectClasses = omtXmlVisitor.getNumObjectClasses(); for (unsigned i = 0; i < numObjectClasses; ++i) { const HLAOMTXmlVisitor::ObjectClass* objectClass = omtXmlVisitor.getObjectClass(i); @@ -772,54 +779,41 @@ HLAFederate::readObjectModelTemplate(const std::string& objectModel, bool publish = objectModelFactory.publishObjectClass(objectClassName, objectClass->getSharing()); bool subscribe = objectModelFactory.subscribeObjectClass(objectClassName, objectClass->getSharing()); - std::set subscriptions; - std::set publications; - // process the attributes for (unsigned j = 0; j < objectClass->getNumAttributes(); ++j) { const simgear::HLAOMTXmlVisitor::Attribute* attribute; attribute = objectClass->getAttribute(j); std::string attributeName = attribute->getName(); - unsigned index = hlaObjectClass->getAttributeIndex(attributeName); + unsigned index = hlaObjectClass->addAttribute(attributeName); if (index == ~0u) { SG_LOG(SG_IO, SG_WARN, "RTI does not know the \"" << attributeName << "\" attribute!"); continue; } - SGSharedPtr dataType; - dataType = omtXmlVisitor.getAttributeDataType(objectClassName, attributeName); + // the attributes datatype + SGSharedPtr dataType = getDataType(attribute->getDataType()); if (!dataType.valid()) { SG_LOG(SG_IO, SG_WARN, "Could not find data type for attribute \"" << attributeName << "\" in object class \"" << objectClassName << "\"!"); } hlaObjectClass->setAttributeDataType(index, dataType); - - HLAUpdateType updateType = HLAUndefinedUpdate; - if (attribute->_updateType == "Periodic") - updateType = HLAPeriodicUpdate; - else if (attribute->_updateType == "Static") - updateType = HLAStaticUpdate; - else if (attribute->_updateType == "Conditional") - updateType = HLAConditionalUpdate; - hlaObjectClass->setAttributeUpdateType(index, updateType); - + hlaObjectClass->setAttributeUpdateType(index, attribute->getUpdateType()); if (subscribe && objectModelFactory.subscribeAttribute(objectClassName, attributeName, attribute->_sharing)) - subscriptions.insert(index); + hlaObjectClass->setAttributeSubscriptionType(index, attribute->getSubscriptionType()); if (publish && objectModelFactory.publishAttribute(objectClassName, attributeName, attribute->_sharing)) - publications.insert(index); + hlaObjectClass->setAttributePublicationType(index, attribute->getPublicationType()); } if (publish) - hlaObjectClass->publish(publications); + hlaObjectClass->publish(); if (subscribe) - hlaObjectClass->subscribe(subscriptions, true); + hlaObjectClass->subscribe(); - _objectClassMap[objectClassName] = hlaObjectClass; } - return true; + return resolveObjectModel(); } bool @@ -832,8 +826,23 @@ HLAFederate::readRTI13ObjectModelTemplate(const std::string& objectModel) bool HLAFederate::readRTI1516ObjectModelTemplate(const std::string& objectModel) { - ObjectModelFactory objectModelFactory; - return readObjectModelTemplate(objectModel, objectModelFactory); + // The XML version of the federate object model. + // This one covers the generic attributes, parameters and data types. + HLAOMTXmlVisitor omtXmlVisitor; + try { + readXML(objectModel, omtXmlVisitor); + } catch (const sg_throwable& e) { + SG_LOG(SG_IO, SG_ALERT, "Could not open HLA XML object model file: " + << e.getMessage()); + return false; + } catch (...) { + SG_LOG(SG_IO, SG_ALERT, "Could not open HLA XML object model file"); + return false; + } + + omtXmlVisitor.setToFederate(*this); + + return resolveObjectModel(); } bool @@ -843,6 +852,98 @@ HLAFederate::readRTI1516EObjectModelTemplate(const std::string& objectModel) return false; } +bool +HLAFederate::resolveObjectModel() +{ + if (!_rtiFederate.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "HLA: Accessing unconnected federate!"); + return false; + } + + for (InteractionClassMap::iterator i = _interactionClassMap.begin(); i != _interactionClassMap.end(); ++i) { + RTIInteractionClass* rtiInteractionClass = _rtiFederate->createInteractionClass(i->second->getName(), i->second.get()); + if (!rtiInteractionClass) { + SG_LOG(SG_NETWORK, SG_ALERT, "HLAFederate::_insertInteractionClass(): " + "No RTIInteractionClass found for \"" << i->second->getName() << "\"!"); + return false; + } + i->second->_setRTIInteractionClass(rtiInteractionClass); + } + + for (ObjectClassMap::iterator i = _objectClassMap.begin(); i != _objectClassMap.end(); ++i) { + RTIObjectClass* rtiObjectClass = _rtiFederate->createObjectClass(i->second->getName(), i->second.get()); + if (!rtiObjectClass) { + SG_LOG(SG_NETWORK, SG_ALERT, "HLAFederate::_insertObjectClass(): " + "No RTIObjectClass found for \"" << i->second->getName() << "\"!"); + return false; + } + i->second->_setRTIObjectClass(rtiObjectClass); + } + + return true; +} + +const HLADataType* +HLAFederate::getDataType(const std::string& name) const +{ + DataTypeMap::const_iterator i = _dataTypeMap.find(name); + if (i == _dataTypeMap.end()) + return 0; + return i->second.get(); +} + +bool +HLAFederate::insertDataType(const std::string& name, const SGSharedPtr& dataType) +{ + if (!dataType.valid()) + return false; + if (_dataTypeMap.find(name) != _dataTypeMap.end()) { + SG_LOG(SG_IO, SG_ALERT, "HLAFederate::insertDataType: data type with name \"" + << name << "\" already known to federate!"); + return false; + } + _dataTypeMap.insert(DataTypeMap::value_type(name, dataType)); + return true; +} + +void +HLAFederate::recomputeDataTypeAlignment() +{ + // Finish alignment computations + bool changed; + do { + changed = false; + for (DataTypeMap::iterator i = _dataTypeMap.begin(); i != _dataTypeMap.end(); ++i) { + if (i->second->recomputeAlignment()) + changed = true; + } + } while (changed); +} + +HLAInteractionClass* +HLAFederate::getInteractionClass(const std::string& name) +{ + InteractionClassMap::const_iterator i = _interactionClassMap.find(name); + if (i == _interactionClassMap.end()) + return 0; + return i->second.get(); +} + +const HLAInteractionClass* +HLAFederate::getInteractionClass(const std::string& name) const +{ + InteractionClassMap::const_iterator i = _interactionClassMap.find(name); + if (i == _interactionClassMap.end()) + return 0; + return i->second.get(); +} + +HLAInteractionClass* +HLAFederate::createInteractionClass(const std::string& name) +{ + return new HLAInteractionClass(name, this); +} + HLAObjectClass* HLAFederate::getObjectClass(const std::string& name) { @@ -864,27 +965,33 @@ HLAFederate::getObjectClass(const std::string& name) const HLAObjectClass* HLAFederate::createObjectClass(const std::string& name) { - return new HLAObjectClass(name, *this); + return new HLAObjectClass(name, this); } -HLAInteractionClass* -HLAFederate::getInteractionClass(const std::string& name) +HLAObjectInstance* +HLAFederate::getObjectInstance(const std::string& name) { - InteractionClassMap::const_iterator i = _interactionClassMap.find(name); - if (i == _interactionClassMap.end()) + ObjectInstanceMap::const_iterator i = _objectInstanceMap.find(name); + if (i == _objectInstanceMap.end()) return 0; return i->second.get(); } -const HLAInteractionClass* -HLAFederate::getInteractionClass(const std::string& name) const +const HLAObjectInstance* +HLAFederate::getObjectInstance(const std::string& name) const { - InteractionClassMap::const_iterator i = _interactionClassMap.find(name); - if (i == _interactionClassMap.end()) + ObjectInstanceMap::const_iterator i = _objectInstanceMap.find(name); + if (i == _objectInstanceMap.end()) return 0; return i->second.get(); } +HLAObjectInstance* +HLAFederate::createObjectInstance(HLAObjectClass* objectClass, const std::string& name) +{ + return new HLAObjectInstance(objectClass); +} + void HLAFederate::setDone(bool done) { @@ -900,30 +1007,62 @@ HLAFederate::getDone() const bool HLAFederate::readObjectModel() { - /// Currently empty, but is called at the right time so that - /// the object model is present when it is needed - // switch (getVersion()) { - // case RTI13: - // return readRTI13ObjectModelTemplate(getFederationObjectModel()); - // case RTI1516: - // return readRTI1516ObjectModelTemplate(getFederationObjectModel()); - // case RTI1516E: - // return readRTI1516EObjectModelTemplate(getFederationObjectModel()); - // } - return true; + // Depending on the actual version, try to find an apropriate + // file format for the given file. The first one is always the + // version native object model file format. + switch (getVersion()) { + case RTI13: + if (readRTI13ObjectModelTemplate(getFederationObjectModel())) + return true; + if (readRTI1516ObjectModelTemplate(getFederationObjectModel())) + return true; + return readRTI1516EObjectModelTemplate(getFederationObjectModel()); + case RTI1516: + if (readRTI1516ObjectModelTemplate(getFederationObjectModel())) + return true; + if (readRTI1516EObjectModelTemplate(getFederationObjectModel())) + return true; + return readRTI13ObjectModelTemplate(getFederationObjectModel()); + case RTI1516E: + if (readRTI1516EObjectModelTemplate(getFederationObjectModel())) + return true; + if (readRTI1516ObjectModelTemplate(getFederationObjectModel())) + return true; + return readRTI13ObjectModelTemplate(getFederationObjectModel()); + default: + return false; + } } bool HLAFederate::subscribe() { - /// Currently empty, but is called at the right time + for (InteractionClassMap::iterator i = _interactionClassMap.begin(); i != _interactionClassMap.end(); ++i) { + if (!i->second->subscribe()) + return false; + } + + for (ObjectClassMap::iterator i = _objectClassMap.begin(); i != _objectClassMap.end(); ++i) { + if (!i->second->subscribe()) + return false; + } + return true; } bool HLAFederate::publish() { - /// Currently empty, but is called at the right time + for (InteractionClassMap::iterator i = _interactionClassMap.begin(); i != _interactionClassMap.end(); ++i) { + if (!i->second->publish()) + return false; + } + + for (ObjectClassMap::iterator i = _objectClassMap.begin(); i != _objectClassMap.end(); ++i) { + if (!i->second->publish()) + return false; + } + return true; } @@ -1035,4 +1174,75 @@ HLAFederate::exec() return true; } +void +HLAFederate::_clearRTI() +{ + for (InteractionClassMap::iterator i = _interactionClassMap.begin(); i != _interactionClassMap.end(); ++i) + i->second->_clearRTIInteractionClass(); + for (ObjectInstanceMap::iterator i = _objectInstanceMap.begin(); i != _objectInstanceMap.end(); ++i) + i->second->_clearRTIObjectInstance(); + for (ObjectClassMap::iterator i = _objectClassMap.begin(); i != _objectClassMap.end(); ++i) + i->second->_clearRTIObjectClass(); + + _rtiFederate = 0; +} + +bool +HLAFederate::_insertInteractionClass(const SGSharedPtr& interactionClass) +{ + if (!interactionClass.valid()) + return false; + if (_interactionClassMap.find(interactionClass->getName()) != _interactionClassMap.end()) { + SG_LOG(SG_IO, SG_ALERT, "HLA: _insertInteractionClass: object instance with name \"" + << interactionClass->getName() << "\" already known to federate!"); + return false; + } + _interactionClassMap.insert(InteractionClassMap::value_type(interactionClass->getName(), interactionClass)); + return true; +} + +bool +HLAFederate::_insertObjectClass(const SGSharedPtr& objectClass) +{ + if (!objectClass.valid()) + return false; + if (_objectClassMap.find(objectClass->getName()) != _objectClassMap.end()) { + SG_LOG(SG_IO, SG_ALERT, "HLA: _insertObjectClass: object instance with name \"" + << objectClass->getName() << "\" already known to federate!"); + return false; + } + _objectClassMap.insert(ObjectClassMap::value_type(objectClass->getName(), objectClass)); + return true; +} + +bool +HLAFederate::_insertObjectInstance(const SGSharedPtr& objectInstance) +{ + if (!objectInstance.valid()) + return false; + if (objectInstance->getName().empty()) { + SG_LOG(SG_IO, SG_ALERT, "HLA: _insertObjectInstance: trying to insert object instance with empty name!"); + return false; + } + if (_objectInstanceMap.find(objectInstance->getName()) != _objectInstanceMap.end()) { + SG_LOG(SG_IO, SG_WARN, "HLA: _insertObjectInstance: object instance with name \"" + << objectInstance->getName() << "\" already known to federate!"); + return false; + } + _objectInstanceMap.insert(ObjectInstanceMap::value_type(objectInstance->getName(), objectInstance)); + return true; +} + +void +HLAFederate::_eraseObjectInstance(const std::string& name) +{ + ObjectInstanceMap::iterator i = _objectInstanceMap.find(name); + if (i == _objectInstanceMap.end()) { + SG_LOG(SG_IO, SG_WARN, "HLA: _eraseObjectInstance: object instance with name \"" + << name << "\" not known to federate!"); + return; + } + _objectInstanceMap.erase(i); +} + } // namespace simgear diff --git a/simgear/hla/HLAFederate.hxx b/simgear/hla/HLAFederate.hxx index 2326a385..eb0c8424 100644 --- a/simgear/hla/HLAFederate.hxx +++ b/simgear/hla/HLAFederate.hxx @@ -193,20 +193,45 @@ public: /// Read an rti1516e omt xml file bool readRTI1516EObjectModelTemplate(const std::string& objectModel); + /// Is called past a successful join to populate the rti classes + bool resolveObjectModel(); + + /// Access data types + const HLADataType* getDataType(const std::string& name) const; + // virtual const HLADataType* createDataType(const std::string& name); + bool insertDataType(const std::string& name, const SGSharedPtr& dataType); + void recomputeDataTypeAlignment(); + + /// Get the interaction class of a given name + HLAInteractionClass* getInteractionClass(const std::string& name); + const HLAInteractionClass* getInteractionClass(const std::string& name) const; + /// Default create function. Creates a default interaction class + virtual HLAInteractionClass* createInteractionClass(const std::string& name); + /// Get the object class of a given name HLAObjectClass* getObjectClass(const std::string& name); const HLAObjectClass* getObjectClass(const std::string& name) const; /// Default create function. Creates a default object class virtual HLAObjectClass* createObjectClass(const std::string& name); - /// Get the interaction class of a given name - HLAInteractionClass* getInteractionClass(const std::string& name); - const HLAInteractionClass* getInteractionClass(const std::string& name) const; + /// Get the object instance of a given name + HLAObjectInstance* getObjectInstance(const std::string& name); + const HLAObjectInstance* getObjectInstance(const std::string& name) const; + virtual HLAObjectInstance* createObjectInstance(HLAObjectClass* objectClass, const std::string& name); /// Tells the main exec loop to continue or not. void setDone(bool done); bool getDone() const; + /// The user overridable slot that is called to set up an object model + /// By default, depending on the set up rti version, the apropriate + /// bool read{RTI13,RTI1516,RTI1516E}ObjectModelTemplate(const std::string& objectModel); + /// method is called. + /// Note that the RTI13 files do not contain any information about the data types. + /// A user needs to set up the data types and assign them to the object classes/ + /// interaction classes theirselves. + /// Past reading the object model, it is still possible to change the subscription/publication + /// types without introducing traffic on the backend rti. virtual bool readObjectModel(); virtual bool subscribe(); @@ -222,6 +247,16 @@ private: HLAFederate(const HLAFederate&); HLAFederate& operator=(const HLAFederate&); + void _clearRTI(); + + /// Internal helpers for interaction classes + bool _insertInteractionClass(const SGSharedPtr& interactionClass); + /// Internal helpers for object classes + bool _insertObjectClass(const SGSharedPtr& objectClass); + /// Internal helpers for object instances + bool _insertObjectInstance(const SGSharedPtr& objectInstance); + void _eraseObjectInstance(const std::string& name); + /// The underlying interface to the rti implementation SGSharedPtr _rtiFederate; @@ -256,14 +291,27 @@ private: /// If true the exec method returns. bool _done; - typedef std::map > ObjectClassMap; - ObjectClassMap _objectClassMap; + /// The Data Types by name + typedef std::map > DataTypeMap; + DataTypeMap _dataTypeMap; + /// The Interaction Classes by name typedef std::map > InteractionClassMap; InteractionClassMap _interactionClassMap; + /// The Object Classes by name + typedef std::map > ObjectClassMap; + ObjectClassMap _objectClassMap; + + /// The Object Instances by name + typedef std::map > ObjectInstanceMap; + ObjectInstanceMap _objectInstanceMap; + /// The Object Instances by name, the ones that have an explicit given name, may be not yet registered + // ObjectInstanceMap _explicitNamedObjectInstanceMap; + friend class HLAInteractionClass; friend class HLAObjectClass; + friend class HLAObjectInstance; }; } // namespace simgear diff --git a/simgear/hla/HLAFixedRecordDataType.cxx b/simgear/hla/HLAFixedRecordDataType.cxx index acec73a1..92e36e26 100644 --- a/simgear/hla/HLAFixedRecordDataType.cxx +++ b/simgear/hla/HLAFixedRecordDataType.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public @@ -43,6 +43,14 @@ HLAFixedRecordDataType::toFixedRecordDataType() const return this; } +void +HLAFixedRecordDataType::releaseDataTypeReferences() +{ + unsigned numFields = getNumFields(); + for (unsigned i = 0; i < numFields; ++i) + _fieldList[i].releaseDataTypeReferences(); +} + bool HLAFixedRecordDataType::decode(HLADecodeStream& stream, HLAAbstractFixedRecordDataElement& value) const { @@ -68,10 +76,18 @@ HLAFixedRecordDataType::encode(HLAEncodeStream& stream, const HLAAbstractFixedRe void HLAFixedRecordDataType::addField(const std::string& name, const HLADataType* dataType) { - // FIXME this only works if we do not reset the alignment to something smaller - if (getAlignment() < dataType->getAlignment()) - setAlignment(dataType->getAlignment()); _fieldList.push_back(Field(name, dataType)); } +void +HLAFixedRecordDataType::_recomputeAlignmentImplementation() +{ + unsigned alignment = 1; + for (unsigned i = 0; i < getNumFields(); ++i) { + if (const HLADataType* dataType = getFieldDataType(i)) + alignment = std::max(alignment, dataType->getAlignment()); + } + setAlignment(alignment); +} + } // namespace simgear diff --git a/simgear/hla/HLAFixedRecordDataType.hxx b/simgear/hla/HLAFixedRecordDataType.hxx index 17c32ac4..5858c792 100644 --- a/simgear/hla/HLAFixedRecordDataType.hxx +++ b/simgear/hla/HLAFixedRecordDataType.hxx @@ -1,4 +1,4 @@ -// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public @@ -36,6 +36,8 @@ public: virtual const HLAFixedRecordDataType* toFixedRecordDataType() const; + virtual void releaseDataTypeReferences(); + virtual bool decode(HLADecodeStream& stream, HLAAbstractFixedRecordDataElement& value) const; virtual bool encode(HLAEncodeStream& stream, const HLAAbstractFixedRecordDataElement& value) const; @@ -67,6 +69,9 @@ public: void addField(const std::string& name, const HLADataType* dataType); +protected: + virtual void _recomputeAlignmentImplementation(); + private: struct Field { Field(const std::string& name, const HLADataType* dataType) : @@ -76,6 +81,8 @@ private: const HLADataType* getDataType() const { return _dataType.get(); } + void releaseDataTypeReferences() + { _dataType = 0; } private: std::string _name; diff --git a/simgear/hla/HLAInteractionClass.cxx b/simgear/hla/HLAInteractionClass.cxx new file mode 100644 index 00000000..b56aec44 --- /dev/null +++ b/simgear/hla/HLAInteractionClass.cxx @@ -0,0 +1,239 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include "HLAInteractionClass.hxx" + +#include + +#include "HLADataElement.hxx" +#include "HLAFederate.hxx" + +#include "RTIInteractionClass.hxx" + +namespace simgear { + +HLAInteractionClass::HLAInteractionClass(const std::string& name, HLAFederate* federate) : + _federate(federate), + _rtiInteractionClass(0), + _name(name), + _subscriptionType(HLAUnsubscribed), + _publicationType(HLAUnpublished) +{ + if (!federate) { + SG_LOG(SG_NETWORK, SG_ALERT, "HLAInteractionClass::HLAInteractionClass(): " + "No parent federate given for interaction class \"" << getName() << "\"!"); + return; + } + federate->_insertInteractionClass(this); +} + +HLAInteractionClass::~HLAInteractionClass() +{ + // HLAInteractionClass objects only get deleted when the parent federate + // dies. So we do not need to deregister there. + + _clearRTIInteractionClass(); +} + +const std::string& +HLAInteractionClass::getName() const +{ + return _name; +} + +HLASubscriptionType +HLAInteractionClass::getSubscriptionType() const +{ + return _subscriptionType; +} + +void +HLAInteractionClass::setSubscriptionType(HLASubscriptionType subscriptionType) +{ + _subscriptionType = subscriptionType; +} + +HLAPublicationType +HLAInteractionClass::getPublicationType() const +{ + return _publicationType; +} + +void +HLAInteractionClass::setPublicationType(HLAPublicationType publicationType) +{ + _publicationType = publicationType; +} + +unsigned +HLAInteractionClass::getNumParameters() const +{ + return _parameterVector.size(); +} + +unsigned +HLAInteractionClass::addParameter(const std::string& name) +{ + unsigned index = _parameterVector.size(); + _nameIndexMap[name] = index; + _parameterVector.push_back(Parameter(name)); + _resolveParameterIndex(name, index); + return index; +} + +unsigned +HLAInteractionClass::getParameterIndex(const std::string& name) const +{ + NameIndexMap::const_iterator i = _nameIndexMap.find(name); + if (i == _nameIndexMap.end()) + return ~0u; + return i->second; +} + +std::string +HLAInteractionClass::getParameterName(unsigned index) const +{ + if (_parameterVector.size() <= index) + return std::string(); + return _parameterVector[index]._name; +} + +const HLADataType* +HLAInteractionClass::getParameterDataType(unsigned index) const +{ + if (_parameterVector.size() <= index) + return 0; + return _parameterVector[index]._dataType.get(); +} + +void +HLAInteractionClass::setParameterDataType(unsigned index, const SGSharedPtr& dataType) +{ + if (_parameterVector.size() <= index) + return; + _parameterVector[index]._dataType = dataType; +} + +HLADataElement::IndexPathPair +HLAInteractionClass::getIndexPathPair(const HLADataElement::StringPathPair& stringPathPair) const +{ + unsigned index = getParameterIndex(stringPathPair.first); + if (getNumParameters() <= index) { + SG_LOG(SG_NETWORK, SG_ALERT, "HLAInteractionClass::getIndexPathPair(\"" + << HLADataElement::toString(stringPathPair) + << "\"): Could not resolve attribute \"" << stringPathPair.first + << "\" for interaction class \"" << getName() << "\"!"); + } + return HLADataElement::IndexPathPair(index, stringPathPair.second); +} + +HLADataElement::IndexPathPair +HLAInteractionClass::getIndexPathPair(const std::string& path) const +{ + return getIndexPathPair(HLADataElement::toStringPathPair(path)); +} + +bool +HLAInteractionClass::subscribe() +{ + if (!_rtiInteractionClass) { + SG_LOG(SG_NETWORK, SG_WARN, "HLAInteractionClass::subscribe(): No RTIInteractionClass!"); + return false; + } + switch (_subscriptionType) { + case HLAUnsubscribed: + return _rtiInteractionClass->unsubscribe(); + case HLASubscribedActive: + return _rtiInteractionClass->subscribe(true); + case HLASubscribedPassive: + return _rtiInteractionClass->subscribe(false); + } + return false; +} + +bool +HLAInteractionClass::unsubscribe() +{ + if (!_rtiInteractionClass) { + SG_LOG(SG_NETWORK, SG_WARN, "HLAInteractionClass::unsubscribe(): No RTIInteractionClass!"); + return false; + } + return _rtiInteractionClass->unsubscribe(); +} + +bool +HLAInteractionClass::publish() +{ + if (!_rtiInteractionClass) { + SG_LOG(SG_NETWORK, SG_WARN, "HLAInteractionClass::publish(): No RTIInteractionClass\"!"); + return false; + } + switch (_publicationType) { + case HLAUnpublished: + return _rtiInteractionClass->unpublish(); + case HLAPublished: + return _rtiInteractionClass->publish(); + } + return false; +} + +bool +HLAInteractionClass::unpublish() +{ + if (!_rtiInteractionClass) { + SG_LOG(SG_NETWORK, SG_WARN, "HLAInteractionClass::unpublish(): No RTIInteractionClass\"!"); + return false; + } + return _rtiInteractionClass->unpublish(); +} + +void +HLAInteractionClass::_setRTIInteractionClass(RTIInteractionClass* interactionClass) +{ + if (_rtiInteractionClass) { + SG_LOG(SG_NETWORK, SG_ALERT, "HLAInteractionClass: Setting RTIInteractionClass twice for interaction class \"" << getName() << "\"!"); + return; + } + _rtiInteractionClass = interactionClass; + if (_rtiInteractionClass->_interactionClass != this) { + SG_LOG(SG_NETWORK, SG_ALERT, "HLAInteractionClass: backward reference does not match!"); + return; + } + for (unsigned i = 0; i < _parameterVector.size(); ++i) + _resolveParameterIndex(_parameterVector[i]._name, i); +} + +void +HLAInteractionClass::_resolveParameterIndex(const std::string& name, unsigned index) +{ + if (!_rtiInteractionClass) + return; + if (!_rtiInteractionClass->resolveParameterIndex(name, index)) + SG_LOG(SG_NETWORK, SG_ALERT, "HLAInteractionClass: Could not resolve parameter \"" + << name << "\" for interaction class \"" << getName() << "\"!"); +} + +void +HLAInteractionClass::_clearRTIInteractionClass() +{ + if (!_rtiInteractionClass) + return; + _rtiInteractionClass->_interactionClass = 0; + _rtiInteractionClass = 0; +} + +} // namespace simgear diff --git a/simgear/hla/HLAInteractionClass.hxx b/simgear/hla/HLAInteractionClass.hxx index 021dff7e..4e1d1531 100644 --- a/simgear/hla/HLAInteractionClass.hxx +++ b/simgear/hla/HLAInteractionClass.hxx @@ -1,4 +1,4 @@ -// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public @@ -18,17 +18,89 @@ #ifndef HLAInteractionClass_hxx #define HLAInteractionClass_hxx +#include +#include +#include + +#include + +#include "HLADataElement.hxx" +#include "HLADataType.hxx" +#include "HLATypes.hxx" + namespace simgear { class RTIInteractionClass; +class HLADataType; +class HLAFederate; class HLAInteractionClass : public SGWeakReferenced { public: - virtual ~HLAInteractionClass() {} + HLAInteractionClass(const std::string& name, HLAFederate* federate); + virtual ~HLAInteractionClass(); + + const std::string& getName() const; + + HLASubscriptionType getSubscriptionType() const; + void setSubscriptionType(HLASubscriptionType subscriptionType); + + HLAPublicationType getPublicationType() const; + void setPublicationType(HLAPublicationType publicationType); + + unsigned getNumParameters() const; + unsigned addParameter(const std::string& name); + + unsigned getParameterIndex(const std::string& name) const; + std::string getParameterName(unsigned index) const; + + const HLADataType* getParameterDataType(unsigned index) const; + void setParameterDataType(unsigned index, const SGSharedPtr& dataType); + + HLADataElement::IndexPathPair getIndexPathPair(const HLADataElement::StringPathPair& stringPathPair) const; + HLADataElement::IndexPathPair getIndexPathPair(const std::string& path) const; + + virtual bool subscribe(); + virtual bool unsubscribe(); + + virtual bool publish(); + virtual bool unpublish(); private: HLAInteractionClass(const HLAInteractionClass&); HLAInteractionClass& operator=(const HLAInteractionClass&); + + void _setRTIInteractionClass(RTIInteractionClass* interactionClass); + void _resolveParameterIndex(const std::string& name, unsigned index); + void _clearRTIInteractionClass(); + + struct Parameter { + Parameter() {} + Parameter(const std::string& name) : _name(name) {} + std::string _name; + SGSharedPtr _dataType; + }; + typedef std::vector ParameterVector; + typedef std::map NameIndexMap; + + /// The parent federate. + SGWeakPtr _federate; + + /// The rti class if already instantiated. + RTIInteractionClass* _rtiInteractionClass; + + /// The interaction class name + std::string _name; + + /// The configured subscription and publication type + HLASubscriptionType _subscriptionType; + HLAPublicationType _publicationType; + + /// The parameter data + ParameterVector _parameterVector; + /// The mapping from parameter names to parameter indices + NameIndexMap _nameIndexMap; + + friend class HLAFederate; }; } // namespace simgear diff --git a/simgear/hla/HLAOMTXmlVisitor.cxx b/simgear/hla/HLAOMTXmlVisitor.cxx index 89784b1c..3783cf72 100644 --- a/simgear/hla/HLAOMTXmlVisitor.cxx +++ b/simgear/hla/HLAOMTXmlVisitor.cxx @@ -27,6 +27,7 @@ #include "HLABasicDataType.hxx" #include "HLADataTypeVisitor.hxx" #include "HLAEnumeratedDataType.hxx" +#include "HLAFederate.hxx" #include "HLAFixedRecordDataType.hxx" #include "HLAVariantRecordDataType.hxx" @@ -68,18 +69,6 @@ HLAOMTXmlVisitor::ObjectClass::getAttribute(unsigned index) const return _attributes[index]; } -const HLAOMTXmlVisitor::Attribute* -HLAOMTXmlVisitor::ObjectClass::getAttribute(const std::string& name) const -{ - for (AttributeList::const_iterator i = _attributes.begin(); i != _attributes.end(); ++i) { - if ((*i)->_name != name) - continue; - return i->get(); - } - SG_LOG(SG_IO, SG_ALERT, "Could not find class attribute \"" << name << "\"."); - return 0; -} - const HLAOMTXmlVisitor::ObjectClass* HLAOMTXmlVisitor::ObjectClass::getParentObjectClass() const { @@ -107,6 +96,12 @@ HLAOMTXmlVisitor::InteractionClass::getDimensions() const return _dimensions; } +const std::string& +HLAOMTXmlVisitor::InteractionClass::getSharing() const +{ + return _sharing; +} + const std::string& HLAOMTXmlVisitor::InteractionClass::getTransportation() const { @@ -133,18 +128,6 @@ HLAOMTXmlVisitor::InteractionClass::getParameter(unsigned index) const return _parameters[index]; } -const HLAOMTXmlVisitor::Parameter* -HLAOMTXmlVisitor::InteractionClass::getParameter(const std::string& name) const -{ - for (ParameterList::const_iterator i = _parameters.begin(); i != _parameters.end(); ++i) { - if ((*i)->_name != name) - continue; - return i->get(); - } - SG_LOG(SG_IO, SG_ALERT, "Could not find parameter \"" << name << "\"."); - return 0; -} - const HLAOMTXmlVisitor::InteractionClass* HLAOMTXmlVisitor::InteractionClass::getParentInteractionClass() const { @@ -159,48 +142,93 @@ HLAOMTXmlVisitor::~HLAOMTXmlVisitor() { } -unsigned -HLAOMTXmlVisitor::getNumObjectClasses() const -{ - return _objectClassList.size(); +void +HLAOMTXmlVisitor::setDataTypesToFederate(HLAFederate& federate) +{ + // Provide all the data types + for (BasicDataMap::iterator i = _basicDataMap.begin(); i != _basicDataMap.end(); ++i) + federate.insertDataType(i->first, getDataType(i->first)); + for (SimpleDataMap::iterator i = _simpleDataMap.begin(); i != _simpleDataMap.end(); ++i) + federate.insertDataType(i->first, getDataType(i->first)); + for (EnumeratedDataMap::iterator i = _enumeratedDataMap.begin(); i != _enumeratedDataMap.end(); ++i) + federate.insertDataType(i->first, getDataType(i->first)); + for (ArrayDataMap::iterator i = _arrayDataMap.begin(); i != _arrayDataMap.end(); ++i) + federate.insertDataType(i->first, getDataType(i->first)); + for (FixedRecordDataMap::iterator i = _fixedRecordDataMap.begin(); i != _fixedRecordDataMap.end(); ++i) + federate.insertDataType(i->first, getDataType(i->first)); + for (VariantRecordDataMap::iterator i = _variantRecordDataMap.begin(); i != _variantRecordDataMap.end(); ++i) + federate.insertDataType(i->first, getDataType(i->first)); + + // Finish alignment computations + federate.recomputeDataTypeAlignment(); } -const HLAOMTXmlVisitor::ObjectClass* -HLAOMTXmlVisitor::getObjectClass(unsigned i) const +void +HLAOMTXmlVisitor::setToFederate(HLAFederate& federate) { - if (_objectClassList.size() <= i) - return 0; - return _objectClassList[i]; -} + setDataTypesToFederate(federate); -const HLAOMTXmlVisitor::ObjectClass* -HLAOMTXmlVisitor::getObjectClass(const std::string& name) const -{ - for (ObjectClassList::const_iterator i = _objectClassList.begin(); i != _objectClassList.end(); ++i) { - if ((*i)->_name != name) + // Provide all interaction classes + unsigned numInteractionClasses = getNumInteractionClasses(); + for (unsigned i = 0; i < numInteractionClasses; ++i) { + const InteractionClass* interactionClass = getInteractionClass(i); + + SGSharedPtr hlaInteractionClass; + hlaInteractionClass = federate.createInteractionClass(interactionClass->getName()); + if (!hlaInteractionClass.valid()) { + SG_LOG(SG_IO, SG_INFO, "Ignoring Interaction class \"" << interactionClass->getName() << "\"."); continue; - return i->get(); + } + + hlaInteractionClass->setSubscriptionType(interactionClass->getSubscriptionType()); + hlaInteractionClass->setPublicationType(interactionClass->getPublicationType()); + + // process the parameters + for (unsigned j = 0; j < interactionClass->getNumParameters(); ++j) { + const Parameter* parameter = interactionClass->getParameter(j); + unsigned index = hlaInteractionClass->addParameter(parameter->getName()); + hlaInteractionClass->setParameterDataType(index, federate.getDataType(parameter->getDataType())); + } + } + + // Provide all object classes + unsigned numObjectClasses = getNumObjectClasses(); + for (unsigned i = 0; i < numObjectClasses; ++i) { + const ObjectClass* objectClass = getObjectClass(i); + + SGSharedPtr hlaObjectClass; + hlaObjectClass = federate.createObjectClass(objectClass->getName()); + if (!hlaObjectClass.valid()) { + SG_LOG(SG_IO, SG_INFO, "Ignoring Object class \"" << objectClass->getName() << "\"."); + continue; + } + + // process the attributes + for (unsigned j = 0; j < objectClass->getNumAttributes(); ++j) { + const Attribute* attribute = objectClass->getAttribute(j); + + unsigned index = hlaObjectClass->addAttribute(attribute->getName()); + hlaObjectClass->setAttributeDataType(index, federate.getDataType(attribute->getDataType())); + + hlaObjectClass->setAttributeSubscriptionType(index, attribute->getSubscriptionType()); + hlaObjectClass->setAttributePublicationType(index, attribute->getPublicationType()); + hlaObjectClass->setAttributeUpdateType(index, attribute->getUpdateType()); + } } - SG_LOG(SG_IO, SG_ALERT, "Could not resolve ObjectClass \"" << name << "\"."); - return 0; } -const HLAOMTXmlVisitor::Attribute* -HLAOMTXmlVisitor::getAttribute(const std::string& objectClassName, const std::string& attributeName) const +unsigned +HLAOMTXmlVisitor::getNumObjectClasses() const { - const ObjectClass* objectClass = getObjectClass(objectClassName); - if (!objectClass) - return 0; - return objectClass->getAttribute(attributeName); + return _objectClassList.size(); } -HLADataType* -HLAOMTXmlVisitor::getAttributeDataType(const std::string& objectClassName, const std::string& attributeName) const +const HLAOMTXmlVisitor::ObjectClass* +HLAOMTXmlVisitor::getObjectClass(unsigned i) const { - const Attribute* attribute = getAttribute(objectClassName, attributeName); - if (!attribute) + if (_objectClassList.size() <= i) return 0; - return getDataType(attribute->_dataType); + return _objectClassList[i]; } unsigned @@ -217,59 +245,19 @@ HLAOMTXmlVisitor::getInteractionClass(unsigned i) const return _interactionClassList[i]; } -const HLAOMTXmlVisitor::InteractionClass* -HLAOMTXmlVisitor::getInteractionClass(const std::string& name) const -{ - for (InteractionClassList::const_iterator i = _interactionClassList.begin(); i != _interactionClassList.end(); ++i) { - if ((*i)->_name != name) - continue; - return i->get(); - } - SG_LOG(SG_IO, SG_ALERT, "Could not resolve InteractionClass \"" << name << "\"."); - return 0; -} - -const HLAOMTXmlVisitor::Parameter* -HLAOMTXmlVisitor::getParameter(const std::string& interactionClassName, const std::string& parameterName) const -{ - const InteractionClass* interactionClass = getInteractionClass(interactionClassName); - if (!interactionClass) - return 0; - return interactionClass->getParameter(parameterName); -} - -HLADataType* -HLAOMTXmlVisitor::getParameterDataType(const std::string& interactionClassName, const std::string& parameterName) const -{ - const Parameter* parameter = getParameter(interactionClassName, parameterName); - if (!parameter) - return 0; - return getDataType(parameter->_dataType); -} - -HLADataType* -HLAOMTXmlVisitor::getDataType(const std::string& dataTypeName) const -{ - SGSharedPtr dataType; - { - // Playing dirty things with reference counts - StringDataTypeMap dataTypeMap; - dataType = getDataType(dataTypeName, dataTypeMap); - } - return dataType.release(); -} - SGSharedPtr -HLAOMTXmlVisitor::getDataType(const std::string& dataTypeName, HLAOMTXmlVisitor::StringDataTypeMap& dataTypeMap) const +HLAOMTXmlVisitor::getDataType(const std::string& dataTypeName) { - StringDataTypeMap::const_iterator i = dataTypeMap.find(dataTypeName); - if (i != dataTypeMap.end()) - return new HLADataTypeReference(i->second); + StringDataTypeMap::const_iterator i = _dataTypeMap.find(dataTypeName); + if (i != _dataTypeMap.end()) + return i->second; SGSharedPtr dataType; dataType = getBasicDataType(dataTypeName); - if (dataType.valid()) + if (dataType.valid()) { + _dataTypeMap[dataTypeName] = dataType; return dataType; + } dataType = getSimpleDataType(dataTypeName); if (dataType.valid()) @@ -279,15 +267,15 @@ HLAOMTXmlVisitor::getDataType(const std::string& dataTypeName, HLAOMTXmlVisitor: if (dataType.valid()) return dataType; - dataType = getArrayDataType(dataTypeName, dataTypeMap); + dataType = getArrayDataType(dataTypeName); if (dataType.valid()) return dataType; - dataType = getFixedRecordDataType(dataTypeName, dataTypeMap); + dataType = getFixedRecordDataType(dataTypeName); if (dataType.valid()) return dataType; - dataType = getVariantRecordDataType(dataTypeName, dataTypeMap); + dataType = getVariantRecordDataType(dataTypeName); if (dataType.valid()) return dataType; @@ -296,7 +284,7 @@ HLAOMTXmlVisitor::getDataType(const std::string& dataTypeName, HLAOMTXmlVisitor: } SGSharedPtr -HLAOMTXmlVisitor::getBasicDataType(const std::string& dataTypeName) const +HLAOMTXmlVisitor::getBasicDataType(const std::string& dataTypeName) { BasicDataMap::const_iterator i = _basicDataMap.find(dataTypeName); if (i == _basicDataMap.end()) @@ -369,7 +357,7 @@ HLAOMTXmlVisitor::getBasicDataType(const std::string& dataTypeName) const } SGSharedPtr -HLAOMTXmlVisitor::getSimpleDataType(const std::string& dataTypeName) const +HLAOMTXmlVisitor::getSimpleDataType(const std::string& dataTypeName) { SimpleDataMap::const_iterator i = _simpleDataMap.find(dataTypeName); if (i == _simpleDataMap.end()) @@ -378,13 +366,14 @@ HLAOMTXmlVisitor::getSimpleDataType(const std::string& dataTypeName) const } SGSharedPtr -HLAOMTXmlVisitor::getEnumeratedDataType(const std::string& dataTypeName) const +HLAOMTXmlVisitor::getEnumeratedDataType(const std::string& dataTypeName) { EnumeratedDataMap::const_iterator i = _enumeratedDataMap.find(dataTypeName); if (i == _enumeratedDataMap.end()) return 0; SGSharedPtr enumeratedDataType = new HLAEnumeratedDataType(dataTypeName); + _dataTypeMap[dataTypeName] = enumeratedDataType; enumeratedDataType->setRepresentation(getBasicDataType(i->second._representation)); for (EnumeratorList::const_iterator j = i->second._enumeratorList.begin(); @@ -400,7 +389,7 @@ HLAOMTXmlVisitor::getEnumeratedDataType(const std::string& dataTypeName) const } SGSharedPtr -HLAOMTXmlVisitor::getArrayDataType(const std::string& dataTypeName, HLAOMTXmlVisitor::StringDataTypeMap& dataTypeMap) const +HLAOMTXmlVisitor::getArrayDataType(const std::string& dataTypeName) { ArrayDataMap::const_iterator i = _arrayDataMap.find(dataTypeName); if (i == _arrayDataMap.end()) @@ -428,13 +417,13 @@ HLAOMTXmlVisitor::getArrayDataType(const std::string& dataTypeName, HLAOMTXmlVis return 0; } - dataTypeMap[dataTypeName] = arrayDataType; - SGSharedPtr elementDataType = getDataType(i->second._dataType, dataTypeMap); + _dataTypeMap[dataTypeName] = arrayDataType; + SGSharedPtr elementDataType = getDataType(i->second._dataType); if (!elementDataType.valid()) { SG_LOG(SG_IO, SG_ALERT, "Could not interpret dataType \"" << i->second._dataType << "\" for array data type \"" << dataTypeName << "\"."); - dataTypeMap.erase(dataTypeName); + _dataTypeMap.erase(dataTypeName); return 0; } arrayDataType->setElementDataType(elementDataType.get()); @@ -452,20 +441,20 @@ HLAOMTXmlVisitor::getArrayDataType(const std::string& dataTypeName, HLAOMTXmlVis } SGSharedPtr -HLAOMTXmlVisitor::getFixedRecordDataType(const std::string& dataTypeName, HLAOMTXmlVisitor::StringDataTypeMap& dataTypeMap) const +HLAOMTXmlVisitor::getFixedRecordDataType(const std::string& dataTypeName) { FixedRecordDataMap::const_iterator i = _fixedRecordDataMap.find(dataTypeName); if (i == _fixedRecordDataMap.end()) return 0; SGSharedPtr dataType = new HLAFixedRecordDataType(dataTypeName); - dataTypeMap[dataTypeName] = dataType; + _dataTypeMap[dataTypeName] = dataType; for (FieldList::size_type j = 0; j < i->second._fieldList.size(); ++j) { - SGSharedPtr fieldDataType = getDataType(i->second._fieldList[j]._dataType, dataTypeMap); + SGSharedPtr fieldDataType = getDataType(i->second._fieldList[j]._dataType); if (!fieldDataType.valid()) { SG_LOG(SG_IO, SG_ALERT, "Could not get data type \"" << i->second._fieldList[j]._dataType << "\" for field " << j << "of fixed record data type \"" << dataTypeName << "\"."); - dataTypeMap.erase(dataTypeName); + _dataTypeMap.erase(dataTypeName); return 0; } dataType->addField(i->second._fieldList[j]._name, fieldDataType.get()); @@ -474,13 +463,13 @@ HLAOMTXmlVisitor::getFixedRecordDataType(const std::string& dataTypeName, HLAOMT } SGSharedPtr -HLAOMTXmlVisitor::getVariantRecordDataType(const std::string& dataTypeName, HLAOMTXmlVisitor::StringDataTypeMap& dataTypeMap) const +HLAOMTXmlVisitor::getVariantRecordDataType(const std::string& dataTypeName) { VariantRecordDataMap::const_iterator i = _variantRecordDataMap.find(dataTypeName); if (i == _variantRecordDataMap.end()) return 0; SGSharedPtr dataType = new HLAVariantRecordDataType(dataTypeName); - dataTypeMap[dataTypeName] = dataType; + _dataTypeMap[dataTypeName] = dataType; SGSharedPtr enumeratedDataType = getEnumeratedDataType(i->second._dataType); if (!enumeratedDataType.valid()) { @@ -492,11 +481,11 @@ HLAOMTXmlVisitor::getVariantRecordDataType(const std::string& dataTypeName, HLAO for (AlternativeList::const_iterator j = i->second._alternativeList.begin(); j != i->second._alternativeList.end(); ++j) { - SGSharedPtr alternativeDataType = getDataType(j->_dataType, dataTypeMap); + SGSharedPtr alternativeDataType = getDataType(j->_dataType); if (!alternativeDataType.valid()) { SG_LOG(SG_IO, SG_ALERT, "Could not resolve alternative dataType \"" << j->_dataType << "\" for alternative \"" << j->_name << "\"."); - dataTypeMap.erase(dataTypeName); + _dataTypeMap.erase(dataTypeName); return 0; } if (!dataType->addAlternative(j->_name, j->_enumerator, alternativeDataType.get(), j->_semantics)) { @@ -540,6 +529,7 @@ HLAOMTXmlVisitor::endXML() throw sg_exception("Internal parse error!"); // propagate parent attributes to the derived classes + // Note that this preserves the order og the attributes starting from the root object for (ObjectClassList::const_iterator i = _objectClassList.begin(); i != _objectClassList.end(); ++i) { SGSharedPtr objectClass = (*i)->_parentObjectClass; while (objectClass) { @@ -552,6 +542,7 @@ HLAOMTXmlVisitor::endXML() } // propagate parent parameter to the derived interactions + // Note that this preserves the order og the parameters starting from the root object for (InteractionClassList::const_iterator i = _interactionClassList.begin(); i != _interactionClassList.end(); ++i) { SGSharedPtr interactionClass = (*i)->_parentInteractionClass; while (interactionClass) { diff --git a/simgear/hla/HLAOMTXmlVisitor.hxx b/simgear/hla/HLAOMTXmlVisitor.hxx index ce52eb1a..7bf48156 100644 --- a/simgear/hla/HLAOMTXmlVisitor.hxx +++ b/simgear/hla/HLAOMTXmlVisitor.hxx @@ -25,9 +25,12 @@ #include #include #include "HLADataType.hxx" +#include "HLATypes.hxx" namespace simgear { +class HLAFederate; + class HLAOMTXmlVisitor : public XMLVisitor { public: /// structures representing the federate object model data @@ -37,6 +40,10 @@ public: { } const std::string& getName() const { return _name; } + const std::string& getDataType() const + { return _dataType; } + const std::string& getSharing() const + { return _sharing; } const std::string& getDimensions() const { return _dimensions; } const std::string& getTransportation() const @@ -44,6 +51,34 @@ public: const std::string& getOrder() const { return _order; } + HLASubscriptionType getSubscriptionType() const + { + if (_sharing.find("Subscribe") != std::string::npos) + return HLASubscribedActive; + else + return HLAUnsubscribed; + } + + HLAPublicationType getPublicationType() const + { + if (_sharing.find("Publish") != std::string::npos) + return HLAPublished; + else + return HLAUnpublished; + } + + HLAUpdateType getUpdateType() const + { + if (_updateType == "Periodic") + return HLAPeriodicUpdate; + else if (_updateType == "Static") + return HLAStaticUpdate; + else if (_updateType == "Conditional") + return HLAConditionalUpdate; + else + return HLAUndefinedUpdate; + } + std::string _name; std::string _dataType; std::string _updateType; @@ -66,7 +101,6 @@ public: unsigned getNumAttributes() const; const Attribute* getAttribute(unsigned index) const; - const Attribute* getAttribute(const std::string& name) const; const ObjectClass* getParentObjectClass() const; @@ -101,12 +135,28 @@ public: const std::string& getName() const; const std::string& getDimensions() const; + const std::string& getSharing() const; const std::string& getTransportation() const; const std::string& getOrder() const; + HLASubscriptionType getSubscriptionType() const + { + if (_sharing.find("Subscribe") != std::string::npos) + return HLASubscribedActive; + else + return HLAUnsubscribed; + } + + HLAPublicationType getPublicationType() const + { + if (_sharing.find("Publish") != std::string::npos) + return HLAPublished; + else + return HLAUnpublished; + } + unsigned getNumParameters() const; const Parameter* getParameter(unsigned index) const; - const Parameter* getParameter(const std::string& name) const; const InteractionClass* getParentInteractionClass() const; @@ -114,6 +164,7 @@ public: friend class HLAOMTXmlVisitor; std::string _name; std::string _dimensions; + std::string _sharing; std::string _transportation; std::string _order; ParameterList _parameters; @@ -124,36 +175,23 @@ public: HLAOMTXmlVisitor(); ~HLAOMTXmlVisitor(); + void setDataTypesToFederate(HLAFederate& federate); + void setToFederate(HLAFederate& federate); + unsigned getNumObjectClasses() const; const ObjectClass* getObjectClass(unsigned i) const; - const ObjectClass* getObjectClass(const std::string& name) const; - - /// Return the data type from the fom data - const Attribute* getAttribute(const std::string& objectClassName, const std::string& attributeName) const; - /// Return the data type from the fom data - HLADataType* getAttributeDataType(const std::string& objectClassName, const std::string& attributeName) const; unsigned getNumInteractionClasses() const; const InteractionClass* getInteractionClass(unsigned i) const; - const InteractionClass* getInteractionClass(const std::string& name) const; - - /// Return the data type from the fom data - const Parameter* getParameter(const std::string& interactionClassName, const std::string& parameterName) const; - - /// Return the data type from the fom data - HLADataType* getParameterDataType(const std::string& interactionClassName, const std::string& parameterName) const; - - HLADataType* getDataType(const std::string& dataTypeName) const; private: - typedef std::map > StringDataTypeMap; - SGSharedPtr getDataType(const std::string& dataTypeName, StringDataTypeMap& dataTypeMap) const; - SGSharedPtr getBasicDataType(const std::string& dataTypeName) const; - SGSharedPtr getSimpleDataType(const std::string& dataTypeName) const; - SGSharedPtr getEnumeratedDataType(const std::string& dataTypeName) const; - SGSharedPtr getArrayDataType(const std::string& dataTypeName, StringDataTypeMap& dataTypeMap) const; - SGSharedPtr getFixedRecordDataType(const std::string& dataTypeName, StringDataTypeMap& dataTypeMap) const; - SGSharedPtr getVariantRecordDataType(const std::string& dataTypeName, StringDataTypeMap& dataTypeMap) const; + SGSharedPtr getDataType(const std::string& dataTypeName); + SGSharedPtr getBasicDataType(const std::string& dataTypeName); + SGSharedPtr getSimpleDataType(const std::string& dataTypeName); + SGSharedPtr getEnumeratedDataType(const std::string& dataTypeName); + SGSharedPtr getArrayDataType(const std::string& dataTypeName); + SGSharedPtr getFixedRecordDataType(const std::string& dataTypeName); + SGSharedPtr getVariantRecordDataType(const std::string& dataTypeName); enum Mode { UnknownMode, @@ -195,8 +233,8 @@ private: virtual void startElement(const char* name, const XMLAttributes& atts); virtual void endElement(const char* name); - std::string getAttribute(const char* name, const XMLAttributes& atts); - std::string getAttribute(const std::string& name, const XMLAttributes& atts); + static std::string getAttribute(const char* name, const XMLAttributes& atts); + static std::string getAttribute(const std::string& name, const XMLAttributes& atts); struct BasicData { // std::string _name; @@ -276,6 +314,9 @@ private: InteractionClassList _interactionClassList; InteractionClassList _interactionClassStack; + typedef std::map > StringDataTypeMap; + StringDataTypeMap _dataTypeMap; + /// DataType definitions BasicDataMap _basicDataMap; SimpleDataMap _simpleDataMap; diff --git a/simgear/hla/HLAObjectClass.cxx b/simgear/hla/HLAObjectClass.cxx index 40cef871..9d4146d2 100644 --- a/simgear/hla/HLAObjectClass.cxx +++ b/simgear/hla/HLAObjectClass.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public @@ -17,6 +17,7 @@ #include "HLAObjectClass.hxx" +#include "simgear/debug/logstream.hxx" #include "RTIFederate.hxx" #include "RTIObjectClass.hxx" #include "RTIObjectInstance.hxx" @@ -54,87 +55,127 @@ HLAObjectClass::RegistrationCallback::~RegistrationCallback() { } -HLAObjectClass::HLAObjectClass(const std::string& name, HLAFederate& federate) : +HLAObjectClass::HLAObjectClass(const std::string& name, HLAFederate* federate) : + _federate(federate), _name(name) { - _rtiObjectClass = federate._rtiFederate->createObjectClass(name, this); - if (!_rtiObjectClass.valid()) - SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::HLAObjectClass(): No RTIObjectClass found for \"" << name << "\"!"); + if (!federate) { + SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass::HLAObjectClass(): " + "No parent federate given for object class \"" << getName() << "\"!"); + return; + } + federate->_insertObjectClass(this); } HLAObjectClass::~HLAObjectClass() { + // HLAObjectClass objects only get deleted when the parent federate + // dies. So we do not need to deregister there. + + _clearRTIObjectClass(); +} + +const std::string& +HLAObjectClass::getName() const +{ + return _name; } unsigned HLAObjectClass::getNumAttributes() const { - if (!_rtiObjectClass.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::getAttributeIndex(): No RTIObject class for object class \"" << getName() << "\"!"); - return 0; - } - return _rtiObjectClass->getNumAttributes(); + return _attributeVector.size(); +} + +unsigned +HLAObjectClass::addAttribute(const std::string& name) +{ + unsigned index = _attributeVector.size(); + _nameIndexMap[name] = index; + _attributeVector.push_back(Attribute(name)); + _resolveAttributeIndex(name, index); + return index; } unsigned HLAObjectClass::getAttributeIndex(const std::string& name) const { - if (!_rtiObjectClass.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::getAttributeIndex(): No RTIObject class for object class \"" << getName() << "\"!"); + NameIndexMap::const_iterator i = _nameIndexMap.find(name); + if (i == _nameIndexMap.end()) return ~0u; - } - return _rtiObjectClass->getOrCreateAttributeIndex(name); + return i->second; } std::string HLAObjectClass::getAttributeName(unsigned index) const { - if (!_rtiObjectClass.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::getAttributeIndex(): No RTIObject class for object class \"" << getName() << "\"!"); - return 0; - } - return _rtiObjectClass->getAttributeName(index); + if (_attributeVector.size() <= index) + return std::string(); + return _attributeVector[index]._name; } const HLADataType* HLAObjectClass::getAttributeDataType(unsigned index) const { - if (!_rtiObjectClass.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::getAttributeDataType(): No RTIObject class for object class \"" << getName() << "\"!"); + if (_attributeVector.size() <= index) return 0; - } - return _rtiObjectClass->getAttributeDataType(index); + return _attributeVector[index]._dataType.get(); } void HLAObjectClass::setAttributeDataType(unsigned index, const HLADataType* dataType) { - if (!_rtiObjectClass.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::setAttributeDataType(): No RTIObject class for object class \"" << getName() << "\"!"); + if (_attributeVector.size() <= index) return; - } - _rtiObjectClass->setAttributeDataType(index, dataType); + _attributeVector[index]._dataType = dataType; } HLAUpdateType HLAObjectClass::getAttributeUpdateType(unsigned index) const { - if (!_rtiObjectClass.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::getAttributeUpdateType(): No RTIObject class for object class \"" << getName() << "\"!"); + if (_attributeVector.size() <= index) return HLAUndefinedUpdate; - } - return _rtiObjectClass->getAttributeUpdateType(index); + return _attributeVector[index]._updateType; } void HLAObjectClass::setAttributeUpdateType(unsigned index, HLAUpdateType updateType) { - if (!_rtiObjectClass.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::setAttributeUpdateType(): " - "No RTIObject class for object class \"" << getName() << "\"!"); + if (_attributeVector.size() <= index) return; - } - _rtiObjectClass->setAttributeUpdateType(index, updateType); + _attributeVector[index]._updateType = updateType; +} + +HLASubscriptionType +HLAObjectClass::getAttributeSubscriptionType(unsigned index) const +{ + if (_attributeVector.size() <= index) + return HLAUnsubscribed; + return _attributeVector[index]._subscriptionType; +} + +void +HLAObjectClass::setAttributeSubscriptionType(unsigned index, HLASubscriptionType subscriptionType) +{ + if (_attributeVector.size() <= index) + return; + _attributeVector[index]._subscriptionType = subscriptionType; +} + +HLAPublicationType +HLAObjectClass::getAttributePublicationType(unsigned index) const +{ + if (_attributeVector.size() <= index) + return HLAUnpublished; + return _attributeVector[index]._publicationType; +} + +void +HLAObjectClass::setAttributePublicationType(unsigned index, HLAPublicationType publicationType) +{ + if (_attributeVector.size() <= index) + return; + _attributeVector[index]._publicationType = publicationType; } HLADataElement::IndexPathPair @@ -157,40 +198,77 @@ HLAObjectClass::getIndexPathPair(const std::string& path) const } bool -HLAObjectClass::subscribe(const std::set& indexSet, bool active) +HLAObjectClass::subscribe() { if (!_rtiObjectClass.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::subscribe(): No RTIObject class for object class \"" << getName() << "\"!"); + SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::subscribe(): " + "No RTIObject class for object class \"" << getName() << "\"!"); return false; } - return _rtiObjectClass->subscribe(indexSet, active); + + HLAIndexList indexList; + for (unsigned i = 1; i < getNumAttributes(); ++i) { + if (_attributeVector[i]._subscriptionType != HLASubscribedActive) + continue; + indexList.push_back(i); + } + if (!indexList.empty()) { + if (!_rtiObjectClass->subscribe(indexList, true)) + return false; + } + + indexList.clear(); + for (unsigned i = 1; i < getNumAttributes(); ++i) { + if (_attributeVector[i]._subscriptionType != HLASubscribedPassive) + continue; + indexList.push_back(i); + } + if (!indexList.empty()) { + if (!_rtiObjectClass->subscribe(indexList, false)) + return false; + } + return true; } bool HLAObjectClass::unsubscribe() { if (!_rtiObjectClass.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::unsubscribe(): No RTIObject class for object class \"" << getName() << "\"!"); + SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::unsubscribe(): " + "No RTIObject class for object class \"" << getName() << "\"!"); return false; } return _rtiObjectClass->unsubscribe(); } bool -HLAObjectClass::publish(const std::set& indexSet) +HLAObjectClass::publish() { if (!_rtiObjectClass.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::publish(): No RTIObject class for object class \"" << getName() << "\"!"); + SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::publish(): " + "No RTIObject class for object class \"" << getName() << "\"!"); return false; } - return _rtiObjectClass->publish(indexSet); + + HLAIndexList indexList; + for (unsigned i = 1; i < getNumAttributes(); ++i) { + if (_attributeVector[i]._publicationType == HLAUnpublished) + continue; + indexList.push_back(i); + } + if (indexList.empty()) + return true; + if (!_rtiObjectClass->publish(indexList)) + return false; + return true; } bool HLAObjectClass::unpublish() { if (!_rtiObjectClass.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::unpublish(): No RTIObject class for object class \"" << getName() << "\"!"); + SG_LOG(SG_NETWORK, SG_WARN, "HLAObjectClass::unpublish(): " + "No RTIObject class for object class \"" << getName() << "\"!"); return false; } return _rtiObjectClass->unpublish(); @@ -207,82 +285,135 @@ HLAObjectClass::stopRegistration() const } HLAObjectInstance* -HLAObjectClass::createObjectInstance(RTIObjectInstance* rtiObjectInstance) +HLAObjectClass::createObjectInstance(const std::string& name) { - return new HLAObjectInstance(this, rtiObjectInstance); + HLAObjectInstance* objectInstance = createObjectInstance(); + if (objectInstance) + return objectInstance; + SGSharedPtr federate = _federate.lock(); + if (!federate.valid()) + return 0; + return federate->createObjectInstance(this, name); } -void -HLAObjectClass::discoverInstance(RTIObjectInstance* objectInstance, const RTIData& tag) -{ - SGSharedPtr hlaObjectInstance = createObjectInstance(objectInstance); - if (hlaObjectInstance.valid()) { - SG_LOG(SG_NETWORK, SG_INFO, "RTI: create new object instance for discovered \"" - << hlaObjectInstance->getName() << "\" object"); - _objectInstanceSet.insert(hlaObjectInstance); - discoverInstanceCallback(*hlaObjectInstance, tag); - } else { - SG_LOG(SG_NETWORK, SG_INFO, "RTI: local delete of \"" << objectInstance->getName() << "\""); - objectInstance->localDeleteObjectInstance(); - } +HLAObjectInstance* +HLAObjectClass::createObjectInstance() +{ + return 0; } void -HLAObjectClass::removeInstance(HLAObjectInstance& hlaObjectInstance, const RTIData& tag) +HLAObjectClass::_setRTIObjectClass(RTIObjectClass* objectClass) { - SG_LOG(SG_NETWORK, SG_INFO, "RTI: remove object instance \"" << hlaObjectInstance.getName() << "\""); - removeInstanceCallback(hlaObjectInstance, tag); - _objectInstanceSet.erase(&hlaObjectInstance); + if (_rtiObjectClass) { + SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: Setting RTIObjectClass twice for object class \"" << getName() << "\"!"); + return; + } + _rtiObjectClass = objectClass; + if (_rtiObjectClass->_objectClass != this) { + SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: backward reference does not match!"); + return; + } + for (unsigned i = 0; i < _attributeVector.size(); ++i) + _resolveAttributeIndex(_attributeVector[i]._name, i); } void -HLAObjectClass::registerInstance(HLAObjectInstance& objectInstance) +HLAObjectClass::_resolveAttributeIndex(const std::string& name, unsigned index) { - _objectInstanceSet.insert(&objectInstance); - registerInstanceCallback(objectInstance); + if (!_rtiObjectClass) + return; + if (!_rtiObjectClass->resolveAttributeIndex(name, index)) + SG_LOG(SG_NETWORK, SG_ALERT, "HLAObjectClass: Could not resolve attribute \"" + << name << "\" for object class \"" << getName() << "\"!"); } void -HLAObjectClass::deleteInstance(HLAObjectInstance& objectInstance) +HLAObjectClass::_clearRTIObjectClass() { - deleteInstanceCallback(objectInstance); - _objectInstanceSet.erase(&objectInstance); + if (!_rtiObjectClass.valid()) + return; + _rtiObjectClass->_objectClass = 0; + _rtiObjectClass = 0; } void -HLAObjectClass::discoverInstanceCallback(HLAObjectInstance& objectInstance, const RTIData& tag) const +HLAObjectClass::_discoverInstance(RTIObjectInstance* rtiObjectInstance, const RTIData& tag) { - if (!_instanceCallback.valid()) + SGSharedPtr federate = _federate.lock(); + if (!federate.valid()) { + SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not find parent federate while discovering object instance"); + return; + } + + SGSharedPtr objectInstance = createObjectInstance(rtiObjectInstance->getName()); + if (!objectInstance.valid()) { + SG_LOG(SG_NETWORK, SG_INFO, "RTI: could not create new object instance for discovered \"" + << rtiObjectInstance->getName() << "\" object"); + return; + } + SG_LOG(SG_NETWORK, SG_INFO, "RTI: create new object instance for discovered \"" + << rtiObjectInstance->getName() << "\" object"); + objectInstance->_setRTIObjectInstance(rtiObjectInstance); + if (!federate->_insertObjectInstance(objectInstance)) { + SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not insert new object instance for discovered \"" + << rtiObjectInstance->getName() << "\" object"); return; - _instanceCallback->discoverInstance(*this, objectInstance, tag); + } + if (_instanceCallback.valid()) + _instanceCallback->discoverInstance(*this, *objectInstance, tag); } void -HLAObjectClass::removeInstanceCallback(HLAObjectInstance& objectInstance, const RTIData& tag) const +HLAObjectClass::_removeInstance(HLAObjectInstance& objectInstance, const RTIData& tag) { - if (!_instanceCallback.valid()) + SGSharedPtr federate = _federate.lock(); + if (!federate.valid()) { + SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not find parent federate while removing object instance"); return; - _instanceCallback->removeInstance(*this, objectInstance, tag); + } + SG_LOG(SG_NETWORK, SG_INFO, "RTI: remove object instance \"" << objectInstance.getName() << "\""); + if (_instanceCallback.valid()) + _instanceCallback->removeInstance(*this, objectInstance, tag); + federate->_eraseObjectInstance(objectInstance.getName()); } void -HLAObjectClass::registerInstanceCallback(HLAObjectInstance& objectInstance) const +HLAObjectClass::_registerInstance(HLAObjectInstance* objectInstance) { - if (!_instanceCallback.valid()) + SGSharedPtr federate = _federate.lock(); + if (!federate.valid()) { + SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not find parent federate while registering object instance"); return; - _instanceCallback->registerInstance(*this, objectInstance); + } + if (!objectInstance) + return; + // We can only register object instances with a valid name at the rti. + // So, we cannot do that at HLAObjectInstance creation time. + if (!federate->_insertObjectInstance(objectInstance)) { + SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not insert new object instance \"" + << objectInstance->getName() << "\" object"); + return; + } + if (_instanceCallback.valid()) + _instanceCallback->registerInstance(*this, *objectInstance); } void -HLAObjectClass::deleteInstanceCallback(HLAObjectInstance& objectInstance) const +HLAObjectClass::_deleteInstance(HLAObjectInstance& objectInstance) { - if (!_instanceCallback.valid()) + SGSharedPtr federate = _federate.lock(); + if (!federate.valid()) { + SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not find parent federate while deleting object instance"); return; - _instanceCallback->deleteInstance(*this, objectInstance); + } + if (_instanceCallback.valid()) + _instanceCallback->deleteInstance(*this, objectInstance); + federate->_eraseObjectInstance(objectInstance.getName()); } void -HLAObjectClass::startRegistrationCallback() +HLAObjectClass::_startRegistration() { if (_registrationCallback.valid()) _registrationCallback->startRegistration(*this); @@ -291,7 +422,7 @@ HLAObjectClass::startRegistrationCallback() } void -HLAObjectClass::stopRegistrationCallback() +HLAObjectClass::_stopRegistration() { if (_registrationCallback.valid()) _registrationCallback->stopRegistration(*this); diff --git a/simgear/hla/HLAObjectClass.hxx b/simgear/hla/HLAObjectClass.hxx index 68ffcc53..ea054a48 100644 --- a/simgear/hla/HLAObjectClass.hxx +++ b/simgear/hla/HLAObjectClass.hxx @@ -1,4 +1,4 @@ -// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public @@ -18,7 +18,6 @@ #ifndef HLAObjectClass_hxx #define HLAObjectClass_hxx -#include #include #include @@ -33,30 +32,53 @@ class HLAFederate; class HLAObjectClass : public SGWeakReferenced { public: - HLAObjectClass(const std::string& name, HLAFederate& federate); + HLAObjectClass(const std::string& name, HLAFederate* federate); virtual ~HLAObjectClass(); - const std::string& getName() const - { return _name; } + /// Return the name of this object class + const std::string& getName() const; + /// Return the number of attributes in this object class unsigned getNumAttributes() const; + + /// Adds a new attribute to this object class, return the index + unsigned addAttribute(const std::string& name); + + /// Return the attribute index for the attribute with the given name unsigned getAttributeIndex(const std::string& name) const; + /// Return the attribute name for the attribute with the given index std::string getAttributeName(unsigned index) const; + /// Return the data type of the attribute with the given index const HLADataType* getAttributeDataType(unsigned index) const; - void setAttributeDataType(unsigned index, const HLADataType*); + /// Sets the data type of the attribute with the given index to dataType + void setAttributeDataType(unsigned index, const HLADataType* dataType); + /// Return the update type of the attribute with the given index HLAUpdateType getAttributeUpdateType(unsigned index) const; + /// Sets the update type of the attribute with the given index to updateType void setAttributeUpdateType(unsigned index, HLAUpdateType updateType); + /// Return the subscription type of the attribute with the given index + HLASubscriptionType getAttributeSubscriptionType(unsigned index) const; + /// Sets the subscription type of the attribute with the given index to subscriptionType + void setAttributeSubscriptionType(unsigned index, HLASubscriptionType subscriptionType); + + /// Return the publication type of the attribute with the given index + HLAPublicationType getAttributePublicationType(unsigned index) const; + /// Sets the publication type of the attribute with the given index to publicationType + void setAttributePublicationType(unsigned index, HLAPublicationType publicationType); + + /// Return the index, path pair for the given string path pair HLADataElement::IndexPathPair getIndexPathPair(const HLADataElement::StringPathPair&) const; + /// Return the index, path pair for the given string path HLADataElement::IndexPathPair getIndexPathPair(const std::string& path) const; - bool subscribe(const std::set& indexSet, bool active); - bool unsubscribe(); + virtual bool subscribe(); + virtual bool unsubscribe(); - bool publish(const std::set& indexSet); - bool unpublish(); + virtual bool publish(); + virtual bool unpublish(); // Object instance creation and destruction class InstanceCallback : public SGReferenced { @@ -75,6 +97,11 @@ public: const SGSharedPtr& getInstanceCallback() const { return _instanceCallback; } + // Is called by the default registration callback if installed + // Should register the already known object instances of this class. + virtual void startRegistration() const; + virtual void stopRegistration() const; + // Handles startRegistrationForObjectClass and stopRegistrationForObjectClass events class RegistrationCallback : public SGReferenced { public: @@ -88,46 +115,61 @@ public: const SGSharedPtr& getRegistrationCallback() const { return _registrationCallback; } - // Is called by the default registration callback if installed - void startRegistration() const; - void stopRegistration() const; - -protected: - virtual HLAObjectInstance* createObjectInstance(RTIObjectInstance* rtiObjectInstance); + /// Create a new instance of this class. + virtual HLAObjectInstance* createObjectInstance(const std::string& name); + virtual HLAObjectInstance* createObjectInstance(); // deprecated private: HLAObjectClass(const HLAObjectClass&); HLAObjectClass& operator=(const HLAObjectClass&); + void _setRTIObjectClass(RTIObjectClass* objectClass); + void _resolveAttributeIndex(const std::string& name, unsigned index); + void _clearRTIObjectClass(); + // The internal entry points from the RTILObjectClass callback functions - void discoverInstance(RTIObjectInstance* objectInstance, const RTIData& tag); - void removeInstance(HLAObjectInstance& objectInstance, const RTIData& tag); - void registerInstance(HLAObjectInstance& objectInstance); - void deleteInstance(HLAObjectInstance& objectInstance); - - void discoverInstanceCallback(HLAObjectInstance& objectInstance, const RTIData& tag) const; - void removeInstanceCallback(HLAObjectInstance& objectInstance, const RTIData& tag) const; - void registerInstanceCallback(HLAObjectInstance& objectInstance) const; - void deleteInstanceCallback(HLAObjectInstance& objectInstance) const; - - void startRegistrationCallback(); - void stopRegistrationCallback(); + void _discoverInstance(RTIObjectInstance* objectInstance, const RTIData& tag); + void _removeInstance(HLAObjectInstance& objectInstance, const RTIData& tag); + void _registerInstance(HLAObjectInstance* objectInstance); + void _deleteInstance(HLAObjectInstance& objectInstance); + + void _startRegistration(); + void _stopRegistration(); + friend class HLAObjectInstance; friend class RTIObjectClass; - // The object class name + struct Attribute { + Attribute() : _subscriptionType(HLAUnsubscribed), _publicationType(HLAUnpublished), _updateType(HLAUndefinedUpdate) {} + Attribute(const std::string& name) : _name(name), _subscriptionType(HLAUnsubscribed), _publicationType(HLAUnpublished), _updateType(HLAUndefinedUpdate) {} + std::string _name; + SGSharedPtr _dataType; + HLASubscriptionType _subscriptionType; + HLAPublicationType _publicationType; + HLAUpdateType _updateType; + }; + typedef std::vector AttributeVector; + typedef std::map NameIndexMap; + + /// The parent federate. + SGWeakPtr _federate; + + /// The object class name std::string _name; - // The underlying rti dispatcher class + /// The underlying rti dispatcher class SGSharedPtr _rtiObjectClass; + /// The attribute data + AttributeVector _attributeVector; + /// The mapping from attribute names to attribute indices + NameIndexMap _nameIndexMap; + // Callback classes SGSharedPtr _instanceCallback; SGSharedPtr _registrationCallback; - // The set of active objects - typedef std::set > ObjectInstanceSet; - ObjectInstanceSet _objectInstanceSet; + friend class HLAFederate; }; } // namespace simgear diff --git a/simgear/hla/HLAObjectInstance.cxx b/simgear/hla/HLAObjectInstance.cxx index 22d8309e..390b70db 100644 --- a/simgear/hla/HLAObjectInstance.cxx +++ b/simgear/hla/HLAObjectInstance.cxx @@ -18,10 +18,12 @@ #include "HLAObjectInstance.hxx" #include +#include "simgear/debug/logstream.hxx" #include "HLAArrayDataElement.hxx" #include "HLABasicDataElement.hxx" #include "HLADataElement.hxx" #include "HLAEnumeratedDataElement.hxx" +#include "HLAFederate.hxx" #include "HLAFixedRecordDataElement.hxx" #include "HLAObjectClass.hxx" #include "HLAVariantRecordDataElement.hxx" @@ -30,97 +32,93 @@ namespace simgear { -HLAObjectInstance::HLAObjectInstance(HLAObjectClass* objectClass) : - _objectClass(objectClass) +HLAObjectInstance::UpdateCallback::~UpdateCallback() { } -HLAObjectInstance::HLAObjectInstance(HLAObjectClass* objectClass, RTIObjectInstance* rtiObjectInstance) : - _objectClass(objectClass), - _rtiObjectInstance(rtiObjectInstance) +HLAObjectInstance::ReflectCallback::~ReflectCallback() { - _rtiObjectInstance->_hlaObjectInstance = this; - _name = _rtiObjectInstance->getName(); } -HLAObjectInstance::~HLAObjectInstance() +HLAObjectInstance::HLAObjectInstance(HLAObjectClass* objectClass) : + _federate(objectClass->_federate), + _objectClass(objectClass) { } -SGSharedPtr -HLAObjectInstance::getObjectClass() const +HLAObjectInstance::~HLAObjectInstance() { - return _objectClass.lock(); + _clearRTIObjectInstance(); } unsigned HLAObjectInstance::getNumAttributes() const { - if (!_rtiObjectInstance.valid()) { - SG_LOG(SG_IO, SG_ALERT, "Trying to get number of attributes for inactive object!"); - return 0; - } - return _rtiObjectInstance->getNumAttributes(); + return _objectClass->getNumAttributes(); } unsigned HLAObjectInstance::getAttributeIndex(const std::string& name) const { - if (!_rtiObjectInstance.valid()) { - SG_LOG(SG_IO, SG_ALERT, "Trying to get attribute index for inactive object!"); - return 0; - } - return _rtiObjectInstance->getAttributeIndex(name); + return _objectClass->getAttributeIndex(name); } std::string HLAObjectInstance::getAttributeName(unsigned index) const { - if (!_rtiObjectInstance.valid()) { - SG_LOG(SG_IO, SG_ALERT, "Trying to get attribute name for inactive object!"); - return std::string(); - } - return _rtiObjectInstance->getAttributeName(index); + return _objectClass->getAttributeName(index); } -const HLADataType* -HLAObjectInstance::getAttributeDataType(unsigned index) const +bool +HLAObjectInstance::getAttributeOwned(unsigned index) const { - if (!_rtiObjectInstance.valid()) { - SG_LOG(SG_IO, SG_ALERT, "Trying to get attribute index for inactive object!"); - return 0; - } - return _rtiObjectInstance->getAttributeDataType(index); + if (!_rtiObjectInstance.valid()) + return false; + return _rtiObjectInstance->getAttributeOwned(index); } -void -HLAObjectInstance::setAttributeDataElement(unsigned index, SGSharedPtr dataElement) +const HLADataType* +HLAObjectInstance::getAttributeDataType(unsigned index) const { - if (!_rtiObjectInstance.valid()) { - SG_LOG(SG_IO, SG_ALERT, "Trying to set data element for inactive object!"); - return; - } - _rtiObjectInstance->setDataElement(index, dataElement); + return _objectClass->getAttributeDataType(index); } HLADataElement* HLAObjectInstance::getAttributeDataElement(unsigned index) { - if (!_rtiObjectInstance.valid()) { - SG_LOG(SG_IO, SG_ALERT, "Trying to set data element for inactive object!"); + if (_attributeVector.size() <= index) return 0; - } - return _rtiObjectInstance->getDataElement(index); + return _attributeVector[index]._dataElement.get(); } const HLADataElement* HLAObjectInstance::getAttributeDataElement(unsigned index) const { - if (!_rtiObjectInstance.valid()) { - SG_LOG(SG_IO, SG_ALERT, "Trying to set data element for inactive object!"); + if (_attributeVector.size() <= index) return 0; + return _attributeVector[index]._dataElement.get(); +} + +bool +HLAObjectInstance::getAttributeData(unsigned index, RTIData& data) const +{ + if (!_rtiObjectInstance.valid()) { + SG_LOG(SG_IO, SG_ALERT, "Trying to get raw attribute data without rti object instance for \"" << getName() << "\"!"); + return false; } - return _rtiObjectInstance->getDataElement(index); + return _rtiObjectInstance->getAttributeData(index, data); +} + +void +HLAObjectInstance::setAttributeDataElement(unsigned index, const SGSharedPtr& dataElement) +{ + unsigned numAttributes = getNumAttributes(); + if (numAttributes <= index) + return; + _attributeVector.resize(numAttributes); + _attributeVector[index]._dataElement = dataElement; + if (getAttributeOwned(index)) + encodeAttributeValue(index); } class HLAObjectInstance::DataElementFactoryVisitor : public HLADataElementFactoryVisitor { @@ -387,8 +385,8 @@ HLAObjectInstance::setAttribute(unsigned index, const HLAPathElementMap& pathEle { const HLADataType* dataType = getAttributeDataType(index); if (!dataType) { - SG_LOG(SG_IO, SG_ALERT, "Cannot get attribute data type for setting attribute at index " - << index << "!"); + SG_LOG(SG_IO, SG_ALERT, "Cannot get attribute data type for setting attribute \"" + << getAttributeName(index) << "\" at index " << index << "!"); return; } @@ -416,21 +414,19 @@ HLAObjectInstance::registerInstance() SG_LOG(SG_IO, SG_ALERT, "Trying to register object " << getName() << " already known to the RTI!"); return; } - SGSharedPtr objectClass = _objectClass.lock(); - if (!objectClass.valid()) { + if (!_objectClass.valid()) { SG_LOG(SG_IO, SG_ALERT, "Could not register object with unknown object class!"); return; } // This error must have been flagged before - if (!objectClass->_rtiObjectClass.valid()) + if (!_objectClass->_rtiObjectClass.valid()) return; - _rtiObjectInstance = objectClass->_rtiObjectClass->registerObjectInstance(this); + _setRTIObjectInstance(_objectClass->_rtiObjectClass->registerObjectInstance(this)); if (!_rtiObjectInstance.valid()) { SG_LOG(SG_IO, SG_ALERT, "Could not register object at the RTI!"); return; } - _name = _rtiObjectInstance->getName(); - objectClass->registerInstance(*this); + _objectClass->_registerInstance(this); } void @@ -440,61 +436,214 @@ HLAObjectInstance::deleteInstance(const RTIData& tag) SG_LOG(SG_IO, SG_ALERT, "Trying to delete inactive object!"); return; } - SGSharedPtr objectClass = _objectClass.lock(); - if (!objectClass.valid()) + if (!_objectClass.valid()) return; - objectClass->deleteInstance(*this); + _objectClass->_deleteInstance(*this); _rtiObjectInstance->deleteObjectInstance(tag); } void HLAObjectInstance::updateAttributeValues(const RTIData& tag) +{ + if (_attributeCallback.valid()) + _attributeCallback->updateAttributeValues(*this, tag); + if (_updateCallback.valid()) { + _updateCallback->updateAttributeValues(*this, tag); + } else { + encodeAttributeValues(); + sendAttributeValues(tag); + } +} + +void +HLAObjectInstance::updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag) +{ + if (_attributeCallback.valid()) + _attributeCallback->updateAttributeValues(*this, tag); + if (_updateCallback.valid()) { + _updateCallback->updateAttributeValues(*this, timeStamp, tag); + } else { + encodeAttributeValues(); + sendAttributeValues(timeStamp, tag); + } +} + +void +HLAObjectInstance::encodeAttributeValues() +{ + unsigned numAttributes = _attributeVector.size(); + for (unsigned i = 0; i < numAttributes;++i) { + if (!_attributeVector[i]._unconditionalUpdate) + continue; + encodeAttributeValue(i); + } +} + +void +HLAObjectInstance::encodeAttributeValue(unsigned index) +{ + if (!_rtiObjectInstance.valid()) { + SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!"); + return; + } + const HLADataElement* dataElement = getAttributeDataElement(index); + if (!dataElement) + return; + _rtiObjectInstance->encodeAttributeData(index, *dataElement); +} + +void +HLAObjectInstance::sendAttributeValues(const RTIData& tag) { if (!_rtiObjectInstance.valid()) { SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!"); return; } - if (_attributeCallback.valid()) - _attributeCallback->updateAttributeValues(*this, tag); _rtiObjectInstance->updateAttributeValues(tag); } void -HLAObjectInstance::updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag) +HLAObjectInstance::sendAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag) { if (!_rtiObjectInstance.valid()) { SG_LOG(SG_IO, SG_INFO, "Not updating inactive object!"); return; } - if (_attributeCallback.valid()) - _attributeCallback->updateAttributeValues(*this, tag); _rtiObjectInstance->updateAttributeValues(timeStamp, tag); } void -HLAObjectInstance::removeInstance(const RTIData& tag) +HLAObjectInstance::reflectAttributeValues(const HLAIndexList& indexList, const RTIData& tag) +{ + for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i) + reflectAttributeValue(*i, tag); +} + +void +HLAObjectInstance::reflectAttributeValues(const HLAIndexList& indexList, + const SGTimeStamp& timeStamp, const RTIData& tag) +{ + for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i) + reflectAttributeValue(*i, timeStamp, tag); +} + +void +HLAObjectInstance::reflectAttributeValue(unsigned index, const RTIData& tag) { - SGSharedPtr objectClass = _objectClass.lock(); - if (!objectClass.valid()) + HLADataElement* dataElement = getAttributeDataElement(index); + if (!dataElement) return; - objectClass->removeInstanceCallback(*this, tag); + _rtiObjectInstance->decodeAttributeData(index, *dataElement); } void -HLAObjectInstance::reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const RTIData& tag) +HLAObjectInstance::reflectAttributeValue(unsigned index, const SGTimeStamp& timeStamp, const RTIData& tag) { - if (!_attributeCallback.valid()) + HLADataElement* dataElement = getAttributeDataElement(index); + if (!dataElement) return; - _attributeCallback->reflectAttributeValues(*this, dataPairList, tag); + // dataElement->setTimeStamp(timeStamp); + _rtiObjectInstance->decodeAttributeData(index, *dataElement); } void -HLAObjectInstance::reflectAttributeValues(const RTIIndexDataPairList& dataPairList, - const SGTimeStamp& timeStamp, const RTIData& tag) +HLAObjectInstance::_setRTIObjectInstance(RTIObjectInstance* rtiObjectInstance) +{ + _rtiObjectInstance = rtiObjectInstance; + _rtiObjectInstance->setObjectInstance(this); + _name = _rtiObjectInstance->getName(); + + unsigned numAttributes = getNumAttributes(); + _attributeVector.resize(numAttributes); + for (unsigned i = 0; i < numAttributes; ++i) { + HLAUpdateType updateType = getObjectClass()->getAttributeUpdateType(i); + if (getAttributeOwned(i) && updateType != HLAUndefinedUpdate) { + _attributeVector[i]._enabledUpdate = true; + _attributeVector[i]._unconditionalUpdate = (updateType == HLAPeriodicUpdate); + // In case of an owned attribute, now encode its value + encodeAttributeValue(i); + } else { + _attributeVector[i]._enabledUpdate = false; + _attributeVector[i]._unconditionalUpdate = false; + } + } + + // This makes sense with any new object. Even if we registered one, there might be unpublished attributes. + HLAIndexList indexList; + for (unsigned i = 0; i < numAttributes; ++i) { + HLAUpdateType updateType = getObjectClass()->getAttributeUpdateType(i); + if (getAttributeOwned(i)) + continue; + if (updateType == HLAUndefinedUpdate) + continue; + if (updateType == HLAPeriodicUpdate) + continue; + indexList.push_back(i); + } + _rtiObjectInstance->requestObjectAttributeValueUpdate(indexList); +} + +void +HLAObjectInstance::_clearRTIObjectInstance() +{ + if (!_rtiObjectInstance.valid()) + return; + + for (unsigned i = 0; i < _attributeVector.size(); ++i) { + _attributeVector[i]._enabledUpdate = false; + _attributeVector[i]._unconditionalUpdate = false; + } + + _rtiObjectInstance->setObjectInstance(0); + _rtiObjectInstance = 0; +} + +void +HLAObjectInstance::_removeInstance(const RTIData& tag) { - if (!_attributeCallback.valid()) + if (!_objectClass.valid()) return; - _attributeCallback->reflectAttributeValues(*this, dataPairList, timeStamp, tag); + _objectClass->_removeInstance(*this, tag); +} + +void +HLAObjectInstance::_reflectAttributeValues(const HLAIndexList& indexList, const RTIData& tag) +{ + if (_reflectCallback.valid()) { + _reflectCallback->reflectAttributeValues(*this, indexList, tag); + } else if (_attributeCallback.valid()) { + reflectAttributeValues(indexList, tag); + + RTIIndexDataPairList dataPairList; + for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i) { + dataPairList.push_back(RTIIndexDataPair()); + dataPairList.back().first = *i; + getAttributeData(*i, dataPairList.back().second); + } + _attributeCallback->reflectAttributeValues(*this, dataPairList, tag); + } else { + reflectAttributeValues(indexList, tag); + } +} + +void +HLAObjectInstance::_reflectAttributeValues(const HLAIndexList& indexList, const SGTimeStamp& timeStamp, const RTIData& tag) +{ + if (_reflectCallback.valid()) { + _reflectCallback->reflectAttributeValues(*this, indexList, timeStamp, tag); + } else if (_attributeCallback.valid()) { + reflectAttributeValues(indexList, timeStamp, tag); + + RTIIndexDataPairList dataPairList; + for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i) { + dataPairList.push_back(RTIIndexDataPair()); + dataPairList.back().first = *i; + getAttributeData(*i, dataPairList.back().second); + } + _attributeCallback->reflectAttributeValues(*this, dataPairList, timeStamp, tag); + } else { + reflectAttributeValues(indexList, timeStamp, tag); + } } } // namespace simgear diff --git a/simgear/hla/HLAObjectInstance.hxx b/simgear/hla/HLAObjectInstance.hxx index 974d2a98..1262d6de 100644 --- a/simgear/hla/HLAObjectInstance.hxx +++ b/simgear/hla/HLAObjectInstance.hxx @@ -1,4 +1,4 @@ -// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public @@ -18,51 +18,117 @@ #ifndef HLAObjectInstance_hxx #define HLAObjectInstance_hxx +#include + #include #include "HLADataElement.hxx" +#include "HLATypes.hxx" class SGTimeStamp; namespace simgear { class RTIObjectInstance; +class HLAFederate; class HLAObjectClass; class HLAObjectInstance : public SGWeakReferenced { public: HLAObjectInstance(HLAObjectClass* objectClass); - HLAObjectInstance(HLAObjectClass* objectClass, RTIObjectInstance* rtiObjectInstance); virtual ~HLAObjectInstance(); + /// Return the name of this object instance const std::string& getName() const { return _name; } - SGSharedPtr getObjectClass() const; + /// Return the object class of this instance. + /// Should always return a valid object class. + const SGSharedPtr& getObjectClass() const + { return _objectClass; } + /// Return the number of attributes unsigned getNumAttributes() const; + + /// Return the attribute index for the attribute with the given name unsigned getAttributeIndex(const std::string& name) const; + /// Return the attribute name for the attribute with the given index std::string getAttributeName(unsigned index) const; + /// Return true if the attribute with the given index is owned by this federate + bool getAttributeOwned(unsigned index) const; + + /// Return the data type of the attribute with the given index const HLADataType* getAttributeDataType(unsigned index) const; - void setAttributeDataElement(unsigned index, SGSharedPtr dataElement); + /// Return the data element of the attribute with the given index HLADataElement* getAttributeDataElement(unsigned index); const HLADataElement* getAttributeDataElement(unsigned index) const; + + /// Write the raw attribute data value into data, works only of the object is backed up with an rti object instance + bool getAttributeData(unsigned index, RTIData& data) const; + + /// Sets the data element of the attribute with the given index to dataElement + void setAttributeDataElement(unsigned index, const SGSharedPtr& dataElement); + /// Sets the data element of the attribute with the given index to the content of pathElementMap void setAttribute(unsigned index, const HLAPathElementMap& pathElementMap); void setAttributes(const HLAAttributePathElementMap& attributePathElementMap); void registerInstance(); void deleteInstance(const RTIData& tag); + // Push the current values into the RTI + virtual void updateAttributeValues(const RTIData& tag); + virtual void updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag); + // encode periodic and dirty attribute values for the next sendAttributeValues + void encodeAttributeValues(); + // encode the attribute value at index i for the next sendAttributeValues + void encodeAttributeValue(unsigned index); + + // Really sends the prepared attribute update values into the RTI + void sendAttributeValues(const RTIData& tag); + void sendAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag); + + class UpdateCallback : public SGReferenced { + public: + virtual ~UpdateCallback(); + + virtual void updateAttributeValues(HLAObjectInstance&, const RTIData&) = 0; + virtual void updateAttributeValues(HLAObjectInstance&, const SGTimeStamp&, const RTIData&) = 0; + }; + + void setUpdateCallback(const SGSharedPtr& updateCallback) + { _updateCallback = updateCallback; } + const SGSharedPtr& getUpdateCallback() const + { return _updateCallback; } + + + // Reflects the indices given in the index vector into the attributes HLADataElements. + virtual void reflectAttributeValues(const HLAIndexList& indexList, const RTIData& tag); + virtual void reflectAttributeValues(const HLAIndexList& indexList, const SGTimeStamp& timeStamp, const RTIData& tag); + // Reflect a single attribute value at the given index into the attributes HLADataELement. + virtual void reflectAttributeValue(unsigned index, const RTIData& tag); + virtual void reflectAttributeValue(unsigned index, const SGTimeStamp& timeStamp, const RTIData& tag); + + class ReflectCallback : public SGReferenced { + public: + virtual ~ReflectCallback(); + + virtual void reflectAttributeValues(HLAObjectInstance&, const HLAIndexList&, const RTIData&) = 0; + virtual void reflectAttributeValues(HLAObjectInstance&, const HLAIndexList&, const SGTimeStamp&, const RTIData&) = 0; + }; + + void setReflectCallback(const SGSharedPtr& reflectCallback) + { _reflectCallback = reflectCallback; } + const SGSharedPtr& getReflectCallback() const + { return _reflectCallback; } + + // deprecated. class AttributeCallback : public SGReferenced { public: virtual ~AttributeCallback() {} - // Notification about reflect and whatever TBD - // Hmm, don't know yet how this should look like virtual void updateAttributeValues(HLAObjectInstance& objectInstance, const RTIData& tag) { } - virtual void reflectAttributeValues(HLAObjectInstance& objectInstance, const RTIIndexDataPairList& dataPairList, const RTIData& tag) { } @@ -76,24 +142,58 @@ public: const SGSharedPtr& getAttributeCallback() const { return _attributeCallback; } - // Push the current values into the RTI - void updateAttributeValues(const RTIData& tag); - void updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag); - private: - void removeInstance(const RTIData& tag); - void reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const RTIData& tag); - void reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const SGTimeStamp& timeStamp, const RTIData& tag); - friend class RTIObjectInstance; - friend class HLAObjectClass; + void _setRTIObjectInstance(RTIObjectInstance* rtiObjectInstance); + void _clearRTIObjectInstance(); + + // The callback entry points from the RTI interface classes. + void _removeInstance(const RTIData& tag); + void _reflectAttributeValues(const HLAIndexList& indexList, const RTIData& tag); + void _reflectAttributeValues(const HLAIndexList& indexList, const SGTimeStamp& timeStamp, const RTIData& tag); class DataElementFactoryVisitor; + struct Attribute { + Attribute() : _enabledUpdate(false), _unconditionalUpdate(false) {} + SGSharedPtr _dataElement; + // SGSharedPtr _timeStamp; + bool _enabledUpdate; + bool _unconditionalUpdate; + // HLAIndexList::iterator _unconditionalUpdateAttributeIndexListIterator; + // HLAIndexList::iterator _conditionalUpdateAttributeIndexListIterator; + }; + typedef std::vector AttributeVector; + + // At some time we want these: Until then, use the _enabledUpdate and _unconditionalUpdate flags in the Attribute struct. + // HLAIndexList _unconditionalUpdateAttributeIndexList; + // HLAIndexList _conditionalUpdateAttributeIndexList; + + /// The parent Federate + SGWeakPtr _federate; + + /// The ObjectClass + SGSharedPtr _objectClass; + + /// The name as known in the RTI std::string _name; - SGWeakPtr _objectClass; + // /// The name as given by the local created instance + // std::string _givenName; + + /// The underlying rti dispatcher class SGSharedPtr _rtiObjectInstance; + + /// The attribute data + AttributeVector _attributeVector; + + // Callback classes + SGSharedPtr _updateCallback; + SGSharedPtr _reflectCallback; SGSharedPtr _attributeCallback; + + friend class HLAFederate; + friend class HLAObjectClass; + friend class RTIObjectInstance; }; } // namespace simgear diff --git a/simgear/hla/HLATypes.hxx b/simgear/hla/HLATypes.hxx index 931a4aa0..b968b1cf 100644 --- a/simgear/hla/HLATypes.hxx +++ b/simgear/hla/HLATypes.hxx @@ -18,6 +18,8 @@ #ifndef HLATypes_hxx #define HLATypes_hxx +#include + namespace simgear { enum HLASubscriptionType { @@ -38,6 +40,8 @@ enum HLAUpdateType { HLAUndefinedUpdate }; +typedef std::list HLAIndexList; + } // namespace simgear #endif diff --git a/simgear/hla/HLAVariantRecordDataType.cxx b/simgear/hla/HLAVariantRecordDataType.cxx index ff7488b9..8f62f2e0 100644 --- a/simgear/hla/HLAVariantRecordDataType.cxx +++ b/simgear/hla/HLAVariantRecordDataType.cxx @@ -43,6 +43,13 @@ HLAVariantRecordDataType::toVariantRecordDataType() const return this; } +void +HLAVariantRecordDataType::releaseDataTypeReferences() +{ + for (AlternativeList::iterator i = _alternativeList.begin(); i != _alternativeList.end(); ++i) + i->_dataType = 0; +} + bool HLAVariantRecordDataType::decode(HLADecodeStream& stream, HLAAbstractVariantRecordDataElement& value) const { @@ -94,8 +101,20 @@ HLAVariantRecordDataType::addAlternative(const std::string& name, const std::str _alternativeList[index]._name = name; _alternativeList[index]._dataType = dataType; _alternativeList[index]._semantics = semantics; - setAlignment(SGMisc::max(getAlignment(), dataType->getAlignment())); return true; } +void +HLAVariantRecordDataType::_recomputeAlignmentImplementation() +{ + unsigned alignment = 1; + if (const HLADataType* dataType = getEnumeratedDataType()) + alignment = std::max(alignment, dataType->getAlignment()); + for (unsigned i = 0; i < getNumAlternatives(); ++i) { + if (const HLADataType* dataType = getAlternativeDataType(i)) + alignment = std::max(alignment, dataType->getAlignment()); + } + setAlignment(alignment); +} + } // namespace simgear diff --git a/simgear/hla/HLAVariantRecordDataType.hxx b/simgear/hla/HLAVariantRecordDataType.hxx index 06226da9..dc586a9f 100644 --- a/simgear/hla/HLAVariantRecordDataType.hxx +++ b/simgear/hla/HLAVariantRecordDataType.hxx @@ -37,6 +37,8 @@ public: virtual const HLAVariantRecordDataType* toVariantRecordDataType() const; + virtual void releaseDataTypeReferences(); + virtual bool decode(HLADecodeStream& stream, HLAAbstractVariantRecordDataElement& value) const; virtual bool encode(HLAEncodeStream& stream, const HLAAbstractVariantRecordDataElement& value) const; @@ -84,6 +86,9 @@ public: std::string getAlternativeSemantics(const std::string& enumerator) const { return getAlternativeSemantics(getAlternativeIndex(enumerator)); } +protected: + virtual void _recomputeAlignmentImplementation(); + private: SGSharedPtr _enumeratedDataType; diff --git a/simgear/hla/RTI13Ambassador.hxx b/simgear/hla/RTI13Ambassador.hxx index 95a2ab38..85779fa7 100644 --- a/simgear/hla/RTI13Ambassador.hxx +++ b/simgear/hla/RTI13Ambassador.hxx @@ -71,11 +71,22 @@ public: { _rtiAmbassador.publishObjectClass(handle, attributeHandleSet); } void unpublishObjectClass(const RTI::ObjectClassHandle& handle) { _rtiAmbassador.unpublishObjectClass(handle); } + + void publishInteractionClass(const RTI::InteractionClassHandle& handle) + { _rtiAmbassador.publishInteractionClass(handle); } + void unpublishInteractionClass(const RTI::InteractionClassHandle& handle) + { _rtiAmbassador.unpublishInteractionClass(handle); } + void subscribeObjectClassAttributes(const RTI::ObjectClassHandle& handle, const RTI::AttributeHandleSet& attributeHandleSet, bool active) { _rtiAmbassador.subscribeObjectClassAttributes(handle, attributeHandleSet, active ? RTI::RTI_TRUE : RTI::RTI_FALSE); } void unsubscribeObjectClass(const RTI::ObjectClassHandle& handle) { _rtiAmbassador.unsubscribeObjectClass(handle); } + void subscribeInteractionClass(const RTI::InteractionClassHandle& handle, bool active) + { _rtiAmbassador.subscribeInteractionClass(handle, active ? RTI::RTI_TRUE : RTI::RTI_FALSE); } + void unsubscribeInteractionClass(const RTI::InteractionClassHandle& handle) + { _rtiAmbassador.unsubscribeInteractionClass(handle); } + RTI::ObjectHandle registerObjectInstance(const RTI::ObjectClassHandle& handle) { return _rtiAmbassador.registerObjectInstance(handle); } void updateAttributeValues(const RTI::ObjectHandle& objectHandle, const RTI::AttributeHandleValuePairSet& attributeValues, @@ -264,20 +275,8 @@ public: // } // return false; // } - // bool isAttributeOwnedByFederate(const RTIHandle& objectHandle, const RTIHandle& attributeHandle) - // { - // try { - // return _rtiAmbassador.isAttributeOwnedByFederate(objectHandle, attributeHandle); - // } catch (RTI::ObjectNotKnown& e) { - // } catch (RTI::AttributeNotDefined& e) { - // } catch (RTI::FederateNotExecutionMember& e) { - // } catch (RTI::ConcurrentAccessAttempted& e) { - // } catch (RTI::SaveInProgress& e) { - // } catch (RTI::RestoreInProgress& e) { - // } catch (RTI::RTIinternalError& e) { - // } - // return false; - // } + bool isAttributeOwnedByFederate(const RTI::ObjectHandle& objectHandle, const RTI::AttributeHandle& attributeHandle) + { return _rtiAmbassador.isAttributeOwnedByFederate(objectHandle, attributeHandle); } /// Time Management @@ -347,55 +346,15 @@ public: std::string getAttributeName(const RTI::AttributeHandle& attributeHandle, const RTI::ObjectClassHandle& objectClassHandle) { return rtiToStdString(_rtiAmbassador.getAttributeName(attributeHandle, objectClassHandle)); } - // RTIHandle getInteractionClassHandle(const std::string& name) - // { - // try { - // return _rtiAmbassador.getInteractionClassHandle(name.c_str()); - // } catch (RTI::NameNotFound& e) { - // } catch (RTI::FederateNotExecutionMember& e) { - // } catch (RTI::ConcurrentAccessAttempted& e) { - // } catch (RTI::RTIinternalError& e) { - // } - // return RTIHandle(-1); - // } - // std::string getInteractionClassName(const RTIHandle& handle) - // { - // std::string name; - // try { - // rtiToStdString(name, _rtiAmbassador.getInteractionClassName(handle)); - // } catch (RTI::InteractionClassNotDefined& e) { - // } catch (RTI::FederateNotExecutionMember& e) { - // } catch (RTI::ConcurrentAccessAttempted& e) { - // } catch (RTI::RTIinternalError& e) { - // } - // return name; - // } + RTI::InteractionClassHandle getInteractionClassHandle(const std::string& name) + { return _rtiAmbassador.getInteractionClassHandle(name.c_str()); } + std::string getInteractionClassName(const RTI::InteractionClassHandle& handle) + { return rtiToStdString(_rtiAmbassador.getInteractionClassName(handle)); } - // RTIHandle getParameterHandle(const std::string& parameterName, const RTIHandle& interactionClassHandle) - // { - // try { - // return _rtiAmbassador.getParameterHandle(parameterName.c_str(), interactionClassHandle); - // } catch (RTI::InteractionClassNotDefined& e) { - // } catch (RTI::NameNotFound& e) { - // } catch (RTI::FederateNotExecutionMember& e) { - // } catch (RTI::ConcurrentAccessAttempted& e) { - // } catch (RTI::RTIinternalError& e) { - // } - // return RTIHandle(-1); - // } - // std::string getParameterName(const RTIHandle& parameterHandle, const RTIHandle& interactionClassHandle) - // { - // std::string parameterName; - // try { - // rtiToStdString(parameterName, _rtiAmbassador.getParameterName(parameterHandle, interactionClassHandle)); - // } catch (RTI::InteractionClassNotDefined& e) { - // } catch (RTI::InteractionParameterNotDefined& e) { - // } catch (RTI::FederateNotExecutionMember& e) { - // } catch (RTI::ConcurrentAccessAttempted& e) { - // } catch (RTI::RTIinternalError& e) { - // } - // return parameterName; - // } + RTI::ParameterHandle getParameterHandle(const std::string& parameterName, const RTI::InteractionClassHandle& interactionClassHandle) + { return _rtiAmbassador.getParameterHandle(parameterName.c_str(), interactionClassHandle); } + std::string getParameterName(const RTI::ParameterHandle& parameterHandle, const RTI::InteractionClassHandle& interactionClassHandle) + { return rtiToStdString(_rtiAmbassador.getParameterName(parameterHandle, interactionClassHandle)); } RTI::ObjectHandle getObjectInstanceHandle(const std::string& name) { return _rtiAmbassador.getObjectInstanceHandle(name.c_str()); } diff --git a/simgear/hla/RTI13Federate.cxx b/simgear/hla/RTI13Federate.cxx index 08dbdd86..c9dbfac2 100644 --- a/simgear/hla/RTI13Federate.cxx +++ b/simgear/hla/RTI13Federate.cxx @@ -222,7 +222,7 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { return; if (!i->second.valid()) return; - SGSharedPtr objectInstance = new RTI13ObjectInstance(objectHandle, 0, i->second, _rtiAmbassador.get(), false); + SGSharedPtr objectInstance = new RTI13ObjectInstance(objectHandle, 0, i->second, _rtiAmbassador.get()); _objectInstanceMap[objectHandle] = objectInstance; i->second->discoverInstance(objectInstance.get(), tag); } @@ -278,7 +278,7 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { return; if (!i->second.valid()) return; - i->second->reflectAttributeValues(attributeHandleDataPairList, timeStamp, tag); + i->second->reflectAttributeValues(attributeHandleDataPairList, timeStamp, tag, _indexPool); } class ReflectAttributeValuesCallback : public TagQueueCallback { @@ -327,7 +327,7 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { return; if (!i->second.valid()) return; - i->second->reflectAttributeValues(attributeHandleDataPairList, tag); + i->second->reflectAttributeValues(attributeHandleDataPairList, tag, _indexPool); } virtual void receiveInteraction(RTI::InteractionClassHandle interactionClassHandle, const RTI::ParameterHandleValuePairSet& parameters, @@ -855,6 +855,9 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { void freeAttributeHandleDataPairList(RTI13AttributeHandleDataPairList& attributeHandleDataPairList) { _attributeHandleDataPairPool.splice(_attributeHandleDataPairPool.end(), attributeHandleDataPairList); } + // For attribute reflection, pool or indices + HLAIndexList _indexPool; + // Top level information for dispatching federate object attribute updates typedef std::map > ObjectInstanceMap; // Map of all available objects @@ -864,6 +867,10 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador { typedef std::map > ObjectClassMap; ObjectClassMap _objectClassMap; + // Top level information for dispatching creation of federate objects + typedef std::map > InteractionClassMap; + InteractionClassMap _interactionClassMap; + bool _timeRegulationEnabled; bool _timeConstrainedEnabled; bool _timeAdvancePending; @@ -1602,6 +1609,35 @@ RTI13Federate::createObjectClass(const std::string& objectClassName, HLAObjectCl } } +RTI13InteractionClass* +RTI13Federate::createInteractionClass(const std::string& interactionClassName, HLAInteractionClass* interactionClass) +{ + try { + RTI::InteractionClassHandle interactionClassHandle; + interactionClassHandle = _ambassador->getInteractionClassHandle(interactionClassName); + if (_federateAmbassador->_interactionClassMap.find(interactionClassHandle) != _federateAmbassador->_interactionClassMap.end()) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not create interaction class, interaction class already exists!"); + return 0; + } + RTI13InteractionClass* rtiInteractionClass; + rtiInteractionClass = new RTI13InteractionClass(interactionClass, interactionClassHandle, _ambassador.get()); + _federateAmbassador->_interactionClassMap[interactionClassHandle] = rtiInteractionClass; + return rtiInteractionClass; + } catch (RTI::NameNotFound& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get interaction class: " << e._name << " " << e._reason); + return 0; + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get interaction class: " << e._name << " " << e._reason); + return 0; + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get interaction class: " << e._name << " " << e._reason); + return 0; + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get interaction class: " << e._name << " " << e._reason); + return 0; + } +} + RTI13ObjectInstance* RTI13Federate::getObjectInstance(const std::string& objectInstanceName) { diff --git a/simgear/hla/RTI13Federate.hxx b/simgear/hla/RTI13Federate.hxx index 9b8341d2..83878ad0 100644 --- a/simgear/hla/RTI13Federate.hxx +++ b/simgear/hla/RTI13Federate.hxx @@ -25,6 +25,7 @@ #include #include "RTIFederate.hxx" +#include "RTI13InteractionClass.hxx" #include "RTI13ObjectClass.hxx" #include "RTI13ObjectInstance.hxx" @@ -78,6 +79,7 @@ public: virtual bool processMessages(const double& minimum, const double& maximum); virtual RTI13ObjectClass* createObjectClass(const std::string& name, HLAObjectClass* hlaObjectClass); + virtual RTI13InteractionClass* createInteractionClass(const std::string& name, HLAInteractionClass* interactionClass); virtual RTI13ObjectInstance* getObjectInstance(const std::string& name); void insertObjectInstance(RTI13ObjectInstance* objectInstance); diff --git a/simgear/hla/RTI13InteractionClass.cxx b/simgear/hla/RTI13InteractionClass.cxx new file mode 100644 index 00000000..f5508fa0 --- /dev/null +++ b/simgear/hla/RTI13InteractionClass.cxx @@ -0,0 +1,239 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include "RTI13InteractionClass.hxx" + +#include "RTI13Ambassador.hxx" + +namespace simgear { + +RTI13InteractionClass::RTI13InteractionClass(HLAInteractionClass* interactionClass, const RTI::InteractionClassHandle& handle, RTI13Ambassador* ambassador) : + RTIInteractionClass(interactionClass), + _handle(handle), + _ambassador(ambassador) +{ +} + +RTI13InteractionClass::~RTI13InteractionClass() +{ +} + +bool +RTI13InteractionClass::resolveParameterIndex(const std::string& name, unsigned index) +{ + if (!_ambassador.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero."); + return false; + } + + if (index != _parameterHandleVector.size()) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Resolving needs to happen in growing index order!"); + return false; + } + + try { + RTI::ParameterHandle parameterHandle = _ambassador->getParameterHandle(name, _handle); + + ParameterHandleIndexMap::const_iterator i = _parameterHandleIndexMap.find(parameterHandle); + if (i != _parameterHandleIndexMap.end()) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Resolving parameterIndex for parameter \"" << name << "\" twice!"); + return false; + } + + _parameterHandleIndexMap[parameterHandle] = index; + _parameterHandleVector.push_back(parameterHandle); + + return true; + + } catch (RTI::NameNotFound& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get interaction class parameter: " << e._name << " " << e._reason); + return false; + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get interaction class parameter: " << e._name << " " << e._reason); + return false; + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get interaction class parameter: " << e._name << " " << e._reason); + return false; + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get interaction class parameter: " << e._name << " " << e._reason); + return false; + } catch (...) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get interaction class parameter."); + return false; + } + + return false; +} + +bool +RTI13InteractionClass::publish() +{ + if (!_ambassador.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero."); + return false; + } + + try { + _ambassador->publishInteractionClass(_handle); + return true; + } catch (RTI::InteractionClassNotDefined& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not publish interaction class: " << e._name << " " << e._reason); + return false; + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not publish interaction class: " << e._name << " " << e._reason); + return false; + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not publish interaction class: " << e._name << " " << e._reason); + return false; + } catch (RTI::SaveInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not publish interaction class: " << e._name << " " << e._reason); + return false; + } catch (RTI::RestoreInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not publish interaction class: " << e._name << " " << e._reason); + return false; + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not publish interaction class: " << e._name << " " << e._reason); + return false; + } catch (...) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not publish interaction class."); + return false; + } + + return false; +} + +bool +RTI13InteractionClass::unpublish() +{ + if (!_ambassador.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero."); + return false; + } + + try { + _ambassador->unpublishInteractionClass(_handle); + return true; + } catch (RTI::InteractionClassNotDefined& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unpublish interaction class: " << e._name << " " << e._reason); + return false; + } catch (RTI::InteractionClassNotPublished& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unpublish interaction class: " << e._name << " " << e._reason); + return false; + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unpublish interaction class: " << e._name << " " << e._reason); + return false; + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unpublish interaction class: " << e._name << " " << e._reason); + return false; + } catch (RTI::SaveInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unpublish interaction class: " << e._name << " " << e._reason); + return false; + } catch (RTI::RestoreInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unpublish interaction class: " << e._name << " " << e._reason); + return false; + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unpublish interaction class: " << e._name << " " << e._reason); + return false; + } catch (...) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unpublish interaction class."); + return false; + } + + return false; +} + +bool +RTI13InteractionClass::subscribe(bool active) +{ + if (!_ambassador.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero."); + return false; + } + + try { + _ambassador->subscribeInteractionClass(_handle, active); + return true; + } catch (RTI::InteractionClassNotDefined& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not subscribe interaction class: " << e._name << " " << e._reason); + return false; + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not subscribe interaction class: " << e._name << " " << e._reason); + return false; + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not subscribe interaction class: " << e._name << " " << e._reason); + return false; + } catch (RTI::FederateLoggingServiceCalls& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not subscribe interaction class: " << e._name << " " << e._reason); + return false; + } catch (RTI::SaveInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not subscribe interaction class: " << e._name << " " << e._reason); + return false; + } catch (RTI::RestoreInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not subscribe interaction class: " << e._name << " " << e._reason); + return false; + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not subscribe interaction class: " << e._name << " " << e._reason); + return false; + } catch (...) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not subscribe interaction class."); + return false; + } + + return false; +} + +bool +RTI13InteractionClass::unsubscribe() +{ + if (!_ambassador.valid()) { + SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero."); + return false; + } + + try { + _ambassador->unsubscribeInteractionClass(_handle); + return true; + } catch (RTI::InteractionClassNotDefined& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unsubscribe interaction class: " << e._name << " " << e._reason); + return false; + } catch (RTI::InteractionClassNotSubscribed& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unsubscribe interaction class: " << e._name << " " << e._reason); + return false; + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unsubscribe interaction class: " << e._name << " " << e._reason); + return false; + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unsubscribe interaction class: " << e._name << " " << e._reason); + return false; + } catch (RTI::SaveInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unsubscribe interaction class: " << e._name << " " << e._reason); + return false; + } catch (RTI::RestoreInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unsubscribe interaction class: " << e._name << " " << e._reason); + return false; + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unsubscribe interaction class: " << e._name << " " << e._reason); + return false; + } catch (...) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unsubscribe interaction class."); + return false; + } + + return false; +} + +} diff --git a/simgear/hla/RTI13InteractionClass.hxx b/simgear/hla/RTI13InteractionClass.hxx new file mode 100644 index 00000000..80faae88 --- /dev/null +++ b/simgear/hla/RTI13InteractionClass.hxx @@ -0,0 +1,64 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#ifndef RTI13InteractionClass_hxx +#define RTI13InteractionClass_hxx + +#include +#include + +#ifndef RTI_USES_STD_FSTREAM +#define RTI_USES_STD_FSTREAM +#endif + +#include + +#include "RTIInteractionClass.hxx" + +#include + +namespace simgear { + +class RTI13Ambassador; + +class RTI13InteractionClass : public RTIInteractionClass { +public: + RTI13InteractionClass(HLAInteractionClass* interactionClass, const RTI::InteractionClassHandle& handle, RTI13Ambassador* ambassador); + virtual ~RTI13InteractionClass(); + + virtual bool resolveParameterIndex(const std::string& name, unsigned index); + + virtual bool publish(); + virtual bool unpublish(); + + virtual bool subscribe(bool); + virtual bool unsubscribe(); + +private: + RTI::InteractionClassHandle _handle; + SGSharedPtr _ambassador; + + typedef std::map ParameterHandleIndexMap; + ParameterHandleIndexMap _parameterHandleIndexMap; + + typedef std::vector ParameterHandleVector; + ParameterHandleVector _parameterHandleVector; +}; + +} + +#endif diff --git a/simgear/hla/RTI13ObjectClass.cxx b/simgear/hla/RTI13ObjectClass.cxx index fcc41682..298330bb 100644 --- a/simgear/hla/RTI13ObjectClass.cxx +++ b/simgear/hla/RTI13ObjectClass.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public @@ -20,151 +20,73 @@ namespace simgear { -RTI13ObjectClass::RTI13ObjectClass(HLAObjectClass* hlaObjectClass, RTI::ObjectClassHandle& handle, RTI13Ambassador* ambassador) : +RTI13ObjectClass::RTI13ObjectClass(HLAObjectClass* hlaObjectClass, const RTI::ObjectClassHandle& handle, RTI13Ambassador* ambassador) : RTIObjectClass(hlaObjectClass), _handle(handle), _ambassador(ambassador) { - if (0 != getOrCreateAttributeIndex("privilegeToDelete") && - 0 != getOrCreateAttributeIndex("HLAprivilegeToDeleteObject")) - SG_LOG(SG_NETWORK, SG_WARN, "RTI13ObjectClass: Cannot find object root attribute."); } RTI13ObjectClass::~RTI13ObjectClass() { } -std::string -RTI13ObjectClass::getName() const -{ - if (!_ambassador.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero."); - return std::string(); - } - return _ambassador->getObjectClassName(_handle); -} - -unsigned -RTI13ObjectClass::getNumAttributes() const -{ - return _attributeHandleVector.size(); -} - -unsigned -RTI13ObjectClass::getAttributeIndex(const std::string& name) const +bool +RTI13ObjectClass::resolveAttributeIndex(const std::string& name, unsigned index) { if (!_ambassador.valid()) { SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero."); - return ~0u; - } - - try { - RTI::AttributeHandle attributeHandle = _ambassador->getAttributeHandle(name, _handle); - - AttributeHandleIndexMap::const_iterator i = _attributeHandleIndexMap.find(attributeHandle); - if (i != _attributeHandleIndexMap.end()) - return i->second; - - return ~0u; - - } catch (RTI::ObjectClassNotDefined& e) { - SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute: " << e._name << " " << e._reason); - return ~0u; - } catch (RTI::NameNotFound& e) { - SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute: " << e._name << " " << e._reason); - return ~0u; - } catch (RTI::FederateNotExecutionMember& e) { - SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute: " << e._name << " " << e._reason); - return ~0u; - } catch (RTI::ConcurrentAccessAttempted& e) { - SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute: " << e._name << " " << e._reason); - return ~0u; - } catch (RTI::RTIinternalError& e) { - SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute: " << e._name << " " << e._reason); - return ~0u; - } catch (...) { - SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute."); - return ~0u; + return false; } -} -unsigned -RTI13ObjectClass::getOrCreateAttributeIndex(const std::string& name) -{ - if (!_ambassador.valid()) { - SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero."); - return ~0u; + if (index != _attributeHandleVector.size()) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Resolving needs to happen in growing index order!"); + return false; } try { RTI::AttributeHandle attributeHandle = _ambassador->getAttributeHandle(name, _handle); AttributeHandleIndexMap::const_iterator i = _attributeHandleIndexMap.find(attributeHandle); - if (i != _attributeHandleIndexMap.end()) - return i->second; + if (i != _attributeHandleIndexMap.end()) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Resolving attributeIndex for attribute \"" << name << "\" twice!"); + return false; + } - unsigned index = _attributeHandleVector.size(); _attributeHandleIndexMap[attributeHandle] = index; _attributeHandleVector.push_back(attributeHandle); - _attributeDataVector.push_back(name); - return index; + return true; } catch (RTI::ObjectClassNotDefined& e) { SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute: " << e._name << " " << e._reason); - return ~0u; + return false; } catch (RTI::NameNotFound& e) { SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute: " << e._name << " " << e._reason); - return ~0u; + return false; } catch (RTI::FederateNotExecutionMember& e) { SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute: " << e._name << " " << e._reason); - return ~0u; + return false; } catch (RTI::ConcurrentAccessAttempted& e) { SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute: " << e._name << " " << e._reason); - return ~0u; + return false; } catch (RTI::RTIinternalError& e) { SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute: " << e._name << " " << e._reason); - return ~0u; + return false; } catch (...) { SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute."); - return ~0u; + return false; } } -// std::string -// RTI13ObjectClass::getAttributeName(unsigned index) const -// { -// SGSharedPtr ambassador = _ambassador.lock(); -// if (!ambassador.valid()) { -// SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero."); -// return std::string(); -// } - -// try { -// return ambassador->getAttributeName(getAttributeHandle(index), _handle); -// } catch (RTI::ObjectClassNotDefined& e) { -// SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute name: " << e._name << " " << e._reason); -// return std::string(); -// } catch (RTI::AttributeNotDefined& e) { -// SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute name: " << e._name << " " << e._reason); -// return std::string(); -// } catch (RTI::FederateNotExecutionMember& e) { -// SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute name: " << e._name << " " << e._reason); -// return std::string(); -// } catch (RTI::ConcurrentAccessAttempted& e) { -// SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute name: " << e._name << " " << e._reason); -// return std::string(); -// } catch (RTI::RTIinternalError& e) { -// SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute name: " << e._name << " " << e._reason); -// return std::string(); -// } catch (...) { -// SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not get object class attribute name."); -// return std::string(); -// } -// } +unsigned +RTI13ObjectClass::getNumAttributes() const +{ + return _attributeHandleVector.size(); +} bool -RTI13ObjectClass::publish(const std::set& indexSet) +RTI13ObjectClass::publish(const HLAIndexList& indexList) { if (!_ambassador.valid()) { SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero."); @@ -172,8 +94,9 @@ RTI13ObjectClass::publish(const std::set& indexSet) } try { - std::auto_ptr attributeHandleSet(RTI::AttributeHandleSetFactory::create(indexSet.size())); - for (std::set::const_iterator i = indexSet.begin(); i != indexSet.end(); ++i) { + unsigned numAttributes = getNumAttributes(); + std::auto_ptr attributeHandleSet(RTI::AttributeHandleSetFactory::create(numAttributes)); + for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i) { if (_attributeHandleVector.size() <= *i) { SG_LOG(SG_NETWORK, SG_WARN, "RTI13ObjectClass::publish(): Invalid attribute index!"); continue; @@ -183,10 +106,6 @@ RTI13ObjectClass::publish(const std::set& indexSet) _ambassador->publishObjectClass(_handle, *attributeHandleSet); - for (unsigned i = 0; i < getNumAttributes(); ++i) { - _attributeDataVector[i]._published = true; - } - return true; } catch (RTI::ObjectClassNotDefined& e) { SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not publish object class: " << e._name << " " << e._reason); @@ -229,10 +148,6 @@ RTI13ObjectClass::unpublish() try { _ambassador->unpublishObjectClass(_handle); - for (unsigned i = 0; i < getNumAttributes(); ++i) { - _attributeDataVector[i]._published = false; - } - return true; } catch (RTI::ObjectClassNotDefined& e) { SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unpublish object class: " << e._name << " " << e._reason); @@ -265,7 +180,7 @@ RTI13ObjectClass::unpublish() } bool -RTI13ObjectClass::subscribe(const std::set& indexSet, bool active) +RTI13ObjectClass::subscribe(const HLAIndexList& indexList, bool active) { if (!_ambassador.valid()) { SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero."); @@ -273,9 +188,9 @@ RTI13ObjectClass::subscribe(const std::set& indexSet, bool active) } try { - std::auto_ptr attributeHandleSet(RTI::AttributeHandleSetFactory::create(indexSet.size())); - for (std::set::const_iterator i = indexSet.begin(); - i != indexSet.end(); ++i) { + unsigned numAttributes = getNumAttributes(); + std::auto_ptr attributeHandleSet(RTI::AttributeHandleSetFactory::create(numAttributes)); + for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i) { if (_attributeHandleVector.size() <= *i) { SG_LOG(SG_NETWORK, SG_WARN, "RTI13ObjectClass::subscribe(): Invalid attribute index!"); continue; @@ -285,10 +200,6 @@ RTI13ObjectClass::subscribe(const std::set& indexSet, bool active) _ambassador->subscribeObjectClassAttributes(_handle, *attributeHandleSet, active); - for (unsigned i = 0; i < getNumAttributes(); ++i) { - _attributeDataVector[i]._subscribed = true; - } - return true; } catch (RTI::ObjectClassNotDefined& e) { SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not subscribe object class: " << e._name << " " << e._reason); @@ -328,10 +239,6 @@ RTI13ObjectClass::unsubscribe() try { _ambassador->unsubscribeObjectClass(_handle); - for (unsigned i = 0; i < getNumAttributes(); ++i) { - _attributeDataVector[i]._subscribed = false; - } - return true; } catch (RTI::ObjectClassNotDefined& e) { SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not unsubscribe object class: " << e._name << " " << e._reason); @@ -376,7 +283,7 @@ RTI13ObjectClass::registerObjectInstance(HLAObjectInstance* hlaObjectInstance) try { RTI::ObjectHandle objectHandle = _ambassador->registerObjectInstance(getHandle()); - RTI13ObjectInstance* objectInstance = new RTI13ObjectInstance(objectHandle, hlaObjectInstance, this, _ambassador.get(), true); + RTI13ObjectInstance* objectInstance = new RTI13ObjectInstance(objectHandle, hlaObjectInstance, this, _ambassador.get()); federate->insertObjectInstance(objectInstance); return objectInstance; } catch (RTI::ObjectClassNotDefined& e) { diff --git a/simgear/hla/RTI13ObjectClass.hxx b/simgear/hla/RTI13ObjectClass.hxx index c4949ca9..492bc792 100644 --- a/simgear/hla/RTI13ObjectClass.hxx +++ b/simgear/hla/RTI13ObjectClass.hxx @@ -1,4 +1,4 @@ -// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public @@ -37,17 +37,15 @@ class RTIObjectInstance; class RTI13ObjectClass : public RTIObjectClass { public: - RTI13ObjectClass(HLAObjectClass* hlaObjectClass, RTI::ObjectClassHandle& handle, RTI13Ambassador* ambassador); + RTI13ObjectClass(HLAObjectClass* hlaObjectClass, const RTI::ObjectClassHandle& handle, RTI13Ambassador* ambassador); virtual ~RTI13ObjectClass(); const RTI::ObjectClassHandle& getHandle() const { return _handle; } - virtual std::string getName() const; + virtual bool resolveAttributeIndex(const std::string& name, unsigned index); virtual unsigned getNumAttributes() const; - virtual unsigned getAttributeIndex(const std::string& name) const; - virtual unsigned getOrCreateAttributeIndex(const std::string& name); unsigned getAttributeIndex(const RTI::AttributeHandle& handle) const { @@ -63,10 +61,10 @@ public: return _attributeHandleVector[index]; } - virtual bool publish(const std::set& indexSet); + virtual bool publish(const HLAIndexList& indexList); virtual bool unpublish(); - virtual bool subscribe(const std::set& indexSet, bool); + virtual bool subscribe(const HLAIndexList& indexList, bool); virtual bool unsubscribe(); virtual RTIObjectInstance* registerObjectInstance(HLAObjectInstance* hlaObjectInstance); diff --git a/simgear/hla/RTI13ObjectInstance.cxx b/simgear/hla/RTI13ObjectInstance.cxx index f8ba657f..7333d43c 100644 --- a/simgear/hla/RTI13ObjectInstance.cxx +++ b/simgear/hla/RTI13ObjectInstance.cxx @@ -20,15 +20,15 @@ namespace simgear { -RTI13ObjectInstance::RTI13ObjectInstance(const RTI::ObjectHandle& handle, HLAObjectInstance* hlaObjectInstance, - const RTI13ObjectClass* objectClass, RTI13Ambassador* ambassador, bool owned) : - RTIObjectInstance(hlaObjectInstance), +RTI13ObjectInstance::RTI13ObjectInstance(const RTI::ObjectHandle& handle, HLAObjectInstance* objectInstance, + const RTI13ObjectClass* objectClass, RTI13Ambassador* ambassador) : + RTIObjectInstance(objectInstance), _handle(handle), _objectClass(objectClass), _ambassador(ambassador), _attributeValuePairSet(RTI::AttributeSetFactory::create(objectClass->getNumAttributes())) { - updateAttributesFromClass(owned); + _setNumAttributes(getNumAttributes()); } RTI13ObjectInstance::~RTI13ObjectInstance() @@ -177,82 +177,80 @@ RTI13ObjectInstance::localDeleteObjectInstance() } void -RTI13ObjectInstance::reflectAttributeValues(RTI13AttributeHandleDataPairList& attributeHandleDataPairList, const RTIData& tag) +RTI13ObjectInstance::reflectAttributeValues(RTI13AttributeHandleDataPairList& attributeHandleDataPairList, + const RTIData& tag, HLAIndexList& indexPool) { - // Retrieve an empty update struct from the memory pool - RTIIndexDataPairList indexDataPairList; + HLAIndexList reflectedIndices; for (RTI13AttributeHandleDataPairList::iterator i = attributeHandleDataPairList.begin(); i != attributeHandleDataPairList.end(); ++i) { unsigned index = getAttributeIndex(i->first); - // Get a RTIData from the data pool - getDataFromPool(indexDataPairList); - indexDataPairList.back().first = index; - indexDataPairList.back().second.swap(i->second); - } + _attributeData[index]._data.swap(i->second); - RTIObjectInstance::reflectAttributeValues(indexDataPairList, tag); - - RTIIndexDataPairList::iterator j = indexDataPairList.begin(); - for (RTI13AttributeHandleDataPairList::iterator i = attributeHandleDataPairList.begin(); - i != attributeHandleDataPairList.end(); ++i, ++j) { - i->second.swap(j->second); + if (indexPool.empty()) + reflectedIndices.push_back(index); + else { + reflectedIndices.splice(reflectedIndices.end(), indexPool, indexPool.begin()); + reflectedIndices.back() = index; + } } - // Return the update data back to the pool - putDataToPool(indexDataPairList); + RTIObjectInstance::reflectAttributeValues(reflectedIndices, tag); + + // Return the index list to the pool + indexPool.splice(indexPool.end(), reflectedIndices); } void RTI13ObjectInstance::reflectAttributeValues(RTI13AttributeHandleDataPairList& attributeHandleDataPairList, - const SGTimeStamp& timeStamp, const RTIData& tag) + const SGTimeStamp& timeStamp, const RTIData& tag, HLAIndexList& indexPool) { - // Retrieve an empty update struct from the memory pool - RTIIndexDataPairList indexDataPairList; + HLAIndexList reflectedIndices; for (RTI13AttributeHandleDataPairList::iterator i = attributeHandleDataPairList.begin(); i != attributeHandleDataPairList.end(); ++i) { unsigned index = getAttributeIndex(i->first); - // Get a RTIData from the data pool - getDataFromPool(indexDataPairList); - indexDataPairList.back().first = index; - indexDataPairList.back().second.swap(i->second); - } - - RTIObjectInstance::reflectAttributeValues(indexDataPairList, timeStamp, tag); + _attributeData[index]._data.swap(i->second); - RTIIndexDataPairList::iterator j = indexDataPairList.begin(); - for (RTI13AttributeHandleDataPairList::iterator i = attributeHandleDataPairList.begin(); - i != attributeHandleDataPairList.end(); ++i, ++j) { - i->second.swap(j->second); + if (indexPool.empty()) + reflectedIndices.push_back(index); + else { + reflectedIndices.splice(reflectedIndices.end(), indexPool, indexPool.begin()); + reflectedIndices.back() = index; + } } - // Return the update data back to the pool - putDataToPool(indexDataPairList); + RTIObjectInstance::reflectAttributeValues(reflectedIndices, timeStamp, tag); + + // Return the index list to the pool + indexPool.splice(indexPool.end(), reflectedIndices); } void -RTI13ObjectInstance::requestObjectAttributeValueUpdate() +RTI13ObjectInstance::requestObjectAttributeValueUpdate(const HLAIndexList& indexList) { if (!_ambassador.valid()) { SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero."); return; } + if (indexList.empty()) + return; + try { unsigned numAttributes = getNumAttributes(); std::auto_ptr attributeHandleSet(RTI::AttributeHandleSetFactory::create(numAttributes)); - for (unsigned i = 0; i < numAttributes; ++i) { - if (!getRequestAttributeUpdate(i)) + for (HLAIndexList::const_iterator i = indexList.begin(); i != indexList.end(); ++i) { + if (getAttributeOwned(*i)) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI13ObjectInstance::requestObjectAttributeValueUpdate(): " + "Invalid attribute index!"); continue; - attributeHandleSet->add(getAttributeHandle(i)); + } + attributeHandleSet->add(getAttributeHandle(*i)); } if (!attributeHandleSet->size()) return; _ambassador->requestObjectAttributeValueUpdate(_handle, *attributeHandleSet); - for (unsigned i = 0; i < numAttributes; ++i) - setRequestAttributeUpdate(i, false); - return; } catch (RTI::ObjectNotKnown& e) { SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not request attribute update for object instance: " << e._name << " " << e._reason); @@ -288,7 +286,7 @@ RTI13ObjectInstance::provideAttributeValueUpdate(const std::vectorencode(stream); + const RTIData& data = _attributeData[i]._data; _attributeValuePairSet->add(getAttributeHandle(i), data.data(), data.size()); } @@ -324,7 +316,7 @@ RTI13ObjectInstance::updateAttributeValues(const RTIData& tag) _ambassador->updateAttributeValues(_handle, *_attributeValuePairSet, tag); for (unsigned i = 0; i < numAttributes; ++i) { - setAttributeUpdated(i); + _attributeData[i]._dirty = false; } } catch (RTI::ObjectNotKnown& e) { @@ -363,15 +355,9 @@ RTI13ObjectInstance::updateAttributeValues(const SGTimeStamp& timeStamp, const R unsigned numAttributes = getNumAttributes(); for (unsigned i = 0; i < numAttributes; ++i) { - if (!getAttributeEffectiveUpdateEnabled(i)) + if (!_attributeData[i]._dirty) continue; - const HLADataElement* dataElement = getDataElement(i); - if (!dataElement) - continue; - // FIXME cache somewhere - RTIData data; - HLAEncodeStream stream(data); - dataElement->encode(stream); + const RTIData& data = _attributeData[i]._data; _attributeValuePairSet->add(getAttributeHandle(i), data.data(), data.size()); } @@ -381,7 +367,7 @@ RTI13ObjectInstance::updateAttributeValues(const SGTimeStamp& timeStamp, const R _ambassador->updateAttributeValues(_handle, *_attributeValuePairSet, timeStamp, tag); for (unsigned i = 0; i < numAttributes; ++i) { - setAttributeUpdated(i); + _attributeData[i]._dirty = false; } } catch (RTI::ObjectNotKnown& e) { @@ -448,6 +434,48 @@ RTI13ObjectInstance::turnUpdatesOffForObjectInstance(const std::vectorisAttributeOwnedByFederate(_handle, attributeHandle); + } catch (RTI::ObjectNotKnown& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query attribute ownership for index " << index << ": " + << e._name << " " << e._reason); + return false; + } catch (RTI::AttributeNotDefined& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query attribute ownership for index " << index << ": " + << e._name << " " << e._reason); + return false; + } catch (RTI::FederateNotExecutionMember& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query attribute ownership for index " << index << ": " + << e._name << " " << e._reason); + return false; + } catch (RTI::ConcurrentAccessAttempted& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query attribute ownership for index " << index << ": " + << e._name << " " << e._reason); + return false; + } catch (RTI::SaveInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query attribute ownership for index " << index << ": " + << e._name << " " << e._reason); + return false; + } catch (RTI::RestoreInProgress& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query attribute ownership for index " << index << ": " + << e._name << " " << e._reason); + return false; + } catch (RTI::RTIinternalError& e) { + SG_LOG(SG_NETWORK, SG_WARN, "RTI: Could not query attribute ownership for index " << index << ": " + << e._name << " " << e._reason); + return false; + } + return false; + } + void RTI13ObjectInstance::requestAttributeOwnershipAssumption(const std::vector& attributes, const RTIData& tag) { diff --git a/simgear/hla/RTI13ObjectInstance.hxx b/simgear/hla/RTI13ObjectInstance.hxx index 38fd92b2..cfba3872 100644 --- a/simgear/hla/RTI13ObjectInstance.hxx +++ b/simgear/hla/RTI13ObjectInstance.hxx @@ -42,7 +42,7 @@ typedef std::list RTI13AttributeHandleDataPairList class RTI13ObjectInstance : public RTIObjectInstance { public: - RTI13ObjectInstance(const RTI::ObjectHandle& handle, HLAObjectInstance* hlaObjectInstance, const RTI13ObjectClass* objectClass, RTI13Ambassador* ambassador, bool owned); + RTI13ObjectInstance(const RTI::ObjectHandle& handle, HLAObjectInstance* hlaObjectInstance, const RTI13ObjectClass* objectClass, RTI13Ambassador* ambassador); virtual ~RTI13ObjectInstance(); const RTI::ObjectHandle& getHandle() const @@ -55,8 +55,6 @@ public: unsigned getNumAttributes() const { return get13ObjectClass()->getNumAttributes(); } - unsigned getAttributeIndex(const std::string& name) const - { return get13ObjectClass()->getAttributeIndex(name); } unsigned getAttributeIndex(const RTI::AttributeHandle& handle) const { return get13ObjectClass()->getAttributeIndex(handle); } RTI::AttributeHandle getAttributeHandle(unsigned index) const @@ -68,14 +66,18 @@ public: virtual void deleteObjectInstance(const SGTimeStamp& timeStamp, const RTIData& tag); virtual void localDeleteObjectInstance(); - void reflectAttributeValues(RTI13AttributeHandleDataPairList& attributeHandleDataPairList, const RTIData& tag); - void reflectAttributeValues(RTI13AttributeHandleDataPairList& attributeHandleDataPairList, const SGTimeStamp& timeStamp, const RTIData& tag); - virtual void requestObjectAttributeValueUpdate(); + void reflectAttributeValues(RTI13AttributeHandleDataPairList& attributeHandleDataPairList, + const RTIData& tag, HLAIndexList& indexPool); + void reflectAttributeValues(RTI13AttributeHandleDataPairList& attributeHandleDataPairList, + const SGTimeStamp& timeStamp, const RTIData& tag, HLAIndexList& indexPool); + virtual void requestObjectAttributeValueUpdate(const HLAIndexList& indexList); void provideAttributeValueUpdate(const std::vector& attributes); virtual void updateAttributeValues(const RTIData& tag); virtual void updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag); + virtual bool isAttributeOwnedByFederate(unsigned index) const; + void attributesInScope(const std::vector& attributes); void attributesOutOfScope(const std::vector& attributes); diff --git a/simgear/hla/RTIFederate.hxx b/simgear/hla/RTIFederate.hxx index a4c137ff..002e22b2 100644 --- a/simgear/hla/RTIFederate.hxx +++ b/simgear/hla/RTIFederate.hxx @@ -1,4 +1,4 @@ -// Copyright (C) 2009 - 2011 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public @@ -20,6 +20,7 @@ #include #include "simgear/structure/SGWeakReferenced.hxx" +#include "RTIInteractionClass.hxx" #include "RTIObjectClass.hxx" #include "RTIObjectInstance.hxx" @@ -79,7 +80,7 @@ public: virtual bool processMessages(const double& minimum, const double& maximum) = 0; virtual RTIObjectClass* createObjectClass(const std::string& name, HLAObjectClass* hlaObjectClass) = 0; - // virtual RTIInteractionClass* createInteractionClass(const std::string& name) = 0; + virtual RTIInteractionClass* createInteractionClass(const std::string& name, HLAInteractionClass* interactionClass) = 0; virtual RTIObjectInstance* getObjectInstance(const std::string& name) = 0; diff --git a/simgear/hla/RTIInteractionClass.cxx b/simgear/hla/RTIInteractionClass.cxx new file mode 100644 index 00000000..23aa741b --- /dev/null +++ b/simgear/hla/RTIInteractionClass.cxx @@ -0,0 +1,32 @@ +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library 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 +// Library 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + +#include "RTIInteractionClass.hxx" + +namespace simgear { + +RTIInteractionClass::RTIInteractionClass(HLAInteractionClass* interactionClass) : + _interactionClass(interactionClass) +{ +} + +RTIInteractionClass::~RTIInteractionClass() +{ + _interactionClass = 0; +} + +} diff --git a/simgear/hla/RTIInteractionClass.hxx b/simgear/hla/RTIInteractionClass.hxx index 9cfafbd1..81e975c0 100644 --- a/simgear/hla/RTIInteractionClass.hxx +++ b/simgear/hla/RTIInteractionClass.hxx @@ -1,4 +1,4 @@ -// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public @@ -18,44 +18,33 @@ #ifndef RTIInteractionClass_hxx #define RTIInteractionClass_hxx -#include #include -#include #include "simgear/structure/SGReferenced.hxx" -#include "simgear/structure/SGSharedPtr.hxx" -#include "simgear/structure/SGReferenced.hxx" -#include "RTIData.hxx" namespace simgear { +class HLAInteractionClass; + class RTIInteractionClass : public SGReferenced { public: - RTIInteractionClass(const std::string& name); + RTIInteractionClass(HLAInteractionClass* interactionClass); virtual ~RTIInteractionClass(); - const std::string& getName() const - { return _name; } - - virtual unsigned getNumParameters() const = 0; - virtual unsigned getParameterIndex(const std::string& name) const = 0; - virtual unsigned getOrCreateParameterIndex(const std::string& name) = 0; + virtual bool resolveParameterIndex(const std::string& name, unsigned index) = 0; - virtual bool publish(const std::set& indexSet) = 0; + virtual bool publish() = 0; virtual bool unpublish() = 0; - virtual bool subscribe(const std::set& indexSet, bool) = 0; + virtual bool subscribe(bool) = 0; virtual bool unsubscribe() = 0; - virtual void send(const RTIData& tag) = 0; - virtual void send(const SGTimeStamp& timeStamp, const RTIData& tag) = 0; - - class ReceiveCallback : public SGReferenced { - public: - virtual ~ReceiveCallback() {} - }; + // virtual void send(const RTIData& tag) = 0; + // virtual void send(const SGTimeStamp& timeStamp, const RTIData& tag) = 0; private: - std::string _name; + HLAInteractionClass* _interactionClass; + + friend class HLAInteractionClass; }; } diff --git a/simgear/hla/RTIObjectClass.cxx b/simgear/hla/RTIObjectClass.cxx index dceb3029..9b4d36c1 100644 --- a/simgear/hla/RTIObjectClass.cxx +++ b/simgear/hla/RTIObjectClass.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public @@ -17,12 +17,13 @@ #include "RTIObjectClass.hxx" +#include "simgear/debug/logstream.hxx" #include "RTIObjectInstance.hxx" namespace simgear { -RTIObjectClass::RTIObjectClass(HLAObjectClass* hlaObjectClass) : - _hlaObjectClass(hlaObjectClass) +RTIObjectClass::RTIObjectClass(HLAObjectClass* objectClass) : + _objectClass(objectClass) { } @@ -33,35 +34,31 @@ RTIObjectClass::~RTIObjectClass() void RTIObjectClass::discoverInstance(RTIObjectInstance* objectInstance, const RTIData& tag) const { - SGSharedPtr hlaObjectClass = _hlaObjectClass.lock(); - if (!hlaObjectClass.valid()) { + if (!_objectClass) { SG_LOG(SG_NETWORK, SG_WARN, "RTI: Invalid hla object class pointer in RTIObjectClass::discoverInstance()."); return; } - hlaObjectClass->discoverInstance(objectInstance, tag); - objectInstance->requestObjectAttributeValueUpdate(); + _objectClass->_discoverInstance(objectInstance, tag); } void RTIObjectClass::startRegistration() const { - SGSharedPtr hlaObjectClass = _hlaObjectClass.lock(); - if (!hlaObjectClass.valid()) { + if (!_objectClass) { SG_LOG(SG_NETWORK, SG_WARN, "RTI: Invalid hla object class pointer in RTIObjectClass::startRegstration()."); return; } - hlaObjectClass->startRegistrationCallback(); + _objectClass->_startRegistration(); } void RTIObjectClass::stopRegistration() const { - SGSharedPtr hlaObjectClass = _hlaObjectClass.lock(); - if (!hlaObjectClass.valid()) { + if (!_objectClass) { SG_LOG(SG_NETWORK, SG_WARN, "RTI: Invalid hla object class pointer in RTIObjectClass::stopRegistration()."); return; } - hlaObjectClass->stopRegistrationCallback(); + _objectClass->_stopRegistration(); } } diff --git a/simgear/hla/RTIObjectClass.hxx b/simgear/hla/RTIObjectClass.hxx index e659b983..80101ea5 100644 --- a/simgear/hla/RTIObjectClass.hxx +++ b/simgear/hla/RTIObjectClass.hxx @@ -1,4 +1,4 @@ -// Copyright (C) 2009 - 2010 Mathias Froehlich - Mathias.Froehlich@web.de +// Copyright (C) 2009 - 2012 Mathias Froehlich - Mathias.Froehlich@web.de // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public @@ -19,102 +19,44 @@ #define RTIObjectClass_hxx #include -#include #include "simgear/structure/SGReferenced.hxx" -#include "simgear/structure/SGSharedPtr.hxx" -#include "simgear/structure/SGWeakPtr.hxx" #include "RTIData.hxx" #include "HLAObjectClass.hxx" namespace simgear { +class RTIData; class RTIObjectInstance; class HLAObjectClass; class RTIObjectClass : public SGReferenced { public: - RTIObjectClass(HLAObjectClass* hlaObjectClass); + RTIObjectClass(HLAObjectClass* objectClass); virtual ~RTIObjectClass(); - virtual std::string getName() const = 0; + virtual bool resolveAttributeIndex(const std::string& name, unsigned index) = 0; virtual unsigned getNumAttributes() const = 0; - virtual unsigned getAttributeIndex(const std::string& name) const = 0; - virtual unsigned getOrCreateAttributeIndex(const std::string& name) = 0; - virtual bool publish(const std::set& indexSet) = 0; + virtual bool publish(const HLAIndexList& indexList) = 0; virtual bool unpublish() = 0; - virtual bool subscribe(const std::set& indexSet, bool) = 0; + virtual bool subscribe(const HLAIndexList& indexList, bool) = 0; virtual bool unsubscribe() = 0; // Factory to create an object instance that can be used in this current federate virtual RTIObjectInstance* registerObjectInstance(HLAObjectInstance*) = 0; + // Call back into HLAObjectClass void discoverInstance(RTIObjectInstance* objectInstance, const RTIData& tag) const; void startRegistration() const; void stopRegistration() const; - void setAttributeDataType(unsigned index, SGSharedPtr dataType) - { - if (_attributeDataVector.size() <= index) - return; - _attributeDataVector[index]._dataType = dataType; - } - const HLADataType* getAttributeDataType(unsigned index) const - { - if (_attributeDataVector.size() <= index) - return 0; - return _attributeDataVector[index]._dataType.get(); - } - - HLAUpdateType getAttributeUpdateType(unsigned index) const - { - if (_attributeDataVector.size() <= index) - return HLAUndefinedUpdate; - return _attributeDataVector[index]._updateType; - } - void setAttributeUpdateType(unsigned index, HLAUpdateType updateType) - { - if (_attributeDataVector.size() <= index) - return; - _attributeDataVector[index]._updateType = updateType; - } - - bool getAttributeSubscribed(unsigned index) const - { - if (_attributeDataVector.size() <= index) - return false; - return _attributeDataVector[index]._subscribed; - } - bool getAttributePublished(unsigned index) const - { - if (_attributeDataVector.size() <= index) - return false; - return _attributeDataVector[index]._published; - } - std::string getAttributeName(unsigned index) const - { - if (_attributeDataVector.size() <= index) - return std::string(); - return _attributeDataVector[index]._name; - } - -protected: - struct AttributeData { - AttributeData(const std::string& name) : _name(name), _subscribed(false), _published(false), _updateType(HLAUndefinedUpdate) {} - std::string _name; - SGSharedPtr _dataType; - bool _subscribed; - bool _published; - HLAUpdateType _updateType; - }; - typedef std::vector AttributeDataVector; - AttributeDataVector _attributeDataVector; - private: - SGWeakPtr _hlaObjectClass; + HLAObjectClass* _objectClass; + + friend class HLAObjectClass; }; } diff --git a/simgear/hla/RTIObjectInstance.cxx b/simgear/hla/RTIObjectInstance.cxx index 74544146..2baedaae 100644 --- a/simgear/hla/RTIObjectInstance.cxx +++ b/simgear/hla/RTIObjectInstance.cxx @@ -22,8 +22,7 @@ namespace simgear { RTIObjectInstance::RTIObjectInstance(HLAObjectInstance* hlaObjectInstance) : - _hlaObjectInstance(hlaObjectInstance), - _pendingAttributeUpdateRequest(false) + _objectInstance(hlaObjectInstance) { } @@ -37,54 +36,29 @@ RTIObjectInstance::getNumAttributes() const return getObjectClass()->getNumAttributes(); } -unsigned -RTIObjectInstance::getAttributeIndex(const std::string& name) const -{ - return getObjectClass()->getAttributeIndex(name); -} - -std::string -RTIObjectInstance::getAttributeName(unsigned index) const -{ - return getObjectClass()->getAttributeName(index); -} - void RTIObjectInstance::removeInstance(const RTIData& tag) { - SGSharedPtr hlaObjectInstance = _hlaObjectInstance.lock(); - if (!hlaObjectInstance.valid()) + if (!_objectInstance) return; - hlaObjectInstance->removeInstance(tag); + _objectInstance->_removeInstance(tag); } void -RTIObjectInstance::reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const RTIData& tag) +RTIObjectInstance::reflectAttributeValues(const HLAIndexList& indexList, const RTIData& tag) { - for (RTIIndexDataPairList::const_iterator i = dataPairList.begin(); - i != dataPairList.end(); ++i) { - reflectAttributeValue(i->first, i->second); - } - - SGSharedPtr hlaObjectInstance = _hlaObjectInstance.lock(); - if (!hlaObjectInstance.valid()) + if (!_objectInstance) return; - hlaObjectInstance->reflectAttributeValues(dataPairList, tag); + _objectInstance->_reflectAttributeValues(indexList, tag); } void -RTIObjectInstance::reflectAttributeValues(const RTIIndexDataPairList& dataPairList, +RTIObjectInstance::reflectAttributeValues(const HLAIndexList& indexList, const SGTimeStamp& timeStamp, const RTIData& tag) { - for (RTIIndexDataPairList::const_iterator i = dataPairList.begin(); - i != dataPairList.end(); ++i) { - reflectAttributeValue(i->first, i->second); - } - - SGSharedPtr hlaObjectInstance = _hlaObjectInstance.lock(); - if (!hlaObjectInstance.valid()) + if (!_objectInstance) return; - hlaObjectInstance->reflectAttributeValues(dataPairList, timeStamp, tag); + _objectInstance->_reflectAttributeValues(indexList, timeStamp, tag); } } diff --git a/simgear/hla/RTIObjectInstance.hxx b/simgear/hla/RTIObjectInstance.hxx index 61ff9328..00f22a1d 100644 --- a/simgear/hla/RTIObjectInstance.hxx +++ b/simgear/hla/RTIObjectInstance.hxx @@ -18,13 +18,9 @@ #ifndef RTIObjectInstance_hxx #define RTIObjectInstance_hxx -#include -#include #include #include -#include "simgear/debug/logstream.hxx" #include "simgear/structure/SGReferenced.hxx" -#include "simgear/structure/SGWeakPtr.hxx" #include "simgear/timing/timestamp.hxx" #include "RTIData.hxx" #include "RTIObjectClass.hxx" @@ -39,247 +35,117 @@ class HLAObjectInstance; class RTIObjectInstance : public SGReferenced { public: - RTIObjectInstance(HLAObjectInstance* hlaObjectInstance); + RTIObjectInstance(HLAObjectInstance* objectInstance); virtual ~RTIObjectInstance(); + void setObjectInstance(HLAObjectInstance* objectInstance) + { _objectInstance = objectInstance; } + virtual const RTIObjectClass* getObjectClass() const = 0; virtual std::string getName() const = 0; unsigned getNumAttributes() const; - unsigned getAttributeIndex(const std::string& name) const; - std::string getAttributeName(unsigned index) const; virtual void deleteObjectInstance(const RTIData& tag) = 0; virtual void deleteObjectInstance(const SGTimeStamp& timeStamp, const RTIData& tag) = 0; virtual void localDeleteObjectInstance() = 0; - virtual void requestObjectAttributeValueUpdate() = 0; + virtual void requestObjectAttributeValueUpdate(const HLAIndexList& indexList) = 0; virtual void updateAttributeValues(const RTIData& tag) = 0; virtual void updateAttributeValues(const SGTimeStamp& timeStamp, const RTIData& tag) = 0; + virtual bool isAttributeOwnedByFederate(unsigned index) const = 0; + void removeInstance(const RTIData& tag); - void reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const RTIData& tag); - void reflectAttributeValues(const RTIIndexDataPairList& dataPairList, const SGTimeStamp& timeStamp, const RTIData& tag); - void reflectAttributeValue(unsigned i, const RTIData& data) - { - if (_attributeData.size() <= i) - return; - HLADataElement* dataElement = _attributeData[i]._dataElement.get(); - if (!dataElement) - return; - HLADecodeStream stream(data); - dataElement->decode(stream); - } + void reflectAttributeValues(const HLAIndexList& indexList, const RTIData& tag); + void reflectAttributeValues(const HLAIndexList& indexList, const SGTimeStamp& timeStamp, const RTIData& tag); - const HLADataType* getAttributeDataType(unsigned i) const + bool encodeAttributeData(unsigned index, const HLADataElement& dataElement) { - return getObjectClass()->getAttributeDataType(i); - } - HLAUpdateType getAttributeUpdateType(unsigned i) const - { - return getObjectClass()->getAttributeUpdateType(i); - } - bool getAttributeSubscribed(unsigned i) const - { - return getObjectClass()->getAttributeSubscribed(i); - } - bool getAttributePublished(unsigned i) const - { - return getObjectClass()->getAttributePublished(i); + if (_attributeData.size() <= index) + return false; + return _attributeData[index].encodeAttributeData(dataElement); } - HLADataElement* getDataElement(unsigned i) - { - if (_attributeData.size() <= i) - return 0; - return _attributeData[i]._dataElement.get(); - } - const HLADataElement* getDataElement(unsigned i) const - { - if (_attributeData.size() <= i) - return 0; - return _attributeData[i]._dataElement.get(); - } - void setDataElement(unsigned i, HLADataElement* dataElement) + bool decodeAttributeData(unsigned index, HLADataElement& dataElement) const { - if (_attributeData.size() <= i) - return; - _attributeData[i]._dataElement = dataElement; + if (_attributeData.size() <= index) + return false; + return _attributeData[index].decodeAttributeData(dataElement); } - void updateAttributesFromClass(bool owned) + bool getAttributeData(unsigned index, RTIData& data) const { - // FIXME: rethink that!!! - unsigned numAttributes = getNumAttributes(); - unsigned i = 0; - for (; i < _attributeData.size(); ++i) { - if (getAttributePublished(i)) { - } else { - _attributeData[i].setUpdateEnabled(false); - _attributeData[i].setOwned(false); - if (getAttributeSubscribed(i)) - _attributeData[i].setRequestUpdate(true); - } - } - _attributeData.resize(numAttributes); - for (; i < numAttributes; ++i) { - if (getAttributePublished(i)) { - _attributeData[i].setUpdateEnabled(true); - _attributeData[i].setOwned(owned); - if (!owned && getAttributeSubscribed(i)) - _attributeData[i].setRequestUpdate(true); - } else { - _attributeData[i].setUpdateEnabled(false); - _attributeData[i].setOwned(false); - if (getAttributeSubscribed(i)) - _attributeData[i].setRequestUpdate(true); - } - } + if (_attributeData.size() <= index) + return false; + data = _attributeData[index]._data; + return true; } - void setAttributeForceUpdate(unsigned i) + bool getAttributeOwned(unsigned index) const { - if (_attributeData.size() <= i) - return; - _attributeData[i].setForceUpdate(true); + if (_attributeData.size() <= index) + return false; + return _attributeData[index]._owned; } + void setAttributeInScope(unsigned i, bool inScope) { if (_attributeData.size() <= i) return; - _attributeData[i].setInScope(inScope); + _attributeData[i]._inScope = inScope; } void setAttributeUpdateEnabled(unsigned i, bool enabled) { if (_attributeData.size() <= i) return; - _attributeData[i].setUpdateEnabled(enabled); - } - void setAttributeUpdated(unsigned i) - { - if (_attributeData.size() <= i) - return; - _attributeData[i].setForceUpdate(false); - } - bool getAttributeEffectiveUpdateEnabled(unsigned i) - { - if (_attributeData.size() <= i) - return false; - if (!getAttributePublished(i)) - return false; - if (!_attributeData[i]._updateEnabled) - return false; - if (!_attributeData[i]._inScope) - return false; - if (_attributeData[i]._forceUpdate) - return true; - switch (getAttributeUpdateType(i)) { - case HLAPeriodicUpdate: - return true; - case HLAConditionalUpdate: - return true; // FIXME - case HLAStaticUpdate: - return false; - default: - return false; - } - } - void setRequestAttributeUpdate(bool request) - { - for (unsigned i = 0; i < getNumAttributes(); ++i) { - if (getAttributeUpdateType(i) == HLAPeriodicUpdate) - continue; - setRequestAttributeUpdate(i, request); - } - } - void setRequestAttributeUpdate(unsigned i, bool request) - { - if (_attributeData.size() <= i) - return; - _attributeData[i].setRequestUpdate(request); - if (request) { - if (!_pendingAttributeUpdateRequest) { - _pendingAttributeUpdateRequest = true; - } - } - } - bool getRequestAttributeUpdate(unsigned i) const - { - if (_attributeData.size() <= i) - return false; - return _attributeData[i]._requestUpdate; - } - - void flushPendingRequests() - { - if (_pendingAttributeUpdateRequest) { - requestObjectAttributeValueUpdate(); - _pendingAttributeUpdateRequest = false; - } + _attributeData[i]._updateEnabled = enabled; } protected: - // The backward reference to the user visible object - SGWeakPtr _hlaObjectInstance; - - // Is true if we should emit a requestattr - bool _pendingAttributeUpdateRequest; - - // Pool of update list entries - RTIIndexDataPairList _indexDataPairList; - - // This adds raw storage for attribute index i to the end of the dataPairList. - void getDataFromPool(RTIIndexDataPairList& dataPairList) + // Initially set the number of attributes, do an initial query for the attribute ownership + void _setNumAttributes(unsigned numAttributes) { - // Nothing left in the pool - so allocate something - if (_indexDataPairList.empty()) { - dataPairList.push_back(RTIIndexDataPairList::value_type()); - return; - } - - // Take one from the pool - dataPairList.splice(dataPairList.end(), _indexDataPairList, _indexDataPairList.begin()); + _attributeData.resize(numAttributes); + for (unsigned i = 0; i < numAttributes; ++i) + _attributeData[i]._owned = isAttributeOwnedByFederate(i); } - void putDataToPool(RTIIndexDataPairList& dataPairList) - { - _indexDataPairList.splice(_indexDataPairList.begin(), dataPairList); - } + // The backward reference to the user visible object + HLAObjectInstance* _objectInstance; struct AttributeData { - AttributeData() : _owned(false), _inScope(true), _updateEnabled(true), _forceUpdate(false), _requestUpdate(false) + AttributeData() : _owned(false), _inScope(true), _updateEnabled(true), _dirty(false) { } - // The hla level data element with tha actual local program - // accessible data. - SGSharedPtr _dataElement; - // SGSharedPtr _timeStamp; + bool encodeAttributeData(const HLADataElement& dataElement) + { + _dirty = true; + _data.resize(0); + HLAEncodeStream stream(_data); + return dataElement.encode(stream); + } - // Pool of already allocated raw data used for reflection of updates - RTIIndexDataPairList _indexDataPairList; + bool decodeAttributeData(HLADataElement& dataElement) const + { + HLADecodeStream stream(_data); + return dataElement.decode(stream); + } - void setOwned(bool owned) - { _owned = owned; } - void setInScope(bool inScope) - { _inScope = inScope; } - void setUpdateEnabled(bool updateEnabled) - { _updateEnabled = updateEnabled; } - void setForceUpdate(bool forceUpdate) - { _forceUpdate = forceUpdate; } - void setRequestUpdate(bool requestUpdate) - { _requestUpdate = requestUpdate; } + // The rti level raw data element + RTIData _data; + // The state of the attribute as tracked from the rti. bool _owned; bool _inScope; bool _updateEnabled; - bool _forceUpdate; - bool _requestUpdate; + + // Is set to true if _data has be reencoded + bool _dirty; }; std::vector _attributeData; - - friend class HLAObjectInstance; }; }