gh-112075: Accessing a single element should optimistically avoid locking (#115109)

Makes accessing a single element thread safe and typically lock free
This commit is contained in:
Dino Viehland 2024-02-20 17:08:14 -08:00 committed by GitHub
parent 176df09adb
commit 54071460d7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 496 additions and 175 deletions

View File

@ -211,6 +211,8 @@ static inline PyDictUnicodeEntry* DK_UNICODE_ENTRIES(PyDictKeysObject *dk) {
#define DICT_WATCHER_MASK ((1 << DICT_MAX_WATCHERS) - 1) #define DICT_WATCHER_MASK ((1 << DICT_MAX_WATCHERS) - 1)
#define DICT_WATCHER_AND_MODIFICATION_MASK ((1 << (DICT_MAX_WATCHERS + DICT_WATCHED_MUTATION_BITS)) - 1) #define DICT_WATCHER_AND_MODIFICATION_MASK ((1 << (DICT_MAX_WATCHERS + DICT_WATCHED_MUTATION_BITS)) - 1)
#define DICT_VALUES_SIZE(values) ((uint8_t *)values)[-1]
#ifdef Py_GIL_DISABLED #ifdef Py_GIL_DISABLED
#define DICT_NEXT_VERSION(INTERP) \ #define DICT_NEXT_VERSION(INTERP) \
(_Py_atomic_add_uint64(&(INTERP)->dict_state.global_version, DICT_VERSION_INCREMENT) + DICT_VERSION_INCREMENT) (_Py_atomic_add_uint64(&(INTERP)->dict_state.global_version, DICT_VERSION_INCREMENT) + DICT_VERSION_INCREMENT)
@ -256,7 +258,7 @@ _PyDictValues_AddToInsertionOrder(PyDictValues *values, Py_ssize_t ix)
assert(ix < SHARED_KEYS_MAX_SIZE); assert(ix < SHARED_KEYS_MAX_SIZE);
uint8_t *size_ptr = ((uint8_t *)values)-2; uint8_t *size_ptr = ((uint8_t *)values)-2;
int size = *size_ptr; int size = *size_ptr;
assert(size+2 < ((uint8_t *)values)[-1]); assert(size+2 < DICT_VALUES_SIZE(values));
size++; size++;
size_ptr[-size] = (uint8_t)ix; size_ptr[-size] = (uint8_t)ix;
*size_ptr = size; *size_ptr = size;

View File

@ -66,21 +66,6 @@ PyDoc_STRVAR(dict___contains____doc__,
#define DICT___CONTAINS___METHODDEF \ #define DICT___CONTAINS___METHODDEF \
{"__contains__", (PyCFunction)dict___contains__, METH_O|METH_COEXIST, dict___contains____doc__}, {"__contains__", (PyCFunction)dict___contains__, METH_O|METH_COEXIST, dict___contains____doc__},
static PyObject *
dict___contains___impl(PyDictObject *self, PyObject *key);
static PyObject *
dict___contains__(PyDictObject *self, PyObject *key)
{
PyObject *return_value = NULL;
Py_BEGIN_CRITICAL_SECTION(self);
return_value = dict___contains___impl(self, key);
Py_END_CRITICAL_SECTION();
return return_value;
}
PyDoc_STRVAR(dict_get__doc__, PyDoc_STRVAR(dict_get__doc__,
"get($self, key, default=None, /)\n" "get($self, key, default=None, /)\n"
"--\n" "--\n"
@ -327,4 +312,4 @@ dict_values(PyDictObject *self, PyObject *Py_UNUSED(ignored))
{ {
return dict_values_impl(self); return dict_values_impl(self);
} }
/*[clinic end generated code: output=c8fda06bac5b05f3 input=a9049054013a1b77]*/ /*[clinic end generated code: output=f3dd5f3fb8122aef input=a9049054013a1b77]*/

File diff suppressed because it is too large Load Diff