+ if (!n)
+ return std::string();
+ return std::string(n);
+}
+
+/// Just the interface class doing the callbacks into the parent class
+struct RTI13Federate::FederateAmbassador : public RTI::FederateAmbassador {
+ FederateAmbassador() :
+ _timeRegulationEnabled(false),
+ _timeConstrainedEnabled(false),
+ _timeAdvancePending(false)
+ {
+ }
+ virtual ~FederateAmbassador()
+ throw (RTI::FederateInternalError)
+ {
+ }
+
+ /// RTI federate ambassador callback functions.
+ virtual void synchronizationPointRegistrationSucceeded(const char* label)
+ throw (RTI::FederateInternalError)
+ {
+ }
+
+ virtual void synchronizationPointRegistrationFailed(const char* label)
+ throw (RTI::FederateInternalError)
+ {
+ }
+
+ virtual void announceSynchronizationPoint(const char* label, const char* tag)
+ throw (RTI::FederateInternalError)
+ {
+ _pendingSyncLabels.insert(toStdString(label));
+ }
+
+ virtual void federationSynchronized(const char* label)
+ throw (RTI::FederateInternalError)
+ {
+ std::string s = toStdString(label);
+ _pendingSyncLabels.erase(s);
+ _syncronizedSyncLabels.insert(s);
+ }
+
+ virtual void initiateFederateSave(const char* label)
+ throw (RTI::UnableToPerformSave,
+ RTI::FederateInternalError)
+ {
+ }
+
+ virtual void federationSaved()
+ throw (RTI::FederateInternalError)
+ {
+ }
+
+ virtual void federationNotSaved()
+ throw (RTI::FederateInternalError)
+ {
+ }
+
+ virtual void requestFederationRestoreSucceeded(const char* label)
+ throw (RTI::FederateInternalError)
+ {
+ }
+
+ virtual void requestFederationRestoreFailed(const char* label, const char* reason)
+ throw (RTI::FederateInternalError)
+ {
+ }
+
+ virtual void federationRestoreBegun()
+ throw (RTI::FederateInternalError)
+ {
+ }
+
+ virtual void initiateFederateRestore(const char* label, RTI::FederateHandle federateHandle)
+ throw (RTI::SpecifiedSaveLabelDoesNotExist,
+ RTI::CouldNotRestore,
+ RTI::FederateInternalError)
+ {
+ }
+
+ virtual void federationRestored()
+ throw (RTI::FederateInternalError)
+ {
+ }
+
+ virtual void federationNotRestored()
+ throw (RTI::FederateInternalError)
+ {
+ }
+
+ // Declaration Management
+ virtual void startRegistrationForObjectClass(RTI::ObjectClassHandle objectClassHandle)
+ throw (RTI::ObjectClassNotPublished,
+ RTI::FederateInternalError)
+ {
+ ObjectClassMap::iterator i = _objectClassMap.find(objectClassHandle);
+ if (i == _objectClassMap.end())
+ return;
+ if (!i->second.valid())
+ return;
+ i->second->startRegistration();
+ }
+
+ virtual void stopRegistrationForObjectClass(RTI::ObjectClassHandle objectClassHandle)
+ throw (RTI::ObjectClassNotPublished,
+ RTI::FederateInternalError)
+ {
+ ObjectClassMap::iterator i = _objectClassMap.find(objectClassHandle);
+ if (i == _objectClassMap.end())
+ return;
+ if (!i->second.valid())
+ return;
+ i->second->stopRegistration();
+ }
+
+ virtual void turnInteractionsOn(RTI::InteractionClassHandle interactionClassHandle)
+ throw (RTI::InteractionClassNotPublished,
+ RTI::FederateInternalError)
+ {
+ }
+
+ virtual void turnInteractionsOff(RTI::InteractionClassHandle interactionClassHandle)
+ throw (RTI::InteractionClassNotPublished,
+ RTI::FederateInternalError)
+ {
+ }
+
+
+ // Object Management
+ virtual void discoverObjectInstance(RTI::ObjectHandle objectHandle, RTI::ObjectClassHandle objectClassHandle, const char* tag)
+ throw (RTI::CouldNotDiscover,
+ RTI::ObjectClassNotKnown,
+ RTI::FederateInternalError)
+ {
+ ObjectClassMap::iterator i = _objectClassMap.find(objectClassHandle);
+ if (i == _objectClassMap.end())
+ throw RTI::ObjectClassNotKnown("Federate: discoverObjectInstance()!");
+ if (!i->second.valid())
+ return;
+ SGSharedPtr<RTI13ObjectInstance> objectInstance = new RTI13ObjectInstance(objectHandle, 0, i->second, _rtiAmbassador.get(), false);
+ _objectInstanceMap[objectHandle] = objectInstance;
+ _queueCallbackList.push_back(new DiscoverObjectCallback(i->second, objectInstance, tagToData(tag)));
+ }
+
+ virtual void reflectAttributeValues(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleValuePairSet& attributeValuePairSet,
+ const RTI::FedTime& fedTime, const char* tag, RTI::EventRetractionHandle eventRetractionHandle)
+ throw (RTI::ObjectNotKnown,
+ RTI::AttributeNotKnown,
+ RTI::FederateOwnsAttributes,
+ RTI::InvalidFederationTime,
+ RTI::FederateInternalError)
+ {
+ ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+ if (i == _objectInstanceMap.end())
+ throw RTI::ObjectNotKnown("Reflect attributes for unknown object!");
+ if (!i->second.valid())
+ return;
+ i->second->reflectAttributeValues(attributeValuePairSet, RTI13Ambassador::toTimeStamp(fedTime), tagToData(tag));
+ }
+
+ virtual void reflectAttributeValues(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleValuePairSet& attributeValuePairSet,
+ const char* tag)
+ throw (RTI::ObjectNotKnown,
+ RTI::AttributeNotKnown,
+ RTI::FederateOwnsAttributes,
+ RTI::FederateInternalError)
+ {
+ ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+ if (i == _objectInstanceMap.end())
+ throw RTI::ObjectNotKnown("Reflect attributes for unknown object!");
+ if (!i->second.valid())
+ return;
+ i->second->reflectAttributeValues(attributeValuePairSet, tagToData(tag));
+ }
+
+ virtual void receiveInteraction(RTI::InteractionClassHandle interactionClassHandle, const RTI::ParameterHandleValuePairSet& parameters,
+ const RTI::FedTime& fedTime, const char* tag, RTI::EventRetractionHandle eventRetractionHandle)
+ throw (RTI::InteractionClassNotKnown,
+ RTI::InteractionParameterNotKnown,
+ RTI::InvalidFederationTime,
+ RTI::FederateInternalError)
+ {
+ }
+
+ virtual void receiveInteraction(RTI::InteractionClassHandle interactionClassHandle,
+ const RTI::ParameterHandleValuePairSet& parameters, const char* tag)
+ throw (RTI::InteractionClassNotKnown,
+ RTI::InteractionParameterNotKnown,
+ RTI::FederateInternalError)
+ {
+ }
+
+ virtual void removeObjectInstance(RTI::ObjectHandle objectHandle, const RTI::FedTime& fedTime,
+ const char* tag, RTI::EventRetractionHandle eventRetractionHandle)
+ throw (RTI::ObjectNotKnown,
+ RTI::InvalidFederationTime,
+ RTI::FederateInternalError)
+ {
+ ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+ if (i == _objectInstanceMap.end())
+ throw RTI::ObjectNotKnown("Federate: removeObjectInstance()!");
+ if (i->second.valid())
+ _queueCallbackList.push_back(new RemoveObjectCallback(i->second, tagToData(tag)));
+ _objectInstanceMap.erase(i);
+ }
+
+ virtual void removeObjectInstance(RTI::ObjectHandle objectHandle, const char* tag)
+ throw (RTI::ObjectNotKnown,
+ RTI::FederateInternalError)
+ {
+ ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+ if (i == _objectInstanceMap.end())
+ throw RTI::ObjectNotKnown("Federate: removeObjectInstance()!");
+ if (i->second.valid())
+ _queueCallbackList.push_back(new RemoveObjectCallback(i->second, tagToData(tag)));
+ _objectInstanceMap.erase(i);
+ }
+
+ virtual void attributesInScope(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
+ throw (RTI::ObjectNotKnown,
+ RTI::AttributeNotKnown,
+ RTI::FederateInternalError)
+ {
+ ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+ if (i == _objectInstanceMap.end())
+ throw RTI::ObjectNotKnown("Attributes in scope for unknown object!");
+ if (!i->second.valid())
+ return;
+ i->second->attributesInScope(attributes);
+ }
+
+ virtual void attributesOutOfScope(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
+ throw (RTI::ObjectNotKnown,
+ RTI::AttributeNotKnown,
+ RTI::FederateInternalError)
+ {
+ ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+ if (i == _objectInstanceMap.end())
+ throw RTI::ObjectNotKnown("Attributes in scope for unknown object!");
+ if (!i->second.valid())
+ return;
+ i->second->attributesOutOfScope(attributes);
+ }
+
+ virtual void provideAttributeValueUpdate(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
+ throw (RTI::ObjectNotKnown,
+ RTI::AttributeNotKnown,
+ RTI::AttributeNotOwned,
+ RTI::FederateInternalError)
+ {
+ ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+ if (i == _objectInstanceMap.end())
+ throw RTI::ObjectNotKnown("Reflect attributes for unknown object!");
+ if (!i->second.valid())
+ return;
+ i->second->provideAttributeValueUpdate(attributes);
+ }
+
+ virtual void turnUpdatesOnForObjectInstance(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
+ throw (RTI::ObjectNotKnown,
+ RTI::AttributeNotOwned,
+ RTI::FederateInternalError)
+ {
+ ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+ if (i == _objectInstanceMap.end())
+ throw RTI::ObjectNotKnown("Turn on attributes for unknown object!");
+ if (!i->second.valid())
+ return;
+ i->second->turnUpdatesOnForObjectInstance(attributes);
+ }
+
+ virtual void turnUpdatesOffForObjectInstance(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
+ throw (RTI::ObjectNotKnown,
+ RTI::AttributeNotOwned,
+ RTI::FederateInternalError)
+ {
+ ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+ if (i == _objectInstanceMap.end())
+ throw RTI::ObjectNotKnown("Turn off attributes for unknown object!");
+ if (!i->second.valid())
+ return;
+ i->second->turnUpdatesOffForObjectInstance(attributes);
+ }
+
+ // Ownership Management
+ virtual void requestAttributeOwnershipAssumption(RTI::ObjectHandle objectHandle,
+ const RTI::AttributeHandleSet& attributes, const char* tag)
+ throw (RTI::ObjectNotKnown,
+ RTI::AttributeNotKnown,
+ RTI::AttributeAlreadyOwned,
+ RTI::AttributeNotPublished,
+ RTI::FederateInternalError)
+ {
+ ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+ if (i == _objectInstanceMap.end())
+ throw RTI::ObjectNotKnown("requestAttributeOwnershipAssumption for unknown object!");
+ if (!i->second.valid())
+ return;
+ i->second->requestAttributeOwnershipAssumption(attributes, tagToData(tag));
+ }
+
+ virtual void attributeOwnershipDivestitureNotification(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
+ throw (RTI::ObjectNotKnown,
+ RTI::AttributeNotKnown,
+ RTI::AttributeNotOwned,
+ RTI::AttributeDivestitureWasNotRequested,
+ RTI::FederateInternalError)
+ {
+ ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+ if (i == _objectInstanceMap.end())
+ throw RTI::ObjectNotKnown("attributeOwnershipDivestitureNotification for unknown object!");
+ if (!i->second.valid())
+ return;
+ i->second->attributeOwnershipDivestitureNotification(attributes);
+ }
+
+ virtual void attributeOwnershipAcquisitionNotification(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
+ throw (RTI::ObjectNotKnown,
+ RTI::AttributeNotKnown,
+ RTI::AttributeAcquisitionWasNotRequested,
+ RTI::AttributeAlreadyOwned,
+ RTI::AttributeNotPublished,
+ RTI::FederateInternalError)
+ {
+ ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+ if (i == _objectInstanceMap.end())
+ throw RTI::ObjectNotKnown("attributeOwnershipAcquisitionNotification for unknown object!");
+ if (!i->second.valid())
+ return;
+ i->second->attributeOwnershipAcquisitionNotification(attributes);
+ }
+
+ virtual void attributeOwnershipUnavailable(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
+ throw (RTI::ObjectNotKnown,
+ RTI::AttributeNotKnown,
+ RTI::AttributeAlreadyOwned,
+ RTI::AttributeAcquisitionWasNotRequested,
+ RTI::FederateInternalError)
+ {
+ ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+ if (i == _objectInstanceMap.end())
+ throw RTI::ObjectNotKnown("attributeOwnershipUnavailable for unknown object!");
+ if (!i->second.valid())
+ return;
+ i->second->attributeOwnershipUnavailable(attributes);
+ }
+
+ virtual void requestAttributeOwnershipRelease(RTI::ObjectHandle objectHandle,
+ const RTI::AttributeHandleSet& attributes, const char* tag)
+ throw (RTI::ObjectNotKnown,
+ RTI::AttributeNotKnown,
+ RTI::AttributeNotOwned,
+ RTI::FederateInternalError)
+ {
+ ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+ if (i == _objectInstanceMap.end())
+ throw RTI::ObjectNotKnown("requestAttributeOwnershipRelease for unknown object!");
+ if (!i->second.valid())
+ return;
+ i->second->requestAttributeOwnershipRelease(attributes, tagToData(tag));
+ }
+
+ virtual void confirmAttributeOwnershipAcquisitionCancellation(RTI::ObjectHandle objectHandle, const RTI::AttributeHandleSet& attributes)
+ throw (RTI::ObjectNotKnown,
+ RTI::AttributeNotKnown,
+ RTI::AttributeAlreadyOwned,
+ RTI::AttributeAcquisitionWasNotCanceled,
+ RTI::FederateInternalError)
+ {
+ ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+ if (i == _objectInstanceMap.end())
+ throw RTI::ObjectNotKnown("confirmAttributeOwnershipAcquisitionCancellation for unknown object!");
+ if (!i->second.valid())
+ return;
+ i->second->confirmAttributeOwnershipAcquisitionCancellation(attributes);
+ }
+
+ virtual void informAttributeOwnership(RTI::ObjectHandle objectHandle, RTI::AttributeHandle attributeHandle,
+ RTI::FederateHandle federateHandle)
+ throw (RTI::ObjectNotKnown,
+ RTI::AttributeNotKnown,
+ RTI::FederateInternalError)
+ {
+ ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+ if (i == _objectInstanceMap.end())
+ throw RTI::ObjectNotKnown("informAttributeOwnership for unknown object!");
+ if (!i->second.valid())
+ return;
+ i->second->informAttributeOwnership(attributeHandle, federateHandle);
+ }
+
+ virtual void attributeIsNotOwned(RTI::ObjectHandle objectHandle, RTI::AttributeHandle attributeHandle)
+ throw (RTI::ObjectNotKnown,
+ RTI::AttributeNotKnown,
+ RTI::FederateInternalError)
+ {
+ ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+ if (i == _objectInstanceMap.end())
+ throw RTI::ObjectNotKnown("attributeIsNotOwned for unknown object!");
+ if (!i->second.valid())
+ return;
+ i->second->attributeIsNotOwned(attributeHandle);
+ }
+
+ virtual void attributeOwnedByRTI(RTI::ObjectHandle objectHandle, RTI::AttributeHandle attributeHandle)
+ throw (RTI::ObjectNotKnown,
+ RTI::AttributeNotKnown,
+ RTI::FederateInternalError)
+ {
+ ObjectInstanceMap::iterator i = _objectInstanceMap.find(objectHandle);
+ if (i == _objectInstanceMap.end())
+ throw RTI::ObjectNotKnown("attributeOwnedByRTI for unknown object!");
+ if (!i->second.valid())
+ return;
+ i->second->attributeOwnedByRTI(attributeHandle);
+ }
+
+ // Time Management
+ virtual void timeRegulationEnabled(const RTI::FedTime& fedTime)
+ throw (RTI::InvalidFederationTime,
+ RTI::EnableTimeRegulationWasNotPending,
+ RTI::FederateInternalError)
+ {
+ _timeRegulationEnabled = true;
+ _federateTime = RTI13Ambassador::toTimeStamp(fedTime);
+ SG_LOG(SG_NETWORK, SG_INFO, "RTI: timeRegulationEnabled: " << _federateTime);
+ }
+
+ virtual void timeConstrainedEnabled(const RTI::FedTime& fedTime)
+ throw (RTI::InvalidFederationTime,
+ RTI::EnableTimeConstrainedWasNotPending,
+ RTI::FederateInternalError)
+ {
+ _timeConstrainedEnabled = true;
+ _federateTime = RTI13Ambassador::toTimeStamp(fedTime);
+ SG_LOG(SG_NETWORK, SG_INFO, "RTI: timeConstrainedEnabled: " << _federateTime);
+ }
+
+ virtual void timeAdvanceGrant(const RTI::FedTime& fedTime)
+ throw (RTI::InvalidFederationTime,
+ RTI::TimeAdvanceWasNotInProgress,
+ RTI::FederateInternalError)
+ {
+ _federateTime = RTI13Ambassador::toTimeStamp(fedTime);
+ _timeAdvancePending = false;
+ SG_LOG(SG_NETWORK, SG_INFO, "RTI: timeAdvanceGrant: " << _federateTime);
+ }
+
+ virtual void requestRetraction(RTI::EventRetractionHandle eventRetractionHandle)
+ throw (RTI::EventNotKnown,
+ RTI::FederateInternalError)
+ {
+ // No retraction concept yet
+ }
+
+ // processes the queues that filled up during the past
+ void processQueues()
+ {
+ while (!_queueCallbackList.empty()) {
+ (*_queueCallbackList.front())();
+ _queueCallbackList.pop_front();
+ }
+ }
+
+ bool getFederationSynchronizationPointAnnounced(const std::string& label)
+ { return _pendingSyncLabels.find(label) != _pendingSyncLabels.end(); }
+ bool getFederationSynchronized(const std::string& label)
+ {
+ std::set<std::string>::iterator i = _syncronizedSyncLabels.find(label);
+ if (i == _syncronizedSyncLabels.end())
+ return false;
+ _syncronizedSyncLabels.erase(i);
+ return true;
+ }
+
+ /// Generic callback to execute some notification on objects in a way that they are not prone to
+ /// ConcurrentAccess exceptions.
+ class QueueCallback : public SGReferenced {
+ public:
+ virtual ~QueueCallback() {}
+ virtual void operator()() = 0;
+ };
+
+ class DiscoverObjectCallback : public QueueCallback {
+ public:
+ DiscoverObjectCallback(SGSharedPtr<RTIObjectClass> objectClass, SGSharedPtr<RTIObjectInstance> objectInstance, const RTIData& tag) :
+ _objectClass(objectClass),
+ _objectInstance(objectInstance),
+ _tag(tag)
+ { }
+ virtual void operator()()
+ {
+ _objectClass->discoverInstance(_objectInstance.get(), _tag);
+ _objectInstance->requestObjectAttributeValueUpdate();
+ }
+ private:
+ SGSharedPtr<RTIObjectClass> _objectClass;
+ SGSharedPtr<RTIObjectInstance> _objectInstance;
+ RTIData _tag;
+ };
+ class RemoveObjectCallback : public QueueCallback {
+ public:
+ RemoveObjectCallback(SGSharedPtr<RTIObjectInstance> objectInstance, const RTIData& tag) :
+ _objectInstance(objectInstance),
+ _tag(tag)
+ { }
+ virtual void operator()()
+ {
+ _objectInstance->removeInstance(_tag);
+ }
+ private:
+ SGSharedPtr<RTIObjectInstance> _objectInstance;
+ RTIData _tag;
+ };
+
+ // The rtiambassador to issue requests
+ SGSharedPtr<RTI13Ambassador> _rtiAmbassador;
+
+ // All the sync labels we got an announcement for
+ std::set<std::string> _pendingSyncLabels;
+ std::set<std::string> _syncronizedSyncLabels;
+
+ // All that calls back into user code is just queued.
+ // That is to make sure we do not call recursively into the RTI
+ typedef std::list<SGSharedPtr<QueueCallback> > QueueCallbackList;
+ QueueCallbackList _queueCallbackList;
+
+ // Top level information for dispatching federate object attribute updates
+ typedef std::map<RTI::ObjectHandle, SGSharedPtr<RTI13ObjectInstance> > ObjectInstanceMap;
+ // Map of all available objects
+ ObjectInstanceMap _objectInstanceMap;
+
+ // Top level information for dispatching creation of federate objects
+ typedef std::map<RTI::ObjectClassHandle, SGSharedPtr<RTI13ObjectClass> > ObjectClassMap;
+ ObjectClassMap _objectClassMap;
+
+ bool _timeRegulationEnabled;
+ bool _timeConstrainedEnabled;
+ bool _timeAdvancePending;
+ SGTimeStamp _federateTime;
+
+private:
+ const RTIData& tagToData(const char* tag)
+ {
+ if (tag)
+ _cachedTag.setData(tag, std::strlen(tag) + 1);
+ else
+ _cachedTag.setData("", 1);
+ return _cachedTag;
+ }
+ RTIData _cachedTag;
+};
+
+RTI13Federate::RTI13Federate(const std::list<std::string>& stringList) :
+ _joined(false),
+ _ambassador(new RTI13Ambassador),
+ _federateAmbassador(new FederateAmbassador)
+{
+ _ambassador->_federate = this;
+ _federateAmbassador->_rtiAmbassador = _ambassador;
+ if (stringList.empty()) {
+ SG_LOG(SG_NETWORK, SG_WARN, "RTI: Ignoring non empty connect arguments while connecting to an RTI13 federation!");
+ }