void TimeWarpMatternGVTManager::receiveMatternGVTToken( std::unique_ptr<TimeWarpKernelMessage> kmsg) { auto msg = unique_cast<TimeWarpKernelMessage, MatternGVTToken>(std::move(kmsg)); unsigned int process_id = comm_manager_->getID(); if (process_id == 0) { // Initiator received the message if ((white_msg_counter_ + msg->count == 0) && (token_iteration_ > 1)) { // At this point all white messages are accounted for so we can // calculate the GVT now gVT_token_pending_ = false; sendGVTUpdate(std::min(msg->m_clock, msg->m_send)); // Reset msg_count_ = 0; } else { // Accumulations min_red_msg_timestamp_ = std::min(msg->m_send, min_red_msg_timestamp_); global_min_ = infinityVT(); msg_count_ = 0; // Set flags need_local_gvt_ = true; gVT_token_pending_ = true; } } else { // A node other than the initiator is now receiving a control message if (color_ == MatternColor::WHITE) { min_red_msg_timestamp_ = infinityVT(); color_ = MatternColor::RED; } // Accumulations min_red_msg_timestamp_ = std::min(msg->m_send, min_red_msg_timestamp_); global_min_ = std::min(global_min_, msg->m_clock); msg_count_ = msg->count; // Set flags need_local_gvt_ = true; gVT_token_pending_ = true; } }
void ThreadedMatternGVTManager::receiveKernelMessage(KernelMessage *msg) { ASSERT(msg != NULL); if (dynamic_cast<MatternGVTMessage *>(msg) != 0) { const MatternGVTMessage *gVTMessage = dynamic_cast<MatternGVTMessage *>(msg); const int count = gVTMessage->getNumMessagesInTransit(); if (mySimulationManager->getSimulationManagerID() == 0) { // Initiator has received the control message. // Check to see if the count is zero and this is at least the second // round of the token. Continue until the count is 0 and all messages // in transit are accounted for. if (objectRecord->getTokenIterationNumber() > 1 && (objectRecord->getNumberOfWhiteMessages() + count == 0)) { // Need to remember the old gvt to compare it to the new. const VTime &oldGVT = getGVT(); // Determine GVT. setGVT( MIN_FUNC(gVTMessage->getLastScheduledEventTime(), gVTMessage->getMinimumTimeStamp())); ASSERT(getGVT() >= oldGVT); // Send out the GVT update to the other simulation managers and reset to white. objectRecord->setTokenIterationNumber(0); objectRecord->setNumberOfWhiteMessages(0); objectRecord->setColor(WHITE); sendGVTUpdate(); // End of this gvt calculation cycle. gVTTokenPending = false; // Only output the value and fossil collect when it actually changes. if (getGVT() > oldGVT) { // Fossil collect now with the new GVT. cout << "GVT = " << getGVT() << endl; //mySimulationManager->resetGVTTokenPending(); mySimulationManager->fossilCollect(getGVT()); } } else { // Not yet ready to calculate gvt, send the token around again. // cout <<"NUmber of Transit messages "<<count <<endl; // cout <<"NUmber of White messages "<<objectRecord->getNumberOfWhiteMessages()<<endl; objectRecord->setNumberOfWhiteMessages( objectRecord->getNumberOfWhiteMessages() + count); mySimulationManager->setGVTTokenPending(); mySimulationManager->initiateLocalGVT(); GVTMessageLastScheduledEventTime = gVTMessage->getLastScheduledEventTime().clone(); GVTMessageMinimumTimeStamp = gVTMessage->getMinimumTimeStamp().clone(); objectRecord->setNumberOfWhiteMessages(0); } } else { // The gvt token has been received by another simulation manager. // [a] Set color of this sim mgr to RED; set tMin = positive infinity. // [b] Pass on the token to processor(i mod n) + 1. if (objectRecord->getColor() == WHITE) { objectRecord->resetMinTimeStamp( mySimulationManager->getPositiveInfinity()); objectRecord->setColor(RED); } // Add the the local white message count to the simulation's white message total. objectRecord->setNumberOfWhiteMessages( objectRecord->getNumberOfWhiteMessages() + count); mySimulationManager->setGVTTokenPending(); mySimulationManager->initiateLocalGVT(); GVTMessageLastScheduledEventTime = gVTMessage->getLastScheduledEventTime().clone(); GVTMessageMinimumTimeStamp = gVTMessage->getMinimumTimeStamp().clone(); } } else if (dynamic_cast<GVTUpdateMessage *>(msg) != 0) { const GVTUpdateMessage *gVTMessage = dynamic_cast<GVTUpdateMessage *>(msg); const VTime &oldGVT = getGVT(); setGVT(gVTMessage->getNewGVT()); //mySimulationManager->resetGVTTokenPending(); ASSERT(getGVT() >= oldGVT); // Only fossil collect if the value has increased. if (getGVT() > oldGVT) { // Fossil collect now with the new GVT. mySimulationManager->fossilCollect(getGVT()); } // VERY IMPORTANT NOTE!! // The white message count is not reset here because by the time this // simulation manager gets the update token, it may have already received some // white messages from another simulation manager that already switched back // to white. These need to be taken into account for the next GVT calculation. objectRecord->setTokenIterationNumber(0); objectRecord->setColor(WHITE); } else { cerr << "MatternGVTManager::receiveKernelMessage() received" << " unknown (" << msg->getDataType() << ") message type" << endl; cerr << "Aborting simulation ..." << endl; abort(); } // We are done with this kernel message. delete msg; }