Skip to content

Commit 0c6b97e

Browse files
Replace use of py::handle to store global_registry
Use py::gil_safe_call_once_and_store facility pybind11 provides.
1 parent 5dd5d4a commit 0c6b97e

File tree

1 file changed

+13
-11
lines changed

1 file changed

+13
-11
lines changed

python/src/py_nvbench.cpp

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,8 @@ struct nvbench_run_error : std::runtime_error
124124
// that are defined for the base class
125125
using std::runtime_error::runtime_error;
126126
};
127-
py::handle benchmark_exc{};
127+
128+
PYBIND11_CONSTINIT static py::gil_safe_call_once_and_store<py::object> exc_storage;
128129

129130
void run_interruptible(nvbench::option_parser &parser)
130131
{
@@ -223,18 +224,18 @@ class GlobalBenchmarkRegistry
223224
}
224225
catch (py::error_already_set &e)
225226
{
226-
py::raise_from(e, benchmark_exc.ptr(), "Python error raised ");
227+
py::raise_from(e, exc_storage.get_stored().ptr(), "Python error raised ");
227228
throw py::error_already_set();
228229
}
229230
catch (const std::exception &e)
230231
{
231232
const std::string &exc_message = e.what();
232-
py::set_error(benchmark_exc, exc_message.c_str());
233+
py::set_error(exc_storage.get_stored(), exc_message.c_str());
233234
throw py::error_already_set();
234235
}
235236
catch (...)
236237
{
237-
py::set_error(benchmark_exc, "Caught unknown exception in nvbench_main");
238+
py::set_error(exc_storage.get_stored(), "Caught unknown exception in nvbench_main");
238239
throw py::error_already_set();
239240
}
240241
}
@@ -1158,11 +1159,12 @@ PYBIND11_MODULE(_nvbench, m)
11581159
static constexpr const char *exception_nvbench_runtime_error_doc = R"XXXX(
11591160
An exception raised if running benchmarks encounters an error
11601161
)XXXX";
1161-
py::object benchmark_exc_ =
1162-
py::exception<nvbench_run_error>(m, "NVBenchRuntimeError", PyExc_RuntimeError);
1163-
benchmark_exc_.attr("__doc__") = exception_nvbench_runtime_error_doc;
1164-
1165-
benchmark_exc = benchmark_exc_.release();
1162+
exc_storage.call_once_and_store_result([&]() {
1163+
py::object benchmark_exc_ =
1164+
py::exception<nvbench_run_error>(m, "NVBenchRuntimeError", PyExc_RuntimeError);
1165+
benchmark_exc_.attr("__doc__") = exception_nvbench_runtime_error_doc;
1166+
return benchmark_exc_;
1167+
});
11661168

11671169
// ATTN: nvbench::benchmark_manager is a singleton, it is exposed through
11681170
// GlobalBenchmarkRegistry class
@@ -1171,7 +1173,7 @@ An exception raised if running benchmarks encounters an error
11711173
py::nodelete{});
11721174

11731175
// function register
1174-
auto func_register_impl = [&](py::object fn) { return std::ref(global_registry->add_bench(fn)); };
1176+
auto func_register_impl = [](py::object fn) { return std::ref(global_registry->add_bench(fn)); };
11751177
static constexpr const char *func_register_doc = R"XXXX(
11761178
Register benchmark function of type Callable[[nvbench.State], None]
11771179
)XXXX";
@@ -1206,7 +1208,7 @@ Register benchmark function of type Callable[[nvbench.State], None]
12061208
// Testing utilities
12071209
m.def("test_cpp_exception", []() { throw nvbench_run_error("Test"); });
12081210
m.def("test_py_exception", []() {
1209-
py::set_error(benchmark_exc, "Test");
1211+
py::set_error(exc_storage.get_stored(), "Test");
12101212
throw py::error_already_set();
12111213
});
12121214
}

0 commit comments

Comments
 (0)