Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Move the actor lifecycle markers from Context to ActorImpl
[simgrid.git] / src / kernel / actor / ActorImpl.cpp
index 7551774..8acb38f 100644 (file)
@@ -157,8 +157,8 @@ void ActorImpl::cleanup_from_kernel()
 
   undaemonize();
 
-  while (not mailboxes.empty())
-    mailboxes.back()->set_receiver(nullptr);
+  while (not mailboxes_.empty())
+    mailboxes_.back()->set_receiver(nullptr);
 }
 
 /* Do all the cleanups from the actor context. Warning, the simcall mechanism was not reignited so doing simcalls in
@@ -166,11 +166,11 @@ void ActorImpl::cleanup_from_kernel()
 void ActorImpl::cleanup_from_self()
 {
   xbt_assert(not ActorImpl::is_maestro(), "Cleanup_from_self called from maestro on '%s'", get_cname());
-  context_->set_to_be_freed();
+  set_to_be_freed();
 
   if (on_exit) {
     // Execute the termination callbacks
-    bool failed = context_->wannadie();
+    bool failed = wannadie();
     for (auto exit_fun = on_exit->crbegin(); exit_fun != on_exit->crend(); ++exit_fun)
       (*exit_fun)(failed);
     on_exit.reset();
@@ -193,33 +193,31 @@ void ActorImpl::cleanup_from_self()
     simcall_.timeout_cb_ = nullptr;
   }
 
-  context_->set_wannadie(false); // don't let the simcall's yield() do a Context::stop(), to avoid infinite loops
+  set_wannadie(false); // don't let the simcall's yield() do a Context::stop(), to avoid infinite loops
   actor::simcall_answered([this] { s4u::Actor::on_termination(*get_ciface()); });
-  context_->set_wannadie();
+  set_wannadie();
 }
 
 void ActorImpl::exit()
 {
-  context_->set_wannadie();
+  set_wannadie();
   suspended_ = false;
   exception_ = nullptr;
 
-  /* destroy the blocking synchro if any */
-  if (auto activity = waiting_synchro_) {
-    activities_.remove(waiting_synchro_);
-    waiting_synchro_ = nullptr;
-
+  if (waiting_synchro_ != nullptr) {
+    /* Take an extra reference on the activity object that may be unref by Comm::finish() or friends */
+    activity::ActivityImplPtr activity = waiting_synchro_;
     activity->cancel();
     activity->set_state(activity::State::FAILED);
     activity->post();
+
+    activities_.remove(waiting_synchro_);
+    waiting_synchro_ = nullptr;
   }
   for (auto const& activity : activities_)
     activity->cancel();
   activities_.clear();
 
-  while (not mailboxes.empty())
-    mailboxes.back()->set_receiver(nullptr);
-
   // Forcefully kill the actor if its host is turned off. Not a HostFailureException because you should not survive that
   this->throw_exception(std::make_exception_ptr(ForcefulKillException(host_->is_on() ? "exited" : "host failed")));
 }
@@ -227,7 +225,7 @@ void ActorImpl::exit()
 void ActorImpl::kill(ActorImpl* actor) const
 {
   xbt_assert(not actor->is_maestro(), "Killing maestro is a rather bad idea.");
-  if (actor->context_->wannadie()) {
+  if (actor->wannadie()) {
     XBT_DEBUG("Ignoring request to kill actor %s@%s that is already dead", actor->get_cname(),
               actor->host_->get_cname());
     return;
@@ -259,6 +257,7 @@ void ActorImpl::set_kill_time(double kill_time)
   kill_timer_ = timer::Timer::set(kill_time, [this] {
     this->exit();
     kill_timer_ = nullptr;
+    EngineImpl::get_instance()->add_actor_to_run_list(this);
   });
 }
 
@@ -276,7 +275,7 @@ void ActorImpl::yield()
   /* Ok, maestro returned control to us */
   XBT_DEBUG("Control returned to me: '%s'", get_cname());
 
-  if (context_->wannadie()) {
+  if (wannadie()) {
     XBT_DEBUG("Actor %s@%s is dead", get_cname(), host_->get_cname());
     context_->stop();
     THROW_IMPOSSIBLE;
@@ -299,7 +298,7 @@ void ActorImpl::yield()
     }
   }
 #if HAVE_SMPI
-  if (not context_->wannadie())
+  if (not wannadie())
     smpi_switch_data_segment(get_iface());
 #endif
 }
@@ -355,7 +354,7 @@ void ActorImpl::resume()
 {
   XBT_IN("actor = %p", this);
 
-  if (context_->wannadie()) {
+  if (wannadie()) {
     XBT_VERB("Ignoring request to resume an actor that is currently dying.");
     return;
   }
@@ -376,10 +375,15 @@ void ActorImpl::resume()
 activity::ActivityImplPtr ActorImpl::join(const ActorImpl* actor, double timeout)
 {
   activity::ActivityImplPtr sleep = this->sleep(timeout);
-  actor->on_exit->emplace_back([sleep](bool) {
+  if (actor->wannadie() || actor->to_be_freed()) {
     if (sleep->surf_action_)
       sleep->surf_action_->finish(resource::Action::State::FINISHED);
-  });
+  } else {
+    actor->on_exit->emplace_back([sleep](bool) {
+      if (sleep->surf_action_)
+        sleep->surf_action_->finish(resource::Action::State::FINISHED);
+    });
+  }
   return sleep;
 }
 
@@ -502,6 +506,11 @@ ActorImplPtr ActorImpl::create(ProcessArg* args)
     actor->daemonize();
   return actor;
 }
+void ActorImpl::set_wannadie(bool value)
+{
+  XBT_DEBUG("Actor %s gonna die.", get_cname());
+  iwannadie_ = value;
+}
 
 void create_maestro(const std::function<void()>& code)
 {