@@ -467,6 +467,7 @@ Potential Optimizations
467
467
#include "Python.h"
468
468
#include "pycore_call.h" // _PyObject_CallNoArgs()
469
469
#include "pycore_ceval.h" // _PyEval_GetBuiltin()
470
+ #include "pycore_critical_section.h" // Py_BEGIN_CRITICAL_SECTION
470
471
#include "pycore_dict.h" // _Py_dict_lookup()
471
472
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
472
473
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
@@ -984,6 +985,7 @@ odict_reduce(register PyODictObject *od, PyObject *Py_UNUSED(ignored))
984
985
985
986
986
987
/*[clinic input]
988
+ @critical_section
987
989
OrderedDict.setdefault
988
990
989
991
key: object
@@ -997,7 +999,7 @@ Return the value for key if key is in the dictionary, else default.
997
999
static PyObject *
998
1000
OrderedDict_setdefault_impl (PyODictObject * self , PyObject * key ,
999
1001
PyObject * default_value )
1000
- /*[clinic end generated code: output=97537cb7c28464b6 input=38e098381c1efbc6 ]*/
1002
+ /*[clinic end generated code: output=97537cb7c28464b6 input=d7b93e92734f99b5 ]*/
1001
1003
{
1002
1004
PyObject * result = NULL ;
1003
1005
@@ -1069,6 +1071,7 @@ _odict_popkey_hash(PyObject *od, PyObject *key, PyObject *failobj,
1069
1071
1070
1072
/* Skips __missing__() calls. */
1071
1073
/*[clinic input]
1074
+ @critical_section
1072
1075
OrderedDict.pop
1073
1076
1074
1077
key: object
@@ -1083,7 +1086,7 @@ raise a KeyError.
1083
1086
static PyObject *
1084
1087
OrderedDict_pop_impl (PyODictObject * self , PyObject * key ,
1085
1088
PyObject * default_value )
1086
- /*[clinic end generated code: output=7a6447d104e7494b input=7efe36601007dff7 ]*/
1089
+ /*[clinic end generated code: output=7a6447d104e7494b input=a79988887b4a651f ]*/
1087
1090
{
1088
1091
Py_hash_t hash = PyObject_Hash (key );
1089
1092
if (hash == -1 )
@@ -1095,6 +1098,7 @@ OrderedDict_pop_impl(PyODictObject *self, PyObject *key,
1095
1098
/* popitem() */
1096
1099
1097
1100
/*[clinic input]
1101
+ @critical_section
1098
1102
OrderedDict.popitem
1099
1103
1100
1104
last: bool = True
@@ -1106,7 +1110,7 @@ Pairs are returned in LIFO order if last is true or FIFO order if false.
1106
1110
1107
1111
static PyObject *
1108
1112
OrderedDict_popitem_impl (PyODictObject * self , int last )
1109
- /*[clinic end generated code: output=98e7d986690d49eb input=d992ac5ee8305e1a ]*/
1113
+ /*[clinic end generated code: output=98e7d986690d49eb input=8aafc7433e0a40e7 ]*/
1110
1114
{
1111
1115
PyObject * key , * value , * item = NULL ;
1112
1116
_ODictNode * node ;
@@ -1251,6 +1255,7 @@ odict_reversed(PyODictObject *od, PyObject *Py_UNUSED(ignored))
1251
1255
/* move_to_end() */
1252
1256
1253
1257
/*[clinic input]
1258
+ @critical_section
1254
1259
OrderedDict.move_to_end
1255
1260
1256
1261
key: object
@@ -1263,7 +1268,7 @@ Raise KeyError if the element does not exist.
1263
1268
1264
1269
static PyObject *
1265
1270
OrderedDict_move_to_end_impl (PyODictObject * self , PyObject * key , int last )
1266
- /*[clinic end generated code: output=fafa4c5cc9b92f20 input=d6ceff7132a2fcd7 ]*/
1271
+ /*[clinic end generated code: output=fafa4c5cc9b92f20 input=09f8bc7053c0f6d4 ]*/
1267
1272
{
1268
1273
_ODictNode * node ;
1269
1274
@@ -1556,7 +1561,10 @@ static int
1556
1561
_PyODict_SetItem_KnownHash (PyObject * od , PyObject * key , PyObject * value ,
1557
1562
Py_hash_t hash )
1558
1563
{
1559
- int res = _PyDict_SetItem_KnownHash (od , key , value , hash );
1564
+ int res ;
1565
+ Py_BEGIN_CRITICAL_SECTION (od );
1566
+
1567
+ res = _PyDict_SetItem_KnownHash_LockHeld (od , key , value , hash );
1560
1568
if (res == 0 ) {
1561
1569
res = _odict_add_new_node ((PyODictObject * )od , key , hash );
1562
1570
if (res < 0 ) {
@@ -1566,11 +1574,13 @@ _PyODict_SetItem_KnownHash(PyObject *od, PyObject *key, PyObject *value,
1566
1574
_PyErr_ChainExceptions1 (exc );
1567
1575
}
1568
1576
}
1577
+ Py_END_CRITICAL_SECTION ();
1569
1578
return res ;
1570
1579
}
1571
1580
1572
- int
1573
- PyODict_SetItem (PyObject * od , PyObject * key , PyObject * value )
1581
+
1582
+ static int
1583
+ setitem_lock_held (PyObject * od , PyObject * key , PyObject * value )
1574
1584
{
1575
1585
Py_hash_t hash = PyObject_Hash (key );
1576
1586
if (hash == -1 )
@@ -1579,7 +1589,17 @@ PyODict_SetItem(PyObject *od, PyObject *key, PyObject *value)
1579
1589
}
1580
1590
1581
1591
int
1582
- PyODict_DelItem (PyObject * od , PyObject * key )
1592
+ PyODict_SetItem (PyObject * od , PyObject * key , PyObject * value )
1593
+ {
1594
+ int res ;
1595
+ Py_BEGIN_CRITICAL_SECTION (od );
1596
+ res = setitem_lock_held (od , key , value );
1597
+ Py_END_CRITICAL_SECTION ();
1598
+ return res ;
1599
+ }
1600
+
1601
+ static int
1602
+ del_item_lock_held (PyObject * od , PyObject * key )
1583
1603
{
1584
1604
int res ;
1585
1605
Py_hash_t hash = PyObject_Hash (key );
@@ -1591,6 +1611,16 @@ PyODict_DelItem(PyObject *od, PyObject *key)
1591
1611
return _PyDict_DelItem_KnownHash (od , key , hash );
1592
1612
}
1593
1613
1614
+ int
1615
+ PyODict_DelItem (PyObject * od , PyObject * key )
1616
+ {
1617
+ int res ;
1618
+ Py_BEGIN_CRITICAL_SECTION (od );
1619
+ res = del_item_lock_held (od , key );
1620
+ Py_END_CRITICAL_SECTION ();
1621
+ return res ;
1622
+ }
1623
+
1594
1624
1595
1625
/* -------------------------------------------
1596
1626
* The OrderedDict views (keys/values/items)
@@ -1630,17 +1660,12 @@ odictiter_traverse(odictiterobject *di, visitproc visit, void *arg)
1630
1660
/* In order to protect against modifications during iteration, we track
1631
1661
* the current key instead of the current node. */
1632
1662
static PyObject *
1633
- odictiter_nextkey (odictiterobject * di )
1663
+ odictiter_nextkey_lock_held (odictiterobject * di )
1634
1664
{
1635
1665
PyObject * key = NULL ;
1636
1666
_ODictNode * node ;
1637
1667
int reversed = di -> kind & _odict_ITER_REVERSED ;
1638
1668
1639
- if (di -> di_odict == NULL )
1640
- return NULL ;
1641
- if (di -> di_current == NULL )
1642
- goto done ; /* We're already done. */
1643
-
1644
1669
/* Check for unsupported changes. */
1645
1670
if (di -> di_odict -> od_state != di -> di_state ) {
1646
1671
PyErr_SetString (PyExc_RuntimeError ,
@@ -1682,6 +1707,24 @@ odictiter_nextkey(odictiterobject *di)
1682
1707
return key ;
1683
1708
}
1684
1709
1710
+ static PyObject *
1711
+ odictiter_nextkey (odictiterobject * di )
1712
+ {
1713
+ if (di -> di_odict == NULL )
1714
+ return NULL ;
1715
+ if (di -> di_current == NULL ) {
1716
+ Py_CLEAR (di -> di_odict );
1717
+ return NULL ;
1718
+ }
1719
+
1720
+
1721
+ PyObject * res ;
1722
+ Py_BEGIN_CRITICAL_SECTION (di -> di_odict );
1723
+ res = odictiter_nextkey_lock_held (di );
1724
+ Py_END_CRITICAL_SECTION ();
1725
+ return res ;
1726
+ }
1727
+
1685
1728
static PyObject *
1686
1729
odictiter_iternext (odictiterobject * di )
1687
1730
{
0 commit comments