summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorCarl Meyer <carl@oddbird.net>2022-10-07 00:08:00 (GMT)
committerGitHub <noreply@github.com>2022-10-07 00:08:00 (GMT)
commita4b7794887929f82c532fcd055326954ff1197ce (patch)
tree257e2dc783858251f893d75c17663913b05a0fad /Python
parent683ab859554c34831fcecc854de35745d7fd603c (diff)
downloadcpython-a4b7794887929f82c532fcd055326954ff1197ce.zip
cpython-a4b7794887929f82c532fcd055326954ff1197ce.tar.gz
cpython-a4b7794887929f82c532fcd055326954ff1197ce.tar.bz2
GH-91052: Add C API for watching dictionaries (GH-31787)
Diffstat (limited to 'Python')
-rw-r--r--Python/ceval.c5
-rw-r--r--Python/pystate.c4
2 files changed, 8 insertions, 1 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index c08c794..ee1baba 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -3252,6 +3252,7 @@ handle_eval_breaker:
uint16_t hint = cache->index;
DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, STORE_ATTR);
PyObject *value, *old_value;
+ uint64_t new_version;
if (DK_IS_UNICODE(dict->ma_keys)) {
PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint;
DEOPT_IF(ep->me_key != name, STORE_ATTR);
@@ -3259,6 +3260,7 @@ handle_eval_breaker:
DEOPT_IF(old_value == NULL, STORE_ATTR);
STACK_SHRINK(1);
value = POP();
+ new_version = _PyDict_NotifyEvent(PyDict_EVENT_MODIFIED, dict, name, value);
ep->me_value = value;
}
else {
@@ -3268,6 +3270,7 @@ handle_eval_breaker:
DEOPT_IF(old_value == NULL, STORE_ATTR);
STACK_SHRINK(1);
value = POP();
+ new_version = _PyDict_NotifyEvent(PyDict_EVENT_MODIFIED, dict, name, value);
ep->me_value = value;
}
Py_DECREF(old_value);
@@ -3277,7 +3280,7 @@ handle_eval_breaker:
_PyObject_GC_TRACK(dict);
}
/* PEP 509 */
- dict->ma_version_tag = DICT_NEXT_VERSION();
+ dict->ma_version_tag = new_version;
Py_DECREF(owner);
JUMPBY(INLINE_CACHE_ENTRIES_STORE_ATTR);
DISPATCH();
diff --git a/Python/pystate.c b/Python/pystate.c
index 50ae0ce..c74868d 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -451,6 +451,10 @@ interpreter_clear(PyInterpreterState *interp, PyThreadState *tstate)
Py_CLEAR(interp->sysdict);
Py_CLEAR(interp->builtins);
+ for (int i=0; i < DICT_MAX_WATCHERS; i++) {
+ interp->dict_watchers[i] = NULL;
+ }
+
// XXX Once we have one allocator per interpreter (i.e.
// per-interpreter GC) we must ensure that all of the interpreter's
// objects have been cleaned up at the point.