@@ -709,18 +709,20 @@ _shuffle_bits(Py_uhash_t h)
709
709
large primes with "interesting bit patterns" and that passed tests
710
710
for good collision statistics on a variety of problematic datasets
711
711
including powersets and graph structures (such as David Eppstein's
712
- graph recipes in Lib/test/test_set.py) */
712
+ graph recipes in Lib/test/test_set.py).
713
+
714
+ This hash algorithm can be used on either a frozenset or a set.
715
+ When it is used on a set, it computes the hash value of the equivalent
716
+ frozenset without creating a new frozenset object. */
713
717
714
718
static Py_hash_t
715
- frozenset_hash (PyObject * self )
719
+ frozenset_hash_impl (PyObject * self )
716
720
{
721
+ assert (PyAnySet_Check (self ));
717
722
PySetObject * so = (PySetObject * )self ;
718
723
Py_uhash_t hash = 0 ;
719
724
setentry * entry ;
720
725
721
- if (so -> hash != -1 )
722
- return so -> hash ;
723
-
724
726
/* Xor-in shuffled bits from every entry's hash field because xor is
725
727
commutative and a frozenset hash should be independent of order.
726
728
@@ -753,6 +755,20 @@ frozenset_hash(PyObject *self)
753
755
if (hash == (Py_uhash_t )- 1 )
754
756
hash = 590923713UL ;
755
757
758
+ return (Py_hash_t )hash ;
759
+ }
760
+
761
+ static Py_hash_t
762
+ frozenset_hash (PyObject * self )
763
+ {
764
+ PySetObject * so = (PySetObject * )self ;
765
+ Py_uhash_t hash ;
766
+
767
+ if (so -> hash != -1 ) {
768
+ return so -> hash ;
769
+ }
770
+
771
+ hash = frozenset_hash_impl (self );
756
772
so -> hash = hash ;
757
773
return hash ;
758
774
}
@@ -2137,19 +2153,18 @@ set_add_impl(PySetObject *so, PyObject *key)
2137
2153
static int
2138
2154
set_contains_lock_held (PySetObject * so , PyObject * key )
2139
2155
{
2140
- PyObject * tmpkey ;
2141
2156
int rv ;
2142
2157
2143
2158
rv = set_contains_key (so , key );
2144
2159
if (rv < 0 ) {
2145
2160
if (!PySet_Check (key ) || !PyErr_ExceptionMatches (PyExc_TypeError ))
2146
2161
return -1 ;
2147
2162
PyErr_Clear ();
2148
- tmpkey = make_new_set ( & PyFrozenSet_Type , key ) ;
2149
- if ( tmpkey == NULL )
2150
- return -1 ;
2151
- rv = set_contains_key ( so , tmpkey );
2152
- Py_DECREF ( tmpkey );
2163
+ Py_hash_t hash ;
2164
+ Py_BEGIN_CRITICAL_SECTION ( key );
2165
+ hash = frozenset_hash_impl ( key ) ;
2166
+ Py_END_CRITICAL_SECTION ( );
2167
+ rv = set_contains_entry ( so , key , hash );
2153
2168
}
2154
2169
return rv ;
2155
2170
}
@@ -2203,19 +2218,18 @@ static PyObject *
2203
2218
set_remove_impl (PySetObject * so , PyObject * key )
2204
2219
/*[clinic end generated code: output=0b9134a2a2200363 input=893e1cb1df98227a]*/
2205
2220
{
2206
- PyObject * tmpkey ;
2207
2221
int rv ;
2208
2222
2209
2223
rv = set_discard_key (so , key );
2210
2224
if (rv < 0 ) {
2211
2225
if (!PySet_Check (key ) || !PyErr_ExceptionMatches (PyExc_TypeError ))
2212
2226
return NULL ;
2213
2227
PyErr_Clear ();
2214
- tmpkey = make_new_set ( & PyFrozenSet_Type , key ) ;
2215
- if ( tmpkey == NULL )
2216
- return NULL ;
2217
- rv = set_discard_key ( so , tmpkey );
2218
- Py_DECREF ( tmpkey );
2228
+ Py_hash_t hash ;
2229
+ Py_BEGIN_CRITICAL_SECTION ( key );
2230
+ hash = frozenset_hash_impl ( key ) ;
2231
+ Py_END_CRITICAL_SECTION ( );
2232
+ rv = set_discard_entry ( so , key , hash );
2219
2233
if (rv < 0 )
2220
2234
return NULL ;
2221
2235
}
@@ -2244,19 +2258,18 @@ static PyObject *
2244
2258
set_discard_impl (PySetObject * so , PyObject * key )
2245
2259
/*[clinic end generated code: output=eec3b687bf32759e input=861cb7fb69b4def0]*/
2246
2260
{
2247
- PyObject * tmpkey ;
2248
2261
int rv ;
2249
2262
2250
2263
rv = set_discard_key (so , key );
2251
2264
if (rv < 0 ) {
2252
2265
if (!PySet_Check (key ) || !PyErr_ExceptionMatches (PyExc_TypeError ))
2253
2266
return NULL ;
2254
2267
PyErr_Clear ();
2255
- tmpkey = make_new_set ( & PyFrozenSet_Type , key ) ;
2256
- if ( tmpkey == NULL )
2257
- return NULL ;
2258
- rv = set_discard_key ( so , tmpkey );
2259
- Py_DECREF ( tmpkey );
2268
+ Py_hash_t hash ;
2269
+ Py_BEGIN_CRITICAL_SECTION ( key );
2270
+ hash = frozenset_hash_impl ( key ) ;
2271
+ Py_END_CRITICAL_SECTION ( );
2272
+ rv = set_discard_entry ( so , key , hash );
2260
2273
if (rv < 0 )
2261
2274
return NULL ;
2262
2275
}
0 commit comments