Skip to content

Commit 58082f7

Browse files
Add RAII class to release the GIL.
Rename the existing RAII class for acquiring the GIL to something slightly less verbose.
1 parent 7c57012 commit 58082f7

4 files changed

Lines changed: 79 additions & 85 deletions

File tree

dynd/include/callables/apply_pyobject_callable.hpp

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -24,35 +24,35 @@ namespace nd {
2424
return dst_tp;
2525
}
2626

27-
/*
28-
void instantiate(dynd::nd::call_node *&node, char *DYND_UNUSED(data), dynd::nd::kernel_builder *ckb,
29-
const dynd::ndt::type &dst_tp, const char *dst_arrmeta, intptr_t nsrc,
30-
const dynd::ndt::type *src_tp, const char *const *src_arrmeta, dynd::kernel_request_t kernreq,
31-
intptr_t nkwd, const dynd::nd::array *kwds,
32-
const std::map<std::string, dynd::ndt::type> &tp_vars)
33-
{
34-
pydynd::PyGILState_RAII pgs;
35-
36-
std::vector<dynd::ndt::type> src_tp_copy(nsrc);
37-
for (int i = 0; i < nsrc; ++i) {
38-
src_tp_copy[i] = src_tp[i];
39-
}
40-
41-
intptr_t ckb_offset = ckb->size();
42-
ckb->emplace_back<apply_pyobject_kernel>(kernreq);
43-
apply_pyobject_kernel *self = ckb->get_at<apply_pyobject_kernel>(ckb_offset);
44-
self->m_proto = dynd::ndt::callable_type::make(dst_tp, src_tp_copy);
45-
self->m_pyfunc = func;
46-
Py_XINCREF(self->m_pyfunc);
47-
self->m_dst_arrmeta = dst_arrmeta;
48-
self->m_src_arrmeta.resize(nsrc);
49-
copy(src_arrmeta, src_arrmeta + nsrc, self->m_src_arrmeta.begin());
50-
51-
dynd::ndt::type child_src_tp = dynd::ndt::make_type<pyobject_type>();
52-
dynd::nd::assign->instantiate(node, nullptr, ckb, dst_tp, dst_arrmeta, 1, &child_src_tp, nullptr,
53-
dynd::kernel_request_single, 0, nullptr, tp_vars);
54-
}
55-
*/
27+
/*
28+
void instantiate(dynd::nd::call_node *&node, char *DYND_UNUSED(data), dynd::nd::kernel_builder *ckb,
29+
const dynd::ndt::type &dst_tp, const char *dst_arrmeta, intptr_t nsrc,
30+
const dynd::ndt::type *src_tp, const char *const *src_arrmeta, dynd::kernel_request_t kernreq,
31+
intptr_t nkwd, const dynd::nd::array *kwds,
32+
const std::map<std::string, dynd::ndt::type> &tp_vars)
33+
{
34+
pydynd::with_gil pgs;
35+
36+
std::vector<dynd::ndt::type> src_tp_copy(nsrc);
37+
for (int i = 0; i < nsrc; ++i) {
38+
src_tp_copy[i] = src_tp[i];
39+
}
40+
41+
intptr_t ckb_offset = ckb->size();
42+
ckb->emplace_back<apply_pyobject_kernel>(kernreq);
43+
apply_pyobject_kernel *self = ckb->get_at<apply_pyobject_kernel>(ckb_offset);
44+
self->m_proto = dynd::ndt::callable_type::make(dst_tp, src_tp_copy);
45+
self->m_pyfunc = func;
46+
Py_XINCREF(self->m_pyfunc);
47+
self->m_dst_arrmeta = dst_arrmeta;
48+
self->m_src_arrmeta.resize(nsrc);
49+
copy(src_arrmeta, src_arrmeta + nsrc, self->m_src_arrmeta.begin());
50+
51+
dynd::ndt::type child_src_tp = dynd::ndt::make_type<pyobject_type>();
52+
dynd::nd::assign->instantiate(node, nullptr, ckb, dst_tp, dst_arrmeta, 1, &child_src_tp, nullptr,
53+
dynd::kernel_request_single, 0, nullptr, tp_vars);
54+
}
55+
*/
5656
};
5757

5858
} // namespace pydynd::nd::functional

dynd/include/kernels/apply_pyobject_kernel.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ struct apply_pyobject_kernel : dynd::nd::base_strided_kernel<apply_pyobject_kern
2222
~apply_pyobject_kernel()
2323
{
2424
if (m_pyfunc != NULL) {
25-
pydynd::PyGILState_RAII pgs;
25+
pydynd::with_gil pgs;
2626
Py_DECREF(m_pyfunc);
2727
get_child()->destroy();
2828
}

dynd/include/kernels/numpy_ufunc.hpp

Lines changed: 28 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ namespace nd {
1616
{
1717
if (ufunc != NULL) {
1818
// Acquire the GIL for the python decref
19-
PyGILState_RAII pgs;
19+
with_gil pgs;
2020
Py_DECREF(ufunc);
2121
}
2222
}
@@ -26,8 +26,7 @@ namespace nd {
2626
struct scalar_ufunc_ck;
2727

2828
template <>
29-
struct scalar_ufunc_ck<false>
30-
: dynd::nd::base_strided_kernel<scalar_ufunc_ck<false>, 1> {
29+
struct scalar_ufunc_ck<false> : dynd::nd::base_strided_kernel<scalar_ufunc_ck<false>, 1> {
3130
typedef scalar_ufunc_ck self_type;
3231

3332
const scalar_ufunc_data *data;
@@ -47,46 +46,34 @@ namespace nd {
4746
data->funcptr(args, &dimsize, strides, data->ufunc_data);
4847
}
4948

50-
void strided(char *dst, intptr_t dst_stride, char *const *src,
51-
const intptr_t *src_stride, size_t count)
49+
void strided(char *dst, intptr_t dst_stride, char *const *src, const intptr_t *src_stride, size_t count)
5250
{
5351
char *args[NPY_MAXARGS];
5452
// Set up the args array the way the numpy ufunc wants it
5553
memcpy(&args[0], &src[0], data->param_count * sizeof(void *));
5654
args[data->param_count] = dst;
5755
// Call the ufunc loop with a dim size of 1
5856
intptr_t strides[NPY_MAXARGS];
59-
memcpy(&strides[0], &src_stride[0],
60-
data->param_count * sizeof(intptr_t));
57+
memcpy(&strides[0], &src_stride[0], data->param_count * sizeof(intptr_t));
6158
strides[data->param_count] = dst_stride;
62-
data->funcptr(args, reinterpret_cast<intptr_t *>(&count), strides,
63-
data->ufunc_data);
59+
data->funcptr(args, reinterpret_cast<intptr_t *>(&count), strides, data->ufunc_data);
6460
}
6561

66-
static void
67-
instantiate(char *static_data, char *DYND_UNUSED(data),
68-
kernel_builder *ckb, intptr_t ckb_offset,
69-
const dynd::ndt::type &dst_tp,
70-
const char *DYND_UNUSED(dst_arrmeta),
71-
intptr_t DYND_UNUSED(nsrc), const dynd::ndt::type *src_tp,
72-
const char *const *DYND_UNUSED(src_arrmeta),
73-
dynd::kernel_request_t kernreq,
74-
const dynd::eval::eval_context *DYND_UNUSED(ectx),
75-
intptr_t nkwd, const dynd::nd::array *kwds,
76-
const std::map<std::string, dynd::ndt::type> &tp_vars)
62+
static void instantiate(char *static_data, char *DYND_UNUSED(data), kernel_builder *ckb, intptr_t ckb_offset,
63+
const dynd::ndt::type &dst_tp, const char *DYND_UNUSED(dst_arrmeta),
64+
intptr_t DYND_UNUSED(nsrc), const dynd::ndt::type *src_tp,
65+
const char *const *DYND_UNUSED(src_arrmeta), dynd::kernel_request_t kernreq,
66+
const dynd::eval::eval_context *DYND_UNUSED(ectx), intptr_t nkwd,
67+
const dynd::nd::array *kwds, const std::map<std::string, dynd::ndt::type> &tp_vars)
7768
{
7869
// Acquire the GIL for creating the ckernel
79-
PyGILState_RAII pgs;
80-
self_type::make(
81-
ckb, kernreq,
82-
reinterpret_cast<std::shared_ptr<scalar_ufunc_data> *>(static_data)
83-
->get());
70+
with_gil pgs;
71+
self_type::make(ckb, kernreq, reinterpret_cast<std::shared_ptr<scalar_ufunc_data> *>(static_data)->get());
8472
}
8573
};
8674

8775
template <>
88-
struct scalar_ufunc_ck<true>
89-
: dynd::nd::base_strided_kernel<scalar_ufunc_ck<true>, 1> {
76+
struct scalar_ufunc_ck<true> : dynd::nd::base_strided_kernel<scalar_ufunc_ck<true>, 1> {
9077
typedef scalar_ufunc_ck self_type;
9178

9279
const scalar_ufunc_data *data;
@@ -104,47 +91,38 @@ namespace nd {
10491
intptr_t strides[NPY_MAXARGS];
10592
memset(strides, 0, (data->param_count + 1) * sizeof(void *));
10693
{
107-
PyGILState_RAII pgs;
94+
with_gil pgs;
10895
data->funcptr(args, &dimsize, strides, data->ufunc_data);
10996
}
11097
}
11198

112-
void strided(char *dst, intptr_t dst_stride, char *const *src,
113-
const intptr_t *src_stride, size_t count)
99+
void strided(char *dst, intptr_t dst_stride, char *const *src, const intptr_t *src_stride, size_t count)
114100
{
115101
char *args[NPY_MAXARGS];
116102
// Set up the args array the way the numpy ufunc wants it
117103
memcpy(&args[0], &src[0], data->param_count * sizeof(void *));
118104
args[data->param_count] = dst;
119105
// Call the ufunc loop with a dim size of 1
120106
intptr_t strides[NPY_MAXARGS];
121-
memcpy(&strides[0], &src_stride[0],
122-
data->param_count * sizeof(intptr_t));
107+
memcpy(&strides[0], &src_stride[0], data->param_count * sizeof(intptr_t));
123108
strides[data->param_count] = dst_stride;
124109
{
125-
PyGILState_RAII pgs;
126-
data->funcptr(args, reinterpret_cast<intptr_t *>(&count), strides,
127-
data->ufunc_data);
110+
with_gil pgs;
111+
data->funcptr(args, reinterpret_cast<intptr_t *>(&count), strides, data->ufunc_data);
128112
}
129113
}
130114

131-
static intptr_t
132-
instantiate(char *static_data, char *DYND_UNUSED(data), void *ckb,
133-
intptr_t ckb_offset, const dynd::ndt::type &dst_tp,
134-
const char *DYND_UNUSED(dst_arrmeta),
135-
intptr_t DYND_UNUSED(nsrc), const dynd::ndt::type *src_tp,
136-
const char *const *DYND_UNUSED(src_arrmeta),
137-
dynd::kernel_request_t kernreq,
138-
const dynd::eval::eval_context *DYND_UNUSED(ectx),
139-
intptr_t nkwd, const dynd::nd::array *kwds,
140-
const std::map<std::string, dynd::ndt::type> &tp_vars)
115+
static intptr_t instantiate(char *static_data, char *DYND_UNUSED(data), void *ckb, intptr_t ckb_offset,
116+
const dynd::ndt::type &dst_tp, const char *DYND_UNUSED(dst_arrmeta),
117+
intptr_t DYND_UNUSED(nsrc), const dynd::ndt::type *src_tp,
118+
const char *const *DYND_UNUSED(src_arrmeta), dynd::kernel_request_t kernreq,
119+
const dynd::eval::eval_context *DYND_UNUSED(ectx), intptr_t nkwd,
120+
const dynd::nd::array *kwds, const std::map<std::string, dynd::ndt::type> &tp_vars)
141121
{
142122
// Acquire the GIL for creating the ckernel
143-
PyGILState_RAII pgs;
144-
self_type::make(
145-
ckb, kernreq, ckb_offset,
146-
reinterpret_cast<std::shared_ptr<scalar_ufunc_data> *>(static_data)
147-
->get());
123+
with_gil pgs;
124+
self_type::make(ckb, kernreq, ckb_offset,
125+
reinterpret_cast<std::shared_ptr<scalar_ufunc_data> *>(static_data)->get());
148126
return ckb_offset;
149127
}
150128
};

dynd/include/utility_functions.hpp

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -386,16 +386,32 @@ inline py_ref capture_if_not_null(PyObject *o)
386386
// return py_ref(o, true);
387387
}
388388

389-
class PyGILState_RAII {
389+
// RAII class to acquire GIL.
390+
class with_gil {
390391
PyGILState_STATE m_gstate;
391392

392-
PyGILState_RAII(const PyGILState_RAII &);
393-
PyGILState_RAII &operator=(const PyGILState_RAII &);
393+
with_gil(const with_gil &) = delete;
394+
395+
with_gil &operator=(const with_gil &) = delete;
396+
397+
public:
398+
inline with_gil() { m_gstate = PyGILState_Ensure(); }
399+
400+
inline ~with_gil() { PyGILState_Release(m_gstate); }
401+
};
402+
403+
// RAII class to release GIL.
404+
class with_nogil {
405+
PyThreadState *m_tstate;
406+
407+
with_nogil(const with_nogil &) = delete;
408+
409+
with_nogil &operator=(const with_nogil &) = delete;
394410

395411
public:
396-
inline PyGILState_RAII() { m_gstate = PyGILState_Ensure(); }
412+
inline with_nogil() { m_tstate = PyEval_SaveThread(); }
397413

398-
inline ~PyGILState_RAII() { PyGILState_Release(m_gstate); }
414+
inline ~with_nogil() { PyEval_RestoreThread(m_tstate); }
399415
};
400416

401417
/**

0 commit comments

Comments
 (0)