Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Ensure that the GIL is held when using inc_ref/dec_ref.
[simgrid.git] / src / bindings / python / simgrid_python.cpp
index a3589e7..b32042b 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018-2022. The SimGrid Team. All rights reserved.          */
+/* Copyright (c) 2018-2023. The SimGrid Team. All rights reserved.          */
 
 /* This program is free software; you can redistribute it and/or modify it
  * under the terms of the license (GNU LGPL) which comes with this package. */
@@ -118,14 +118,12 @@ PYBIND11_MODULE(simgrid, m)
            py::call_guard<py::gil_scoped_release>())
       .def("exec_async", py::overload_cast<double>(&simgrid::s4u::this_actor::exec_async),
            py::call_guard<py::gil_scoped_release>())
-      .def("parallel_execute", &simgrid::s4u::this_actor::parallel_execute,
-           py::call_guard<py::gil_scoped_release>(),
+      .def("parallel_execute", &simgrid::s4u::this_actor::parallel_execute, py::call_guard<py::gil_scoped_release>(),
            "Run a parallel task (requires the 'ptask_L07' model)")
       .def("exec_init",
            py::overload_cast<const std::vector<simgrid::s4u::Host*>&, const std::vector<double>&,
-           const std::vector<double>&>  (&simgrid::s4u::this_actor::exec_init),
-           py::call_guard<py::gil_scoped_release>(),
-           "Initiate a parallel task (requires the 'ptask_L07' model)")
+                             const std::vector<double>&>(&simgrid::s4u::this_actor::exec_init),
+           py::call_guard<py::gil_scoped_release>(), "Initiate a parallel task (requires the 'ptask_L07' model)")
       .def("get_host", &simgrid::s4u::this_actor::get_host, "Retrieves host on which the current actor is located")
       .def("set_host", &simgrid::s4u::this_actor::set_host, py::call_guard<py::gil_scoped_release>(),
            "Moves the current actor to another host.", py::arg("dest"))
@@ -144,8 +142,9 @@ PYBIND11_MODULE(simgrid, m)
           [](py::object cb) {
             py::function fun = py::reinterpret_borrow<py::function>(cb);
             fun.inc_ref(); // FIXME: why is this needed for tests like actor-kill and actor-lifetime?
+            const py::gil_scoped_release gil_release;
             simgrid::s4u::this_actor::on_exit([fun](bool failed) {
-              py::gil_scoped_acquire py_context; // need a new context for callback
+              const py::gil_scoped_acquire py_context; // need a new context for callback
               try {
                 fun(failed);
               } catch (const py::error_already_set& e) {
@@ -153,7 +152,6 @@ PYBIND11_MODULE(simgrid, m)
               }
             });
           },
-          py::call_guard<py::gil_scoped_release>(),
           "Define a lambda to be called when the actor ends. It takes a bool parameter indicating whether the actor "
           "was killed. If False, the actor finished peacefully.")
       .def("get_pid", &simgrid::s4u::this_actor::get_pid, "Retrieves PID of the current actor")
@@ -190,7 +188,7 @@ PYBIND11_MODULE(simgrid, m)
                           "get_all_hosts() is deprecated and  will be dropped after v3.33, use all_hosts instead.", 1);
              return self.attr("all_hosts");
            })
-      .def("host_by_name", &Engine::host_by_name_or_null, py::call_guard<py::gil_scoped_release>(),
+      .def("host_by_name", &Engine::host_by_name_or_null,
            "Retrieve a host by its name, or None if it does not exist in the platform.")
       .def_property_readonly("all_hosts", &Engine::get_all_hosts, "Returns the list of all hosts found in the platform")
       .def("get_all_links",
@@ -226,10 +224,8 @@ PYBIND11_MODULE(simgrid, m)
            "Change one of SimGrid's configurations")
       .def("load_platform", &Engine::load_platform, "Load a platform file describing the environment")
       .def("load_deployment", &Engine::load_deployment, "Load a deployment file and launch the actors that it contains")
-      .def("mailbox_by_name_or_create", &Engine::mailbox_by_name_or_create,
-           py::call_guard<py::gil_scoped_release>(),
-           py::arg("name"),
-           "Find a mailbox from its name or create one if it does not exist")
+      .def("mailbox_by_name_or_create", &Engine::mailbox_by_name_or_create, py::call_guard<py::gil_scoped_release>(),
+           py::arg("name"), "Find a mailbox from its name or create one if it does not exist")
       .def("run", &Engine::run, py::call_guard<py::gil_scoped_release>(), "Run the simulation until its end")
       .def("run_until", py::overload_cast<double>(&Engine::run_until, py::const_),
            py::call_guard<py::gil_scoped_release>(), "Run the simulation until the given date",
@@ -238,7 +234,7 @@ PYBIND11_MODULE(simgrid, m)
           "register_actor",
           [](Engine* e, const std::string& name, py::object fun_or_class) {
             e->register_actor(name, [fun_or_class](std::vector<std::string> args) {
-              py::gil_scoped_acquire py_context;
+              const py::gil_scoped_acquire py_context;
               try {
                 /* Convert the std::vector into a py::tuple */
                 py::tuple params(args.size() - 1);
@@ -404,8 +400,7 @@ PYBIND11_MODULE(simgrid, m)
                  "get_pstate_speed() is deprecated and  will be dropped after v3.33, use pstate_speed instead.", 1);
              return self.attr("pstate_speed")(state);
            })
-      .def("pstate_speed", &Host::get_pstate_speed, py::call_guard<py::gil_scoped_release>(),
-           "Retrieve the maximal speed at the given pstate")
+      .def("pstate_speed", &Host::get_pstate_speed, "Retrieve the maximal speed at the given pstate")
       .def("get_netpoint",
            [](py::object self) // XBT_ATTRIB_DEPRECATED_v334
            {
@@ -458,7 +453,7 @@ PYBIND11_MODULE(simgrid, m)
           [](py::object cb) {
             Host::on_creation_cb([cb](Host& h) {
               py::function fun = py::reinterpret_borrow<py::function>(cb);
-              py::gil_scoped_acquire py_context; // need a new context for callback
+              const py::gil_scoped_acquire py_context; // need a new context for callback
               try {
                 fun(&h);
               } catch (const py::error_already_set& e) {
@@ -633,43 +628,42 @@ PYBIND11_MODULE(simgrid, m)
       .def_static("by_name", &Mailbox::by_name, py::call_guard<py::gil_scoped_release>(), py::arg("name"),
                   "Retrieve a Mailbox from its name")
       .def_property_readonly("name", &Mailbox::get_name, "The name of that mailbox (read-only property).")
-      .def_property_readonly("ready", &Mailbox::ready, py::call_guard<py::gil_scoped_release>(),
+      .def_property_readonly("ready", &Mailbox::ready,
                              "Check if there is a communication ready to be consumed from a mailbox.")
       .def(
           "put",
           [](Mailbox* self, py::object data, uint64_t size, double timeout) {
-            data.inc_ref();
-            self->put(data.ptr(), size, timeout);
+            auto* data_ptr = data.inc_ref().ptr();
+            const py::gil_scoped_release gil_release;
+            self->put(data_ptr, size, timeout);
           },
-          py::call_guard<py::gil_scoped_release>(), "Blocking data transmission with a timeout")
+          "Blocking data transmission with a timeout")
       .def(
           "put",
           [](Mailbox* self, py::object data, uint64_t size) {
-            data.inc_ref();
-            self->put(data.ptr(), size);
+            auto* data_ptr = data.inc_ref().ptr();
+            const py::gil_scoped_release gil_release;
+            self->put(data_ptr, size);
           },
-          py::call_guard<py::gil_scoped_release>(), "Blocking data transmission")
+          "Blocking data transmission")
       .def(
           "put_async",
           [](Mailbox* self, py::object data, uint64_t size) {
-            data.inc_ref();
-            return self->put_async(data.ptr(), size);
+            auto* data_ptr = data.inc_ref().ptr();
+            const py::gil_scoped_release gil_release;
+            return self->put_async(data_ptr, size);
           },
-          py::call_guard<py::gil_scoped_release>(), "Non-blocking data transmission")
+          "Non-blocking data transmission")
       .def(
           "put_init",
           [](Mailbox* self, py::object data, uint64_t size) {
-            data.inc_ref();
-            return self->put_init(data.ptr(), size);
+            auto* data_ptr = data.inc_ref().ptr();
+            const py::gil_scoped_release gil_release;
+            return self->put_init(data_ptr, size);
           },
-          py::call_guard<py::gil_scoped_release>(), "Creates (but don’t start) a data transmission to that mailbox.")
+          "Creates (but don’t start) a data transmission to that mailbox.")
       .def(
-          "get",
-          [](Mailbox* self) {
-            py::object data = py::reinterpret_steal<py::object>(self->get<PyObject>());
-            // data.dec_ref(); // FIXME: why does it break python-actor-create?
-            return data;
-          },
+          "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",
@@ -860,11 +854,12 @@ PYBIND11_MODULE(simgrid, m)
                                             "application. See the C++ documentation for details.")
       .def(
           "create",
-          [](py::str name, Host* h, py::object fun, py::args args) {
+          [](const std::string& name, Host* h, py::object fun, py::args args) {
             fun.inc_ref();  // FIXME: why is this needed for tests like exec-async, exec-dvfs and exec-remote?
             args.inc_ref(); // FIXME: why is this needed for tests like actor-migrate?
+            const py::gil_scoped_release gil_release;
             return simgrid::s4u::Actor::create(name, h, [fun, args]() {
-              py::gil_scoped_acquire py_context;
+              const py::gil_scoped_acquire py_context;
               try {
                 fun(*args);
               } catch (const py::error_already_set& ex) {
@@ -876,7 +871,6 @@ PYBIND11_MODULE(simgrid, m)
               }
             });
           },
-          py::call_guard<py::gil_scoped_release>(),
           "Create an actor from a function or an object. See the :ref:`example <s4u_ex_actors_create>`.")
       .def_property(
           "host", &Actor::get_host, py::cpp_function(&Actor::set_host, py::call_guard<py::gil_scoped_release>()),
@@ -908,5 +902,6 @@ PYBIND11_MODULE(simgrid, m)
            "Suspend that actor, that is blocked until resume()ed by another actor.")
       .def("resume", &Actor::resume, py::call_guard<py::gil_scoped_release>(),
            "Resume that actor, that was previously suspend()ed.")
-      .def_static("kill_all", &Actor::kill_all, py::call_guard<py::gil_scoped_release>(), "Kill all actors but the caller.");
+      .def_static("kill_all", &Actor::kill_all, py::call_guard<py::gil_scoped_release>(),
+                  "Kill all actors but the caller.");
 }