#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"
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;
-
- // FIXME: factor out an ambassador base
- virtual void addToRequestQueue() = 0;
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);
- // Call this if you want to roll up the queued timestamed updates
- // and reflect that into the attached data elements.
- void reflectQueuedAttributeValues(const SGTimeStamp& timeStamp)
- {
- // replay all updates up to the given timestamp
- UpdateListMap::iterator last = _updateListMap.upper_bound(timeStamp);
- for (UpdateListMap::iterator i = _updateListMap.begin(); i != last; ++i) {
- for (UpdateList::iterator j = i->second.begin(); j != i->second.end(); ++j) {
- // FIXME have a variant that takes the timestamp?
- reflectAttributeValues(j->_indexDataPairList, j->_tag);
- }
- putUpdateToPool(i->second);
- }
- }
- 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
- {
- return getObjectClass()->getAttributeDataType(i);
- }
- HLAUpdateType getAttributeUpdateType(unsigned i) const
- {
- return getObjectClass()->getAttributeUpdateType(i);
- }
- bool getAttributeSubscribed(unsigned i) const
+ bool encodeAttributeData(unsigned index, const HLADataElement& dataElement)
{
- 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);
- }
- }
- _attributeData.resize(numAttributes);
- for (; i < numAttributes; ++i) {
- if (getAttributePublished(i)) {
- _attributeData[i].setUpdateEnabled(true);
- _attributeData[i].setOwned(owned);
- } else {
- _attributeData[i].setUpdateEnabled(false);
- _attributeData[i].setOwned(false);
- }
- }
+ 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;
- addToRequestQueue();
- }
- }
- }
- 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;
-
- // Contains a full update as it came in from the RTI
- struct Update {
- RTIIndexDataPairList _indexDataPairList;
- RTIData _tag;
- };
- // A bunch of updates for the same timestamp
- typedef std::list<Update> UpdateList;
- // The timestamp sorted list of updates
- typedef std::map<SGTimeStamp, UpdateList> UpdateListMap;
-
- // The timestamped updates sorted by timestamp
- UpdateListMap _updateListMap;
-
- // The pool of unused updates so that we do not need to malloc/free each time
- UpdateList _updateList;
-
- void getUpdateFromPool(UpdateList& updateList)
+ // Initially set the number of attributes, do an initial query for the attribute ownership
+ void _setNumAttributes(unsigned numAttributes)
{
- if (_updateList.empty())
- updateList.push_back(Update());
- else
- updateList.splice(updateList.end(), _updateList, _updateList.begin());
- }
- void putUpdateToPool(UpdateList& updateList)
- {
- for (UpdateList::iterator i = updateList.begin(); i != updateList.end(); ++i)
- putDataToPool(i->_indexDataPairList);
- _updateList.splice(_updateList.end(), updateList);
- }
-
- // Appends the updates in the list to the given timestamps updates
- void scheduleUpdates(const SGTimeStamp& timeStamp, UpdateList& updateList)
- {
- UpdateListMap::iterator i = _updateListMap.find(timeStamp);
- if (i == _updateListMap.end())
- i = _updateListMap.insert(UpdateListMap::value_type(timeStamp, UpdateList())).first;
- i->second.splice(i->second.end(), updateList);
- }
-
- // This adds raw storage for attribute index i to the end of the dataPairList.
- void getDataFromPool(unsigned i, RTIIndexDataPairList& dataPairList)
- {
- if (_attributeData.size() <= i) {
- SG_LOG(SG_NETWORK, SG_WARN, "RTI: Invalid object attribute index!");
- return;
- }
-
- // Nothing left in the pool - so allocate something
- if (_attributeData[i]._indexDataPairList.empty()) {
- dataPairList.push_back(RTIIndexDataPairList::value_type());
- dataPairList.back().first = i;
- return;
- }
-
- // Take one from the pool
- dataPairList.splice(dataPairList.end(),
- _attributeData[i]._indexDataPairList,
- _attributeData[i]._indexDataPairList.begin());
+ _attributeData.resize(numAttributes);
+ for (unsigned i = 0; i < numAttributes; ++i)
+ _attributeData[i]._owned = isAttributeOwnedByFederate(i);
}
- void putDataToPool(RTIIndexDataPairList& dataPairList)
- {
- while (!dataPairList.empty()) {
- // Put back into the pool
- unsigned i = dataPairList.front().first;
- if (_attributeData.size() <= i) {
- // should not happen!!!
- SG_LOG(SG_NETWORK, SG_WARN, "RTI: Invalid object attribute index!");
- dataPairList.pop_front();
- } else {
- _attributeData[i]._indexDataPairList.splice(_attributeData[i]._indexDataPairList.begin(),
- dataPairList, dataPairList.begin());
- }
- }
- }
+ // 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;
};
}