Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Implement TestAnyTransition
authorMartin Quinson <martin.quinson@ens-rennes.fr>
Sat, 12 Feb 2022 22:29:21 +0000 (23:29 +0100)
committerMartin Quinson <martin.quinson@ens-rennes.fr>
Sat, 12 Feb 2022 22:29:21 +0000 (23:29 +0100)
src/kernel/actor/SimcallObserver.cpp
src/kernel/actor/SimcallObserver.hpp
src/mc/ModelChecker.cpp
src/mc/api/Transition.hpp
src/mc/api/TransitionComm.cpp
src/mc/api/TransitionComm.hpp
src/mc/checker/SafetyChecker.cpp
src/mc/mc_base.cpp

index b230c66..befdd70 100644 (file)
@@ -108,39 +108,31 @@ bool SemAcquireSimcall::is_enabled() const
   return true;
 }
 
-int ActivityTestanySimcall::get_max_consider() const
+ActivityTestanySimcall::ActivityTestanySimcall(ActorImpl* actor, const std::vector<activity::ActivityImpl*>& activities)
+    : ResultingSimcall(actor, -1), activities_(activities)
 {
-  // Only Comms are of interest to MC for now. When all types of activities can be consider, this function can simply
-  // return the size of activities_.
-  int count = 0;
-  for (const auto& act : activities_)
-    if (dynamic_cast<activity::CommImpl*>(act) != nullptr)
-      count++;
-  return count;
+  // list all the activities that are ready
+  for (unsigned i = 0; i < activities_.size(); i++)
+    if (activities_[i]->test(get_issuer()))
+      indexes_.push_back(i);
 }
 
-void ActivityTestanySimcall::prepare(int times_considered)
+int ActivityTestanySimcall::get_max_consider() const
 {
-  next_value_ = times_considered;
+  return indexes_.size() + 1;
 }
 
-/*
-std::string ActivityTestanySimcall::to_string(int times_considered) const
+void ActivityTestanySimcall::prepare(int times_considered)
 {
-  std::string res = SimcallObserver::to_string(times_considered);
-  if (times_considered == -1) {
-    res += "TestAny FALSE(-)";
-  } else {
-    res += "TestAny(" + xbt::string_printf("(%d of %zu)", times_considered + 1, activities_.size());
-  }
-
-  return res;
-}*/
-void ActivityWaitSimcall::serialize(std::stringstream& stream) const
+  if (times_considered < static_cast<int>(indexes_.size()))
+    next_value_ = indexes_.at(times_considered);
+  else
+    next_value_ = -1;
+}
+static void serialize_activity(const activity::ActivityImpl* act, std::stringstream& stream)
 {
-  if (auto* comm = dynamic_cast<activity::CommImpl*>(activity_)) {
-    stream << (short)mc::Transition::Type::COMM_WAIT << ' ';
-    stream << (timeout_ > 0) << ' ' << comm;
+  if (auto* comm = dynamic_cast<activity::CommImpl const*>(act)) {
+    stream << (short)mc::Transition::Type::COMM_TEST << ' ';
     stream << ' ' << (comm->src_actor_ != nullptr ? comm->src_actor_->get_pid() : -1);
     stream << ' ' << (comm->dst_actor_ != nullptr ? comm->dst_actor_->get_pid() : -1);
     stream << ' ' << comm->get_mailbox_id();
@@ -149,10 +141,17 @@ void ActivityWaitSimcall::serialize(std::stringstream& stream) const
     stream << (short)mc::Transition::Type::UNKNOWN;
   }
 }
-void ActivityTestSimcall::serialize(std::stringstream& stream) const
+void ActivityTestanySimcall::serialize(std::stringstream& stream) const
+{
+  stream << (short)mc::Transition::Type::TESTANY << ' ' << activities_.size() << ' ';
+  for (auto const& act : activities_)
+    serialize_activity(act, stream);
+}
+void ActivityWaitSimcall::serialize(std::stringstream& stream) const
 {
   if (auto* comm = dynamic_cast<activity::CommImpl*>(activity_)) {
-    stream << (short)mc::Transition::Type::COMM_TEST << ' ';
+    stream << (short)mc::Transition::Type::COMM_WAIT << ' ';
+    stream << (timeout_ > 0) << ' ' << comm;
     stream << ' ' << (comm->src_actor_ != nullptr ? comm->src_actor_->get_pid() : -1);
     stream << ' ' << (comm->dst_actor_ != nullptr ? comm->dst_actor_->get_pid() : -1);
     stream << ' ' << comm->get_mailbox_id();
@@ -161,6 +160,10 @@ void ActivityTestSimcall::serialize(std::stringstream& stream) const
     stream << (short)mc::Transition::Type::UNKNOWN;
   }
 }
+void ActivityTestSimcall::serialize(std::stringstream& stream) const
+{
+  serialize_activity(activity_, stream);
+}
 
 bool ActivityWaitSimcall::is_enabled() const
 {
index 54169d5..9243876 100644 (file)
@@ -160,14 +160,14 @@ public:
 
 class ActivityTestanySimcall : public ResultingSimcall<ssize_t> {
   const std::vector<activity::ActivityImpl*>& activities_;
+  std::vector<int> indexes_; // indexes in activities_ pointing to ready activities (=whose test() is positive)
   int next_value_ = 0;
 
 public:
-  ActivityTestanySimcall(ActorImpl* actor, const std::vector<activity::ActivityImpl*>& activities)
-      : ResultingSimcall(actor, -1), activities_(activities)
-  {
-  }
+  ActivityTestanySimcall(ActorImpl* actor, const std::vector<activity::ActivityImpl*>& activities);
   bool is_visible() const override { return true; }
+  bool is_enabled() const override { return true; /* can return -1 if no activity is ready */ }
+  void serialize(std::stringstream& stream) const override;
   int get_max_consider() const override;
   void prepare(int times_considered) override;
   const std::vector<activity::ActivityImpl*>& get_activities() const { return activities_; }
index 4fdb59d..a7ec948 100644 (file)
@@ -331,9 +331,10 @@ Transition* ModelChecker::handle_simcall(aid_t aid, int times_considered, bool n
   if (this->remote_process_->running())
     checker_side_.dispatch(); // The app may send messages while processing the transition
 
-  if (new_transition)
-    return recv_transition(aid, times_considered, answer.buffer);
-  else
+  if (new_transition) {
+    std::stringstream stream(answer.buffer);
+    return recv_transition(aid, times_considered, stream);
+  } else
     return nullptr;
 }
 bool ModelChecker::simcall_is_visible(aid_t aid)
index 8b8458b..3ee9110 100644 (file)
@@ -32,7 +32,7 @@ class Transition {
   friend State; // FIXME remove this once we have a proper class to handle the statistics
 
 public:
-  XBT_DECLARE_ENUM_CLASS(Type, UNKNOWN, RANDOM, COMM_RECV, COMM_SEND, COMM_TEST, COMM_WAIT);
+  XBT_DECLARE_ENUM_CLASS(Type, UNKNOWN, RANDOM, COMM_RECV, COMM_SEND, COMM_TEST, COMM_WAIT, TESTANY);
   Type type_ = Type::UNKNOWN;
 
   aid_t aid_ = 0;
index 2f86cea..259accc 100644 (file)
@@ -176,6 +176,28 @@ std::string CommSendTransition::to_string(bool verbose = false) const
   res += ")";
   return res;
 }
+TestAnyTransition::TestAnyTransition(aid_t issuer, int times_considered, std::stringstream& stream)
+{
+  int size;
+  stream >> size;
+  for (int i = 0; i < size; i++) {
+
+    Transition* t = recv_transition(issuer, 0, stream);
+    transitions_.push_back(t);
+  }
+}
+std::string TestAnyTransition::to_string(bool verbose) const
+{
+  auto res = xbt::string_printf("%ld: TestAny{ ", aid_);
+  for (auto const* t : transitions_)
+    res += t->to_string(verbose);
+  res += "}";
+  return res;
+}
+bool TestAnyTransition::depends(const Transition* other) const
+{
+  return true;
+}
 
 bool CommSendTransition::depends(const Transition* other) const
 {
@@ -213,9 +235,8 @@ bool CommSendTransition::depends(const Transition* other) const
   return true;
 }
 
-Transition* recv_transition(aid_t issuer, int times_considered, char* buffer)
+Transition* recv_transition(aid_t issuer, int times_considered, std::stringstream& stream)
 {
-  std::stringstream stream(buffer);
   short type;
   stream >> type;
   Transition::Type simcall = static_cast<Transition::Type>(type);
@@ -230,6 +251,9 @@ Transition* recv_transition(aid_t issuer, int times_considered, char* buffer)
     case Transition::Type::COMM_WAIT:
       return new CommWaitTransition(issuer, times_considered, stream);
 
+    case Transition::Type::TESTANY:
+      return new TestAnyTransition(issuer, times_considered, stream);
+
     case Transition::Type::RANDOM:
       return new RandomTransition(issuer, times_considered, stream);
 
index 29ebf67..f65f282 100644 (file)
@@ -76,8 +76,17 @@ public:
   bool depends(const Transition* other) const override;
 };
 
+class TestAnyTransition : public Transition {
+  std::vector<Transition*> transitions_;
+
+public:
+  TestAnyTransition(aid_t issuer, int times_considered, std::stringstream& stream);
+  std::string to_string(bool verbose) const override;
+  bool depends(const Transition* other) const override;
+};
+
 /** Make a new transition from serialized description */
-Transition* recv_transition(aid_t issuer, int times_considered, char* buffer);
+Transition* recv_transition(aid_t issuer, int times_considered, std::stringstream& stream);
 
 } // namespace mc
 } // namespace simgrid
index 3d003aa..6dc565e 100644 (file)
@@ -123,7 +123,7 @@ void SafetyChecker::run()
       continue;
     }
 
-    /* Actually answer the request: let execute the selected request (MCed does one step) */
+    /* Actually answer the request: let's execute the selected request (MCed does one step) */
     state->execute_next(next);
 
     // If there are processes to interleave and the maximum depth has not been
@@ -135,7 +135,7 @@ void SafetyChecker::run()
       req_str = api::get().request_get_dot_output(state->get_transition());
 
     /* Create the new expanded state (copy the state of MCed into our MCer data) */
-    auto next_state              = std::make_unique<State>();
+    auto next_state = std::make_unique<State>();
 
     if (_sg_mc_termination)
       this->check_non_termination(next_state.get());
index 32139fc..236aab7 100644 (file)
@@ -58,8 +58,8 @@ void execute_actors()
   engine->reset_actor_dynar();
   for (auto const& kv : engine->get_actor_list()) {
     auto actor = kv.second;
-    if (actor->simcall_.observer_ != nullptr)
-      actor->simcall_.mc_max_consider_ = actor->simcall_.observer_->get_max_consider();
+    if (auto* observer = actor->simcall_.observer_)
+      actor->simcall_.mc_max_consider_ = observer->get_max_consider();
     engine->add_actor_to_dynar(actor);
   }
 #endif