diff -ru certi.orig/include/RTIambServices.hh certi.new/include/RTIambServices.hh --- certi.orig/include/RTIambServices.hh 2007-06-14 15:00:21.000000000 +0200 +++ certi.new/include/RTIambServices.hh 2008-04-02 13:50:13.000000000 +0200 @@ -475,7 +475,7 @@ Boolean tick2() throw (SpecifiedSaveLabelDoesNotExist, ConcurrentAccessAttempted, RTIinternalError); -Boolean tick_kernel(bool) +Boolean __tick_kernel(Boolean, TickTime, TickTime) throw (SpecifiedSaveLabelDoesNotExist, ConcurrentAccessAttempted, RTIinternalError); Boolean tick(TickTime, TickTime) diff -ru certi.orig/libCERTI/Message.cc certi.new/libCERTI/Message.cc --- certi.orig/libCERTI/Message.cc 2008-02-27 17:38:27.000000000 +0100 +++ certi.new/libCERTI/Message.cc 2008-04-02 13:48:42.000000000 +0200 @@ -194,6 +194,20 @@ // ---------------------------------------------------------------------------- void +Message::setMinTickTime(RTI::TickTime time) +{ + minTickTime = time; +} + +// ---------------------------------------------------------------------------- +void +Message::setMaxTickTime(RTI::TickTime time) +{ + maxTickTime = time; +} + +// ---------------------------------------------------------------------------- +void Message::setDimension(DimensionHandle handle) { dimension = handle ; @@ -603,6 +617,8 @@ dimension = msg.dimension ; // transportation = msg.transportation ; // ordering = msg.ordering ; + minTickTime = msg.minTickTime ; + maxTickTime = msg.maxTickTime ; strcpy(tag, msg.tag); strcpy(name, msg.name); diff -ru certi.orig/libCERTI/Message.hh certi.new/libCERTI/Message.hh --- certi.orig/libCERTI/Message.hh 2007-12-17 17:01:25.000000000 +0100 +++ certi.new/libCERTI/Message.hh 2008-04-02 13:47:45.000000000 +0200 @@ -310,6 +310,12 @@ long getRegion() const { return region ; }; void setRegion(long); + RTI::TickTime getMinTickTime() const { return minTickTime ; }; + void setMinTickTime(RTI::TickTime); + + RTI::TickTime getMaxTickTime() const { return maxTickTime ; }; + void setMaxTickTime(RTI::TickTime); + void setFederationTimeDelta(FederationTimeDelta); FederationTimeDelta getFederationTimeDelta() const { return lookahead ; }; @@ -415,6 +421,8 @@ // OrderingHandle ordering ; unsigned long number ; long region ; + RTI::TickTime minTickTime; + RTI::TickTime maxTickTime; public: // used for both Attributes and Parameters arrays. diff -ru certi.orig/libCERTI/Message_R.cc certi.new/libCERTI/Message_R.cc --- certi.orig/libCERTI/Message_R.cc 2008-03-13 15:39:19.000000000 +0100 +++ certi.new/libCERTI/Message_R.cc 2008-04-02 13:52:15.000000000 +0200 @@ -441,8 +441,14 @@ case DISABLE_TIME_REGULATION: case ENABLE_TIME_CONSTRAINED: case DISABLE_TIME_CONSTRAINED: + boolean = body.readLongInt(); + break ; + + // Body contains boolean, TickTime, TickTime case TICK_REQUEST: boolean = body.readLongInt(); + body.readBlock((char *)&minTickTime, sizeof(minTickTime)); + body.readBlock((char *)&maxTickTime, sizeof(maxTickTime)); break ; // Body contains objectClass, handleArraySize, diff -ru certi.orig/libCERTI/Message_W.cc certi.new/libCERTI/Message_W.cc --- certi.orig/libCERTI/Message_W.cc 2008-03-13 15:39:19.000000000 +0100 +++ certi.new/libCERTI/Message_W.cc 2008-04-02 13:52:52.000000000 +0200 @@ -454,8 +454,14 @@ case DISABLE_TIME_REGULATION: case ENABLE_TIME_CONSTRAINED: case DISABLE_TIME_CONSTRAINED: + body.writeLongInt(boolean); + break ; + + // Body contains boolean, TickTime, TickTime case TICK_REQUEST: body.writeLongInt(boolean); + body.writeBlock((char *)&minTickTime, sizeof(minTickTime)); + body.writeBlock((char *)&maxTickTime, sizeof(maxTickTime)); break ; // Body contains objectClass, handleArray diff -ru certi.orig/libRTI/RTIambassador.cc certi.new/libRTI/RTIambassador.cc --- certi.orig/libRTI/RTIambassador.cc 2008-03-13 15:39:19.000000000 +0100 +++ certi.new/libRTI/RTIambassador.cc 2008-04-02 17:02:52.000000000 +0200 @@ -195,33 +195,46 @@ } // ---------------------------------------------------------------------------- -// Tick +//! Evoke callback (HLA1.3). +/*! Non-blocking callback evocation, returns immediately with or without 1 callback. + * @return Always returns false. + */ RTI::Boolean RTI::RTIambassador::tick() throw (SpecifiedSaveLabelDoesNotExist, ConcurrentAccessAttempted, RTIinternalError) { - // non-blocking tick, returns immediately with or without 1 callback - return tick_kernel (false); + __tick_kernel(RTI_FALSE, 0.0, 0.0); + return RTI_FALSE; } // ---------------------------------------------------------------------------- -// Tick +//! Evoke callback (CERTI extension). +/*! Blocks until a callback delivery and then evokes a single callback. + * Waits until a callback delivery, be careful. + * @return true if additional callbacks pending, false otherwise + * @warning This is a non-standard extension of the HLA 1.3 API. + */ RTI::Boolean RTI::RTIambassador::tick2() throw (SpecifiedSaveLabelDoesNotExist, ConcurrentAccessAttempted, RTIinternalError) { - // blocking tick, waits until a callback delivery, be careful - return tick_kernel (true); + __tick_kernel(RTI_FALSE, std::numeric_limits::infinity(), 0.0); + return RTI_FALSE; } // ---------------------------------------------------------------------------- -// Tick_kernel +//! Generic callback evocation (CERTI extension). +/*! Blocks up to "minimum" seconds until a callback delivery and then evokes a + * single callback. + * @return true if additional callbacks pending, false otherwise + * @warning This is a non-standard extension of the HLA 1.3 API. + */ RTI::Boolean -RTI::RTIambassador::tick_kernel(bool locked) +RTI::RTIambassador::__tick_kernel(RTI::Boolean multiple, TickTime minimum, TickTime maximum) throw (SpecifiedSaveLabelDoesNotExist, ConcurrentAccessAttempted, RTIinternalError) @@ -230,10 +243,9 @@ // Prevenir le RTI vers_RTI.type = Message::TICK_REQUEST ; - if (locked) - vers_RTI.setBoolean(true); - else - vers_RTI.setBoolean(false); + vers_RTI.setBoolean(multiple); + vers_RTI.setMinTickTime(minimum); + vers_RTI.setMaxTickTime(maximum); try { vers_RTI.write(privateRefs->socketUn); @@ -245,285 +257,288 @@ throw RTIinternalError("RTI::RTIambassador::tick_kernel (tick1) : NetworkError-->RTIinternalError"); } - // Lire la reponse du RTIA local - try { - vers_Fed.read(privateRefs->socketUn); - } - catch (NetworkError) { - cout << "tick 2." << endl ; - cout << "LibRTI:: Catched NetworkError, throw RTIinternalError." - << endl ; - throw RTIinternalError("RTI::RTIambassador::tick_kernel (tick2) : NetworkError-->RTIinternalError"); - } + // Read response(s) from the local RTIA until Message::TICK_REQUEST is received. + while (1) { + try { + vers_Fed.read(privateRefs->socketUn); + } + catch (NetworkError) { + cout << "tick 2." << endl ; + cout << "LibRTI:: Catched NetworkError, throw RTIinternalError." + << endl ; + throw RTIinternalError("RTI::RTIambassador::tick_kernel (tick2) : NetworkError-->RTIinternalError"); + } - // Si c'est de type TICK_REQUEST, il n'y a qu'a traiter l'exception. - if (vers_Fed.type == Message::TICK_REQUEST) { - privateRefs->processException(&vers_Fed); - return RTI::Boolean(vers_Fed.getBoolean()); - } + vers_RTI.setException(e_NO_EXCEPTION); + + try { + //D.Mes( pdMessage, 'M', vers_Fed.type); + vers_Fed.trace("RTI::RTIambassador::tick "); + + switch (vers_Fed.type) { + + // If the type is TICK_REQUEST, the __tick_kernel() has terminated. + + case Message::TICK_REQUEST: + if (vers_Fed.getExceptionType() != e_NO_EXCEPTION) + privateRefs->processException(&vers_Fed); + return RTI::Boolean(vers_Fed.getBoolean()); + + // Otherwise, the RTI calls a FederateAmbassador service. + + case Message::SYNCHRONIZATION_POINT_REGISTRATION_SUCCEEDED: + privateRefs->fed_amb->synchronizationPointRegistrationSucceeded(vers_Fed.getLabel()); + break ; + + case Message::ANNOUNCE_SYNCHRONIZATION_POINT: + privateRefs->fed_amb->announceSynchronizationPoint(vers_Fed.getLabel(),vers_Fed.getTag()); + break ; + + case Message::FEDERATION_SYNCHRONIZED: + privateRefs->fed_amb->federationSynchronized(vers_Fed.getLabel()); + break ; + + case Message::INITIATE_FEDERATE_SAVE: + privateRefs->fed_amb->initiateFederateSave(vers_Fed.getLabel()); + break ; + + case Message::FEDERATION_SAVED: + privateRefs->fed_amb->federationSaved(); + break ; + + case Message::REQUEST_FEDERATION_RESTORE_SUCCEEDED: + privateRefs->fed_amb->requestFederationRestoreSucceeded( + vers_Fed.getLabel()); + break ; + + case Message::REQUEST_FEDERATION_RESTORE_FAILED: + privateRefs->fed_amb->requestFederationRestoreFailed(vers_Fed.getLabel(), + vers_Fed.getTag()); + break ; + + case Message::FEDERATION_RESTORE_BEGUN: + privateRefs->fed_amb->federationRestoreBegun(); + break ; + + case Message::INITIATE_FEDERATE_RESTORE: + privateRefs->fed_amb->initiateFederateRestore(vers_Fed.getLabel(), + vers_Fed.getFederate()); + break ; + + case Message::FEDERATION_RESTORED: + privateRefs->fed_amb->federationRestored(); + break ; + + case Message::FEDERATION_NOT_RESTORED: + privateRefs->fed_amb->federationNotRestored(); + break ; + + case Message::START_REGISTRATION_FOR_OBJECT_CLASS: { + privateRefs->fed_amb->startRegistrationForObjectClass( + vers_Fed.getObjectClass()); + } break ; + + case Message::STOP_REGISTRATION_FOR_OBJECT_CLASS: { + privateRefs->fed_amb-> + stopRegistrationForObjectClass(vers_Fed.getObjectClass()); + } break ; + + case Message::TURN_INTERACTIONS_ON: { + privateRefs->fed_amb->turnInteractionsOn(vers_Fed.getInteractionClass()); + } break ; + + case Message::TURN_INTERACTIONS_OFF: { + privateRefs->fed_amb->turnInteractionsOff(vers_Fed.getInteractionClass()); + } break ; + + case Message::DISCOVER_OBJECT_INSTANCE: { + privateRefs->fed_amb-> + discoverObjectInstance(vers_Fed.getObject(), + vers_Fed.getObjectClass(), + vers_Fed.getName()); + } break ; + + case Message::REFLECT_ATTRIBUTE_VALUES: { + G.Out(pdGendoc," tick_kernel call to reflectAttributeValues"); + AttributeHandleValuePairSet *attributes = vers_Fed.getAHVPS(); + if (vers_Fed.getBoolean()) + privateRefs->fed_amb-> + reflectAttributeValues(vers_Fed.getObject(), + *attributes, + vers_Fed.getFedTime(), + vers_Fed.getTag(), + vers_Fed.getEventRetraction()); + else + privateRefs->fed_amb-> + reflectAttributeValues(vers_Fed.getObject(), + *attributes, + vers_Fed.getTag()); + delete attributes ; + } break ; + + case Message::RECEIVE_INTERACTION: + { + ParameterHandleValuePairSet *parameters = vers_Fed.getPHVPS(); + if (vers_Fed.getBoolean()) + privateRefs->fed_amb->receiveInteraction( + vers_Fed.getInteractionClass(), + *parameters, + vers_Fed.getFedTime(), + vers_Fed.getTag(), + vers_Fed.getEventRetraction()); + else + privateRefs->fed_amb->receiveInteraction( + vers_Fed.getInteractionClass(), + *parameters, + vers_Fed.getTag()); + + delete parameters ; + } break ; + + case Message::REMOVE_OBJECT_INSTANCE: { + if (vers_Fed.getBoolean()) { + privateRefs->fed_amb->removeObjectInstance( + vers_Fed.getObject(), + vers_Fed.getFedTime(), + vers_Fed.getTag(), + vers_Fed.getEventRetraction()); + } + else { + privateRefs->fed_amb->removeObjectInstance( + vers_Fed.getObject(), + vers_Fed.getTag()); + } + } break ; - // Sinon, le RTI nous demande un service, donc on appele une methode - // du FederateAmbassador. + case Message::PROVIDE_ATTRIBUTE_VALUE_UPDATE: { + AttributeHandleSet *attributeSet = vers_Fed.getAHS(); - vers_RTI.setException(e_NO_EXCEPTION); + privateRefs->fed_amb->provideAttributeValueUpdate(vers_Fed.getObject(),*attributeSet); + delete attributeSet ; + } break ; + + case Message::REQUEST_RETRACTION: { + } break ; - try { - //D.Mes( pdMessage, 'M', vers_Fed.type); - vers_Fed.trace("RTI::RTIambassador::tick "); - - switch (vers_Fed.type) { - - case Message::SYNCHRONIZATION_POINT_REGISTRATION_SUCCEEDED: - privateRefs->fed_amb->synchronizationPointRegistrationSucceeded(vers_Fed.getLabel()); - break ; - - case Message::ANNOUNCE_SYNCHRONIZATION_POINT: - privateRefs->fed_amb->announceSynchronizationPoint(vers_Fed.getLabel(),vers_Fed.getTag()); - break ; - - case Message::FEDERATION_SYNCHRONIZED: - privateRefs->fed_amb->federationSynchronized(vers_Fed.getLabel()); - break ; - - case Message::INITIATE_FEDERATE_SAVE: - privateRefs->fed_amb->initiateFederateSave(vers_Fed.getLabel()); - break ; - - case Message::FEDERATION_SAVED: - privateRefs->fed_amb->federationSaved(); - break ; - - case Message::REQUEST_FEDERATION_RESTORE_SUCCEEDED: - privateRefs->fed_amb->requestFederationRestoreSucceeded( - vers_Fed.getLabel()); - break ; - - case Message::REQUEST_FEDERATION_RESTORE_FAILED: - privateRefs->fed_amb->requestFederationRestoreFailed(vers_Fed.getLabel(), - vers_Fed.getTag()); - break ; - - case Message::FEDERATION_RESTORE_BEGUN: - privateRefs->fed_amb->federationRestoreBegun(); - break ; - - case Message::INITIATE_FEDERATE_RESTORE: - privateRefs->fed_amb->initiateFederateRestore(vers_Fed.getLabel(), - vers_Fed.getFederate()); - break ; - - case Message::FEDERATION_RESTORED: - privateRefs->fed_amb->federationRestored(); - break ; - - case Message::FEDERATION_NOT_RESTORED: - privateRefs->fed_amb->federationNotRestored(); - break ; - - case Message::START_REGISTRATION_FOR_OBJECT_CLASS: { - privateRefs->fed_amb->startRegistrationForObjectClass( - vers_Fed.getObjectClass()); - } break ; - - case Message::STOP_REGISTRATION_FOR_OBJECT_CLASS: { - privateRefs->fed_amb-> - stopRegistrationForObjectClass(vers_Fed.getObjectClass()); - } break ; - - case Message::TURN_INTERACTIONS_ON: { - privateRefs->fed_amb->turnInteractionsOn(vers_Fed.getInteractionClass()); - } break ; - - case Message::TURN_INTERACTIONS_OFF: { - privateRefs->fed_amb->turnInteractionsOff(vers_Fed.getInteractionClass()); - } break ; - - case Message::DISCOVER_OBJECT_INSTANCE: { - privateRefs->fed_amb-> - discoverObjectInstance(vers_Fed.getObject(), - vers_Fed.getObjectClass(), - vers_Fed.getName()); - } break ; - - case Message::REFLECT_ATTRIBUTE_VALUES: { - G.Out(pdGendoc," tick_kernel call to reflectAttributeValues"); - AttributeHandleValuePairSet *attributes = vers_Fed.getAHVPS(); - if (vers_Fed.getBoolean()) - privateRefs->fed_amb-> - reflectAttributeValues(vers_Fed.getObject(), - *attributes, - vers_Fed.getFedTime(), - vers_Fed.getTag(), - vers_Fed.getEventRetraction()); - else - privateRefs->fed_amb-> - reflectAttributeValues(vers_Fed.getObject(), - *attributes, - vers_Fed.getTag()); - delete attributes ; - } break ; - - case Message::RECEIVE_INTERACTION: - { - ParameterHandleValuePairSet *parameters = vers_Fed.getPHVPS(); - if (vers_Fed.getBoolean()) - privateRefs->fed_amb->receiveInteraction( - vers_Fed.getInteractionClass(), - *parameters, - vers_Fed.getFedTime(), - vers_Fed.getTag(), - vers_Fed.getEventRetraction()); - else - privateRefs->fed_amb->receiveInteraction( - vers_Fed.getInteractionClass(), - *parameters, - vers_Fed.getTag()); + case Message::REQUEST_ATTRIBUTE_OWNERSHIP_ASSUMPTION: { + AttributeHandleSet *attributeSet = vers_Fed.getAHS(); - delete parameters ; + privateRefs->fed_amb-> + requestAttributeOwnershipAssumption(vers_Fed.getObject(), + *attributeSet, + vers_Fed.getTag()); + delete attributeSet ; } break ; - case Message::REMOVE_OBJECT_INSTANCE: { - if (vers_Fed.getBoolean()) { - privateRefs->fed_amb->removeObjectInstance( - vers_Fed.getObject(), - vers_Fed.getFedTime(), - vers_Fed.getTag(), - vers_Fed.getEventRetraction()); - } - else { - privateRefs->fed_amb->removeObjectInstance( - vers_Fed.getObject(), - vers_Fed.getTag()); - } - } break ; - - case Message::PROVIDE_ATTRIBUTE_VALUE_UPDATE: { - AttributeHandleSet *attributeSet = vers_Fed.getAHS(); - - privateRefs->fed_amb->provideAttributeValueUpdate(vers_Fed.getObject(),*attributeSet); - delete attributeSet ; - } break ; - - case Message::REQUEST_RETRACTION: { - - } break ; - - case Message::REQUEST_ATTRIBUTE_OWNERSHIP_ASSUMPTION: { - AttributeHandleSet *attributeSet = vers_Fed.getAHS(); - - privateRefs->fed_amb-> - requestAttributeOwnershipAssumption(vers_Fed.getObject(), - *attributeSet, - vers_Fed.getTag()); - delete attributeSet ; - } break ; - - case Message::REQUEST_ATTRIBUTE_OWNERSHIP_RELEASE: { - AttributeHandleSet *attributeSet = vers_Fed.getAHS(); - - privateRefs->fed_amb->requestAttributeOwnershipRelease( - vers_Fed.getObject(), - *attributeSet, - vers_Fed.getTag()); - - delete attributeSet ; - } break ; - - case Message::ATTRIBUTE_OWNERSHIP_UNAVAILABLE: { - AttributeHandleSet *attributeSet = vers_Fed.getAHS(); - - privateRefs->fed_amb->attributeOwnershipUnavailable(vers_Fed.getObject(), - *attributeSet); - - delete attributeSet ; - } break ; - - case Message::ATTRIBUTE_OWNERSHIP_ACQUISITION_NOTIFICATION: { - AttributeHandleSet *attributeSet = vers_Fed.getAHS(); - - privateRefs->fed_amb->attributeOwnershipAcquisitionNotification( - vers_Fed.getObject(), - *attributeSet); - - delete attributeSet ; - } break ; - - case Message::ATTRIBUTE_OWNERSHIP_DIVESTITURE_NOTIFICATION: { - AttributeHandleSet *attributeSet = vers_Fed.getAHS(); - - privateRefs->fed_amb->attributeOwnershipDivestitureNotification( - vers_Fed.getObject(), - *attributeSet); - - delete attributeSet ; - } break ; - - case Message::CONFIRM_ATTRIBUTE_OWNERSHIP_ACQUISITION_CANCELLATION: { - AttributeHandleSet *attributeSet = vers_Fed.getAHS(); - - privateRefs->fed_amb-> - confirmAttributeOwnershipAcquisitionCancellation - (vers_Fed.getObject(), *attributeSet); - - delete attributeSet ; - } break ; - - case Message::INFORM_ATTRIBUTE_OWNERSHIP: { - privateRefs->fed_amb-> - informAttributeOwnership(vers_Fed.getObject(), - vers_Fed.getAttribute(), - vers_Fed.getFederate()); - } break ; - - case Message::ATTRIBUTE_IS_NOT_OWNED: { - privateRefs->fed_amb->attributeIsNotOwned(vers_Fed.getObject(), - vers_Fed.getAttribute()); - } break ; - - case Message::TIME_ADVANCE_GRANT: { - privateRefs->fed_amb->timeAdvanceGrant(vers_Fed.getFedTime()); - } break ; - - default: { - privateRefs->leave("RTI service requested by RTI is unknown."); - } + case Message::REQUEST_ATTRIBUTE_OWNERSHIP_RELEASE: { + AttributeHandleSet *attributeSet = vers_Fed.getAHS(); + + privateRefs->fed_amb->requestAttributeOwnershipRelease( + vers_Fed.getObject(), + *attributeSet, + vers_Fed.getTag()); + + delete attributeSet ; + } break ; + + case Message::ATTRIBUTE_OWNERSHIP_UNAVAILABLE: { + AttributeHandleSet *attributeSet = vers_Fed.getAHS(); + + privateRefs->fed_amb->attributeOwnershipUnavailable(vers_Fed.getObject(), + *attributeSet); + + delete attributeSet ; + } break ; + + case Message::ATTRIBUTE_OWNERSHIP_ACQUISITION_NOTIFICATION: { + AttributeHandleSet *attributeSet = vers_Fed.getAHS(); + + privateRefs->fed_amb->attributeOwnershipAcquisitionNotification( + vers_Fed.getObject(), + *attributeSet); + + delete attributeSet ; + } break ; + + case Message::ATTRIBUTE_OWNERSHIP_DIVESTITURE_NOTIFICATION: { + AttributeHandleSet *attributeSet = vers_Fed.getAHS(); + + privateRefs->fed_amb->attributeOwnershipDivestitureNotification( + vers_Fed.getObject(), + *attributeSet); + + delete attributeSet ; + } break ; + + case Message::CONFIRM_ATTRIBUTE_OWNERSHIP_ACQUISITION_CANCELLATION: { + AttributeHandleSet *attributeSet = vers_Fed.getAHS(); + + privateRefs->fed_amb-> + confirmAttributeOwnershipAcquisitionCancellation + (vers_Fed.getObject(), *attributeSet); + + delete attributeSet ; + } break ; + + case Message::INFORM_ATTRIBUTE_OWNERSHIP: { + privateRefs->fed_amb-> + informAttributeOwnership(vers_Fed.getObject(), + vers_Fed.getAttribute(), + vers_Fed.getFederate()); + } break ; + + case Message::ATTRIBUTE_IS_NOT_OWNED: { + privateRefs->fed_amb->attributeIsNotOwned(vers_Fed.getObject(), + vers_Fed.getAttribute()); + } break ; + + case Message::TIME_ADVANCE_GRANT: { + privateRefs->fed_amb->timeAdvanceGrant(vers_Fed.getFedTime()); + } break ; + + default: { + privateRefs->leave("RTI service requested by RTI is unknown."); + } + } + } + catch (InvalidFederationTime &e) { + vers_RTI.setException(e_InvalidFederationTime, e._reason); + throw ; + } + catch (TimeAdvanceWasNotInProgress &e) { + vers_RTI.setException(e_TimeAdvanceWasNotInProgress, e._reason); + throw ; + } + catch (FederationTimeAlreadyPassed &e) { + vers_RTI.setException(e_FederationTimeAlreadyPassed, e._reason); + } + catch (FederateInternalError &e) { + vers_RTI.setException(e_FederateInternalError, e._reason); + throw ; + } + catch (Exception &e) { + vers_RTI.setException(e_RTIinternalError, e._reason); + throw ; } } - catch (InvalidFederationTime &e) { - vers_RTI.setException(e_InvalidFederationTime, e._reason); - throw ; - } - catch (TimeAdvanceWasNotInProgress &e) { - vers_RTI.setException(e_TimeAdvanceWasNotInProgress, e._reason); - throw ; - } - catch (FederationTimeAlreadyPassed &e) { - vers_RTI.setException(e_FederationTimeAlreadyPassed, e._reason); - } - catch (FederateInternalError &e) { - vers_RTI.setException(e_FederateInternalError, e._reason); - throw ; - } - catch (Exception &e) { - vers_RTI.setException(e_RTIinternalError, e._reason); - throw ; - } - - return RTI::Boolean(true); - } // ---------------------------------------------------------------------------- +//! Evoke multiple callbacks (HLA1.3). +/*! Blocks up to "minimum" seconds until a callback delivery, then envokes + * multiple callbacks until no callback is pending, or until "maximum" + * duration is reached. + * @return true if additional callbacks pending, false otherwise + */ RTI::Boolean -RTI::RTIambassador::tick(TickTime, TickTime) +RTI::RTIambassador::tick(TickTime minimum, TickTime maximum) throw (SpecifiedSaveLabelDoesNotExist, ConcurrentAccessAttempted, RTIinternalError) { - return tick(); + return __tick_kernel(RTI_TRUE, minimum, maximum); } - // ---------------------------------------------------------------------------- // Create Federation Execution. /** Realization of the Create Federation Execution federation management service diff -ru certi.orig/libRTI/RTIambPrivateRefs.cc certi.new/libRTI/RTIambPrivateRefs.cc --- certi.orig/libRTI/RTIambPrivateRefs.cc 2008-02-18 14:37:30.000000000 +0100 +++ certi.new/libRTI/RTIambPrivateRefs.cc 2008-04-02 13:17:01.000000000 +0200 @@ -84,12 +84,11 @@ D.Out(pdDebug, "RTIA reply received."); - if (req->type != Message::TICK_REQUEST) { - if (rep->type != req->type) { - std::cout << "LibRTI: Assertion failed: rep->type != req->type" << std::endl ; - throw RTIinternalError("RTIambPrivateRefs::executeService: " - "rep->type != req->type"); - } + + if (rep->type != req->type) { + std::cout << "LibRTI: Assertion failed: rep->type != req->type" << std::endl ; + throw RTIinternalError("RTIambPrivateRefs::executeService: " + "rep->type != req->type"); } D.Out(pdDebug, "processing returned exception (from reply)."); diff -ru certi.orig/RTIA/Communications.cc certi.new/RTIA/Communications.cc --- certi.orig/RTIA/Communications.cc 2008-02-22 12:34:30.000000000 +0100 +++ certi.new/RTIA/Communications.cc 2008-04-01 17:22:45.000000000 +0200 @@ -180,7 +180,8 @@ Returns the actual source in the 1st parameter (RTIG=>1 federate=>2) */ void -Communications::readMessage(int &n, NetworkMessage *msg_reseau, Message *msg) +Communications::readMessage(int &n, NetworkMessage *msg_reseau, Message *msg, + struct timeval *timeout) { const int tcp_fd(SecureTCPSocket::returnSocket()); const int udp_fd(SocketUDP::returnSocket()); @@ -241,7 +242,7 @@ else { // waitingList is empty and no data in TCP buffer. // Wait a message (coming from federate or network). - if (select(max_fd, &fdset, NULL, NULL, NULL) < 0) { + if (select(max_fd, &fdset, NULL, NULL, timeout) < 0) { #ifdef _WIN32 if(WSAGetLastError() == WSAEINTR) #else @@ -275,12 +276,16 @@ msg_reseau->read((SocketUDP *) this); n = 1 ; } - else { + else if (FD_ISSET(_socket_un, &fdset)) { // Read a message coming from the federate. - assert(FD_ISSET(_socket_un, &fdset)); receiveUN(msg); n = 2 ; } + else + { + // select() timeout occured + n = 3; + } } } diff -ru certi.orig/RTIA/Communications.hh certi.new/RTIA/Communications.hh --- certi.orig/RTIA/Communications.hh 2008-02-22 12:34:30.000000000 +0100 +++ certi.new/RTIA/Communications.hh 2008-04-01 15:39:54.000000000 +0200 @@ -54,7 +54,7 @@ void sendMessage(NetworkMessage *Msg); void sendUN(Message *Msg); void receiveUN(Message *Msg); - void readMessage(int&, NetworkMessage *, Message *); + void readMessage(int&, NetworkMessage *, Message *, struct timeval *); void requestFederateService(Message *req); unsigned long getAddress(); unsigned int getPort(); diff -ru certi.orig/RTIA/RTIA.cc certi.new/RTIA/RTIA.cc --- certi.orig/RTIA/RTIA.cc 2008-03-14 15:52:23.000000000 +0100 +++ certi.new/RTIA/RTIA.cc 2008-04-02 17:02:19.000000000 +0200 @@ -25,6 +25,7 @@ #include "RTIA.hh" #include +#include namespace certi { namespace rtia { @@ -109,7 +110,7 @@ msg_un = new Message ; try { - comm->readMessage(n, msg_tcp_udp, msg_un); + comm->readMessage(n, msg_tcp_udp, msg_un, NULL); } catch (NetworkSignal) { fm->_fin_execution = true ; @@ -129,20 +130,32 @@ processFederateRequest(msg_un); delete msg_tcp_udp ; break ; + case 3: // timeout + break ; default: assert(false); } - // special case, blocking tick (tick2) - while (!fm->_fin_execution && tm->_ongoing_tick) { + // special case, blocking tick + while (!fm->_fin_execution && tm->_blocking_tick) { // read a message from the rtig // same code is reused, but only the case 1 should match - msg_tcp_udp = new NetworkMessage ; msg_un = new Message ; try { - comm->readMessage(n, msg_tcp_udp, msg_un); + if (isfinite(tm->_tick_timeout) && tm->_tick_timeout < LONG_MAX) + { + struct timeval timev; + timev.tv_sec = int(tm->_tick_timeout); + timev.tv_usec = int((tm->_tick_timeout-timev.tv_sec)*1000000.0); + + comm->readMessage(n, msg_tcp_udp, msg_un, &timev); + } + else + comm->readMessage(n, msg_tcp_udp, msg_un, NULL); + + /* timev is undefined after select() */ } catch (NetworkSignal) { fm->_fin_execution = true ; @@ -156,11 +169,15 @@ break ; case 1: processNetworkMessage(msg_tcp_udp) ; // could authorize a callbak - msg_un->type = Message::TICK_REQUEST ; - msg_un->setBoolean(true) ; - processFederateRequest(msg_un); //could reset _ongoing_tick + // may have reset tm->_blocking_tick + processOngoingTick(); break ; case 2: + assert(false); + case 3: // timeout + tm->_blocking_tick = false; + processOngoingTick(); + break ; default: assert(false); } diff -ru certi.orig/RTIA/RTIA_federate.cc certi.new/RTIA/RTIA_federate.cc --- certi.orig/RTIA/RTIA_federate.cc 2008-03-14 15:52:23.000000000 +0100 +++ certi.new/RTIA/RTIA_federate.cc 2008-04-02 16:56:51.000000000 +0200 @@ -39,6 +39,22 @@ static PrettyDebug G("GENDOC",__FILE__) ; // ---------------------------------------------------------------------------- +static RTI::TickTime currentTickTime() +{ + RTI::TickTime result; +#ifdef _WIN32 + _timeb timev; + _ftime(&timev); + result = timev.time + timev.millitm/1000; +#else + struct timeval timev; + gettimeofday(&timev, NULL); + result = timev.tv_sec + timev.tv_usec/1000000; +#endif + return result; +} + +// ---------------------------------------------------------------------------- //! Verify that federate is not in saving or restoring state. void RTIA::saveAndRestoreStatus(Message::Type type) @@ -938,18 +954,19 @@ break ; case Message::TICK_REQUEST: - tm->_tick_request_ack = true ; - if (req->getBoolean()) { - tm->_ongoing_tick = true ; - D.Out(pdDebug, "Receiving Message from Federate, type TickRequest2."); - - } - else { - D.Out(pdDebug, "Receiving Message from Federate, type TickRequest."); - + tm->_tick_multiple = req->getBoolean(); + + if (req->getMinTickTime() > 0.0) + { + tm->_tick_timeout = req->getMinTickTime(); + tm->_tick_stop_time = currentTickTime() + req->getMaxTickTime(); + + tm->_blocking_tick = true ; } - rep.setBoolean(tm->tick(e)); + else + tm->_blocking_tick = false ; + processOngoingTick(); break ; default: @@ -962,6 +979,43 @@ } // ---------------------------------------------------------------------------- +//! RTIA processes the TICK_REQUEST +void +RTIA::processOngoingTick() +{ + TypeException exc = e_NO_EXCEPTION; + bool pending; + + do { + // send a single callback to federate (if any) + pending = tm->tick(exc); + + // processing a callback may have reset tm->_blocking_tick + + if (!tm->_tick_multiple) + break; + + if (currentTickTime() > tm->_tick_stop_time) + { + tm->_blocking_tick = false; + break; + } + } + while (pending); + + if (!tm->_blocking_tick) + { + Message *msg_un = new Message; + if ( exc != e_RTIinternalError ) + msg_un->setException(exc); + // terminate __tick() call in the federate + msg_un->type = Message::TICK_REQUEST; + msg_un->setBoolean(pending); + comm->requestFederateService(msg_un); + } +} + +// ---------------------------------------------------------------------------- //! RTIA processes a service request coming from federate. void RTIA::processFederateRequest(Message *req) @@ -1308,18 +1362,9 @@ delete req ;; - - if (rep.type == Message::TICK_REQUEST) - if ((!tm->_ongoing_tick) && tm->_tick_request_ack) { - // acknowledgment of an empty tick - comm->sendUN(&rep); - D.Out(pdDebug, "Reply send to Unix socket."); - } - else { - // no answer in the case of a successful tick - } - else { + if (rep.type != Message::TICK_REQUEST) { // generic federate service acknowledgment + // the TICK_REQUEST confirmation is generated in processOngoingTick() comm->sendUN(&rep); D.Out(pdDebug, "Reply send to Unix socket."); } diff -ru certi.orig/RTIA/RTIA.hh certi.new/RTIA/RTIA.hh --- certi.orig/RTIA/RTIA.hh 2008-03-14 15:52:23.000000000 +0100 +++ certi.new/RTIA/RTIA.hh 2008-04-02 15:16:00.000000000 +0200 @@ -67,6 +67,7 @@ void chooseFederateProcessing(Message *, Message &, TypeException &) throw (CouldNotOpenFED,FederationExecutionAlreadyExists,ErrorReadingFED, FederateAlreadyExecutionMember); + void processOngoingTick(); }; }} // namespace certi diff -ru certi.orig/RTIA/TimeManagement.cc certi.new/RTIA/TimeManagement.cc --- certi.orig/RTIA/TimeManagement.cc 2008-03-13 15:39:19.000000000 +0100 +++ certi.new/RTIA/TimeManagement.cc 2008-04-02 15:26:15.000000000 +0200 @@ -82,7 +82,7 @@ lastNullMessageDate = 0.0 ; _avancee_en_cours = PAS_D_AVANCEE ; - _ongoing_tick = false ; + _blocking_tick = false ; _asynchronous_delivery = false ; _heure_courante = 0.0 ; @@ -125,8 +125,7 @@ msg.trace("TimeManagement::executeFederateService "); - _ongoing_tick = false ; // end of the blocking tick, a message is delivered - _tick_request_ack = false ; // the callback message serves as the ack + _blocking_tick = false; // indicate a callback was processed switch (msg.type) { @@ -822,8 +821,7 @@ if (_lookahead_courant == epsilon) _lookahead_courant = 0.0 ; - _ongoing_tick = false ; // end of the blocking tick, a message is delivered - _tick_request_ack = false ; + _blocking_tick = false; // indicate a callback was processed comm->requestFederateService(&req); diff -ru certi.orig/RTIA/TimeManagement.hh certi.new/RTIA/TimeManagement.hh --- certi.orig/RTIA/TimeManagement.hh 2008-03-13 15:39:19.000000000 +0100 +++ certi.new/RTIA/TimeManagement.hh 2008-04-02 15:24:40.000000000 +0200 @@ -105,8 +105,10 @@ bool requestRegulateurState() { return _est_regulateur ; }; // Attribute - bool _ongoing_tick; // tick2 processing - bool _tick_request_ack; // do we have to acknowledge the tick request + bool _blocking_tick; // processing the tick + bool _tick_multiple; // process multiple callbacks + RTI::TickTime _tick_timeout; + RTI::TickTime _tick_stop_time; bool _asynchronous_delivery ; private: