8000 MNT: Add more global state I missed to the thread_unsafe_state struct · numpy/numpy@8d7d57c · GitHub
[go: up one dir, main page]

Skip to content

Commit 8d7d57c

Browse files
committed
MNT: Add more global state I missed to the thread_unsafe_state struct
1 parent 2ba53c3 commit 8d7d57c

File tree

8 files changed

+63
-127
lines changed

8 files changed

+63
-127
lines changed

numpy/_core/src/multiarray/arrayobject.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,7 @@ maintainer email: oliphant.travis@ieee.org
6262

6363
#include "binop_override.h"
6464
#include "array_coercion.h"
65-
66-
67-
NPY_NO_EXPORT npy_bool numpy_warn_if_no_mem_policy = 0;
65+
#include "multiarraymodule.h"
6866

6967
/*NUMPY_API
7068
Compute the size of an array (in number of items)
@@ -429,7 +427,7 @@ array_dealloc(PyArrayObject *self)
429427
}
430428
}
431429
if (fa->mem_handler == NULL) {
432-
if (numpy_warn_if_no_mem_policy) {
430+
if (npy_thread_unsafe_state.warn_if_no_mem_policy) {
433431
char const *msg = "Trying to dealloc data, but a memory policy "
434432
"is not set. If you take ownership of the data, you must "
435433
"set a base owning the data (e.g. a PyCapsule).";

numpy/_core/src/multiarray/arrayobject.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
extern "C" {
1010
#endif
1111

12-
extern NPY_NO_EXPORT npy_bool numpy_warn_if_no_mem_policy;
13-
1412
NPY_NO_EXPORT PyObject *
1513
_strings_richcompare(PyArrayObject *self, PyArrayObject *other, int cmp_op,
1614
int rstrip);

numpy/_core/src/multiarray/conversion_utils.c

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,18 +1190,6 @@ PyArray_IntpFromSequence(PyObject *seq, npy_intp *vals, int maxvals)
11901190
}
11911191

11921192

1193-
/**
1194-
* WARNING: This flag is a bad idea, but was the only way to both
1195-
* 1) Support unpickling legacy pickles with object types.
1196-
* 2) Deprecate (and later disable) usage of O4 and O8
1197-
*
1198-
* The key problem is that the pickled representation unpickles by
1199-
* directly calling the dtype constructor, which has no way of knowing
1200-
* that it is in an unpickle context instead of a normal context without
1201-
* evil global state like we create here.
1202-
*/
1203-
NPY_NO_EXPORT int evil_global_disable_warn_O4O8_flag = 0;
1204-
12051193
/*
12061194
* Convert a gentype (that is actually a generic kind character) and
12071195
* it's itemsize to a NUmPy typenumber, i.e. `itemsize=4` and `gentype='f'`
@@ -1326,7 +1314,7 @@ PyArray_TypestrConvert(int itemsize, int gentype)
13261314
*/
13271315
if (itemsize == 4 || itemsize == 8) {
13281316
int ret = 0;
1329-
if (evil_global_disable_warn_O4O8_flag) {
1317+
if (npy_thread_unsafe_state.disable_warn_O4O8_flag) {
13301318
/* 2012-02-04, 1.7, not sure when this can be removed */
13311319
ret = DEPRECATE("DType strings 'O4' and 'O8' are "
13321320
"deprecated because they are platform "

numpy/_core/src/multiarray/conversion_utils.h

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -103,18 +103,6 @@ typedef enum {
103103
NPY_NO_EXPORT int
104104
PyArray_DeviceConverterOptional(PyObject *object, NPY_DEVICE *device);
105105

106-
/**
107-
* WARNING: This flag is a bad idea, but was the only way to both
108-
* 1) Support unpickling legacy pickles with object types.
109-
* 2) Deprecate (and later disable) usage of O4 and O8
110-
*
111-
* The key problem is that the pickled representation unpickles by
112-
* directly calling the dtype constructor, which has no way of knowing
113-
* that it is in an unpickle context instead of a normal context without
114-
* evil global state like we create here.
115-
*/
116-
extern NPY_NO_EXPORT int evil_global_disable_warn_O4O8_flag;
117-
118106
/*
119107
* Convert function which replaces np._NoValue with NULL.
120108
* As a converter returns 0 on error and 1 on success.

numpy/_core/src/multiarray/descriptor.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
#include "templ_common.h" /* for npy_mul_sizes_with_overflow */
2222
#include "descriptor.h"
2323
#include "npy_static_data.h"
24-
#include "multiarraymodule.h"
24+
#include "multiarraymodule.h" // for thread unsafe state access
2525
#include "alloc.h"
2626
#include "assert.h"
2727
#include "npy_buffer.h"

numpy/_core/src/multiarray/multiarraymodule.c

Lines changed: 15 additions & 76 deletions
2851
Original file line numberDiff line numberDiff line change
@@ -98,24 +98,15 @@ NPY_NO_EXPORT PyObject *
9898
_umath_strings_richcompare(
9999
PyArrayObject *self, PyArrayObject *other, int cmp_op, int rstrip);
100100

101-
/*
102-
* global variable to determine if legacy printing is enabled, accessible from
103-
* C. For simplicity the mode is encoded as an integer where INT_MAX means no
104-
* legacy mode, and '113'/'121' means 1.13/1.21 legacy mode; and 0 maps to
105-
* INT_MAX. We can upgrade this if we have more complex requirements in the
106-
* future.
107-
*/
108-
int npy_legacy_print_mode = INT_MAX;
109-
110101

111102
static PyObject *
112103
set_legacy_print_mode(PyObject *NPY_UNUSED(self), PyObject *args)
113104
{
114-
if (!PyArg_ParseTuple(args, "i", &npy_legacy_print_mode)) {
105+
if (!PyArg_ParseTuple(args, "i", &npy_thread_unsafe_state.legacy_print_mode)) {
115106
return NULL;
116107
}
117-
if (!npy_legacy_print_mode) {
118-
npy_legacy_print_mode = INT_MAX;
108+
if (!npy_thread_unsafe_state.legacy_print_mode) {
109+
npy_thread_unsafe_state.legacy_print_mode = INT_MAX;
119110
}
120111
Py_RETURN_NONE;
121112
}
@@ -3148,7 +3139,7 @@ array__reconstruct(PyObject *NPY_UNUSED(dummy), PyObject *args)
31483139
PyArray_Dims shape = {NULL, 0};
31493140
PyArray_Descr *dtype = NULL;
31503141

3151-
evil_global_disable_warn_O4O8_flag = 1;
3142+
npy_thread_unsafe_state.disable_warn_O4O8_flag = 1;
31523143

31533144
if (!PyArg_ParseTuple(args, "O!O&O&:_reconstruct",
31543145
&PyType_Type, &subtype,
@@ -3165,12 +3156,12 @@ array__reconstruct(PyObject *NPY_UNUSED(dummy), PyObject *args)
31653156
(int)shape.len, shape.ptr, NULL, NULL, 0, NULL);
31663157
npy_free_cache_dim_obj(shape);
31673158

3168-
evil_global_disable_warn_O4O8_flag = 0;
3159+
npy_thread_unsafe_state.disable_warn_O4O8_flag = 0;
31693160

31703161
return ret;
31713162

31723163
fail:
3173-
evil_global_disable_warn_O4O8_flag = 0;
3164+
npy_thread_unsafe_state.disable_warn_O4O8_flag = 0;
31743165

31753166
Py_XDECREF(dtype);
31763167
npy_free_cache_dim_obj(shape);
@@ -4358,8 +4349,8 @@ _set_numpy_warn_if_no_mem_policy(PyObject *NPY_UNUSED(self), PyObject *arg)
43584349
if (res < 0) {
43594350
return NULL;
43604351
}
4361-
int old_value = numpy_warn_if_no_mem_policy;
4362-
numpy_warn_if_no_mem_policy = res;
4352+
int old_value = npy_thread_unsafe_state.warn_if_no_mem_policy;
4353+
npy_thread_unsafe_state.warn_if_no_mem_policy = res;
43634354
if (old_value) {
43644355
Py_RETURN_TRUE;
43654356
}
@@ -4802,69 +4793,13 @@ static int
48024793
initialize_thread_unsafe_state(void) {
48034794
char *env = getenv("NUMPY_WARN_IF_NO_MEM_POLICY");
48044795
if ((env != NULL) && (strncmp(env, "1", 1) == 0)) {
4805-
numpy_warn_if_no_mem_policy = 1;
4796+
npy_thread_unsafe_state.warn_if_no_mem_policy = 1;
48064797
}
48074798
else {
4808-
numpy_warn_if_no_mem_policy = 0;
4809-
}
4810-
4811-
// default_truediv_type_tup
4812-
PyArray_Descr *tmp = PyArray_DescrFromType(NPY_DOUBLE);
4813-
if (tmp == NULL) {
4814-
return -1;
4815-
}
4816-
4817-
npy_static_pydata.default_truediv_type_tup =
4818-
PyTuple_Pack(3, tmp, tmp, tmp);
4819-
if (npy_static_pydata.default_truediv_type_tup == NULL) {
4820-
Py_DECREF(tmp);
4821-
return -1;
4822-
}
4823-
Py_DECREF(tmp);
4824-
4825-
PyObject *flags = PySys_GetObject("flags"); /* borrowed object */
4826-
if (flags == NULL) {
4827-
PyErr_SetString(PyExc_AttributeError, "cannot get sys.flags");
4828-
return -1;
4829-
}
4830-
PyObject *level = PyObject_GetAttrString(flags, "optimize");
4831-
if (level == NULL) {
4832-
return -1;
4833-
}
4834-
npy_static_cdata.optimize = PyLong_AsLong(level);
4835-
Py_DECREF(level);
4836-
4837-
/*
4838-
* see unpack_bits for how this table is used.
4839-
*
4840-
* LUT for bigendian bitorder, littleendian is handled via
4841-
* byteswapping in the loop.
4842-
*
4843-
* 256 8 byte blocks representing 8 bits expanded to 1 or 0 bytes
4844-
*/
4845-
npy_intp j;
4846-
for (j=0; j < 256; j++) {
4847-
npy_intp k;
4848-
for (k=0; k < 8; k++) {
4849-
npy_uint8 v = (j & (1 << k)) == (1 << k);
4850-
npy_static_cdata.unpack_lookup_big[j].bytes[7 - k] = v;
4851-
}
4852-
}
4853-
4854-
npy_static_pydata.kwnames_is_copy = Py_BuildValue("(s)", "copy");
4855-
if (npy_static_pydata.kwnames_is_copy == NULL) {
4856-
return -1;
4799+
npy_thread_unsafe_state.warn_if_no_mem_policy = 0;
48574800
}
48584801

4859-
npy_static_pydata.one_obj = PyLong_FromLong((long) 1);
4860-
if (npy_static_pydata.one_obj == NULL) {
4861-
return -1;
4862-
}
4863-
4864-
npy_static_pydata.zero_obj = PyLong_FromLong((long) 0);
4865-
if (npy_static_pydata.zero_obj == NULL) {
4866-
return -1;
4867-
}
4802+
npy_thread_unsafe_state.legacy_print_mode = INT_MAX;
48684803

48694804
return 0;
48704805
}
@@ -4931,6 +4866,10 @@ PyMODINIT_FUNC PyInit__multiarray_umath(void) {
49314866
goto err;
49324867
}
49334868

4869+
if (initialize_thread_unsafe_state() < 0) {
4870+
goto err;
4871+
}
4872+
49344873
if (init_extobj() < 0) {
49354874
goto err;
49364875
}

numpy/_core/src/multiarray/multiarraymodule.h

Lines changed: 27 additions & 0 deletions
3FA7
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,33 @@ typedef struct npy_thread_unsafe_state_struct {
7878
* used to detect module reloading in the reload guard
7979
*/
8080
int reload_guard_initialized;
81+
82+
/*
83+
* global variable to determine if legacy printing is enabled,
84+
* accessible from C. For simplicity the mode is encoded as an
85+
* integer where INT_MAX means no legacy mode, and '113'/'121'
86+
* means 1.13/1.21 legacy mode; and 0 maps to INT_MAX. We can
87+
* upgrade this if we have more complex requirements in the future.
88+
*/
89+
int legacy_print_mode;
90+
91+
/*
92+
* Holds the user-defined setting for whether or not to warn
93+
* if there is no memory policy set
94+
*/
95+
int warn_if_no_mem_policy;
96+
97+
/*
98+
* WARNING: This flag is a bad idea, but was the only way to both
99+
* 1) Support unpickling legacy pickles with object types.
100+
* 2) Deprecate (and later disable) usage of O4 and O8
101+
*
102+
* The key problem is that the pickled representation unpickles by
103+
* directly calling the dtype constructor, which has no way of knowing
104+
* that it is in an unpickle context instead of a normal context without
105+
* evil global state like we create here.
106+
*/
107+
int disable_warn_O4O8_flag;
81108
} npy_thread_unsafe_state_struct;
82109

83110

0 commit comments

Comments
 (0)
0