https://github.com/python/cpython/commit/5592399313c963c110280a7c98de974889e1d353
commit: 5592399313c963c110280a7c98de974889e1d353
branch: main
author: Dino Viehland <[email protected]>
committer: DinoV <[email protected]>
date: 2024-07-24T10:58:28-07:00
summary:

gh-122208: Don't delivery PyDict_EVENT_ADDED until it can't fail (#122207)

Don't delivery PyDict_EVENT_ADDED until it can't fail

files:
A Misc/NEWS.d/next/Core and 
Builtins/2024-07-23-23-59-04.gh-issue-122208.z8KHsY.rst
M Objects/dictobject.c

diff --git a/Misc/NEWS.d/next/Core and 
Builtins/2024-07-23-23-59-04.gh-issue-122208.z8KHsY.rst b/Misc/NEWS.d/next/Core 
and Builtins/2024-07-23-23-59-04.gh-issue-122208.z8KHsY.rst
new file mode 100644
index 00000000000000..e4a89d137ede0e
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and 
Builtins/2024-07-23-23-59-04.gh-issue-122208.z8KHsY.rst 
@@ -0,0 +1 @@
+Dictionary watchers now only deliver the PyDict_EVENT_ADDED event when the 
insertion is in a known good state to succeed.
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index ee88576cc77dec..6a16a04102a6c0 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -1627,6 +1627,10 @@ insert_combined_dict(PyInterpreterState *interp, 
PyDictObject *mp,
         }
     }
 
+    uint64_t new_version = _PyDict_NotifyEvent(
+        interp, PyDict_EVENT_ADDED, mp, key, value);
+    mp->ma_keys->dk_version = 0;
+
     Py_ssize_t hashpos = find_empty_slot(mp->ma_keys, hash);
     dictkeys_set_index(mp->ma_keys, hashpos, mp->ma_keys->dk_nentries);
 
@@ -1643,6 +1647,7 @@ insert_combined_dict(PyInterpreterState *interp, 
PyDictObject *mp,
         STORE_VALUE(ep, value);
         STORE_HASH(ep, hash);
     }
+    mp->ma_version_tag = new_version;
     STORE_KEYS_USABLE(mp->ma_keys, mp->ma_keys->dk_usable - 1);
     STORE_KEYS_NENTRIES(mp->ma_keys, mp->ma_keys->dk_nentries + 1);
     assert(mp->ma_keys->dk_usable >= 0);
@@ -1746,15 +1751,11 @@ insertdict(PyInterpreterState *interp, PyDictObject *mp,
 
     if (ix == DKIX_EMPTY) {
         assert(!_PyDict_HasSplitTable(mp));
-        uint64_t new_version = _PyDict_NotifyEvent(
-                interp, PyDict_EVENT_ADDED, mp, key, value);
         /* Insert into new slot. */
-        mp->ma_keys->dk_version = 0;
         assert(old_value == NULL);
         if (insert_combined_dict(interp, mp, hash, key, value) < 0) {
             goto Fail;
         }
-        mp->ma_version_tag = new_version;
         STORE_USED(mp, mp->ma_used + 1);
         ASSERT_CONSISTENT(mp);
         return 0;
@@ -1795,9 +1796,6 @@ insert_to_emptydict(PyInterpreterState *interp, 
PyDictObject *mp,
     assert(mp->ma_keys == Py_EMPTY_KEYS);
     ASSERT_DICT_LOCKED(mp);
 
-    uint64_t new_version = _PyDict_NotifyEvent(
-            interp, PyDict_EVENT_ADDED, mp, key, value);
-
     int unicode = PyUnicode_CheckExact(key);
     PyDictKeysObject *newkeys = new_keys_object(
             interp, PyDict_LOG_MINSIZE, unicode);
@@ -1806,6 +1804,9 @@ insert_to_emptydict(PyInterpreterState *interp, 
PyDictObject *mp,
         Py_DECREF(value);
         return -1;
     }
+    uint64_t new_version = _PyDict_NotifyEvent(
+            interp, PyDict_EVENT_ADDED, mp, key, value);
+
     /* We don't decref Py_EMPTY_KEYS here because it is immortal. */
     assert(mp->ma_values == NULL);
 
@@ -4199,9 +4200,6 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, 
PyObject *default_valu
 
     if (ix == DKIX_EMPTY) {
         assert(!_PyDict_HasSplitTable(mp));
-        uint64_t new_version = _PyDict_NotifyEvent(
-            interp, PyDict_EVENT_ADDED, mp, key, default_value);
-        mp->ma_keys->dk_version = 0;
         value = default_value;
 
         if (insert_combined_dict(interp, mp, hash, Py_NewRef(key), 
Py_NewRef(value)) < 0) {
@@ -4214,7 +4212,6 @@ dict_setdefault_ref_lock_held(PyObject *d, PyObject *key, 
PyObject *default_valu
 
         MAINTAIN_TRACKING(mp, key, value);
         STORE_USED(mp, mp->ma_used + 1);
-        mp->ma_version_tag = new_version;
         assert(mp->ma_keys->dk_usable >= 0);
         ASSERT_CONSISTENT(mp);
         if (result) {

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to