@@ -400,7 +400,7 @@ set_empty_to_minsize(PySetObject *so)
400
400
FT_ATOMIC_STORE_SSIZE_RELAXED (so -> used , 0 );
401
401
so -> mask = PySet_MINSIZE - 1 ;
402
402
so -> table = so -> smalltable ;
403
- so -> hash = -1 ;
403
+ FT_ATOMIC_STORE_SSIZE_RELAXED ( so -> hash , -1 ) ;
404
404
}
405
405
406
406
static int
@@ -718,18 +718,15 @@ _shuffle_bits(Py_uhash_t h)
718
718
large primes with "interesting bit patterns" and that passed tests
719
719
for good collision statistics on a variety of problematic datasets
720
720
including powersets and graph structures (such as David Eppstein's
721
- graph recipes in Lib/test/test_set.py) */
721
+ graph recipes in Lib/test/test_set.py). */
722
722
723
723
static Py_hash_t
724
- frozenset_hash (PyObject * self )
724
+ frozenset_hash_impl (PyObject * self )
725
725
{
726
- PySetObject * so = ( PySetObject * ) self ;
726
+ PySetObject * so = _PySet_CAST ( self ) ;
727
727
Py_uhash_t hash = 0 ;
728
728
setentry * entry ;
729
729
730
- if (so -> hash != -1 )
731
- return so -> hash ;
732
-
733
730
/* Xor-in shuffled bits from every entry's hash field because xor is
734
731
commutative and a frozenset hash should be independent of order.
735
732
@@ -762,7 +759,21 @@ frozenset_hash(PyObject *self)
762
759
if (hash == (Py_uhash_t )- 1 )
763
760
hash = 590923713UL ;
764
761
765
- so -> hash = hash ;
762
+ return (Py_hash_t )hash ;
763
+ }
764
+
765
+ static Py_hash_t
766
+ frozenset_hash (PyObject * self )
767
+ {
768
+ PySetObject * so = _PySet_CAST (self );
769
+ Py_uhash_t hash ;
770
+
771
+ if (FT_ATOMIC_LOAD_SSIZE_RELAXED (so -> hash ) != -1 ) {
772
+ return FT_ATOMIC_LOAD_SSIZE_RELAXED (so -> hash );
773
+ }
774
+
775
+ hash = frozenset_hash_impl (self );
776
+ FT_ATOMIC_STORE_SSIZE_RELAXED (so -> hash , hash );
766
777
return hash ;
767
778
}
768
779
@@ -1202,10 +1213,12 @@ set_swap_bodies(PySetObject *a, PySetObject *b)
1202
1213
1203
1214
if (PyType_IsSubtype (Py_TYPE (a ), & PyFrozenSet_Type ) &&
1204
1215
PyType_IsSubtype (Py_TYPE (b ), & PyFrozenSet_Type )) {
1205
- h = a -> hash ; a -> hash = b -> hash ; b -> hash = h ;
1216
+ h = FT_ATOMIC_LOAD_SSIZE_RELAXED (a -> hash );
1217
+ FT_ATOMIC_STORE_SSIZE_RELAXED (a -> hash , FT_ATOMIC_LOAD_SSIZE_RELAXED (b -> hash ));
1218
+ FT_ATOMIC_STORE_SSIZE_RELAXED (b -> hash , h );
1206
1219
} else {
1207
- a -> hash = -1 ;
1208
- b -> hash = -1 ;
1220
+ FT_ATOMIC_STORE_SSIZE_RELAXED ( a -> hash , -1 ) ;
1221
+ FT_ATOMIC_STORE_SSIZE_RELAXED ( b -> hash , -1 ) ;
1209
1222
}
1210
1223
}
1211
1224
@@ -2086,9 +2099,9 @@ set_richcompare(PySetObject *v, PyObject *w, int op)
2086
2099
case Py_EQ :
2087
2100
if (PySet_GET_SIZE (v ) != PySet_GET_SIZE (w ))
2088
2101
Py_RETURN_FALSE ;
2089
- if (v -> hash != -1 &&
2090
- (( PySetObject * )w )-> hash != -1 &&
2091
- v -> hash != (( PySetObject * ) w ) -> hash )
2102
+ Py_hash_t v_hash = FT_ATOMIC_LOAD_SSIZE_RELAXED (v -> hash );
2103
+ Py_hash_t w_hash = FT_ATOMIC_LOAD_SSIZE_RELAXED ((( PySetObject * )w )-> hash );
2104
+ if ( v_hash != -1 && w_hash != -1 && v_hash != w_hash )
2092
2105
Py_RETURN_FALSE ;
2093
2106
return set_issubset (v , w );
2094
2107
case Py_NE :
0 commit comments