]> git.mxchange.org Git - simgear.git/commitdiff
hla: Rework toplevel HLA classes.
authorMathias Froehlich <Mathias.Froehlich@web.de>
Sun, 26 Feb 2012 11:04:12 +0000 (12:04 +0100)
committerMathias Froehlich <Mathias.Froehlich@web.de>
Tue, 28 Feb 2012 06:16:11 +0000 (07:16 +0100)
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.

41 files changed:
simgear/hla/CMakeLists.txt
simgear/hla/HLAArrayDataType.cxx
simgear/hla/HLAArrayDataType.hxx
simgear/hla/HLABasicDataType.cxx
simgear/hla/HLABasicDataType.hxx
simgear/hla/HLADataType.cxx
simgear/hla/HLADataType.hxx
simgear/hla/HLADataTypeVisitor.hxx
simgear/hla/HLAEnumeratedDataType.cxx
simgear/hla/HLAEnumeratedDataType.hxx
simgear/hla/HLAFederate.cxx
simgear/hla/HLAFederate.hxx
simgear/hla/HLAFixedRecordDataType.cxx
simgear/hla/HLAFixedRecordDataType.hxx
simgear/hla/HLAInteractionClass.cxx [new file with mode: 0644]
simgear/hla/HLAInteractionClass.hxx
simgear/hla/HLAOMTXmlVisitor.cxx
simgear/hla/HLAOMTXmlVisitor.hxx
simgear/hla/HLAObjectClass.cxx
simgear/hla/HLAObjectClass.hxx
simgear/hla/HLAObjectInstance.cxx
simgear/hla/HLAObjectInstance.hxx
simgear/hla/HLATypes.hxx
simgear/hla/HLAVariantRecordDataType.cxx
simgear/hla/HLAVariantRecordDataType.hxx
simgear/hla/RTI13Ambassador.hxx
simgear/hla/RTI13Federate.cxx
simgear/hla/RTI13Federate.hxx
simgear/hla/RTI13InteractionClass.cxx [new file with mode: 0644]
simgear/hla/RTI13InteractionClass.hxx [new file with mode: 0644]
simgear/hla/RTI13ObjectClass.cxx
simgear/hla/RTI13ObjectClass.hxx
simgear/hla/RTI13ObjectInstance.cxx
simgear/hla/RTI13ObjectInstance.hxx
simgear/hla/RTIFederate.hxx
simgear/hla/RTIInteractionClass.cxx [new file with mode: 0644]
simgear/hla/RTIInteractionClass.hxx
simgear/hla/RTIObjectClass.cxx
simgear/hla/RTIObjectClass.hxx
simgear/hla/RTIObjectInstance.cxx
simgear/hla/RTIObjectInstance.hxx

index b575c4ce6a80eea3ff5fa28ce5a4835df14c4bda..cd91a81eec00ce0e61837d40cd594c33318d3c74 100644 (file)
@@ -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
index f52da2830828f8fd8a8b05517df7a6f24d11b2bb..8f6435b602f821f7eecc6e9c56fbbcbaff16eb24 100644 (file)
@@ -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<unsigned>::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
index a38f05bcaae88c53399204e2aedb29877164e59e..87be38517b7c34aad14c48391d283cf171350a80 100644 (file)
@@ -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<const HLADataType> _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<const HLADataType> _sizeDataType;
+    SGSharedPtr<const HLABasicDataType> _sizeDataType;
 };
 
 } // namespace simgear
index 106e81587219273e9df80c53f5febeab38d34506..63b8b8720e777d3f5c7f28c0f90df12daa1b865a 100644 (file)
@@ -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
index 60f1ba7dcc89d273ec617bf076e32517008f1c90..2f298122850163782439b36e534c0cdc014c59a6 100644 (file)
@@ -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
index 73198534d3eb33cd79bca569986fe9c24cb05f73..3addcb839f98335323b691613c66aa46e662a662 100644 (file)
@@ -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;
 }
 
 }
index c792edd2c46ffe861b55437a93cda7a84f2fafa2..e728fa8c6a6bc4d1bdbec5f9ec799a5042951186 100644 (file)
@@ -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<HLADataType>& dataType) :
-        HLADataType(dataType->getName(), dataType->getAlignment()),
-        _dataType(dataType)
-    { }
-    virtual ~HLADataTypeReference();
-
-    SGSharedPtr<const HLADataType> getDataType() const
-    { return _dataType.lock(); }
-
-    virtual void accept(HLADataTypeVisitor& visitor) const;
-    virtual const HLADataTypeReference* toDataTypeReference() const;
-
-private:
-    SGWeakPtr<const HLADataType> _dataType;
-};
-
 } // namespace simgear
 
 #endif
index 824b22a349e7c279d31aa3b17e537b5b0b2f0c94..a73488af84e1e90007957910f566acf0aa9403d6 100644 (file)
@@ -38,16 +38,6 @@ public:
     virtual void apply(const HLADataType& dataType)
     { }
 
-    virtual void apply(const HLADataTypeReference& dataType)
-    {
-        SGSharedPtr<const HLADataType> 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<const HLADataType&>(dataType)); }
     virtual void apply(const HLAInt8DataType& dataType)
index 56fd34dddc6d42e3ed246414e6283dde2de6f9ff..d7cc2a9f2ebe84a7ba80ec7a8d1d22a710507619 100644 (file)
@@ -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
 
index 7066adbaacb671977e85ef7b0ade5a4d55fab244..973b2c5a8362531cbdca68f97d544f4b608f05d7 100644 (file)
@@ -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:
index 4a9d93d4626ccce9c3489b538aceba91fbc908e2..141cbc8e91dbce28c87b7a7574383875fe1fe420 100644 (file)
@@ -17,6 +17,8 @@
 
 #include "HLAFederate.hxx"
 
+#include <algorithm>
+
 #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<unsigned> subscriptions;
-        std::set<unsigned> 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<HLADataType> dataType;
-            dataType = omtXmlVisitor.getAttributeDataType(objectClassName, attributeName);
+            // the attributes datatype
+            SGSharedPtr<const HLADataType> 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<HLADataType>& 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<HLAInteractionClass>& 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<HLAObjectClass>& 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<HLAObjectInstance>& 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
index 2326a385d760fcb9cf76c383cb865e79833597d3..eb0c8424abf6f75d71c0fc9daf1fe78589323d47 100644 (file)
@@ -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<HLADataType>& 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<HLAInteractionClass>& interactionClass);
+    /// Internal helpers for object classes
+    bool _insertObjectClass(const SGSharedPtr<HLAObjectClass>& objectClass);
+    /// Internal helpers for object instances
+    bool _insertObjectInstance(const SGSharedPtr<HLAObjectInstance>& objectInstance);
+    void _eraseObjectInstance(const std::string& name);
+
     /// The underlying interface to the rti implementation
     SGSharedPtr<RTIFederate> _rtiFederate;
 
@@ -256,14 +291,27 @@ private:
     /// If true the exec method returns.
     bool _done;
 
-    typedef std::map<std::string, SGSharedPtr<HLAObjectClass> > ObjectClassMap;
-    ObjectClassMap _objectClassMap;
+    /// The Data Types by name
+    typedef std::map<std::string, SGSharedPtr<HLADataType> > DataTypeMap;
+    DataTypeMap _dataTypeMap;
 
+    /// The Interaction Classes by name
     typedef std::map<std::string, SGSharedPtr<HLAInteractionClass> > InteractionClassMap;
     InteractionClassMap _interactionClassMap;
 
+    /// The Object Classes by name
+    typedef std::map<std::string, SGSharedPtr<HLAObjectClass> > ObjectClassMap;
+    ObjectClassMap _objectClassMap;
+
+    /// The Object Instances by name
+    typedef std::map<std::string, SGSharedPtr<HLAObjectInstance> > 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
index acec73a1a0335c8b4bcf35e4dc6c3db441789728..92e36e26c0974830642420d87cafc663bb92168f 100644 (file)
@@ -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
index 17c32ac4151586e08a7b8cfba10b118dc2c07a36..5858c792285ad1f5880bace239ef3aba98c6be24 100644 (file)
@@ -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 (file)
index 0000000..b56aec4
--- /dev/null
@@ -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 <simgear/debug/logstream.hxx>
+
+#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<const HLADataType>& 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
index 021dff7ea73d71397ee2d81d86f35d359531e1c5..4e1d15315b13108d95b1407299d0ff5ea7619b8c 100644 (file)
@@ -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
 #ifndef HLAInteractionClass_hxx
 #define HLAInteractionClass_hxx
 
+#include <map>
+#include <string>
+#include <vector>
+
+#include <simgear/structure/SGWeakReferenced.hxx>
+
+#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<const HLADataType>& 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<const HLADataType> _dataType;
+    };
+    typedef std::vector<Parameter> ParameterVector;
+    typedef std::map<std::string,unsigned> NameIndexMap;
+
+    /// The parent federate.
+    SGWeakPtr<HLAFederate> _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
index 89784b1c25e0de89714e65ab769802aeaf6a037f..3783cf726a9eceef22093330f69490d601a30807 100644 (file)
@@ -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;
+        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;
+        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<HLADataType> dataType;
-    {
-        // Playing dirty things with reference counts
-        StringDataTypeMap dataTypeMap;
-        dataType = getDataType(dataTypeName, dataTypeMap);
-    }
-    return dataType.release();
-}
-
 SGSharedPtr<HLADataType>
-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<HLADataType> 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<HLABasicDataType>
-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<HLADataType>
-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<HLAEnumeratedDataType>
-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<HLAEnumeratedDataType> 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<HLADataType>
-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<HLADataType> elementDataType = getDataType(i->second._dataType, dataTypeMap);
+    _dataTypeMap[dataTypeName] = arrayDataType;
+    SGSharedPtr<HLADataType> 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<HLAFixedRecordDataType>
-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<HLAFixedRecordDataType> dataType = new HLAFixedRecordDataType(dataTypeName);
-    dataTypeMap[dataTypeName] = dataType;
+    _dataTypeMap[dataTypeName] = dataType;
     for (FieldList::size_type j = 0; j < i->second._fieldList.size(); ++j) {
-        SGSharedPtr<HLADataType> fieldDataType = getDataType(i->second._fieldList[j]._dataType, dataTypeMap);
+        SGSharedPtr<HLADataType> 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<HLAVariantRecordDataType>
-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<HLAVariantRecordDataType> dataType = new HLAVariantRecordDataType(dataTypeName);
-    dataTypeMap[dataTypeName] = dataType;
+    _dataTypeMap[dataTypeName] = dataType;
 
     SGSharedPtr<HLAEnumeratedDataType> 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<HLADataType> alternativeDataType = getDataType(j->_dataType, dataTypeMap);
+        SGSharedPtr<HLADataType> 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<const ObjectClass> 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<const InteractionClass> interactionClass = (*i)->_parentInteractionClass;
         while (interactionClass) {
index ce52eb1a2c874f3a6bf4c73563edbf8e4848ef12..7bf481569be9d43a311c94659dfecef231aeed20 100644 (file)
 #include <simgear/structure/SGSharedPtr.hxx>
 #include <simgear/xml/easyxml.hxx>
 #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<std::string, SGSharedPtr<HLADataType> > StringDataTypeMap;
-    SGSharedPtr<HLADataType> getDataType(const std::string& dataTypeName, StringDataTypeMap& dataTypeMap) const;
-    SGSharedPtr<HLABasicDataType> getBasicDataType(const std::string& dataTypeName) const;
-    SGSharedPtr<HLADataType> getSimpleDataType(const std::string& dataTypeName) const;
-    SGSharedPtr<HLAEnumeratedDataType> getEnumeratedDataType(const std::string& dataTypeName) const;
-    SGSharedPtr<HLADataType> getArrayDataType(const std::string& dataTypeName, StringDataTypeMap& dataTypeMap) const;
-    SGSharedPtr<HLAFixedRecordDataType> getFixedRecordDataType(const std::string& dataTypeName, StringDataTypeMap& dataTypeMap) const;
-    SGSharedPtr<HLAVariantRecordDataType> getVariantRecordDataType(const std::string& dataTypeName, StringDataTypeMap& dataTypeMap) const;
+    SGSharedPtr<HLADataType> getDataType(const std::string& dataTypeName);
+    SGSharedPtr<HLABasicDataType> getBasicDataType(const std::string& dataTypeName);
+    SGSharedPtr<HLADataType> getSimpleDataType(const std::string& dataTypeName);
+    SGSharedPtr<HLAEnumeratedDataType> getEnumeratedDataType(const std::string& dataTypeName);
+    SGSharedPtr<HLADataType> getArrayDataType(const std::string& dataTypeName);
+    SGSharedPtr<HLAFixedRecordDataType> getFixedRecordDataType(const std::string& dataTypeName);
+    SGSharedPtr<HLAVariantRecordDataType> 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<std::string, SGSharedPtr<HLADataType> > StringDataTypeMap;
+    StringDataTypeMap _dataTypeMap;
+
     /// DataType definitions
     BasicDataMap _basicDataMap;
     SimpleDataMap _simpleDataMap;
index 40cef871a0adc1400c48e40835a0b1dbaf8e71c3..9d4146d2d8907ba6484919319f721fbfddf3ac43 100644 (file)
@@ -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<unsigned>& 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<unsigned>& 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<HLAFederate> federate = _federate.lock();
+    if (!federate.valid())
+        return 0;
+    return federate->createObjectInstance(this, name);
 }
 
-void
-HLAObjectClass::discoverInstance(RTIObjectInstance* objectInstance, const RTIData& tag)
-{
-    SGSharedPtr<HLAObjectInstance> 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<HLAFederate> federate = _federate.lock();
+    if (!federate.valid()) {
+        SG_LOG(SG_NETWORK, SG_ALERT, "RTI: could not find parent federate while discovering object instance");
+        return;
+    }
+
+    SGSharedPtr<HLAObjectInstance> 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<HLAFederate> 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<HLAFederate> 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<HLAFederate> 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);
index 68ffcc53031525538e0e9e76c35b793b72c97a72..ea054a48f9b71d65a21ebd774000eb8f92024e99 100644 (file)
@@ -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 <set>
 #include <string>
 #include <vector>
 
@@ -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<unsigned>& indexSet, bool active);
-    bool unsubscribe();
+    virtual bool subscribe();
+    virtual bool unsubscribe();
 
-    bool publish(const std::set<unsigned>& 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<InstanceCallback>& 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<RegistrationCallback>& 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<const HLADataType> _dataType;
+        HLASubscriptionType _subscriptionType;
+        HLAPublicationType _publicationType;
+        HLAUpdateType _updateType;
+    };
+    typedef std::vector<Attribute> AttributeVector;
+    typedef std::map<std::string,unsigned> NameIndexMap;
+
+    /// The parent federate.
+    SGWeakPtr<HLAFederate> _federate;
+
+    /// The object class name
     std::string _name;
 
-    // The underlying rti dispatcher class
+    /// The underlying rti dispatcher class
     SGSharedPtr<RTIObjectClass> _rtiObjectClass;
 
+    /// The attribute data
+    AttributeVector _attributeVector;
+    /// The mapping from attribute names to attribute indices
+    NameIndexMap _nameIndexMap;
+
     // Callback classes
     SGSharedPtr<InstanceCallback> _instanceCallback;
     SGSharedPtr<RegistrationCallback> _registrationCallback;
 
-    // The set of active objects
-    typedef std::set<SGSharedPtr<HLAObjectInstance> > ObjectInstanceSet;
-    ObjectInstanceSet _objectInstanceSet;
+    friend class HLAFederate;
 };
 
 } // namespace simgear
index 22d8309e28a37bff77a9dfec28c774e63ff8f25e..390b70db1ef9b24e0bd9dddbed096ab88532fc86 100644 (file)
 #include "HLAObjectInstance.hxx"
 
 #include <algorithm>
+#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"
 
 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<HLAObjectClass>
-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<HLADataElement> 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<HLADataElement>& 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<HLAObjectClass> 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<HLAObjectClass> 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<HLAObjectClass> 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
index 974d2a984d01bee84fe1702cff20ed125fe12460..1262d6dee0c48bd35006afa5df5b65b61a6c1899 100644 (file)
@@ -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
 #ifndef HLAObjectInstance_hxx
 #define HLAObjectInstance_hxx
 
+#include <vector>
+
 #include <simgear/structure/SGWeakPtr.hxx>
 
 #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<HLAObjectClass> getObjectClass() const;
+    /// Return the object class of this instance.
+    /// Should always return a valid object class.
+    const SGSharedPtr<HLAObjectClass>& 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<HLADataElement> 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<HLADataElement>& 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 = updateCallback; }
+    const SGSharedPtr<UpdateCallback>& 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 = reflectCallback; }
+    const SGSharedPtr<ReflectCallback>& 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<AttributeCallback>& 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<HLADataElement> _dataElement;
+        // SGSharedPtr<HLADataElement::TimeStamp> _timeStamp;
+        bool _enabledUpdate;
+        bool _unconditionalUpdate;
+        // HLAIndexList::iterator _unconditionalUpdateAttributeIndexListIterator;
+        // HLAIndexList::iterator _conditionalUpdateAttributeIndexListIterator;
+    };
+    typedef std::vector<Attribute> 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<HLAFederate> _federate;
+
+    /// The ObjectClass
+    SGSharedPtr<HLAObjectClass> _objectClass;
+
+    /// The name as known in the RTI
     std::string _name;
 
-    SGWeakPtr<HLAObjectClass> _objectClass;
+    // /// The name as given by the local created instance
+    // std::string _givenName;
+
+    /// The underlying rti dispatcher class
     SGSharedPtr<RTIObjectInstance> _rtiObjectInstance;
+
+    /// The attribute data
+    AttributeVector _attributeVector;
+
+    // Callback classes
+    SGSharedPtr<UpdateCallback> _updateCallback;
+    SGSharedPtr<ReflectCallback> _reflectCallback;
     SGSharedPtr<AttributeCallback> _attributeCallback;
+
+    friend class HLAFederate;
+    friend class HLAObjectClass;
+    friend class RTIObjectInstance;
 };
 
 } // namespace simgear
index 931a4aa03ebf5f2d2623f2698dccaafc57caf18b..b968b1cf0a0b88ba26e86235b919659ba31f2a56 100644 (file)
@@ -18,6 +18,8 @@
 #ifndef HLATypes_hxx
 #define HLATypes_hxx
 
+#include <list>
+
 namespace simgear {
 
 enum HLASubscriptionType {
@@ -38,6 +40,8 @@ enum HLAUpdateType {
     HLAUndefinedUpdate
 };
 
+typedef std::list<unsigned> HLAIndexList;
+
 } // namespace simgear
 
 #endif
index ff7488b9800dbf0ee4cb7aafbf8fa18616a2697a..8f62f2e0760060890b9fc38a7451c24a1af9f434 100644 (file)
@@ -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<unsigned>::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
index 06226da9ad5ef1a4e07c71177c13c54325c78c1d..dc586a9f2a5fcc2278a1347b2b2dceb27e0e0396 100644 (file)
@@ -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<HLAEnumeratedDataType> _enumeratedDataType;
 
index 95a2ab387ff5037768461297c16882621cbcf90a..85779fa7a037bbc321491341c43515fed5706114 100644 (file)
@@ -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()); }
index 08dbdd8616f43ec600d93b348973971548c5f2a6..c9dbfac2781a4db96d22745fe49da05bc4a9e7ba 100644 (file)
@@ -222,7 +222,7 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador {
             return;
         if (!i->second.valid())
             return;
-        SGSharedPtr<RTI13ObjectInstance> objectInstance = new RTI13ObjectInstance(objectHandle, 0, i->second, _rtiAmbassador.get(), false);
+        SGSharedPtr<RTI13ObjectInstance> 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<RTI::ObjectHandle, SGSharedPtr<RTI13ObjectInstance> > ObjectInstanceMap;
     // Map of all available objects
@@ -864,6 +867,10 @@ struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador {
     typedef std::map<RTI::ObjectClassHandle, SGSharedPtr<RTI13ObjectClass> > ObjectClassMap;
     ObjectClassMap _objectClassMap;
 
+    // Top level information for dispatching creation of federate objects
+    typedef std::map<RTI::InteractionClassHandle, SGSharedPtr<RTI13InteractionClass> > 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)
 {
index 9b8341d2dc833d2a066b8975bc05d7b3094a3de6..83878ad0559baeaaa11e7d2a221825764345c4bd 100644 (file)
@@ -25,6 +25,7 @@
 #include <RTI.hh>
 
 #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 (file)
index 0000000..f5508fa
--- /dev/null
@@ -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 (file)
index 0000000..80faae8
--- /dev/null
@@ -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 <map>
+#include <vector>
+
+#ifndef RTI_USES_STD_FSTREAM
+#define RTI_USES_STD_FSTREAM
+#endif
+
+#include <RTI.hh>
+
+#include "RTIInteractionClass.hxx"
+
+#include <simgear/structure/SGSharedPtr.hxx>
+
+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<RTI13Ambassador> _ambassador;
+
+    typedef std::map<RTI::ParameterHandle, unsigned> ParameterHandleIndexMap;
+    ParameterHandleIndexMap _parameterHandleIndexMap;
+
+    typedef std::vector<RTI::ParameterHandle> ParameterHandleVector;
+    ParameterHandleVector _parameterHandleVector;
+};
+
+}
+
+#endif
index fcc41682cbdda9520f996dc142c9d2e14c624ad3..298330bb163967a35f5dbb388a91e216b0442801 100644 (file)
@@ -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
 
 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<RTI13Ambassador> 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<unsigned>& 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<unsigned>& indexSet)
     }
 
     try {
-        std::auto_ptr<RTI::AttributeHandleSet> attributeHandleSet(RTI::AttributeHandleSetFactory::create(indexSet.size()));
-        for (std::set<unsigned>::const_iterator i = indexSet.begin(); i != indexSet.end(); ++i) {
+        unsigned numAttributes = getNumAttributes();
+        std::auto_ptr<RTI::AttributeHandleSet> 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<unsigned>& 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<unsigned>& 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<unsigned>& indexSet, bool active)
     }
 
     try {
-        std::auto_ptr<RTI::AttributeHandleSet> attributeHandleSet(RTI::AttributeHandleSetFactory::create(indexSet.size()));
-        for (std::set<unsigned>::const_iterator i = indexSet.begin();
-             i != indexSet.end(); ++i) {
+        unsigned numAttributes = getNumAttributes();
+        std::auto_ptr<RTI::AttributeHandleSet> 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<unsigned>& 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) {
index c4949ca9cffe434316dfd62e8ce9442280e8d54e..492bc7921ddb6992b2f35ab6e9b9538cba7c081d 100644 (file)
@@ -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<unsigned>& indexSet);
+    virtual bool publish(const HLAIndexList& indexList);
     virtual bool unpublish();
 
-    virtual bool subscribe(const std::set<unsigned>& indexSet, bool);
+    virtual bool subscribe(const HLAIndexList& indexList, bool);
     virtual bool unsubscribe();
 
     virtual RTIObjectInstance* registerObjectInstance(HLAObjectInstance* hlaObjectInstance);
index f8ba657f5e4565a37598f7a18dab51fe19c6952f..7333d43c633ead9d792aca976b2dd087abfd278c 100644 (file)
 
 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<RTI::AttributeHandleSet> 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::vector<RTI::Attribut
     size_t numAttribs = attributeHandleSet.size();
     for (RTI::ULong i = 0; i < numAttribs; ++i) {
         unsigned index = getAttributeIndex(attributeHandleSet[i]);
-        setAttributeForceUpdate(index);
+        _attributeData[index]._dirty = true;
     }
 }
 
@@ -306,15 +304,9 @@ RTI13ObjectInstance::updateAttributeValues(const RTIData& tag)
 
         unsigned numAttributes = getNumAttributes();
         for (unsigned i = 0; i < numAttributes; ++i) {
-            if (!getAttributeEffectiveUpdateEnabled(i))
-                continue;
-            const HLADataElement* dataElement = getDataElement(i);
-            if (!dataElement)
+            if (!_attributeData[i]._dirty)
                 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());
         }
 
@@ -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::vector<RTI::Attr
     }
 }
 
+bool
+RTI13ObjectInstance::isAttributeOwnedByFederate(unsigned index) const
+{
+    if (!_ambassador.valid()) {
+        SG_LOG(SG_NETWORK, SG_WARN, "Error: Ambassador is zero.");
+        return false;
+    }
+    try {
+        RTI::AttributeHandle attributeHandle = getAttributeHandle(index);
+        return _ambassador->isAttributeOwnedByFederate(_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<RTI::AttributeHandle>& attributes, const RTIData& tag)
 {
index 38fd92b2d06da413f164bb42de616af7a2ee81eb..cfba387223ea4ef032eeba9ae2794a5feebcc2d4 100644 (file)
@@ -42,7 +42,7 @@ typedef std::list<RTI13AttributeHandleDataPair> 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<RTI::AttributeHandle>& 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<RTI::AttributeHandle>& attributes);
     void attributesOutOfScope(const std::vector<RTI::AttributeHandle>& attributes);
 
index a4c137ff035c2eb0f7794df784aca8efb6090cf7..002e22b2201b911bf55b0298d39d92f55b3c7366 100644 (file)
@@ -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 <string>
 #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 (file)
index 0000000..23aa741
--- /dev/null
@@ -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;
+}
+
+}
index 9cfafbd1427cdf200e73dcf24294dac60b755e2a..81e975c00f3f13de008887f1462c7899a5856c2e 100644 (file)
@@ -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
 #ifndef RTIInteractionClass_hxx
 #define RTIInteractionClass_hxx
 
-#include <set>
 #include <string>
-#include <vector>
 #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<unsigned>& indexSet) = 0;
+    virtual bool publish() = 0;
     virtual bool unpublish() = 0;
 
-    virtual bool subscribe(const std::set<unsigned>& 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;
 };
 
 }
index dceb3029a9a818444447b0ce2458f8777a739aef..9b4d36c152dda9c6fcdb58ac4c0b477e2116dc10 100644 (file)
@@ -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
 
 #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 = _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 = _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 = _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();
 }
 
 }
index e659b983ba58898b79e3fa530a7668826d72ba3e..80101ea554c1b5dd10f1a34667c5d5cb76aeb409 100644 (file)
@@ -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
 #define RTIObjectClass_hxx
 
 #include <string>
-#include <vector>
 #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<unsigned>& indexSet) = 0;
+    virtual bool publish(const HLAIndexList& indexList) = 0;
     virtual bool unpublish() = 0;
 
-    virtual bool subscribe(const std::set<unsigned>& 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<const HLADataType> 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<const HLADataType> _dataType;
-        bool _subscribed;
-        bool _published;
-        HLAUpdateType _updateType;
-    };
-    typedef std::vector<AttributeData> AttributeDataVector;
-    AttributeDataVector _attributeDataVector;
-
 private:
-    SGWeakPtr<HLAObjectClass> _hlaObjectClass;
+    HLAObjectClass* _objectClass;
+
+    friend class HLAObjectClass;
 };
 
 }
index 7454414621cd4d5d18efdc56aa382a3d61fb60a6..2baedaaecaa258a8d9589cabcad70ae902a11a13 100644 (file)
@@ -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 =  _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 =  _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 =  _hlaObjectInstance.lock();
-    if (!hlaObjectInstance.valid())
+    if (!_objectInstance)
         return;
-    hlaObjectInstance->reflectAttributeValues(dataPairList, timeStamp, tag);
+    _objectInstance->_reflectAttributeValues(indexList, timeStamp, tag);
 }
 
 }
index 61ff93284d5881927fa15d508f61cb2509836a11..00f22a1d1e5c0c06cc615fba7e729af258ade6e8 100644 (file)
 #ifndef RTIObjectInstance_hxx
 #define RTIObjectInstance_hxx
 
-#include <list>
-#include <map>
 #include <string>
 #include <vector>
-#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> _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<HLADataElement> _dataElement;
-        // SGSharedPtr<HLADataElement::TimeStamp> _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> _attributeData;
-
-    friend class HLAObjectInstance;
 };
 
 }