#include "simgrid/Exception.hpp"
#include "simgrid/s4u/Comm.hpp"
+#include "simgrid/s4u/Engine.hpp"
#include "simgrid/s4u/Mailbox.hpp"
#include <simgrid/comm.h>
xbt::signal<void(Comm const&, bool is_sender)> Comm::on_start;
xbt::signal<void(Comm const&)> Comm::on_completion;
+void Comm::complete(Activity::State state)
+{
+ Activity::complete(state);
+ on_completion(*this);
+}
+
Comm::~Comm()
{
if (state_ == State::STARTED && not detached_ &&
}
}
-int Comm::wait_any_for(const std::vector<CommPtr>* comms, double timeout)
+ssize_t Comm::wait_any_for(const std::vector<CommPtr>& comms, double timeout)
{
- std::vector<kernel::activity::CommImpl*> rcomms(comms->size());
- std::transform(begin(*comms), end(*comms), begin(rcomms),
+ std::vector<kernel::activity::CommImpl*> rcomms(comms.size());
+ std::transform(begin(comms), end(comms), begin(rcomms),
[](const CommPtr& comm) { return static_cast<kernel::activity::CommImpl*>(comm->pimpl_.get()); });
- int changed_pos = simcall_comm_waitany(rcomms.data(), rcomms.size(), timeout);
- if (changed_pos != -1) {
- on_completion(*(comms->at(changed_pos)));
- comms->at(changed_pos)->release_dependencies();
- }
+ ssize_t changed_pos = simcall_comm_waitany(rcomms.data(), rcomms.size(), timeout);
+ if (changed_pos != -1)
+ comms.at(changed_pos)->complete(State::FINISHED);
return changed_pos;
}
-void Comm::wait_all(const std::vector<CommPtr>* comms)
+void Comm::wait_all(const std::vector<CommPtr>& comms)
{
// TODO: this should be a simcall or something
- // TODO: we are missing a version with timeout
- for (CommPtr comm : *comms)
+ for (auto& comm : comms)
comm->wait();
}
+size_t Comm::wait_all_for(const std::vector<CommPtr>& comms, double timeout)
+{
+ if (timeout < 0.0) {
+ wait_all(comms);
+ return comms.size();
+ }
+
+ double deadline = Engine::get_clock() + timeout;
+ std::vector<CommPtr> waited_comm(1, nullptr);
+ for (size_t i = 0; i < comms.size(); i++) {
+ double wait_timeout = std::max(0.0, deadline - Engine::get_clock());
+ waited_comm[0] = comms[i];
+ // Using wait_any_for() here (and not wait_for) because we don't want comms to be invalidated on timeout
+ if (wait_any_for(waited_comm, wait_timeout) == -1) {
+ XBT_DEBUG("Timeout (%g): i = %zu", wait_timeout, i);
+ return i;
+ }
+ }
+ return comms.size();
+}
+
CommPtr Comm::set_rate(double rate)
{
xbt_assert(state_ == State::INITED, "You cannot use %s() once your communication started (not implemented)",
return res;
}
+void Comm::sendto(Host* from, Host* to, double simulated_size_in_bytes)
+{
+ sendto_async(from, to, simulated_size_in_bytes)->wait();
+}
+
Comm* Comm::start()
{
xbt_assert(get_state() == State::INITED || get_state() == State::STARTING,
return this;
}
-/** @brief Block the calling actor until the communication is finished */
-Comm* Comm::wait()
-{
- return this->wait_for(-1);
-}
-
/** @brief Block the calling actor until the communication is finished, or until timeout
*
* On timeout, an exception is thrown and the communication is invalidated.
simcall_comm_recv(receiver_, mailbox_->get_impl(), dst_buff_, &dst_buff_size_, match_fun_, copy_data_function_,
get_user_data(), timeout, rate_);
}
- state_ = State::FINISHED;
- this->release_dependencies();
break;
case State::STARTED:
simcall_comm_wait(get_impl(), timeout);
- state_ = State::FINISHED;
- this->release_dependencies();
break;
case State::CANCELED:
default:
THROW_IMPOSSIBLE;
}
- on_completion(*this);
+ complete(State::FINISHED);
return this;
}
-int Comm::test_any(const std::vector<CommPtr>* comms)
+ssize_t Comm::test_any(const std::vector<CommPtr>& comms)
{
- std::vector<kernel::activity::CommImpl*> rcomms(comms->size());
- std::transform(begin(*comms), end(*comms), begin(rcomms),
+ std::vector<kernel::activity::CommImpl*> rcomms(comms.size());
+ std::transform(begin(comms), end(comms), begin(rcomms),
[](const CommPtr& comm) { return static_cast<kernel::activity::CommImpl*>(comm->pimpl_.get()); });
- int changed_pos = simcall_comm_testany(rcomms.data(), rcomms.size());
+ ssize_t changed_pos = simcall_comm_testany(rcomms.data(), rcomms.size());
if (changed_pos != -1)
- comms->at(changed_pos)->release_dependencies();
+ comms.at(changed_pos)->complete(State::FINISHED);
return changed_pos;
}
return this;
}
-Comm* Comm::cancel()
-{
- kernel::actor::simcall([this] {
- if (pimpl_)
- boost::static_pointer_cast<kernel::activity::CommImpl>(pimpl_)->cancel();
- });
- state_ = State::CANCELED;
- return this;
-}
-
-bool Comm::test()
+bool Comm::test() // TODO: merge with Activity::test, once modernized
{
xbt_assert(state_ == State::INITED || state_ == State::STARTED || state_ == State::STARTING ||
- state_ == State::FINISHED);
+ state_ == State::CANCELED || state_ == State::FINISHED);
- if (state_ == State::FINISHED)
+ if (state_ == State::CANCELED || state_ == State::FINISHED)
return true;
if (state_ == State::INITED || state_ == State::STARTING)
this->vetoable_start();
if (simcall_comm_test(get_impl())) {
- state_ = State::FINISHED;
- this->release_dependencies();
+ complete(State::FINISHED);
return true;
}
return false;
sg_error_t sg_comm_wait(sg_comm_t comm)
{
- sg_error_t status = SG_OK;
-
- simgrid::s4u::CommPtr s4u_comm(comm, false);
- try {
- s4u_comm->wait_for(-1);
- } catch (const simgrid::TimeoutException&) {
- status = SG_ERROR_TIMEOUT;
- } catch (const simgrid::CancelException&) {
- status = SG_ERROR_CANCELED;
- } catch (const simgrid::NetworkFailureException&) {
- status = SG_ERROR_NETWORK;
- }
- return status;
+ return sg_comm_wait_for(comm, -1);
}
sg_error_t sg_comm_wait_for(sg_comm_t comm, double timeout)
}
void sg_comm_wait_all(sg_comm_t* comms, size_t count)
+{
+ sg_comm_wait_all_for(comms, count, -1);
+}
+
+size_t sg_comm_wait_all_for(sg_comm_t* comms, size_t count, double timeout)
{
std::vector<simgrid::s4u::CommPtr> s4u_comms;
- for (unsigned int i = 0; i < count; i++)
+ for (size_t i = 0; i < count; i++)
s4u_comms.emplace_back(comms[i], false);
- simgrid::s4u::Comm::wait_all(&s4u_comms);
+ size_t pos = simgrid::s4u::Comm::wait_all_for(s4u_comms, timeout);
+ for (size_t i = pos; i < count; i++)
+ s4u_comms[i]->add_ref();
+ return pos;
}
-int sg_comm_wait_any(sg_comm_t* comms, size_t count)
+ssize_t sg_comm_wait_any(sg_comm_t* comms, size_t count)
{
return sg_comm_wait_any_for(comms, count, -1);
}
-int sg_comm_wait_any_for(sg_comm_t* comms, size_t count, double timeout)
+ssize_t sg_comm_wait_any_for(sg_comm_t* comms, size_t count, double timeout)
{
std::vector<simgrid::s4u::CommPtr> s4u_comms;
- for (unsigned int i = 0; i < count; i++)
+ for (size_t i = 0; i < count; i++)
s4u_comms.emplace_back(comms[i], false);
- int pos = simgrid::s4u::Comm::wait_any_for(&s4u_comms, timeout);
- for (unsigned i = 0; i < count; i++) {
- if (pos != -1 && static_cast<unsigned>(pos) != i)
+ ssize_t pos = simgrid::s4u::Comm::wait_any_for(s4u_comms, timeout);
+ for (size_t i = 0; i < count; i++) {
+ if (pos != -1 && static_cast<size_t>(pos) != i)
s4u_comms[i]->add_ref();
}
return pos;