Skip to content

Commit 60ab4b7

Browse files
committed
address review: use counter to allow concurent packing
1 parent 4443101 commit 60ab4b7

File tree

3 files changed

+18
-10
lines changed

3 files changed

+18
-10
lines changed

Include/internal/pycore_pyatomic_ft_wrappers.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ extern "C" {
107107
_Py_atomic_store_ulong_relaxed(&value, new_value)
108108
#define FT_ATOMIC_STORE_SSIZE_RELAXED(value, new_value) \
109109
_Py_atomic_store_ssize_relaxed(&value, new_value)
110+
#define FT_ATOMIC_STORE_SSIZE(value, new_value) \
111+
_Py_atomic_store_ssize(&value, new_value)
110112
#define FT_ATOMIC_STORE_FLOAT_RELAXED(value, new_value) \
111113
_Py_atomic_store_float_relaxed(&value, new_value)
112114
#define FT_ATOMIC_LOAD_FLOAT_RELAXED(value) \
@@ -151,6 +153,7 @@ extern "C" {
151153
#define FT_ATOMIC_STORE_INT8_RELAXED(value, new_value) value = new_value
152154
#define FT_ATOMIC_STORE_INT8_RELEASE(value, new_value) value = new_value
153155
#define FT_ATOMIC_STORE_SSIZE_RELAXED(value, new_value) value = new_value
156+
#define FT_ATOMIC_STORE_SSIZE(value, new_value) value = new_value
154157
#define FT_ATOMIC_STORE_SSIZE_RELEASE(value, new_value) value = new_value
155158
#define FT_ATOMIC_STORE_UINT8_RELAXED(value, new_value) value = new_value
156159
#define FT_ATOMIC_STORE_UINT16_RELAXED(value, new_value) value = new_value

Lib/test/test_struct.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,7 @@ def test_Struct_reinitialization(self):
579579

580580
def check_sizeof(self, format_str, number_of_codes):
581581
# The size of 'PyStructObject'
582-
totalsize = support.calcobjsize('2n3PB')
582+
totalsize = support.calcobjsize('2n3P1n')
583583
# The size taken up by the 'formatcode' dynamic array
584584
totalsize += struct.calcsize('P3n0P') * (number_of_codes + 1)
585585
support.check_sizeof(self, struct.Struct(format_str), totalsize)

Modules/_struct.c

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ typedef struct {
7070
formatcode *s_codes;
7171
PyObject *s_format;
7272
PyObject *weakreflist; /* List of weak references */
73-
PyMutex mutex; /* to prevent mutation during packing */
73+
Py_ssize_t mutex_cnt; /* to prevent mutation during packing */
7474
} PyStructObject;
7575

7676
#define PyStructObject_CAST(op) ((PyStructObject *)(op))
@@ -1774,7 +1774,7 @@ s_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
17741774
s->s_codes = NULL;
17751775
s->s_size = -1;
17761776
s->s_len = -1;
1777-
s->mutex = (PyMutex){0};
1777+
s->mutex_cnt = 0;
17781778
}
17791779
return self;
17801780
}
@@ -1818,7 +1818,7 @@ Struct___init___impl(PyStructObject *self, PyObject *format)
18181818

18191819
Py_SETREF(self->s_format, format);
18201820

1821-
if (PyMutex_IsLocked(&self->mutex)) {
1821+
if (FT_ATOMIC_LOAD_SSIZE(self->mutex_cnt)) {
18221822
PyErr_SetString(PyExc_RuntimeError,
18231823
"Call Struct.__init__() in struct.pack()");
18241824
return -1;
@@ -2266,13 +2266,15 @@ s_pack(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
22662266
char *buf = PyBytesWriter_GetData(writer);
22672267

22682268
/* Call the guts */
2269-
PyMutex_Lock(&soself->mutex);
2269+
Py_ssize_t prev_cnt = FT_ATOMIC_LOAD_SSIZE(soself->mutex_cnt);
2270+
2271+
FT_ATOMIC_ADD_SSIZE(soself->mutex_cnt, 1);
22702272
if ( s_pack_internal(soself, args, 0, buf, state) != 0 ) {
2271-
PyMutex_Unlock(&soself->mutex);
2273+
FT_ATOMIC_STORE_SSIZE(soself->mutex_cnt, prev_cnt);
22722274
PyBytesWriter_Discard(writer);
22732275
return NULL;
22742276
}
2275-
PyMutex_Unlock(&soself->mutex);
2277+
FT_ATOMIC_STORE_SSIZE(soself->mutex_cnt, prev_cnt);
22762278

22772279
return PyBytesWriter_FinishWithSize(writer, soself->s_size);
22782280
}
@@ -2370,13 +2372,16 @@ s_pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
23702372
}
23712373

23722374
/* Call the guts */
2373-
PyMutex_Lock(&soself->mutex);
2375+
Py_ssize_t prev_cnt = FT_ATOMIC_LOAD_SSIZE(soself->mutex_cnt);
2376+
2377+
FT_ATOMIC_ADD_SSIZE(soself->mutex_cnt, 1);
23742378
if (s_pack_internal(soself, args, 2, (char*)buffer.buf + offset, state) != 0) {
2375-
PyMutex_Unlock(&soself->mutex);
2379+
FT_ATOMIC_STORE_SSIZE(soself->mutex_cnt, prev_cnt);
23762380
PyBuffer_Release(&buffer);
23772381
return NULL;
23782382
}
2379-
PyMutex_Unlock(&soself->mutex);
2383+
FT_ATOMIC_STORE_SSIZE(soself->mutex_cnt, prev_cnt);
2384+
23802385
PyBuffer_Release(&buffer);
23812386
Py_RETURN_NONE;
23822387
}

0 commit comments

Comments
 (0)