Skip to content

Commit a5cfe98

Browse files
committed
add code and simple test case.
1 parent 340a684 commit a5cfe98

File tree

2 files changed

+54
-3
lines changed

2 files changed

+54
-3
lines changed

Modules/_collectionsmodule.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2231,11 +2231,23 @@ defdict_missing(PyObject *op, PyObject *key)
22312231
value = _PyObject_CallNoArgs(factory);
22322232
if (value == NULL)
22332233
return value;
2234-
if (PyObject_SetItem(op, key, value) < 0) {
2234+
// if (PyObject_SetItem(op, key, value) < 0) {
2235+
// Py_DECREF(value);
2236+
// return NULL;
2237+
// }
2238+
PyObject* result;
2239+
int res = PyDict_SetDefaultRef(op, key, value, &result);
2240+
if (res < 0) {
2241+
PyObject *tup;
2242+
tup = PyTuple_Pack(1, key);
2243+
if (!tup) return NULL;
2244+
PyErr_SetObject(PyExc_KeyError, tup);
2245+
Py_DECREF(tup);
2246+
} else if (res > 0) {
2247+
// Key was already in the dict
22352248
Py_DECREF(value);
2236-
return NULL;
22372249
}
2238-
return value;
2250+
return result;
22392251
}
22402252

22412253
static inline PyObject*

edward_defaultdict_test.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
from collections import defaultdict
2+
from threading import Barrier, Condition, Thread
3+
4+
5+
def test():
6+
cv = Condition()
7+
8+
key = 'my-key'
9+
setting_ready_flag = False
10+
11+
def default_factory():
12+
with cv:
13+
while not setting_ready_flag:
14+
print("Waiting for value to be set...")
15+
cv.wait()
16+
print("missing value is set, returning it.")
17+
return "default"
18+
19+
mydict = defaultdict(default_factory)
20+
21+
def writer():
22+
with cv:
23+
nonlocal setting_ready_flag
24+
mydict[key] = "setted value"
25+
setting_ready_flag = True
26+
print("Value set, notifying all waiting threads.")
27+
cv.notify()
28+
29+
default_fact_thread = Thread(target=lambda: mydict[key])
30+
writer_thread = Thread(target=writer)
31+
default_fact_thread.start()
32+
writer_thread.start()
33+
34+
default_fact_thread.join()
35+
writer_thread.join()
36+
37+
print(mydict.items()) # Should print "setted value" but actually "default"
38+
39+
test()

0 commit comments

Comments
 (0)