8000 Make PyDictOrValues thread safe · python/cpython@75c4227 · GitHub
[go: up one dir, main page]

Skip to content

Commit 75c4227

Browse files
committed
Make PyDictOrValues thread safe
1 parent 8612230 commit 75c4227

File tree

1 file changed

+12
-2
lines changed

1 file changed

+12
-2
lines changed

Objects/dictobject.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5540,6 +5540,9 @@ make_dict_from_instance_attributes(PyInterpreterState *interp,
55405540
track += _PyObject_GC_MAY_BE_TRACKED(val);
55415541
}
55425542
}
5543+
// free-threading TODO: We'll need to mark the values to be freed via qsbr
5544+
// so that a resize doesn't free them immediately while another thread
5545+
// still has a reference to the old values.
55435546
PyObject *res = new_dict(interp, keys, values, used, 0);
55445547
if (track && res) {
55455548
_PyObject_GC_TRACK(res);
@@ -5572,19 +5575,26 @@ _PyObject_MakeInstanceAttributesFromDict(PyObject *obj, PyDictOrValues *dorv)
55725575
return false;
55735576
}
55745577
assert(_PyType_HasFeature(Py_TYPE(obj), Py_TPFLAGS_HEAPTYPE));
5578+
bool success = true;
5579+
Py_BEGIN_CRITICAL_SECTION(dict);
55755580
if (dict->ma_keys != CACHED_KEYS(Py_TYPE(obj)) || Py_REFCNT(dict) != 1) {
5576-
return false;
5581+
success = false;
5582+
goto exit;
55775583
}
55785584
assert(dict->ma_values);
55795585
// We have an opportunity to do something *really* cool: dematerialize it!
55805586
_PyDictKeys_DecRef(dict->ma_keys);
55815587
_PyDictOrValues_SetValues(dorv, dict->ma_values);
55825588
OBJECT_STAT_INC(dict_dematerialized);
5589+
// Lock free readers will need to contend with NULL values here, but
5590+
// because we locked the dict anyone else will be safe.
55835591
// Don't try this at home, kids:
55845592
dict->ma_keys = NULL;
55855593
dict->ma_values = NULL;
55865594
Py_DECREF(dict);
5587-
return true;
5595+
exit:
5596+
Py_END_CRITICAL_SECTION();
5597+
return success;
55885598
}
55895599

55905600
int

0 commit comments

Comments
 (0)
0