@@ -106,7 +106,7 @@ set_compare_threadsafe(PySetObject *so, setentry *table, setentry *ep,
106106 }
107107 Py_ssize_t ep_hash = FT_ATOMIC_LOAD_SSIZE_ACQUIRE (ep -> hash );
108108 if (ep_hash == hash ) {
109- if (startkey == NULL || !_Py_TryIncrefCompare (& ep -> key , startkey )) {
109+ if (!_Py_TryIncrefCompare (& ep -> key , startkey )) {
110110 return SET_LOOKKEY_CHANGED ;
111111 }
112112 int cmp = PyObject_RichCompareBool (startkey , key , Py_EQ );
@@ -135,9 +135,10 @@ set_compare_threadsafe(PySetObject *so, setentry *table, setentry *ep,
135135#endif
136136
137137static inline Py_ALWAYS_INLINE int
138- set_compare_entry (PySetObject * so , setentry * table , setentry * entry ,
139- PyObject * key , Py_hash_t hash )
138+ set_compare_entry_lock_held (PySetObject * so , setentry * table , setentry * entry ,
139+ PyObject * key , Py_hash_t hash )
140140{
141+ _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED (so );
141142 if (entry -> hash == 0 && entry -> key == NULL )
142143 return SET_LOOKKEY_EMPTY ;
143144 if (entry -> hash == hash ) {
@@ -163,10 +164,10 @@ set_compare_entry(PySetObject *so, setentry *table, setentry *entry,
163164 return SET_LOOKKEY_NO_MATCH ;
164165}
165166
166- // This is similar to set_compare_entry () but we don't need to incref startkey
167- // before comparing and we don't need to check if the set has changed. This
168- // also omits the PyUnicode_CheckExact() special case since it doesn't help
169- // much for frozensets.
167+ // This is similar to set_compare_entry_lock_held () but we don't need to
168+ // incref startkey before comparing and we don't need to check if the set has
169+ // changed. This also omits the PyUnicode_CheckExact() special case since it
170+ // doesn't help much for frozensets.
170171static inline Py_ALWAYS_INLINE int
171172set_compare_frozenset (PySetObject * so , setentry * table , setentry * ep ,
172173 PyObject * key , Py_hash_t hash )
@@ -418,7 +419,7 @@ set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash, setentry **epp)
418419 Py_BEGIN_CRITICAL_SECTION (so );
419420 do {
420421 status = set_do_lookup (so , so -> table , so -> mask , key , hash , epp ,
421- set_compare_entry );
422+ set_compare_entry_lock_held );
422423 } while (status == SET_LOOKKEY_CHANGED );
423424 Py_END_CRITICAL_SECTION ();
424425 }
@@ -2439,10 +2440,12 @@ _PySet_Contains(PySetObject *so, PyObject *key)
24392440 return -1 ;
24402441 }
24412442 PyErr_Clear ();
2443+ // Note that 'key' could be a set() or frozenset() object. Unlike most
2444+ // container types, set allows membership testing with a set key, even
2445+ // though it is not hashable.
24422446 Py_BEGIN_CRITICAL_SECTION (key );
24432447 hash = frozenset_hash_impl (key );
24442448 Py_END_CRITICAL_SECTION ();
2445- return set_contains_entry (so , key , hash );
24462449 }
24472450 return set_contains_entry (so , key , hash );
24482451}
0 commit comments