#include "simgrid/kernel/ProfileBuilder.hpp"
#include "simgrid/kernel/routing/NetPoint.hpp"
+#include "simgrid/plugins/load.h"
#include <simgrid/Exception.hpp>
+#include <simgrid/s4u/ActivitySet.hpp>
#include <simgrid/s4u/Actor.hpp>
#include <simgrid/s4u/Barrier.hpp>
#include <simgrid/s4u/Comm.hpp>
#include <vector>
namespace py = pybind11;
-using simgrid::s4u::CommTask;
-using simgrid::s4u::CommTaskPtr;
-using simgrid::s4u::ExecTask;
-using simgrid::s4u::ExecTaskPtr;
-using simgrid::s4u::IoTask;
-using simgrid::s4u::IoTaskPtr;
-using simgrid::s4u::Task;
-using simgrid::s4u::TaskPtr;
+using simgrid::s4u::Activity;
+using simgrid::s4u::ActivityPtr;
+using simgrid::s4u::ActivitySet;
+using simgrid::s4u::ActivitySetPtr;
using simgrid::s4u::Actor;
using simgrid::s4u::ActorPtr;
using simgrid::s4u::Barrier;
using simgrid::s4u::BarrierPtr;
using simgrid::s4u::Comm;
using simgrid::s4u::CommPtr;
+using simgrid::s4u::CommTask;
+using simgrid::s4u::CommTaskPtr;
using simgrid::s4u::Disk;
using simgrid::s4u::Engine;
+using simgrid::s4u::ExecTask;
+using simgrid::s4u::ExecTaskPtr;
using simgrid::s4u::Host;
using simgrid::s4u::Io;
+using simgrid::s4u::IoTask;
+using simgrid::s4u::IoTaskPtr;
using simgrid::s4u::Link;
using simgrid::s4u::Mailbox;
using simgrid::s4u::Mutex;
using simgrid::s4u::MutexPtr;
using simgrid::s4u::Semaphore;
using simgrid::s4u::SemaphorePtr;
+using simgrid::s4u::Task;
+using simgrid::s4u::TaskPtr;
XBT_LOG_NEW_DEFAULT_CATEGORY(python, "python");
sg_version_get(&major, &minor, &patch);
return simgrid::xbt::string_printf("%i.%i.%i", major, minor, patch);
}
-
-/** @brief Wrap for mailbox::get_async */
-class PyGetAsync {
- std::unique_ptr<PyObject*> data = std::make_unique<PyObject*>();
-
-public:
- PyObject** get() const { return data.get(); }
-};
-
} // namespace
PYBIND11_DECLARE_HOLDER_TYPE(T, boost::intrusive_ptr<T>)
}
});
},
- "Registers the main function of an actor");
+ "Registers the main function of an actor")
+ .def("set_log_control", [](Engine*, const std::string& settings) { xbt_log_control_set(settings.c_str()); });
/* Class Netzone */
py::class_<simgrid::s4u::NetZone, std::unique_ptr<simgrid::s4u::NetZone, py::nodelete>> netzone(
simgrid::kernel::routing::NetPoint*, simgrid::kernel::routing::NetPoint*,
const std::vector<simgrid::s4u::LinkInRoute>&, bool>(&simgrid::s4u::NetZone::add_route),
"Add a route between 2 netpoints")
+ .def("add_route",
+ py::overload_cast<const simgrid::s4u::Host*, const simgrid::s4u::Host*,
+ const std::vector<simgrid::s4u::LinkInRoute>&, bool>(&simgrid::s4u::NetZone::add_route),
+ "Add a route between 2 netpoints")
+ .def("add_route",
+ py::overload_cast<const simgrid::s4u::Host*, const simgrid::s4u::Host*,
+ const std::vector<const simgrid::s4u::Link*>&>(&simgrid::s4u::NetZone::add_route),
+ "Add a route between 2 netpoints")
.def("create_host", py::overload_cast<const std::string&, double>(&simgrid::s4u::NetZone::create_host),
"Creates a host")
.def("create_host",
"")
.def(
"__repr__", [](const Host* h) { return "Host(" + h->get_name() + ")"; },
- "Textual representation of the Host.")
- .def_static(
- "sg_host_load_plugin_init", []() { sg_host_load_plugin_init(); }, py::call_guard<py::gil_scoped_release>(),
- "Initialize host load plugin.")
- .def(
- "reset_load", [](const Host* h) { sg_host_load_reset(h); }, py::call_guard<py::gil_scoped_release>(),
- "Reset counters of the host load plugin for this host.")
- .def_property_readonly(
- "current_load", [](const Host* h) { return sg_host_get_current_load(h); }, "Current load of the host.")
- .def_property_readonly(
- "avg_load", [](const Host* h) { return sg_host_get_avg_load(h); }, "Average load of the host.")
- .def_property_readonly(
- "idle_time", [](const Host* h) { return sg_host_get_idle_time(h); }, "Idle time of the host")
- .def_property_readonly(
- "total_idle_time", [](const Host* h) { return sg_host_get_total_idle_time(h); },
- "Total idle time of the host.")
- .def_property_readonly(
- "computed_flops", [](const Host* h) { return sg_host_get_computed_flops(h); }, "Computed flops of the host.");
+ "Textual representation of the Host.");
+
+ m.def("sg_host_load_plugin_init", [host]() {
+ sg_host_load_plugin_init();
+
+ static_cast<pybind11::class_<simgrid::s4u::Host, std::unique_ptr<simgrid::s4u::Host, pybind11::nodelete>>>(host)
+ .def(
+ "reset_load", [](const Host* h) { sg_host_load_reset(h); }, py::call_guard<py::gil_scoped_release>(),
+ "Reset counters of the host load plugin for this host.")
+ .def_property_readonly(
+ "current_load", [](const Host* h) { return sg_host_get_current_load(h); }, "Current load of the host.")
+ .def_property_readonly(
+ "avg_load", [](const Host* h) { return sg_host_get_avg_load(h); }, "Average load of the host.")
+ .def_property_readonly(
+ "idle_time", [](const Host* h) { return sg_host_get_idle_time(h); }, "Idle time of the host")
+ .def_property_readonly(
+ "total_idle_time", [](const Host* h) { return sg_host_get_total_idle_time(h); },
+ "Total idle time of the host.")
+ .def_property_readonly(
+ "computed_flops", [](const Host* h) { return sg_host_get_computed_flops(h); },
+ "Computed flops of the host.");
+ });
py::enum_<simgrid::s4u::Host::SharingPolicy>(host, "SharingPolicy")
.value("NONLINEAR", simgrid::s4u::Host::SharingPolicy::NONLINEAR)
"get", [](Mailbox* self) { return py::reinterpret_steal<py::object>(self->get<PyObject>()); },
py::call_guard<py::gil_scoped_release>(), "Blocking data reception")
.def(
- "get_async",
- [](Mailbox* self) -> std::tuple<CommPtr, PyGetAsync> {
- PyGetAsync wrap;
- auto comm = self->get_async(wrap.get());
- return std::make_tuple(std::move(comm), std::move(wrap));
- },
+ "get_async", [](Mailbox* self) -> CommPtr { return self->get_async(); },
py::call_guard<py::gil_scoped_release>(),
"Non-blocking data reception. Use data.get() to get the python object after the communication has finished")
.def("set_receiver", &Mailbox::set_receiver, py::call_guard<py::gil_scoped_release>(),
"Sets the actor as permanent receiver");
- /* Class PyGetAsync */
- py::class_<PyGetAsync>(m, "PyGetAsync", "Wrapper for async get communications")
- .def(py::init<>())
- .def(
- "get", [](const PyGetAsync* self) { return py::reinterpret_steal<py::object>(*(self->get())); },
- "Get python object after async communication in receiver side");
+ /* class Activity */
+ py::class_<Activity, ActivityPtr>(m, "Activity", "Activity. See the C++ documentation for details.");
/* Class Comm */
- py::class_<Comm, CommPtr>(m, "Comm", "Communication. See the C++ documentation for details.")
+ py::class_<Comm, CommPtr, Activity>(m, "Comm", "Communication. See the C++ documentation for details.")
.def_property_readonly("dst_data_size", &Comm::get_dst_data_size, py::call_guard<py::gil_scoped_release>(),
"Retrieve the size of the received data.")
.def_property_readonly("mailbox", &Comm::get_mailbox, py::call_guard<py::gil_scoped_release>(),
"Block until the completion of that communication, or raises TimeoutException after the specified timeout.")
.def("wait_until", &Comm::wait_until, py::call_guard<py::gil_scoped_release>(), py::arg("time_limit"),
"Block until the completion of that communication, or raises TimeoutException after the specified time.")
+ .def(
+ "get_payload",
+ [](const Comm* self) { return py::reinterpret_steal<py::object>((PyObject*)self->get_payload()); },
+ py::call_guard<py::gil_scoped_release>(),
+ "Retrieve the message's payload of a get_async. You cannot call this until after the comm termination.")
.def("detach", py::overload_cast<>(&Comm::detach), py::return_value_policy::reference_internal,
py::call_guard<py::gil_scoped_release>(),
"Start the comm, and ignore its result. It can be completely forgotten after that.")
py::arg("to"), py::arg("simulated_size_in_bytes"),
"Do a blocking communication between two arbitrary hosts.\n\nThis initializes a communication that "
"completely bypass the mailbox and actors mechanism. There is really no limit on the hosts involved. "
- "In particular, the actor does not have to be on one of the involved hosts.")
- .def_static("test_any", &Comm::test_any, py::call_guard<py::gil_scoped_release>(), py::arg("comms"),
- "take a vector s4u::CommPtr and return the rank of the first finished one (or -1 if none is done)")
- .def_static("wait_all", &Comm::wait_all, py::call_guard<py::gil_scoped_release>(), py::arg("comms"),
- "Block until the completion of all communications in the list.")
- .def_static("wait_all_for", &Comm::wait_all_for, py::call_guard<py::gil_scoped_release>(), py::arg("comms"),
- py::arg("timeout"),
- "Block until the completion of all communications in the list, or raises TimeoutException after "
- "the specified timeout.")
- .def_static("wait_any", &Comm::wait_any, py::call_guard<py::gil_scoped_release>(), py::arg("comms"),
- "Block until the completion of any communication in the list and return the index of the "
- "terminated one.")
- .def_static("wait_any_for", &Comm::wait_any_for, py::call_guard<py::gil_scoped_release>(), py::arg("comms"),
- py::arg("timeout"),
- "Block until the completion of any communication in the list and return the index of the terminated "
- "one, or -1 if a timeout occurred.");
+ "In particular, the actor does not have to be on one of the involved hosts.");
/* Class Io */
- py::class_<simgrid::s4u::Io, simgrid::s4u::IoPtr>(m, "Io", "I/O activities. See the C++ documentation for details.")
+ py::class_<simgrid::s4u::Io, simgrid::s4u::IoPtr, Activity>(m, "Io",
+ "I/O activities. See the C++ documentation for details.")
.def("test", &simgrid::s4u::Io::test, py::call_guard<py::gil_scoped_release>(),
"Test whether the I/O is terminated.")
.def("wait", &simgrid::s4u::Io::wait, py::call_guard<py::gil_scoped_release>(),
- "Block until the completion of that I/O operation")
- .def_static(
- "wait_any_for", &simgrid::s4u::Io::wait_any_for, py::call_guard<py::gil_scoped_release>(),
- "Block until the completion of any I/O in the list (or timeout) and return the index of the terminated one.")
- .def_static("wait_any", &simgrid::s4u::Io::wait_any, py::call_guard<py::gil_scoped_release>(),
- "Block until the completion of any I/O in the list and return the index of the terminated one.");
+ "Block until the completion of that I/O operation");
/* Class Exec */
- py::class_<simgrid::s4u::Exec, simgrid::s4u::ExecPtr>(m, "Exec", "Execution. See the C++ documentation for details.")
+ py::class_<simgrid::s4u::Exec, simgrid::s4u::ExecPtr, Activity>(m, "Exec",
+ "Execution. See the C++ documentation for details.")
.def_property_readonly("remaining", &simgrid::s4u::Exec::get_remaining, py::call_guard<py::gil_scoped_release>(),
"Amount of flops that remain to be computed until completion (read-only property).")
.def_property_readonly("remaining_ratio", &simgrid::s4u::Exec::get_remaining_ratio,
py::class_<Mutex, MutexPtr>(m, "Mutex",
"A classical mutex, but blocking in the simulation world."
"See the C++ documentation for details.")
- .def(py::init<>(&Mutex::create), py::call_guard<py::gil_scoped_release>(), "Mutex constructor.")
+ .def(py::init<>(&Mutex::create), py::call_guard<py::gil_scoped_release>(),
+ "Mutex constructor (pass True as a parameter to get a recursive Mutex).", py::arg("recursive") = false)
.def("lock", &Mutex::lock, py::call_guard<py::gil_scoped_release>(), "Block until the mutex is acquired.")
.def("try_lock", &Mutex::try_lock, py::call_guard<py::gil_scoped_release>(),
"Try to acquire the mutex. Return true if the mutex was acquired, false otherwise.")
},
"Add a callback called when each task ends.")
.def_property_readonly("name", &Task::get_name, "The name of this task (read-only).")
- .def_property_readonly("count", &Task::get_count, "The execution count of this task (read-only).")
.def_property_readonly("successors", &Task::get_successors, "The successors of this task (read-only).")
.def_property("amount", &Task::get_amount, &Task::set_amount, "The amount of work to do for this task.")
+ .def(
+ "get_count", [](const TaskPtr t) { return t->get_count("instance_0"); },
+ "The execution count of this task instance_0.")
+ .def(
+ "get_count", [](const TaskPtr t, const std::string& instance) { return t->get_count(instance); },
+ "The execution count of this task instance.")
.def("enqueue_firings", py::overload_cast<int>(&Task::enqueue_firings), py::call_guard<py::gil_scoped_release>(),
py::arg("n"), "Enqueue firings for this task.")
.def("add_successor", py::overload_cast<TaskPtr>(&Task::add_successor), py::call_guard<py::gil_scoped_release>(),
.def(
"__repr__", [](const IoTaskPtr io) { return "IoTask(" + io->get_name() + ")"; },
"Textual representation of the IoTask");
+
+ /* Class ActivitySet */
+ py::class_<ActivitySet, ActivitySetPtr>(m, "ActivitySet", "ActivitySet. See the C++ documentation for details.")
+ .def(py::init([](std::vector<simgrid::s4u::ActivityPtr> activities) {
+ auto* ret = new ActivitySet();
+ for (auto a : activities)
+ ret->push(a);
+ return ActivitySetPtr(ret);
+ }),
+ "The constructor should take the parameters from the command line, as is ")
+ .def(py::init([]() { return ActivitySetPtr(new ActivitySet()); }),
+ "The constructor should take the parameters from the command line, as is ")
+
+ .def("push", &ActivitySet::push, py::call_guard<py::gil_scoped_release>(), py::arg("activity"),
+ "Add an activity to the set")
+ .def("erase", &ActivitySet::erase, py::call_guard<py::gil_scoped_release>(), py::arg("activity"),
+ "Remove that activity from the set")
+ .def_property_readonly("size", &ActivitySet::size, "Count of activities in the set")
+ .def("empty", &ActivitySet::empty, "Returns whether the set is empty")
+ .def("has_failed_activities", &ActivitySet::has_failed_activities,
+ "Returns whether there is any failed activities")
+ .def("get_failed_activity", &ActivitySet::get_failed_activity, "Returns a failed activity from the set, or None")
+
+ .def("wait_all_for", &ActivitySet::wait_all_for, py::call_guard<py::gil_scoped_release>(), py::arg("timeout"),
+ "Wait for the completion of all activities in the set, but not longer than the provided timeout")
+ .def("wait_all", &ActivitySet::wait_all, py::call_guard<py::gil_scoped_release>(),
+ "Wait for the completion of all activities in the set, endlessly")
+ .def("test_any", &ActivitySet::test_any, py::call_guard<py::gil_scoped_release>(),
+ "Returns the first terminated activity if any, or None if no activity is terminated")
+ .def("wait_any_for", &ActivitySet::wait_any_for, py::call_guard<py::gil_scoped_release>(), py::arg("timeout"),
+ "Wait for the completion of one activity in the set, but not longer than the provided timeout")
+ .def("wait_any", &ActivitySet::wait_any, py::call_guard<py::gil_scoped_release>(),
+ "Wait for the completion of one activity in the set, endlessly")
+
+ .def(
+ "__repr__", [](const ActivitySetPtr as) { return "ActivitySet([...])"; },
+ "Textual representation of the ActivitySet");
}