+ copied_ = true;
+}
+
+bool CommImpl::test()
+{
+ if ((MC_is_active() || MC_record_replay_is_active()) && src_actor_ && dst_actor_)
+ state_ = State::DONE;
+ return ActivityImpl::test();
+}
+
+void CommImpl::wait_for(actor::ActorImpl* issuer, double timeout)
+{
+ XBT_DEBUG("CommImpl::wait_for(%g), %p, state %s", timeout, this, to_c_str(state_));
+
+ /* Associate this simcall to the wait synchro */
+ register_simcall(&issuer->simcall_);
+
+ if (MC_is_active() || MC_record_replay_is_active()) {
+ int idx = issuer->simcall_.mc_value_;
+ if (idx == 0) {
+ state_ = State::DONE;
+ } else {
+ /* If we reached this point, the wait simcall must have a timeout */
+ /* Otherwise it shouldn't be enabled and executed by the MC */
+ if (timeout < 0.0)
+ THROW_IMPOSSIBLE;
+ state_ = (issuer == src_actor_ ? State::SRC_TIMEOUT : State::DST_TIMEOUT);
+ }
+ finish();
+ return;
+ }
+
+ /* If the synchro has already finish perform the error handling, */
+ /* otherwise set up a waiting timeout on the right side */
+ if (state_ != State::WAITING && state_ != State::RUNNING) {
+ finish();
+ } else { /* we need a sleep action (even when there is no timeout) to be notified of host failures */
+ resource::Action* sleep = issuer->get_host()->get_cpu()->sleep(timeout);
+ sleep->set_activity(this);
+
+ if (issuer == src_actor_)
+ src_timeout_ = sleep;
+ else
+ dst_timeout_ = sleep;
+ }
+}
+
+ssize_t CommImpl::test_any(const actor::ActorImpl* issuer, const std::vector<CommImpl*>& comms)
+{
+ if (MC_is_active() || MC_record_replay_is_active()) {
+ int idx = issuer->simcall_.mc_value_;
+ xbt_assert(idx == -1 || comms[idx]->test());
+ return idx;
+ }
+
+ for (std::size_t i = 0; i < comms.size(); ++i) {
+ if (comms[i]->test())
+ return i;
+ }
+ return -1;
+}
+
+void CommImpl::wait_any_for(actor::ActorImpl* issuer, const std::vector<CommImpl*>& comms, double timeout)
+{
+ if (MC_is_active() || MC_record_replay_is_active()) {
+ xbt_assert(timeout <= 0.0, "Timeout not implemented for waitany in the model-checker");
+ int idx = issuer->simcall_.mc_value_;
+ auto* comm = comms[idx];
+ comm->simcalls_.push_back(&issuer->simcall_);
+ simcall_comm_waitany__set__result(&issuer->simcall_, idx);
+ comm->state_ = State::DONE;
+ comm->finish();
+ return;
+ }
+
+ if (timeout < 0.0) {
+ issuer->simcall_.timeout_cb_ = nullptr;
+ } else {
+ issuer->simcall_.timeout_cb_ = timer::Timer::set(s4u::Engine::get_clock() + timeout, [issuer, comms]() {
+ // FIXME: Vector `comms' is copied here. Use a reference once its lifetime is extended (i.e. when the simcall is
+ // modernized).
+ issuer->simcall_.timeout_cb_ = nullptr;
+ for (auto* comm : comms)
+ comm->unregister_simcall(&issuer->simcall_);
+ simcall_comm_waitany__set__result(&issuer->simcall_, -1);
+ issuer->simcall_answer();
+ });
+ }
+
+ for (auto* comm : comms) {
+ /* associate this simcall to the the synchro */
+ comm->simcalls_.push_back(&issuer->simcall_);
+
+ /* see if the synchro is already finished */
+ if (comm->state_ != State::WAITING && comm->state_ != State::RUNNING) {
+ comm->finish();
+ break;
+ }
+ }