Coverage Report

Created: 2026-01-09 06:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/Objects/setobject.c
Line
Count
Source
1
2
/* set object implementation
3
4
   Written and maintained by Raymond D. Hettinger <python@rcn.com>
5
   Derived from Objects/dictobject.c.
6
7
   The basic lookup function used by all operations.
8
   This is based on Algorithm D from Knuth Vol. 3, Sec. 6.4.
9
10
   The initial probe index is computed as hash mod the table size.
11
   Subsequent probe indices are computed as explained in Objects/dictobject.c.
12
13
   To improve cache locality, each probe inspects a series of consecutive
14
   nearby entries before moving on to probes elsewhere in memory.  This leaves
15
   us with a hybrid of linear probing and randomized probing.  The linear probing
16
   reduces the cost of hash collisions because consecutive memory accesses
17
   tend to be much cheaper than scattered probes.  After LINEAR_PROBES steps,
18
   we then use more of the upper bits from the hash value and apply a simple
19
   linear congruential random number generator.  This helps break-up long
20
   chains of collisions.
21
22
   All arithmetic on hash should ignore overflow.
23
24
   Unlike the dictionary implementation, the lookkey function can return
25
   NULL if the rich comparison returns an error.
26
27
   Use cases for sets differ considerably from dictionaries where looked-up
28
   keys are more likely to be present.  In contrast, sets are primarily
29
   about membership testing where the presence of an element is not known in
30
   advance.  Accordingly, the set implementation needs to optimize for both
31
   the found and not-found case.
32
*/
33
34
#include "Python.h"
35
#include "pycore_ceval.h"               // _PyEval_GetBuiltin()
36
#include "pycore_critical_section.h"    // Py_BEGIN_CRITICAL_SECTION, Py_END_CRITICAL_SECTION
37
#include "pycore_dict.h"                // _PyDict_Contains_KnownHash()
38
#include "pycore_modsupport.h"          // _PyArg_NoKwnames()
39
#include "pycore_object.h"              // _PyObject_GC_UNTRACK()
40
#include "pycore_pyatomic_ft_wrappers.h"  // FT_ATOMIC_LOAD_SSIZE_RELAXED()
41
#include "pycore_pyerrors.h"            // _PyErr_SetKeyError()
42
#include "pycore_setobject.h"           // _PySet_NextEntry() definition
43
#include "pycore_weakref.h"             // FT_CLEAR_WEAKREFS()
44
45
#include "stringlib/eq.h"               // unicode_eq()
46
#include <stddef.h>                     // offsetof()
47
#include "clinic/setobject.c.h"
48
49
/*[clinic input]
50
class set "PySetObject *" "&PySet_Type"
51
class frozenset "PySetObject *" "&PyFrozenSet_Type"
52
[clinic start generated code]*/
53
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=97ad1d3e9f117079]*/
54
55
/*[python input]
56
class setobject_converter(self_converter):
57
    type = "PySetObject *"
58
[python start generated code]*/
59
/*[python end generated code: output=da39a3ee5e6b4b0d input=33a44506d4d57793]*/
60
61
/* Object used as dummy key to fill deleted entries */
62
static PyObject _dummy_struct;
63
64
5.58M
#define dummy (&_dummy_struct)
65
66
106M
#define SET_LOOKKEY_FOUND 1
67
486M
#define SET_LOOKKEY_NO_MATCH 0
68
0
#define SET_LOOKKEY_ERROR (-1)
69
85.6M
#define SET_LOOKKEY_CHANGED (-2)
70
409M
#define SET_LOOKKEY_EMPTY (-3)
71
72
typedef int (*compare_func)(PySetObject *so, setentry *table, setentry *ep,
73
                            PyObject *key, Py_hash_t hash);
74
75
#ifdef Py_GIL_DISABLED
76
77
#define SET_IS_SHARED(so) _PyObject_GC_IS_SHARED(so)
78
#define SET_MARK_SHARED(so) _PyObject_GC_SET_SHARED(so)
79
80
static void
81
ensure_shared_on_read(PySetObject *so)
82
{
83
    if (!_Py_IsOwnedByCurrentThread((PyObject *)so) && !SET_IS_SHARED(so)) {
84
        // The first time we access a set from a non-owning thread we mark it
85
        // as shared. This ensures that a concurrent resize operation will
86
        // delay freeing the old entries using QSBR, which is necessary
87
        // to safely allow concurrent reads without locking...
88
        Py_BEGIN_CRITICAL_SECTION(so);
89
        if (!SET_IS_SHARED(so)) {
90
            SET_MARK_SHARED(so);
91
        }
92
        Py_END_CRITICAL_SECTION();
93
    }
94
}
95
96
static inline Py_ALWAYS_INLINE int
97
set_compare_threadsafe(PySetObject *so, setentry *table, setentry *ep,
98
                       PyObject *key, Py_hash_t hash)
99
{
100
    PyObject *startkey = FT_ATOMIC_LOAD_PTR_ACQUIRE(ep->key);
101
    if (startkey == NULL) {
102
        return SET_LOOKKEY_EMPTY;
103
    }
104
    if (startkey == key) {
105
        return SET_LOOKKEY_FOUND;
106
    }
107
    Py_ssize_t ep_hash = FT_ATOMIC_LOAD_SSIZE_ACQUIRE(ep->hash);
108
    if (ep_hash == hash) {
109
        if (!_Py_TryIncrefCompare(&ep->key, startkey)) {
110
            return SET_LOOKKEY_CHANGED;
111
        }
112
        int cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
113
        Py_DECREF(startkey);
114
        if (cmp < 0) {
115
            return SET_LOOKKEY_ERROR;
116
        }
117
        if (table == FT_ATOMIC_LOAD_PTR_ACQUIRE(so->table) &&
118
            startkey == FT_ATOMIC_LOAD_PTR_ACQUIRE(ep->key)) {
119
            assert(cmp == SET_LOOKKEY_FOUND || cmp == SET_LOOKKEY_NO_MATCH);
120
            return cmp;
121
        }
122
        else {
123
            /* The set was mutated, restart */
124
            return SET_LOOKKEY_CHANGED;
125
        }
126
    }
127
    return SET_LOOKKEY_NO_MATCH;
128
}
129
130
#else
131
132
28.1k
#define SET_IS_SHARED(so) 0
133
#define SET_MARK_SHARED(so)
134
135
#endif
136
137
static inline Py_ALWAYS_INLINE int
138
set_compare_entry_lock_held(PySetObject *so, setentry *table, setentry *entry,
139
                            PyObject *key, Py_hash_t hash)
140
102M
{
141
102M
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
142
102M
    if (entry->hash == 0 && entry->key == NULL)
143
38.1M
        return SET_LOOKKEY_EMPTY;
144
64.2M
    if (entry->hash == hash) {
145
47.4M
        PyObject *startkey = entry->key;
146
47.4M
        assert(startkey != dummy);
147
47.4M
        if (startkey == key)
148
47.4M
            return SET_LOOKKEY_FOUND;
149
20.3k
        if (PyUnicode_CheckExact(startkey)
150
20.3k
            && PyUnicode_CheckExact(key)
151
5.69k
            && unicode_eq(startkey, key))
152
5.69k
            return SET_LOOKKEY_FOUND;
153
14.6k
        table = so->table;
154
14.6k
        Py_INCREF(startkey);
155
14.6k
        int cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
156
14.6k
        Py_DECREF(startkey);
157
14.6k
        if (cmp < 0)
158
0
            return SET_LOOKKEY_ERROR;
159
14.6k
        if (table != so->table || entry->key != startkey)
160
0
            return SET_LOOKKEY_CHANGED;
161
14.6k
        if (cmp > 0)
162
14.6k
            return SET_LOOKKEY_FOUND;
163
14.6k
    }
164
16.8M
    return SET_LOOKKEY_NO_MATCH;
165
64.2M
}
166
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.
171
static inline Py_ALWAYS_INLINE int
172
set_compare_frozenset(PySetObject *so, setentry *table, setentry *ep,
173
                                 PyObject *key, Py_hash_t hash)
174
193M
{
175
193M
    assert(PyFrozenSet_Check(so));
176
193M
    PyObject *startkey = ep->key;
177
193M
    if (startkey == NULL) {
178
113M
        return SET_LOOKKEY_EMPTY;
179
113M
    }
180
80.1M
    if (startkey == key) {
181
58.6M
        return SET_LOOKKEY_FOUND;
182
58.6M
    }
183
21.5M
    Py_ssize_t ep_hash = ep->hash;
184
21.5M
    if (ep_hash == hash) {
185
455
        int cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
186
455
        if (cmp < 0) {
187
0
            return SET_LOOKKEY_ERROR;
188
0
        }
189
455
        assert(cmp == SET_LOOKKEY_FOUND || cmp == SET_LOOKKEY_NO_MATCH);
190
455
        return cmp;
191
455
    }
192
21.5M
    return SET_LOOKKEY_NO_MATCH;
193
21.5M
}
194
195
static void
196
set_zero_table(setentry *table, size_t size)
197
34.9k
{
198
#ifdef Py_GIL_DISABLED
199
    for (size_t i = 0; i < size; i++) {
200
        setentry *entry = &table[i];
201
        FT_ATOMIC_STORE_SSIZE_RELAXED(entry->hash, 0);
202
        FT_ATOMIC_STORE_PTR_RELEASE(entry->key, NULL);
203
    }
204
#else
205
34.9k
    memset(table, 0, sizeof(setentry)*size);
206
34.9k
#endif
207
34.9k
}
208
209
/* ======================================================================== */
210
/* ======= Begin logic for probing the hash table ========================= */
211
212
/* Set this to zero to turn-off linear probing */
213
#ifndef LINEAR_PROBES
214
381M
#define LINEAR_PROBES 9
215
#endif
216
217
/* This must be >= 1 */
218
10.9M
#define PERTURB_SHIFT 5
219
220
static int
221
set_do_lookup(PySetObject *so, setentry *table, size_t mask, PyObject *key,
222
              Py_hash_t hash, setentry **epp, compare_func compare_entry)
223
257M
{
224
257M
    setentry *entry;
225
257M
    size_t perturb = hash;
226
257M
    size_t i = (size_t)hash & mask; /* Unsigned for defined overflow behavior */
227
257M
    int probes;
228
257M
    int status;
229
230
268M
    while (1) {
231
268M
        entry = &table[i];
232
268M
        probes = (i + LINEAR_PROBES <= mask) ? LINEAR_PROBES: 0;
233
296M
        do {
234
296M
            status = compare_entry(so, table, entry, key, hash);
235
296M
            if (status != SET_LOOKKEY_NO_MATCH) {
236
257M
                if (status == SET_LOOKKEY_EMPTY) {
237
151M
                    return SET_LOOKKEY_NO_MATCH;
238
151M
                }
239
106M
                *epp = entry;
240
106M
                return status;
241
257M
            }
242
38.3M
            entry++;
243
38.3M
        } while (probes--);
244
10.8M
        perturb >>= PERTURB_SHIFT;
245
10.8M
        i = (i * 5 + 1 + perturb) & mask;
246
10.8M
    }
247
257M
    Py_UNREACHABLE();
248
257M
}
249
250
static int set_table_resize(PySetObject *, Py_ssize_t);
251
252
static int
253
set_add_entry_takeref(PySetObject *so, PyObject *key, Py_hash_t hash)
254
7.09M
{
255
7.09M
    setentry *table;
256
7.09M
    setentry *freeslot;
257
7.09M
    setentry *entry;
258
7.09M
    size_t perturb;
259
7.09M
    size_t mask;
260
7.09M
    size_t i;                       /* Unsigned for defined overflow behavior */
261
7.09M
    int probes;
262
7.09M
    int cmp;
263
264
7.09M
  restart:
265
266
7.09M
    mask = so->mask;
267
7.09M
    i = (size_t)hash & mask;
268
7.09M
    freeslot = NULL;
269
7.09M
    perturb = hash;
270
271
7.20M
    while (1) {
272
7.20M
        entry = &so->table[i];
273
7.20M
        probes = (i + LINEAR_PROBES <= mask) ? LINEAR_PROBES: 0;
274
9.61M
        do {
275
9.61M
            if (entry->hash == 0 && entry->key == NULL)
276
2.10M
                goto found_unused_or_dummy;
277
7.50M
            if (entry->hash == hash) {
278
4.99M
                PyObject *startkey = entry->key;
279
4.99M
                assert(startkey != dummy);
280
4.99M
                if (startkey == key)
281
49.3k
                    goto found_active;
282
4.94M
                if (PyUnicode_CheckExact(startkey)
283
4.94M
                    && PyUnicode_CheckExact(key)
284
479k
                    && unicode_eq(startkey, key))
285
479k
                    goto found_active;
286
4.46M
                table = so->table;
287
4.46M
                Py_INCREF(startkey);
288
4.46M
                cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
289
4.46M
                Py_DECREF(startkey);
290
4.46M
                if (cmp > 0)
291
4.46M
                    goto found_active;
292
167
                if (cmp < 0)
293
0
                    goto comparison_error;
294
167
                if (table != so->table || entry->key != startkey)
295
0
                    goto restart;
296
167
                mask = so->mask;
297
167
            }
298
2.51M
            else if (entry->hash == -1) {
299
0
                assert (entry->key == dummy);
300
0
                freeslot = entry;
301
0
            }
302
2.51M
            entry++;
303
2.51M
        } while (probes--);
304
103k
        perturb >>= PERTURB_SHIFT;
305
103k
        i = (i * 5 + 1 + perturb) & mask;
306
103k
    }
307
308
2.10M
  found_unused_or_dummy:
309
2.10M
    if (freeslot == NULL)
310
2.10M
        goto found_unused;
311
0
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used + 1);
312
0
    FT_ATOMIC_STORE_SSIZE_RELAXED(freeslot->hash, hash);
313
0
    FT_ATOMIC_STORE_PTR_RELEASE(freeslot->key, key);
314
0
    return 0;
315
316
2.10M
  found_unused:
317
2.10M
    so->fill++;
318
2.10M
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used + 1);
319
2.10M
    FT_ATOMIC_STORE_SSIZE_RELAXED(entry->hash, hash);
320
2.10M
    FT_ATOMIC_STORE_PTR_RELEASE(entry->key, key);
321
2.10M
    if ((size_t)so->fill*5 < mask*3)
322
2.08M
        return 0;
323
21.6k
    return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4);
324
325
4.99M
  found_active:
326
4.99M
    Py_DECREF(key);
327
4.99M
    return 0;
328
329
0
  comparison_error:
330
0
    Py_DECREF(key);
331
0
    return -1;
332
2.10M
}
333
334
static int
335
set_add_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
336
7.09M
{
337
7.09M
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
338
339
7.09M
    return set_add_entry_takeref(so, Py_NewRef(key), hash);
340
7.09M
}
341
342
static void
343
set_unhashable_type(PyObject *key)
344
0
{
345
0
    PyObject *exc = PyErr_GetRaisedException();
346
0
    assert(exc != NULL);
347
0
    if (!Py_IS_TYPE(exc, (PyTypeObject*)PyExc_TypeError)) {
348
0
        PyErr_SetRaisedException(exc);
349
0
        return;
350
0
    }
351
352
0
    PyErr_Format(PyExc_TypeError,
353
0
                 "cannot use '%T' as a set element (%S)",
354
0
                 key, exc);
355
0
    Py_DECREF(exc);
356
0
}
357
358
int
359
_PySet_AddTakeRef(PySetObject *so, PyObject *key)
360
3.58k
{
361
3.58k
    Py_hash_t hash = _PyObject_HashFast(key);
362
3.58k
    if (hash == -1) {
363
0
        set_unhashable_type(key);
364
0
        Py_DECREF(key);
365
0
        return -1;
366
0
    }
367
    // We don't pre-increment here, the caller holds a strong
368
    // reference to the object which we are stealing.
369
3.58k
    return set_add_entry_takeref(so, key, hash);
370
3.58k
}
371
372
/*
373
Internal routine used by set_table_resize() to insert an item which is
374
known to be absent from the set.  Besides the performance benefit,
375
there is also safety benefit since using set_add_entry() risks making
376
a callback in the middle of a set_table_resize(), see issue 1456209.
377
The caller is responsible for updating the key's reference count and
378
the setobject's fill and used fields.
379
*/
380
static void
381
set_insert_clean(setentry *table, size_t mask, PyObject *key, Py_hash_t hash)
382
1.08M
{
383
1.08M
    setentry *entry;
384
1.08M
    size_t perturb = hash;
385
1.08M
    size_t i = (size_t)hash & mask;
386
1.08M
    size_t j;
387
388
1.08M
    while (1) {
389
1.08M
        entry = &table[i];
390
1.08M
        if (entry->key == NULL)
391
1.00M
            goto found_null;
392
80.4k
        if (i + LINEAR_PROBES <= mask) {
393
90.8k
            for (j = 0; j < LINEAR_PROBES; j++) {
394
90.8k
                entry++;
395
90.8k
                if (entry->key == NULL)
396
77.7k
                    goto found_null;
397
90.8k
            }
398
77.7k
        }
399
2.70k
        perturb >>= PERTURB_SHIFT;
400
2.70k
        i = (i * 5 + 1 + perturb) & mask;
401
2.70k
    }
402
1.08M
  found_null:
403
1.08M
    FT_ATOMIC_STORE_SSIZE_RELAXED(entry->hash, hash);
404
1.08M
    FT_ATOMIC_STORE_PTR_RELEASE(entry->key, key);
405
1.08M
}
406
407
/* ======== End logic for probing the hash table ========================== */
408
/* ======================================================================== */
409
410
static int
411
set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash, setentry **epp)
412
257M
{
413
257M
    int status;
414
257M
    if (PyFrozenSet_CheckExact(so)) {
415
172M
        status = set_do_lookup(so, so->table, so->mask, key, hash, epp,
416
172M
                               set_compare_frozenset);
417
172M
    }
418
85.6M
    else {
419
85.6M
        Py_BEGIN_CRITICAL_SECTION(so);
420
85.6M
        do {
421
85.6M
            status = set_do_lookup(so, so->table, so->mask, key, hash, epp,
422
85.6M
                                   set_compare_entry_lock_held);
423
85.6M
        } while (status == SET_LOOKKEY_CHANGED);
424
85.6M
        Py_END_CRITICAL_SECTION();
425
85.6M
    }
426
257M
    assert(status == SET_LOOKKEY_FOUND ||
427
257M
           status == SET_LOOKKEY_NO_MATCH ||
428
257M
           status == SET_LOOKKEY_ERROR);
429
257M
    return status;
430
257M
}
431
432
#ifdef Py_GIL_DISABLED
433
static int
434
set_lookkey_threadsafe(PySetObject *so, PyObject *key, Py_hash_t hash)
435
{
436
    int status;
437
    setentry *entry;
438
    if (PyFrozenSet_CheckExact(so)) {
439
        status = set_do_lookup(so, so->table, so->mask, key, hash, &entry,
440
                               set_compare_frozenset);
441
        assert(status == SET_LOOKKEY_FOUND ||
442
               status == SET_LOOKKEY_NO_MATCH ||
443
               status == SET_LOOKKEY_ERROR);
444
        return status;
445
    }
446
    ensure_shared_on_read(so);
447
    setentry *table = FT_ATOMIC_LOAD_PTR_ACQUIRE(so->table);
448
    size_t mask = FT_ATOMIC_LOAD_SSIZE_ACQUIRE(so->mask);
449
    if (table == NULL || table != FT_ATOMIC_LOAD_PTR_ACQUIRE(so->table)) {
450
        return set_lookkey(so, key, hash, &entry);
451
    }
452
    status = set_do_lookup(so, table, mask, key, hash, &entry,
453
                           set_compare_threadsafe);
454
    if (status == SET_LOOKKEY_CHANGED) {
455
        return set_lookkey(so, key, hash, &entry);
456
    }
457
    assert(status == SET_LOOKKEY_FOUND ||
458
           status == SET_LOOKKEY_NO_MATCH ||
459
           status == SET_LOOKKEY_ERROR);
460
    return status;
461
}
462
#endif
463
464
static void free_entries(setentry *entries, size_t size, bool use_qsbr)
465
28.1k
{
466
#ifdef Py_GIL_DISABLED
467
    if (use_qsbr) {
468
        _PyMem_FreeDelayed(entries, size * sizeof(setentry));
469
        return;
470
    }
471
#endif
472
28.1k
    PyMem_Free(entries);
473
28.1k
}
474
475
/*
476
Restructure the table by allocating a new table and reinserting all
477
keys again.  When entries have been deleted, the new table may
478
actually be smaller than the old one.
479
*/
480
static int
481
set_table_resize(PySetObject *so, Py_ssize_t minused)
482
28.9k
{
483
28.9k
    setentry *oldtable, *newtable, *entry;
484
28.9k
    Py_ssize_t oldmask = so->mask;
485
28.9k
    Py_ssize_t oldsize = (size_t)oldmask + 1;
486
28.9k
    size_t newmask;
487
28.9k
    int is_oldtable_malloced;
488
28.9k
    setentry small_copy[PySet_MINSIZE];
489
490
28.9k
    assert(minused >= 0);
491
492
    /* Find the smallest table size > minused. */
493
    /* XXX speed-up with intrinsics */
494
28.9k
    size_t newsize = PySet_MINSIZE;
495
105k
    while (newsize <= (size_t)minused) {
496
76.1k
        newsize <<= 1; // The largest possible value is PY_SSIZE_T_MAX + 1.
497
76.1k
    }
498
499
    /* Get space for a new table. */
500
28.9k
    oldtable = so->table;
501
28.9k
    assert(oldtable != NULL);
502
28.9k
    is_oldtable_malloced = oldtable != so->smalltable;
503
504
28.9k
    if (newsize == PySet_MINSIZE) {
505
        /* A large table is shrinking, or we can't get any smaller. */
506
0
        newtable = so->smalltable;
507
0
        if (newtable == oldtable) {
508
0
            if (so->fill == so->used) {
509
                /* No dummies, so no point doing anything. */
510
0
                return 0;
511
0
            }
512
            /* We're not going to resize it, but rebuild the
513
               table anyway to purge old dummy entries.
514
               Subtle:  This is *necessary* if fill==size,
515
               as set_lookkey needs at least one virgin slot to
516
               terminate failing searches.  If fill < size, it's
517
               merely desirable, as dummies slow searches. */
518
0
            assert(so->fill > so->used);
519
0
            memcpy(small_copy, oldtable, sizeof(small_copy));
520
0
            oldtable = small_copy;
521
0
        }
522
0
    }
523
28.9k
    else {
524
28.9k
        newtable = PyMem_NEW(setentry, newsize);
525
28.9k
        if (newtable == NULL) {
526
0
            PyErr_NoMemory();
527
0
            return -1;
528
0
        }
529
28.9k
    }
530
531
    /* Make the set empty, using the new table. */
532
28.9k
    assert(newtable != oldtable);
533
28.9k
    set_zero_table(newtable, newsize);
534
28.9k
    FT_ATOMIC_STORE_PTR_RELEASE(so->table, NULL);
535
28.9k
    FT_ATOMIC_STORE_SSIZE_RELEASE(so->mask, newsize - 1);
536
537
    /* Copy the data over; this is refcount-neutral for active entries;
538
       dummy entries aren't copied over, of course */
539
28.9k
    newmask = (size_t)so->mask;
540
28.9k
    if (so->fill == so->used) {
541
1.86M
        for (entry = oldtable; entry <= oldtable + oldmask; entry++) {
542
1.83M
            if (entry->key != NULL) {
543
1.07M
                set_insert_clean(newtable, newmask, entry->key, entry->hash);
544
1.07M
            }
545
1.83M
        }
546
28.9k
    } else {
547
0
        so->fill = so->used;
548
0
        for (entry = oldtable; entry <= oldtable + oldmask; entry++) {
549
0
            if (entry->key != NULL && entry->key != dummy) {
550
0
                set_insert_clean(newtable, newmask, entry->key, entry->hash);
551
0
            }
552
0
        }
553
0
    }
554
555
28.9k
    FT_ATOMIC_STORE_PTR_RELEASE(so->table, newtable);
556
557
28.9k
    if (is_oldtable_malloced)
558
7.39k
        free_entries(oldtable, oldsize, SET_IS_SHARED(so));
559
28.9k
    return 0;
560
28.9k
}
561
562
static int
563
set_contains_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
564
257M
{
565
#ifdef Py_GIL_DISABLED
566
    return set_lookkey_threadsafe(so, key, hash);
567
#else
568
257M
    setentry *entry; // unused
569
257M
    return set_lookkey(so, key, hash, &entry);
570
257M
#endif
571
257M
}
572
573
85.0k
#define DISCARD_NOTFOUND 0
574
1.61k
#define DISCARD_FOUND 1
575
576
static int
577
set_discard_entry(PySetObject *so, PyObject *key, Py_hash_t hash)
578
86.6k
{
579
86.6k
    setentry *entry;
580
86.6k
    PyObject *old_key;
581
86.6k
    int status = set_lookkey(so, key, hash, &entry);
582
86.6k
    if (status < 0) {
583
0
        return -1;
584
0
    }
585
86.6k
    if (status == SET_LOOKKEY_NO_MATCH) {
586
85.0k
        return DISCARD_NOTFOUND;
587
85.0k
    }
588
86.6k
    assert(status == SET_LOOKKEY_FOUND);
589
1.61k
    old_key = entry->key;
590
1.61k
    FT_ATOMIC_STORE_SSIZE_RELAXED(entry->hash, -1);
591
1.61k
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used - 1);
592
1.61k
    FT_ATOMIC_STORE_PTR_RELEASE(entry->key, dummy);
593
1.61k
    Py_DECREF(old_key);
594
1.61k
    return DISCARD_FOUND;
595
86.6k
}
596
597
static int
598
set_add_key(PySetObject *so, PyObject *key)
599
7.04M
{
600
7.04M
    Py_hash_t hash = _PyObject_HashFast(key);
601
7.04M
    if (hash == -1) {
602
0
        set_unhashable_type(key);
603
0
        return -1;
604
0
    }
605
7.04M
    return set_add_entry(so, key, hash);
606
7.04M
}
607
608
static int
609
set_contains_key(PySetObject *so, PyObject *key)
610
6.54M
{
611
6.54M
    Py_hash_t hash = _PyObject_HashFast(key);
612
6.54M
    if (hash == -1) {
613
0
        set_unhashable_type(key);
614
0
        return -1;
615
0
    }
616
6.54M
    return set_contains_entry(so, key, hash);
617
6.54M
}
618
619
static int
620
set_discard_key(PySetObject *so, PyObject *key)
621
86.6k
{
622
86.6k
    Py_hash_t hash = _PyObject_HashFast(key);
623
86.6k
    if (hash == -1) {
624
0
        set_unhashable_type(key);
625
0
        return -1;
626
0
    }
627
86.6k
    return set_discard_entry(so, key, hash);
628
86.6k
}
629
630
static void
631
set_empty_to_minsize(PySetObject *so)
632
6.00k
{
633
6.00k
    FT_ATOMIC_STORE_PTR_RELEASE(so->table, NULL);
634
6.00k
    set_zero_table(so->smalltable, PySet_MINSIZE);
635
6.00k
    so->fill = 0;
636
6.00k
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, 0);
637
6.00k
    FT_ATOMIC_STORE_SSIZE_RELEASE(so->mask, PySet_MINSIZE - 1);
638
6.00k
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->hash, -1);
639
6.00k
    FT_ATOMIC_STORE_PTR_RELEASE(so->table, so->smalltable);
640
6.00k
}
641
642
static int
643
set_clear_internal(PyObject *self)
644
23.7k
{
645
23.7k
    PySetObject *so = _PySet_CAST(self);
646
23.7k
    setentry *entry;
647
23.7k
    setentry *table = so->table;
648
23.7k
    Py_ssize_t fill = so->fill;
649
23.7k
    Py_ssize_t used = so->used;
650
23.7k
    Py_ssize_t oldsize = (size_t)so->mask + 1;
651
23.7k
    int table_is_malloced = table != so->smalltable;
652
23.7k
    setentry small_copy[PySet_MINSIZE];
653
654
23.7k
    assert (PyAnySet_Check(so));
655
23.7k
    assert(table != NULL);
656
657
    /* This is delicate.  During the process of clearing the set,
658
     * decrefs can cause the set to mutate.  To avoid fatal confusion
659
     * (voice of experience), we have to make the set empty before
660
     * clearing the slots, and never refer to anything via so->ref while
661
     * clearing.
662
     */
663
23.7k
    if (table_is_malloced)
664
2.34k
        set_empty_to_minsize(so);
665
666
21.3k
    else if (fill > 0) {
667
        /* It's a small table with something that needs to be cleared.
668
         * Afraid the only safe way is to copy the set entries into
669
         * another small table first.
670
         */
671
3.66k
        memcpy(small_copy, table, sizeof(small_copy));
672
3.66k
        table = small_copy;
673
3.66k
        set_empty_to_minsize(so);
674
3.66k
    }
675
    /* else it's a small table that's already empty */
676
677
    /* Now we can finally clear things.  If C had refcounts, we could
678
     * assert that the refcount on table is 1 now, i.e. that this function
679
     * has unique access to it, so decref side-effects can't alter it.
680
     */
681
1.17M
    for (entry = table; used > 0; entry++) {
682
1.15M
        if (entry->key && entry->key != dummy) {
683
345k
            used--;
684
345k
            Py_DECREF(entry->key);
685
345k
        }
686
1.15M
    }
687
688
23.7k
    if (table_is_malloced)
689
2.34k
        free_entries(table, oldsize, SET_IS_SHARED(so));
690
23.7k
    return 0;
691
23.7k
}
692
693
/*
694
 * Iterate over a set table.  Use like so:
695
 *
696
 *     Py_ssize_t pos;
697
 *     setentry *entry;
698
 *     pos = 0;   # important!  pos should not otherwise be changed by you
699
 *     while (set_next(yourset, &pos, &entry)) {
700
 *              Refer to borrowed reference in entry->key.
701
 *     }
702
 *
703
 * CAUTION:  In general, it isn't safe to use set_next in a loop that
704
 * mutates the table.
705
 */
706
static int
707
set_next(PySetObject *so, Py_ssize_t *pos_ptr, setentry **entry_ptr)
708
5.50M
{
709
5.50M
    Py_ssize_t i;
710
5.50M
    Py_ssize_t mask;
711
5.50M
    setentry *entry;
712
713
5.50M
    assert (PyAnySet_Check(so));
714
5.50M
    i = *pos_ptr;
715
5.50M
    assert(i >= 0);
716
5.50M
    mask = so->mask;
717
5.50M
    entry = &so->table[i];
718
31.1M
    while (i <= mask && (entry->key == NULL || entry->key == dummy)) {
719
25.6M
        i++;
720
25.6M
        entry++;
721
25.6M
    }
722
5.50M
    *pos_ptr = i+1;
723
5.50M
    if (i > mask)
724
2.61M
        return 0;
725
5.50M
    assert(entry != NULL);
726
2.89M
    *entry_ptr = entry;
727
2.89M
    return 1;
728
5.50M
}
729
730
static void
731
set_dealloc(PyObject *self)
732
2.76M
{
733
2.76M
    PySetObject *so = _PySet_CAST(self);
734
2.76M
    setentry *entry;
735
2.76M
    Py_ssize_t used = so->used;
736
2.76M
    Py_ssize_t oldsize = (size_t)so->mask + 1;
737
738
    /* bpo-31095: UnTrack is needed before calling any callbacks */
739
2.76M
    PyObject_GC_UnTrack(so);
740
2.76M
    FT_CLEAR_WEAKREFS(self, so->weakreflist);
741
742
8.60M
    for (entry = so->table; used > 0; entry++) {
743
5.84M
        if (entry->key && entry->key != dummy) {
744
1.82M
                used--;
745
1.82M
                Py_DECREF(entry->key);
746
1.82M
        }
747
5.84M
    }
748
2.76M
    if (so->table != so->smalltable)
749
18.4k
        free_entries(so->table, oldsize, SET_IS_SHARED(so));
750
2.76M
    Py_TYPE(so)->tp_free(so);
751
2.76M
}
752
753
static PyObject *
754
set_repr_lock_held(PySetObject *so)
755
0
{
756
0
    PyObject *result=NULL, *keys, *listrepr, *tmp;
757
0
    int status = Py_ReprEnter((PyObject*)so);
758
759
0
    if (status != 0) {
760
0
        if (status < 0)
761
0
            return NULL;
762
0
        return PyUnicode_FromFormat("%s(...)", Py_TYPE(so)->tp_name);
763
0
    }
764
765
    /* shortcut for the empty set */
766
0
    if (!so->used) {
767
0
        Py_ReprLeave((PyObject*)so);
768
0
        return PyUnicode_FromFormat("%s()", Py_TYPE(so)->tp_name);
769
0
    }
770
771
    // gh-129967: avoid PySequence_List because it might re-lock the object
772
    // lock or the GIL and allow something to clear the set from underneath us.
773
0
    keys = PyList_New(so->used);
774
0
    if (keys == NULL) {
775
0
        goto done;
776
0
    }
777
778
0
    Py_ssize_t pos = 0, idx = 0;
779
0
    setentry *entry;
780
0
    while (set_next(so, &pos, &entry)) {
781
0
        PyList_SET_ITEM(keys, idx++, Py_NewRef(entry->key));
782
0
    }
783
784
    /* repr(keys)[1:-1] */
785
0
    listrepr = PyObject_Repr(keys);
786
0
    Py_DECREF(keys);
787
0
    if (listrepr == NULL)
788
0
        goto done;
789
0
    tmp = PyUnicode_Substring(listrepr, 1, PyUnicode_GET_LENGTH(listrepr)-1);
790
0
    Py_DECREF(listrepr);
791
0
    if (tmp == NULL)
792
0
        goto done;
793
0
    listrepr = tmp;
794
795
0
    if (!PySet_CheckExact(so))
796
0
        result = PyUnicode_FromFormat("%s({%U})",
797
0
                                      Py_TYPE(so)->tp_name,
798
0
                                      listrepr);
799
0
    else
800
0
        result = PyUnicode_FromFormat("{%U}", listrepr);
801
0
    Py_DECREF(listrepr);
802
0
done:
803
0
    Py_ReprLeave((PyObject*)so);
804
0
    return result;
805
0
}
806
807
static PyObject *
808
set_repr(PyObject *self)
809
0
{
810
0
    PySetObject *so = _PySet_CAST(self);
811
0
    PyObject *result;
812
0
    Py_BEGIN_CRITICAL_SECTION(so);
813
0
    result = set_repr_lock_held(so);
814
0
    Py_END_CRITICAL_SECTION();
815
0
    return result;
816
0
}
817
818
static Py_ssize_t
819
set_len(PyObject *self)
820
318k
{
821
318k
    PySetObject *so = _PySet_CAST(self);
822
318k
    return FT_ATOMIC_LOAD_SSIZE_RELAXED(so->used);
823
318k
}
824
825
static int
826
set_merge_lock_held(PySetObject *so, PyObject *otherset)
827
126k
{
828
126k
    PySetObject *other;
829
126k
    PyObject *key;
830
126k
    Py_ssize_t i;
831
126k
    setentry *so_entry;
832
126k
    setentry *other_entry;
833
834
126k
    assert (PyAnySet_Check(so));
835
126k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
836
126k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(otherset);
837
838
126k
    other = _PySet_CAST(otherset);
839
126k
    if (other == so || other->used == 0)
840
        /* a.update(a) or a.update(set()); nothing to do */
841
73.9k
        return 0;
842
    /* Do one big resize at the start, rather than
843
     * incrementally resizing as we insert new keys.  Expect
844
     * that there will be no (or few) overlapping keys.
845
     */
846
52.8k
    if ((so->fill + other->used)*5 >= so->mask*3) {
847
7.26k
        if (set_table_resize(so, (so->used + other->used)*2) != 0)
848
0
            return -1;
849
7.26k
    }
850
52.8k
    so_entry = so->table;
851
52.8k
    other_entry = other->table;
852
853
    /* If our table is empty, and both tables have the same size, and
854
       there are no dummies to eliminate, then just copy the pointers. */
855
52.8k
    if (so->fill == 0 && so->mask == other->mask && other->fill == other->used) {
856
384k
        for (i = 0; i <= other->mask; i++, so_entry++, other_entry++) {
857
348k
            key = other_entry->key;
858
348k
            if (key != NULL) {
859
89.2k
                assert(so_entry->key == NULL);
860
89.2k
                FT_ATOMIC_STORE_SSIZE_RELAXED(so_entry->hash, other_entry->hash);
861
89.2k
                FT_ATOMIC_STORE_PTR_RELEASE(so_entry->key, Py_NewRef(key));
862
89.2k
            }
863
348k
        }
864
35.7k
        so->fill = other->fill;
865
35.7k
        FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, other->used);
866
35.7k
        return 0;
867
35.7k
    }
868
869
    /* If our table is empty, we can use set_insert_clean() */
870
17.0k
    if (so->fill == 0) {
871
1.16k
        setentry *newtable = so->table;
872
1.16k
        size_t newmask = (size_t)so->mask;
873
1.16k
        so->fill = other->used;
874
1.16k
        FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, other->used);
875
45.2k
        for (i = other->mask + 1; i > 0 ; i--, other_entry++) {
876
44.1k
            key = other_entry->key;
877
44.1k
            if (key != NULL && key != dummy) {
878
9.36k
                set_insert_clean(newtable, newmask, Py_NewRef(key),
879
9.36k
                                 other_entry->hash);
880
9.36k
            }
881
44.1k
        }
882
1.16k
        return 0;
883
1.16k
    }
884
885
    /* We can't assure there are no duplicates, so do normal insertions */
886
179k
    for (i = 0; i <= other->mask; i++) {
887
163k
        other_entry = &other->table[i];
888
163k
        key = other_entry->key;
889
163k
        if (key != NULL && key != dummy) {
890
46.9k
            if (set_add_entry(so, key, other_entry->hash))
891
0
                return -1;
892
46.9k
        }
893
163k
    }
894
15.8k
    return 0;
895
15.8k
}
896
897
/*[clinic input]
898
@critical_section
899
set.pop
900
    so: setobject
901
902
Remove and return an arbitrary set element.
903
904
Raises KeyError if the set is empty.
905
[clinic start generated code]*/
906
907
static PyObject *
908
set_pop_impl(PySetObject *so)
909
/*[clinic end generated code: output=4d65180f1271871b input=9296c84921125060]*/
910
237
{
911
    /* Make sure the search finger is in bounds */
912
237
    setentry *entry = so->table + (so->finger & so->mask);
913
237
    setentry *limit = so->table + so->mask;
914
237
    PyObject *key;
915
916
237
    if (so->used == 0) {
917
0
        PyErr_SetString(PyExc_KeyError, "pop from an empty set");
918
0
        return NULL;
919
0
    }
920
706
    while (entry->key == NULL || entry->key==dummy) {
921
469
        entry++;
922
469
        if (entry > limit)
923
0
            entry = so->table;
924
469
    }
925
237
    FT_ATOMIC_STORE_SSIZE_RELAXED(entry->hash, -1);
926
237
    FT_ATOMIC_STORE_SSIZE_RELAXED(so->used, so->used - 1);
927
237
    key = entry->key;
928
237
    FT_ATOMIC_STORE_PTR_RELEASE(entry->key, dummy);
929
237
    so->finger = entry - so->table + 1;   /* next place to start */
930
237
    return key;
931
237
}
932
933
static int
934
set_traverse(PyObject *self, visitproc visit, void *arg)
935
2.59M
{
936
2.59M
    PySetObject *so = _PySet_CAST(self);
937
2.59M
    Py_ssize_t pos = 0;
938
2.59M
    setentry *entry;
939
940
5.39M
    while (set_next(so, &pos, &entry))
941
2.79M
        Py_VISIT(entry->key);
942
2.59M
    return 0;
943
2.59M
}
944
945
/* Work to increase the bit dispersion for closely spaced hash values.
946
   This is important because some use cases have many combinations of a
947
   small number of elements with nearby hashes so that many distinct
948
   combinations collapse to only a handful of distinct hash values. */
949
950
static Py_uhash_t
951
_shuffle_bits(Py_uhash_t h)
952
4.18k
{
953
4.18k
    return ((h ^ 89869747UL) ^ (h << 16)) * 3644798167UL;
954
4.18k
}
955
956
/* Most of the constants in this hash algorithm are randomly chosen
957
   large primes with "interesting bit patterns" and that passed tests
958
   for good collision statistics on a variety of problematic datasets
959
   including powersets and graph structures (such as David Eppstein's
960
   graph recipes in Lib/test/test_set.py).
961
962
   This hash algorithm can be used on either a frozenset or a set.
963
   When it is used on a set, it computes the hash value of the equivalent
964
   frozenset without creating a new frozenset object. */
965
966
static Py_hash_t
967
frozenset_hash_impl(PyObject *self)
968
210
{
969
210
    PySetObject *so = _PySet_CAST(self);
970
210
    Py_uhash_t hash = 0;
971
210
    setentry *entry;
972
973
    /* Xor-in shuffled bits from every entry's hash field because xor is
974
       commutative and a frozenset hash should be independent of order.
975
976
       For speed, include null entries and dummy entries and then
977
       subtract out their effect afterwards so that the final hash
978
       depends only on active entries.  This allows the code to be
979
       vectorized by the compiler and it saves the unpredictable
980
       branches that would arise when trying to exclude null and dummy
981
       entries on every iteration. */
982
983
4.33k
    for (entry = so->table; entry <= &so->table[so->mask]; entry++)
984
4.12k
        hash ^= _shuffle_bits(entry->hash);
985
986
    /* Remove the effect of an odd number of NULL entries */
987
210
    if ((so->mask + 1 - so->fill) & 1)
988
60
        hash ^= _shuffle_bits(0);
989
990
    /* Remove the effect of an odd number of dummy entries */
991
210
    if ((so->fill - so->used) & 1)
992
0
        hash ^= _shuffle_bits(-1);
993
994
    /* Factor in the number of active entries */
995
210
    hash ^= ((Py_uhash_t)PySet_GET_SIZE(self) + 1) * 1927868237UL;
996
997
    /* Disperse patterns arising in nested frozensets */
998
210
    hash ^= (hash >> 11) ^ (hash >> 25);
999
210
    hash = hash * 69069U + 907133923UL;
1000
1001
    /* -1 is reserved as an error code */
1002
210
    if (hash == (Py_uhash_t)-1)
1003
0
        hash = 590923713UL;
1004
1005
210
    return (Py_hash_t)hash;
1006
210
}
1007
1008
static Py_hash_t
1009
frozenset_hash(PyObject *self)
1010
350
{
1011
350
    PySetObject *so = _PySet_CAST(self);
1012
350
    Py_uhash_t hash;
1013
1014
350
    if (FT_ATOMIC_LOAD_SSIZE_RELAXED(so->hash) != -1) {
1015
140
        return FT_ATOMIC_LOAD_SSIZE_ACQUIRE(so->hash);
1016
140
    }
1017
1018
210
    hash = frozenset_hash_impl(self);
1019
210
    FT_ATOMIC_STORE_SSIZE_RELEASE(so->hash, hash);
1020
210
    return hash;
1021
350
}
1022
1023
/***** Set iterator type ***********************************************/
1024
1025
typedef struct {
1026
    PyObject_HEAD
1027
    PySetObject *si_set; /* Set to NULL when iterator is exhausted */
1028
    Py_ssize_t si_used;
1029
    Py_ssize_t si_pos;
1030
    Py_ssize_t len;
1031
} setiterobject;
1032
1033
static void
1034
setiter_dealloc(PyObject *self)
1035
302k
{
1036
302k
    setiterobject *si = (setiterobject*)self;
1037
    /* bpo-31095: UnTrack is needed before calling any callbacks */
1038
302k
    _PyObject_GC_UNTRACK(si);
1039
302k
    Py_XDECREF(si->si_set);
1040
302k
    PyObject_GC_Del(si);
1041
302k
}
1042
1043
static int
1044
setiter_traverse(PyObject *self, visitproc visit, void *arg)
1045
95
{
1046
95
    setiterobject *si = (setiterobject*)self;
1047
95
    Py_VISIT(si->si_set);
1048
95
    return 0;
1049
95
}
1050
1051
static PyObject *
1052
setiter_len(PyObject *op, PyObject *Py_UNUSED(ignored))
1053
10
{
1054
10
    setiterobject *si = (setiterobject*)op;
1055
10
    Py_ssize_t len = 0;
1056
10
    if (si->si_set != NULL && si->si_used == si->si_set->used)
1057
10
        len = si->len;
1058
10
    return PyLong_FromSsize_t(len);
1059
10
}
1060
1061
PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
1062
1063
static PyObject *
1064
setiter_reduce(PyObject *op, PyObject *Py_UNUSED(ignored))
1065
0
{
1066
0
    setiterobject *si = (setiterobject*)op;
1067
1068
    /* copy the iterator state */
1069
0
    setiterobject tmp = *si;
1070
0
    Py_XINCREF(tmp.si_set);
1071
1072
    /* iterate the temporary into a list */
1073
0
    PyObject *list = PySequence_List((PyObject*)&tmp);
1074
0
    Py_XDECREF(tmp.si_set);
1075
0
    if (list == NULL) {
1076
0
        return NULL;
1077
0
    }
1078
0
    return Py_BuildValue("N(N)", _PyEval_GetBuiltin(&_Py_ID(iter)), list);
1079
0
}
1080
1081
PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
1082
1083
static PyMethodDef setiter_methods[] = {
1084
    {"__length_hint__", setiter_len, METH_NOARGS, length_hint_doc},
1085
    {"__reduce__", setiter_reduce, METH_NOARGS, reduce_doc},
1086
    {NULL,              NULL}           /* sentinel */
1087
};
1088
1089
static PyObject *setiter_iternext(PyObject *self)
1090
765k
{
1091
765k
    setiterobject *si = (setiterobject*)self;
1092
765k
    PyObject *key = NULL;
1093
765k
    Py_ssize_t i, mask;
1094
765k
    setentry *entry;
1095
765k
    PySetObject *so = si->si_set;
1096
1097
765k
    if (so == NULL)
1098
0
        return NULL;
1099
765k
    assert (PyAnySet_Check(so));
1100
1101
765k
    Py_ssize_t so_used = FT_ATOMIC_LOAD_SSIZE_RELAXED(so->used);
1102
765k
    Py_ssize_t si_used = FT_ATOMIC_LOAD_SSIZE_RELAXED(si->si_used);
1103
765k
    if (si_used != so_used) {
1104
0
        PyErr_SetString(PyExc_RuntimeError,
1105
0
                        "Set changed size during iteration");
1106
0
        si->si_used = -1; /* Make this state sticky */
1107
0
        return NULL;
1108
0
    }
1109
1110
765k
    Py_BEGIN_CRITICAL_SECTION(so);
1111
765k
    i = si->si_pos;
1112
765k
    assert(i>=0);
1113
765k
    entry = so->table;
1114
765k
    mask = so->mask;
1115
3.77M
    while (i <= mask && (entry[i].key == NULL || entry[i].key == dummy)) {
1116
3.00M
        i++;
1117
3.00M
    }
1118
765k
    if (i <= mask) {
1119
462k
        key = Py_NewRef(entry[i].key);
1120
462k
    }
1121
765k
    Py_END_CRITICAL_SECTION();
1122
765k
    si->si_pos = i+1;
1123
765k
    if (key == NULL) {
1124
302k
        si->si_set = NULL;
1125
302k
        Py_DECREF(so);
1126
302k
        return NULL;
1127
302k
    }
1128
462k
    si->len--;
1129
462k
    return key;
1130
765k
}
1131
1132
PyTypeObject PySetIter_Type = {
1133
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
1134
    "set_iterator",                             /* tp_name */
1135
    sizeof(setiterobject),                      /* tp_basicsize */
1136
    0,                                          /* tp_itemsize */
1137
    /* methods */
1138
    setiter_dealloc,                            /* tp_dealloc */
1139
    0,                                          /* tp_vectorcall_offset */
1140
    0,                                          /* tp_getattr */
1141
    0,                                          /* tp_setattr */
1142
    0,                                          /* tp_as_async */
1143
    0,                                          /* tp_repr */
1144
    0,                                          /* tp_as_number */
1145
    0,                                          /* tp_as_sequence */
1146
    0,                                          /* tp_as_mapping */
1147
    0,                                          /* tp_hash */
1148
    0,                                          /* tp_call */
1149
    0,                                          /* tp_str */
1150
    PyObject_GenericGetAttr,                    /* tp_getattro */
1151
    0,                                          /* tp_setattro */
1152
    0,                                          /* tp_as_buffer */
1153
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
1154
    0,                                          /* tp_doc */
1155
    setiter_traverse,                           /* tp_traverse */
1156
    0,                                          /* tp_clear */
1157
    0,                                          /* tp_richcompare */
1158
    0,                                          /* tp_weaklistoffset */
1159
    PyObject_SelfIter,                          /* tp_iter */
1160
    setiter_iternext,                           /* tp_iternext */
1161
    setiter_methods,                            /* tp_methods */
1162
    0,
1163
};
1164
1165
static PyObject *
1166
set_iter(PyObject *so)
1167
302k
{
1168
302k
    Py_ssize_t size = set_len(so);
1169
302k
    setiterobject *si = PyObject_GC_New(setiterobject, &PySetIter_Type);
1170
302k
    if (si == NULL)
1171
0
        return NULL;
1172
302k
    si->si_set = (PySetObject*)Py_NewRef(so);
1173
302k
    si->si_used = size;
1174
302k
    si->si_pos = 0;
1175
302k
    si->len = size;
1176
302k
    _PyObject_GC_TRACK(si);
1177
302k
    return (PyObject *)si;
1178
302k
}
1179
1180
static int
1181
set_update_dict_lock_held(PySetObject *so, PyObject *other)
1182
180
{
1183
180
    assert(PyDict_CheckExact(other));
1184
1185
180
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1186
180
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(other);
1187
1188
    /* Do one big resize at the start, rather than
1189
    * incrementally resizing as we insert new keys.  Expect
1190
    * that there will be no (or few) overlapping keys.
1191
    */
1192
180
    Py_ssize_t dictsize = PyDict_GET_SIZE(other);
1193
180
    if ((so->fill + dictsize)*5 >= so->mask*3) {
1194
4
        if (set_table_resize(so, (so->used + dictsize)*2) != 0) {
1195
0
            return -1;
1196
0
        }
1197
4
    }
1198
1199
180
    Py_ssize_t pos = 0;
1200
180
    PyObject *key;
1201
180
    PyObject *value;
1202
180
    Py_hash_t hash;
1203
344
    while (_PyDict_Next(other, &pos, &key, &value, &hash)) {
1204
164
        if (set_add_entry(so, key, hash)) {
1205
0
            return -1;
1206
0
        }
1207
164
    }
1208
180
    return 0;
1209
180
}
1210
1211
static int
1212
set_update_iterable_lock_held(PySetObject *so, PyObject *other)
1213
14.7k
{
1214
14.7k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1215
1216
14.7k
    PyObject *it = PyObject_GetIter(other);
1217
14.7k
    if (it == NULL) {
1218
0
        return -1;
1219
0
    }
1220
1221
14.7k
    PyObject *key;
1222
76.5k
    while ((key = PyIter_Next(it)) != NULL) {
1223
61.7k
        if (set_add_key(so, key)) {
1224
0
            Py_DECREF(it);
1225
0
            Py_DECREF(key);
1226
0
            return -1;
1227
0
        }
1228
61.7k
        Py_DECREF(key);
1229
61.7k
    }
1230
14.7k
    Py_DECREF(it);
1231
14.7k
    if (PyErr_Occurred())
1232
0
        return -1;
1233
14.7k
    return 0;
1234
14.7k
}
1235
1236
static int
1237
set_update_lock_held(PySetObject *so, PyObject *other)
1238
0
{
1239
0
    if (PyAnySet_Check(other)) {
1240
0
        return set_merge_lock_held(so, other);
1241
0
    }
1242
0
    else if (PyDict_CheckExact(other)) {
1243
0
        return set_update_dict_lock_held(so, other);
1244
0
    }
1245
0
    return set_update_iterable_lock_held(so, other);
1246
0
}
1247
1248
// set_update for a `so` that is only visible to the current thread
1249
static int
1250
set_update_local(PySetObject *so, PyObject *other)
1251
71.1k
{
1252
71.1k
    assert(Py_REFCNT(so) == 1);
1253
71.1k
    if (PyAnySet_Check(other)) {
1254
56.2k
        int rv;
1255
56.2k
        Py_BEGIN_CRITICAL_SECTION(other);
1256
56.2k
        rv = set_merge_lock_held(so, other);
1257
56.2k
        Py_END_CRITICAL_SECTION();
1258
56.2k
        return rv;
1259
56.2k
    }
1260
14.9k
    else if (PyDict_CheckExact(other)) {
1261
180
        int rv;
1262
180
        Py_BEGIN_CRITICAL_SECTION(other);
1263
180
        rv = set_update_dict_lock_held(so, other);
1264
180
        Py_END_CRITICAL_SECTION();
1265
180
        return rv;
1266
180
    }
1267
14.7k
    return set_update_iterable_lock_held(so, other);
1268
71.1k
}
1269
1270
static int
1271
set_update_internal(PySetObject *so, PyObject *other)
1272
68.4k
{
1273
68.4k
    if (PyAnySet_Check(other)) {
1274
68.4k
        if (Py_Is((PyObject *)so, other)) {
1275
0
            return 0;
1276
0
        }
1277
68.4k
        int rv;
1278
68.4k
        Py_BEGIN_CRITICAL_SECTION2(so, other);
1279
68.4k
        rv = set_merge_lock_held(so, other);
1280
68.4k
        Py_END_CRITICAL_SECTION2();
1281
68.4k
        return rv;
1282
68.4k
    }
1283
0
    else if (PyDict_CheckExact(other)) {
1284
0
        int rv;
1285
0
        Py_BEGIN_CRITICAL_SECTION2(so, other);
1286
0
        rv = set_update_dict_lock_held(so, other);
1287
0
        Py_END_CRITICAL_SECTION2();
1288
0
        return rv;
1289
0
    }
1290
0
    else {
1291
0
        int rv;
1292
0
        Py_BEGIN_CRITICAL_SECTION(so);
1293
0
        rv = set_update_iterable_lock_held(so, other);
1294
0
        Py_END_CRITICAL_SECTION();
1295
0
        return rv;
1296
0
    }
1297
68.4k
}
1298
1299
/*[clinic input]
1300
set.update
1301
    so: setobject
1302
    *others: array
1303
1304
Update the set, adding elements from all others.
1305
[clinic start generated code]*/
1306
1307
static PyObject *
1308
set_update_impl(PySetObject *so, PyObject * const *others,
1309
                Py_ssize_t others_length)
1310
/*[clinic end generated code: output=017c781c992d5c23 input=ed5d78885b076636]*/
1311
0
{
1312
0
    Py_ssize_t i;
1313
1314
0
    for (i = 0; i < others_length; i++) {
1315
0
        PyObject *other = others[i];
1316
0
        if (set_update_internal(so, other))
1317
0
            return NULL;
1318
0
    }
1319
0
    Py_RETURN_NONE;
1320
0
}
1321
1322
/* XXX Todo:
1323
   If aligned memory allocations become available, make the
1324
   set object 64 byte aligned so that most of the fields
1325
   can be retrieved or updated in a single cache line.
1326
*/
1327
1328
static PyObject *
1329
make_new_set(PyTypeObject *type, PyObject *iterable)
1330
2.76M
{
1331
2.76M
    assert(PyType_Check(type));
1332
2.76M
    PySetObject *so;
1333
1334
2.76M
    so = (PySetObject *)type->tp_alloc(type, 0);
1335
2.76M
    if (so == NULL)
1336
0
        return NULL;
1337
1338
2.76M
    so->fill = 0;
1339
2.76M
    so->used = 0;
1340
2.76M
    so->mask = PySet_MINSIZE - 1;
1341
2.76M
    so->table = so->smalltable;
1342
2.76M
    so->hash = -1;
1343
2.76M
    so->finger = 0;
1344
2.76M
    so->weakreflist = NULL;
1345
1346
2.76M
    if (iterable != NULL) {
1347
71.1k
        if (set_update_local(so, iterable)) {
1348
0
            Py_DECREF(so);
1349
0
            return NULL;
1350
0
        }
1351
71.1k
    }
1352
1353
2.76M
    return (PyObject *)so;
1354
2.76M
}
1355
1356
static PyObject *
1357
make_new_set_basetype(PyTypeObject *type, PyObject *iterable)
1358
2.24k
{
1359
2.24k
    if (type != &PySet_Type && type != &PyFrozenSet_Type) {
1360
0
        if (PyType_IsSubtype(type, &PySet_Type))
1361
0
            type = &PySet_Type;
1362
0
        else
1363
0
            type = &PyFrozenSet_Type;
1364
0
    }
1365
2.24k
    return make_new_set(type, iterable);
1366
2.24k
}
1367
1368
static PyObject *
1369
make_new_frozenset(PyTypeObject *type, PyObject *iterable)
1370
333
{
1371
333
    if (type != &PyFrozenSet_Type) {
1372
0
        return make_new_set(type, iterable);
1373
0
    }
1374
1375
333
    if (iterable != NULL && PyFrozenSet_CheckExact(iterable)) {
1376
        /* frozenset(f) is idempotent */
1377
0
        return Py_NewRef(iterable);
1378
0
    }
1379
333
    return make_new_set(type, iterable);
1380
333
}
1381
1382
static PyObject *
1383
frozenset_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1384
0
{
1385
0
    PyObject *iterable = NULL;
1386
1387
0
    if ((type == &PyFrozenSet_Type ||
1388
0
         type->tp_init == PyFrozenSet_Type.tp_init) &&
1389
0
        !_PyArg_NoKeywords("frozenset", kwds)) {
1390
0
        return NULL;
1391
0
    }
1392
1393
0
    if (!PyArg_UnpackTuple(args, type->tp_name, 0, 1, &iterable)) {
1394
0
        return NULL;
1395
0
    }
1396
1397
0
    return make_new_frozenset(type, iterable);
1398
0
}
1399
1400
static PyObject *
1401
frozenset_vectorcall(PyObject *type, PyObject * const*args,
1402
                     size_t nargsf, PyObject *kwnames)
1403
333
{
1404
333
    if (!_PyArg_NoKwnames("frozenset", kwnames)) {
1405
0
        return NULL;
1406
0
    }
1407
1408
333
    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
1409
333
    if (!_PyArg_CheckPositional("frozenset", nargs, 0, 1)) {
1410
0
        return NULL;
1411
0
    }
1412
1413
333
    PyObject *iterable = (nargs ? args[0] : NULL);
1414
333
    return make_new_frozenset(_PyType_CAST(type), iterable);
1415
333
}
1416
1417
static PyObject *
1418
set_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1419
0
{
1420
0
    return make_new_set(type, NULL);
1421
0
}
1422
1423
#ifdef Py_GIL_DISABLED
1424
static void
1425
copy_small_table(setentry *dest, setentry *src)
1426
{
1427
    for (Py_ssize_t i = 0; i < PySet_MINSIZE; i++) {
1428
        _Py_atomic_store_ptr_release(&dest[i].key, src[i].key);
1429
        _Py_atomic_store_ssize_relaxed(&dest[i].hash, src[i].hash);
1430
    }
1431
}
1432
#endif
1433
1434
/* set_swap_bodies() switches the contents of any two sets by moving their
1435
   internal data pointers and, if needed, copying the internal smalltables.
1436
   Semantically equivalent to:
1437
1438
     t=set(a); a.clear(); a.update(b); b.clear(); b.update(t); del t
1439
1440
   The function always succeeds and it leaves both objects in a stable state.
1441
   Useful for operations that update in-place (by allowing an intermediate
1442
   result to be swapped into one of the original inputs).
1443
*/
1444
1445
static void
1446
set_swap_bodies(PySetObject *a, PySetObject *b)
1447
{
1448
    Py_ssize_t t;
1449
    setentry *u;
1450
    setentry tab[PySet_MINSIZE];
1451
    Py_hash_t h;
1452
1453
    setentry *a_table = a->table;
1454
    setentry *b_table = b->table;
1455
    FT_ATOMIC_STORE_PTR_RELEASE(a->table, NULL);
1456
    FT_ATOMIC_STORE_PTR_RELEASE(b->table, NULL);
1457
1458
    t = a->fill;     a->fill   = b->fill;        b->fill  = t;
1459
    t = a->used;
1460
    FT_ATOMIC_STORE_SSIZE_RELAXED(a->used, b->used);
1461
    FT_ATOMIC_STORE_SSIZE_RELAXED(b->used, t);
1462
    t = a->mask;
1463
    FT_ATOMIC_STORE_SSIZE_RELEASE(a->mask, b->mask);
1464
    FT_ATOMIC_STORE_SSIZE_RELEASE(b->mask, t);
1465
1466
    u = a_table;
1467
    if (a_table == a->smalltable)
1468
        u = b->smalltable;
1469
    a_table  = b_table;
1470
    if (b_table == b->smalltable)
1471
        a_table = a->smalltable;
1472
    b_table = u;
1473
1474
    if (a_table == a->smalltable || b_table == b->smalltable) {
1475
        memcpy(tab, a->smalltable, sizeof(tab));
1476
#ifndef Py_GIL_DISABLED
1477
        memcpy(a->smalltable, b->smalltable, sizeof(tab));
1478
        memcpy(b->smalltable, tab, sizeof(tab));
1479
#else
1480
        copy_small_table(a->smalltable, b->smalltable);
1481
        copy_small_table(b->smalltable, tab);
1482
#endif
1483
    }
1484
1485
    if (PyType_IsSubtype(Py_TYPE(a), &PyFrozenSet_Type)  &&
1486
        PyType_IsSubtype(Py_TYPE(b), &PyFrozenSet_Type)) {
1487
        h = FT_ATOMIC_LOAD_SSIZE_RELAXED(a->hash);
1488
        FT_ATOMIC_STORE_SSIZE_RELAXED(a->hash, FT_ATOMIC_LOAD_SSIZE_RELAXED(b->hash));
1489
        FT_ATOMIC_STORE_SSIZE_RELAXED(b->hash, h);
1490
    } else {
1491
        FT_ATOMIC_STORE_SSIZE_RELAXED(a->hash, -1);
1492
        FT_ATOMIC_STORE_SSIZE_RELAXED(b->hash, -1);
1493
    }
1494
    if (!SET_IS_SHARED(b) && SET_IS_SHARED(a)) {
1495
        SET_MARK_SHARED(b);
1496
    }
1497
    if (!SET_IS_SHARED(a) && SET_IS_SHARED(b)) {
1498
        SET_MARK_SHARED(a);
1499
    }
1500
    FT_ATOMIC_STORE_PTR_RELEASE(a->table, a_table);
1501
    FT_ATOMIC_STORE_PTR_RELEASE(b->table, b_table);
1502
}
1503
1504
/*[clinic input]
1505
@critical_section
1506
set.copy
1507
    so: setobject
1508
1509
Return a shallow copy of a set.
1510
[clinic start generated code]*/
1511
1512
static PyObject *
1513
set_copy_impl(PySetObject *so)
1514
/*[clinic end generated code: output=c9223a1e1cc6b041 input=c169a4fbb8209257]*/
1515
2.06k
{
1516
2.06k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1517
2.06k
    PyObject *copy = make_new_set_basetype(Py_TYPE(so), NULL);
1518
2.06k
    if (copy == NULL) {
1519
0
        return NULL;
1520
0
    }
1521
2.06k
    if (set_merge_lock_held((PySetObject *)copy, (PyObject *)so) < 0) {
1522
0
        Py_DECREF(copy);
1523
0
        return NULL;
1524
0
    }
1525
2.06k
    return copy;
1526
2.06k
}
1527
1528
/*[clinic input]
1529
@critical_section
1530
frozenset.copy
1531
    so: setobject
1532
1533
Return a shallow copy of a set.
1534
[clinic start generated code]*/
1535
1536
static PyObject *
1537
frozenset_copy_impl(PySetObject *so)
1538
/*[clinic end generated code: output=b356263526af9e70 input=fbf5bef131268dd7]*/
1539
0
{
1540
0
    if (PyFrozenSet_CheckExact(so)) {
1541
0
        return Py_NewRef(so);
1542
0
    }
1543
0
    return set_copy_impl(so);
1544
0
}
1545
1546
/*[clinic input]
1547
@critical_section
1548
set.clear
1549
    so: setobject
1550
1551
Remove all elements from this set.
1552
[clinic start generated code]*/
1553
1554
static PyObject *
1555
set_clear_impl(PySetObject *so)
1556
/*[clinic end generated code: output=4e71d5a83904161a input=c6f831b366111950]*/
1557
23.7k
{
1558
23.7k
    set_clear_internal((PyObject*)so);
1559
23.7k
    Py_RETURN_NONE;
1560
23.7k
}
1561
1562
/*[clinic input]
1563
set.union
1564
    so: setobject
1565
    *others: array
1566
1567
Return a new set with elements from the set and all others.
1568
[clinic start generated code]*/
1569
1570
static PyObject *
1571
set_union_impl(PySetObject *so, PyObject * const *others,
1572
               Py_ssize_t others_length)
1573
/*[clinic end generated code: output=b1bfa3d74065f27e input=55a2e81db6347a4f]*/
1574
2
{
1575
2
    PySetObject *result;
1576
2
    PyObject *other;
1577
2
    Py_ssize_t i;
1578
1579
2
    result = (PySetObject *)set_copy((PyObject *)so, NULL);
1580
2
    if (result == NULL)
1581
0
        return NULL;
1582
1583
4
    for (i = 0; i < others_length; i++) {
1584
2
        other = others[i];
1585
2
        if ((PyObject *)so == other)
1586
0
            continue;
1587
2
        if (set_update_local(result, other)) {
1588
0
            Py_DECREF(result);
1589
0
            return NULL;
1590
0
        }
1591
2
    }
1592
2
    return (PyObject *)result;
1593
2
}
1594
1595
static PyObject *
1596
set_or(PyObject *self, PyObject *other)
1597
64
{
1598
64
    PySetObject *result;
1599
1600
64
    if (!PyAnySet_Check(self) || !PyAnySet_Check(other))
1601
0
        Py_RETURN_NOTIMPLEMENTED;
1602
1603
64
    result = (PySetObject *)set_copy(self, NULL);
1604
64
    if (result == NULL) {
1605
0
        return NULL;
1606
0
    }
1607
64
    if (Py_Is(self, other)) {
1608
0
        return (PyObject *)result;
1609
0
    }
1610
64
    if (set_update_local(result, other)) {
1611
0
        Py_DECREF(result);
1612
0
        return NULL;
1613
0
    }
1614
64
    return (PyObject *)result;
1615
64
}
1616
1617
static PyObject *
1618
set_ior(PyObject *self, PyObject *other)
1619
68.4k
{
1620
68.4k
    if (!PyAnySet_Check(other))
1621
0
        Py_RETURN_NOTIMPLEMENTED;
1622
68.4k
    PySetObject *so = _PySet_CAST(self);
1623
1624
68.4k
    if (set_update_internal(so, other)) {
1625
0
        return NULL;
1626
0
    }
1627
68.4k
    return Py_NewRef(so);
1628
68.4k
}
1629
1630
static PyObject *
1631
set_intersection(PySetObject *so, PyObject *other)
1632
180
{
1633
180
    PySetObject *result;
1634
180
    PyObject *key, *it, *tmp;
1635
180
    Py_hash_t hash;
1636
180
    int rv;
1637
1638
180
    if ((PyObject *)so == other)
1639
0
        return set_copy_impl(so);
1640
1641
180
    result = (PySetObject *)make_new_set_basetype(Py_TYPE(so), NULL);
1642
180
    if (result == NULL)
1643
0
        return NULL;
1644
1645
180
    if (PyAnySet_Check(other)) {
1646
180
        Py_ssize_t pos = 0;
1647
180
        setentry *entry;
1648
1649
180
        if (PySet_GET_SIZE(other) > PySet_GET_SIZE(so)) {
1650
144
            tmp = (PyObject *)so;
1651
144
            so = (PySetObject *)other;
1652
144
            other = tmp;
1653
144
        }
1654
1655
252
        while (set_next((PySetObject *)other, &pos, &entry)) {
1656
72
            key = entry->key;
1657
72
            hash = entry->hash;
1658
72
            Py_INCREF(key);
1659
72
            rv = set_contains_entry(so, key, hash);
1660
72
            if (rv < 0) {
1661
0
                Py_DECREF(result);
1662
0
                Py_DECREF(key);
1663
0
                return NULL;
1664
0
            }
1665
72
            if (rv) {
1666
0
                if (set_add_entry(result, key, hash)) {
1667
0
                    Py_DECREF(result);
1668
0
                    Py_DECREF(key);
1669
0
                    return NULL;
1670
0
                }
1671
0
            }
1672
72
            Py_DECREF(key);
1673
72
        }
1674
180
        return (PyObject *)result;
1675
180
    }
1676
1677
0
    it = PyObject_GetIter(other);
1678
0
    if (it == NULL) {
1679
0
        Py_DECREF(result);
1680
0
        return NULL;
1681
0
    }
1682
1683
0
    while ((key = PyIter_Next(it)) != NULL) {
1684
0
        hash = PyObject_Hash(key);
1685
0
        if (hash == -1)
1686
0
            goto error;
1687
0
        rv = set_contains_entry(so, key, hash);
1688
0
        if (rv < 0)
1689
0
            goto error;
1690
0
        if (rv) {
1691
0
            if (set_add_entry(result, key, hash))
1692
0
                goto error;
1693
0
            if (PySet_GET_SIZE(result) >= PySet_GET_SIZE(so)) {
1694
0
                Py_DECREF(key);
1695
0
                break;
1696
0
            }
1697
0
        }
1698
0
        Py_DECREF(key);
1699
0
    }
1700
0
    Py_DECREF(it);
1701
0
    if (PyErr_Occurred()) {
1702
0
        Py_DECREF(result);
1703
0
        return NULL;
1704
0
    }
1705
0
    return (PyObject *)result;
1706
0
  error:
1707
0
    Py_DECREF(it);
1708
0
    Py_DECREF(result);
1709
0
    Py_DECREF(key);
1710
0
    return NULL;
1711
0
}
1712
1713
/*[clinic input]
1714
set.intersection as set_intersection_multi
1715
    so: setobject
1716
    *others: array
1717
1718
Return a new set with elements common to the set and all others.
1719
[clinic start generated code]*/
1720
1721
static PyObject *
1722
set_intersection_multi_impl(PySetObject *so, PyObject * const *others,
1723
                            Py_ssize_t others_length)
1724
/*[clinic end generated code: output=db9ff9f875132b6b input=36c7b615694cadae]*/
1725
0
{
1726
0
    Py_ssize_t i;
1727
1728
0
    if (others_length == 0) {
1729
0
        return set_copy((PyObject *)so, NULL);
1730
0
    }
1731
1732
0
    PyObject *result = Py_NewRef(so);
1733
0
    for (i = 0; i < others_length; i++) {
1734
0
        PyObject *other = others[i];
1735
0
        PyObject *newresult;
1736
0
        Py_BEGIN_CRITICAL_SECTION2(result, other);
1737
0
        newresult = set_intersection((PySetObject *)result, other);
1738
0
        Py_END_CRITICAL_SECTION2();
1739
0
        if (newresult == NULL) {
1740
0
            Py_DECREF(result);
1741
0
            return NULL;
1742
0
        }
1743
0
        Py_SETREF(result, newresult);
1744
0
    }
1745
0
    return result;
1746
0
}
1747
1748
static PyObject *
1749
set_intersection_update(PySetObject *so, PyObject *other)
1750
0
{
1751
0
    PyObject *tmp;
1752
1753
0
    tmp = set_intersection(so, other);
1754
0
    if (tmp == NULL)
1755
0
        return NULL;
1756
0
    set_swap_bodies(so, (PySetObject *)tmp);
1757
0
    Py_DECREF(tmp);
1758
0
    Py_RETURN_NONE;
1759
0
}
1760
1761
/*[clinic input]
1762
set.intersection_update as set_intersection_update_multi
1763
    so: setobject
1764
    *others: array
1765
1766
Update the set, keeping only elements found in it and all others.
1767
[clinic start generated code]*/
1768
1769
static PyObject *
1770
set_intersection_update_multi_impl(PySetObject *so, PyObject * const *others,
1771
                                   Py_ssize_t others_length)
1772
/*[clinic end generated code: output=d768b5584675b48d input=782e422fc370e4fc]*/
1773
0
{
1774
0
    PyObject *tmp;
1775
1776
0
    tmp = set_intersection_multi_impl(so, others, others_length);
1777
0
    if (tmp == NULL)
1778
0
        return NULL;
1779
0
    Py_BEGIN_CRITICAL_SECTION(so);
1780
0
    set_swap_bodies(so, (PySetObject *)tmp);
1781
0
    Py_END_CRITICAL_SECTION();
1782
0
    Py_DECREF(tmp);
1783
0
    Py_RETURN_NONE;
1784
0
}
1785
1786
static PyObject *
1787
set_and(PyObject *self, PyObject *other)
1788
180
{
1789
180
    if (!PyAnySet_Check(self) || !PyAnySet_Check(other))
1790
0
        Py_RETURN_NOTIMPLEMENTED;
1791
180
    PySetObject *so = _PySet_CAST(self);
1792
1793
180
    PyObject *rv;
1794
180
    Py_BEGIN_CRITICAL_SECTION2(so, other);
1795
180
    rv = set_intersection(so, other);
1796
180
    Py_END_CRITICAL_SECTION2();
1797
1798
180
    return rv;
1799
180
}
1800
1801
static PyObject *
1802
set_iand(PyObject *self, PyObject *other)
1803
0
{
1804
0
    PyObject *result;
1805
1806
0
    if (!PyAnySet_Check(other))
1807
0
        Py_RETURN_NOTIMPLEMENTED;
1808
0
    PySetObject *so = _PySet_CAST(self);
1809
1810
0
    Py_BEGIN_CRITICAL_SECTION2(so, other);
1811
0
    result = set_intersection_update(so, other);
1812
0
    Py_END_CRITICAL_SECTION2();
1813
1814
0
    if (result == NULL)
1815
0
        return NULL;
1816
0
    Py_DECREF(result);
1817
0
    return Py_NewRef(so);
1818
0
}
1819
1820
/*[clinic input]
1821
@critical_section so other
1822
set.isdisjoint
1823
    so: setobject
1824
    other: object
1825
    /
1826
1827
Return True if two sets have a null intersection.
1828
[clinic start generated code]*/
1829
1830
static PyObject *
1831
set_isdisjoint_impl(PySetObject *so, PyObject *other)
1832
/*[clinic end generated code: output=273493f2d57c565e input=32f8dcab5e0fc7d6]*/
1833
55.2k
{
1834
55.2k
    PyObject *key, *it, *tmp;
1835
55.2k
    int rv;
1836
1837
55.2k
    if ((PyObject *)so == other) {
1838
0
        if (PySet_GET_SIZE(so) == 0)
1839
0
            Py_RETURN_TRUE;
1840
0
        else
1841
0
            Py_RETURN_FALSE;
1842
0
    }
1843
1844
55.2k
    if (PyAnySet_CheckExact(other)) {
1845
0
        Py_ssize_t pos = 0;
1846
0
        setentry *entry;
1847
1848
0
        if (PySet_GET_SIZE(other) > PySet_GET_SIZE(so)) {
1849
0
            tmp = (PyObject *)so;
1850
0
            so = (PySetObject *)other;
1851
0
            other = tmp;
1852
0
        }
1853
0
        while (set_next((PySetObject *)other, &pos, &entry)) {
1854
0
            PyObject *key = entry->key;
1855
0
            Py_INCREF(key);
1856
0
            rv = set_contains_entry(so, key, entry->hash);
1857
0
            Py_DECREF(key);
1858
0
            if (rv < 0) {
1859
0
                return NULL;
1860
0
            }
1861
0
            if (rv) {
1862
0
                Py_RETURN_FALSE;
1863
0
            }
1864
0
        }
1865
0
        Py_RETURN_TRUE;
1866
0
    }
1867
1868
55.2k
    it = PyObject_GetIter(other);
1869
55.2k
    if (it == NULL)
1870
0
        return NULL;
1871
1872
6.36M
    while ((key = PyIter_Next(it)) != NULL) {
1873
6.32M
        rv = set_contains_key(so, key);
1874
6.32M
        Py_DECREF(key);
1875
6.32M
        if (rv < 0) {
1876
0
            Py_DECREF(it);
1877
0
            return NULL;
1878
0
        }
1879
6.32M
        if (rv) {
1880
13.9k
            Py_DECREF(it);
1881
13.9k
            Py_RETURN_FALSE;
1882
13.9k
        }
1883
6.32M
    }
1884
41.2k
    Py_DECREF(it);
1885
41.2k
    if (PyErr_Occurred())
1886
0
        return NULL;
1887
41.2k
    Py_RETURN_TRUE;
1888
41.2k
}
1889
1890
static int
1891
set_difference_update_internal(PySetObject *so, PyObject *other)
1892
10
{
1893
10
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
1894
10
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(other);
1895
1896
10
    if ((PyObject *)so == other)
1897
0
        return set_clear_internal((PyObject*)so);
1898
1899
10
    if (PyAnySet_Check(other)) {
1900
10
        setentry *entry;
1901
10
        Py_ssize_t pos = 0;
1902
1903
        /* Optimization:  When the other set is more than 8 times
1904
           larger than the base set, replace the other set with
1905
           intersection of the two sets.
1906
        */
1907
10
        if ((PySet_GET_SIZE(other) >> 3) > PySet_GET_SIZE(so)) {
1908
0
            other = set_intersection(so, other);
1909
0
            if (other == NULL)
1910
0
                return -1;
1911
10
        } else {
1912
10
            Py_INCREF(other);
1913
10
        }
1914
1915
22
        while (set_next((PySetObject *)other, &pos, &entry)) {
1916
12
            PyObject *key = entry->key;
1917
12
            Py_INCREF(key);
1918
12
            if (set_discard_entry(so, key, entry->hash) < 0) {
1919
0
                Py_DECREF(other);
1920
0
                Py_DECREF(key);
1921
0
                return -1;
1922
0
            }
1923
12
            Py_DECREF(key);
1924
12
        }
1925
1926
10
        Py_DECREF(other);
1927
10
    } else {
1928
0
        PyObject *key, *it;
1929
0
        it = PyObject_GetIter(other);
1930
0
        if (it == NULL)
1931
0
            return -1;
1932
1933
0
        while ((key = PyIter_Next(it)) != NULL) {
1934
0
            if (set_discard_key(so, key) < 0) {
1935
0
                Py_DECREF(it);
1936
0
                Py_DECREF(key);
1937
0
                return -1;
1938
0
            }
1939
0
            Py_DECREF(key);
1940
0
        }
1941
0
        Py_DECREF(it);
1942
0
        if (PyErr_Occurred())
1943
0
            return -1;
1944
0
    }
1945
    /* If more than 1/4th are dummies, then resize them away. */
1946
10
    if ((size_t)(so->fill - so->used) <= (size_t)so->mask / 4)
1947
10
        return 0;
1948
0
    return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4);
1949
10
}
1950
1951
/*[clinic input]
1952
set.difference_update
1953
    so: setobject
1954
    *others: array
1955
1956
Update the set, removing elements found in others.
1957
[clinic start generated code]*/
1958
1959
static PyObject *
1960
set_difference_update_impl(PySetObject *so, PyObject * const *others,
1961
                           Py_ssize_t others_length)
1962
/*[clinic end generated code: output=04a22179b322cfe6 input=93ac28ba5b233696]*/
1963
0
{
1964
0
    Py_ssize_t i;
1965
1966
0
    for (i = 0; i < others_length; i++) {
1967
0
        PyObject *other = others[i];
1968
0
        int rv;
1969
0
        Py_BEGIN_CRITICAL_SECTION2(so, other);
1970
0
        rv = set_difference_update_internal(so, other);
1971
0
        Py_END_CRITICAL_SECTION2();
1972
0
        if (rv) {
1973
0
            return NULL;
1974
0
        }
1975
0
    }
1976
0
    Py_RETURN_NONE;
1977
0
}
1978
1979
static PyObject *
1980
set_copy_and_difference(PySetObject *so, PyObject *other)
1981
10
{
1982
10
    PyObject *result;
1983
1984
10
    result = set_copy_impl(so);
1985
10
    if (result == NULL)
1986
0
        return NULL;
1987
10
    if (set_difference_update_internal((PySetObject *) result, other) == 0)
1988
10
        return result;
1989
0
    Py_DECREF(result);
1990
0
    return NULL;
1991
10
}
1992
1993
static PyObject *
1994
set_difference(PySetObject *so, PyObject *other)
1995
12
{
1996
12
    PyObject *result;
1997
12
    PyObject *key;
1998
12
    Py_hash_t hash;
1999
12
    setentry *entry;
2000
12
    Py_ssize_t pos = 0, other_size;
2001
12
    int rv;
2002
2003
12
    if (PyAnySet_Check(other)) {
2004
12
        other_size = PySet_GET_SIZE(other);
2005
12
    }
2006
0
    else if (PyDict_CheckExact(other)) {
2007
0
        other_size = PyDict_GET_SIZE(other);
2008
0
    }
2009
0
    else {
2010
0
        return set_copy_and_difference(so, other);
2011
0
    }
2012
2013
    /* If len(so) much more than len(other), it's more efficient to simply copy
2014
     * so and then iterate other looking for common elements. */
2015
12
    if ((PySet_GET_SIZE(so) >> 2) > other_size) {
2016
10
        return set_copy_and_difference(so, other);
2017
10
    }
2018
2019
2
    result = make_new_set_basetype(Py_TYPE(so), NULL);
2020
2
    if (result == NULL)
2021
0
        return NULL;
2022
2023
2
    if (PyDict_CheckExact(other)) {
2024
0
        while (set_next(so, &pos, &entry)) {
2025
0
            key = entry->key;
2026
0
            hash = entry->hash;
2027
0
            Py_INCREF(key);
2028
0
            rv = _PyDict_Contains_KnownHash(other, key, hash);
2029
0
            if (rv < 0) {
2030
0
                Py_DECREF(result);
2031
0
                Py_DECREF(key);
2032
0
                return NULL;
2033
0
            }
2034
0
            if (!rv) {
2035
0
                if (set_add_entry((PySetObject *)result, key, hash)) {
2036
0
                    Py_DECREF(result);
2037
0
                    Py_DECREF(key);
2038
0
                    return NULL;
2039
0
                }
2040
0
            }
2041
0
            Py_DECREF(key);
2042
0
        }
2043
0
        return result;
2044
0
    }
2045
2046
    /* Iterate over so, checking for common elements in other. */
2047
28
    while (set_next(so, &pos, &entry)) {
2048
26
        key = entry->key;
2049
26
        hash = entry->hash;
2050
26
        Py_INCREF(key);
2051
26
        rv = set_contains_entry((PySetObject *)other, key, hash);
2052
26
        if (rv < 0) {
2053
0
            Py_DECREF(result);
2054
0
            Py_DECREF(key);
2055
0
            return NULL;
2056
0
        }
2057
26
        if (!rv) {
2058
20
            if (set_add_entry((PySetObject *)result, key, hash)) {
2059
0
                Py_DECREF(result);
2060
0
                Py_DECREF(key);
2061
0
                return NULL;
2062
0
            }
2063
20
        }
2064
26
        Py_DECREF(key);
2065
26
    }
2066
2
    return result;
2067
2
}
2068
2069
/*[clinic input]
2070
set.difference as set_difference_multi
2071
    so: setobject
2072
    *others: array
2073
2074
Return a new set with elements in the set that are not in the others.
2075
[clinic start generated code]*/
2076
2077
static PyObject *
2078
set_difference_multi_impl(PySetObject *so, PyObject * const *others,
2079
                          Py_ssize_t others_length)
2080
/*[clinic end generated code: output=b0d33fb05d5477a7 input=c1eb448d483416ad]*/
2081
0
{
2082
0
    Py_ssize_t i;
2083
0
    PyObject *result, *other;
2084
2085
0
    if (others_length == 0) {
2086
0
        return set_copy((PyObject *)so, NULL);
2087
0
    }
2088
2089
0
    other = others[0];
2090
0
    Py_BEGIN_CRITICAL_SECTION2(so, other);
2091
0
    result = set_difference(so, other);
2092
0
    Py_END_CRITICAL_SECTION2();
2093
0
    if (result == NULL)
2094
0
        return NULL;
2095
2096
0
    for (i = 1; i < others_length; i++) {
2097
0
        other = others[i];
2098
0
        int rv;
2099
0
        Py_BEGIN_CRITICAL_SECTION(other);
2100
0
        rv = set_difference_update_internal((PySetObject *)result, other);
2101
0
        Py_END_CRITICAL_SECTION();
2102
0
        if (rv) {
2103
0
            Py_DECREF(result);
2104
0
            return NULL;
2105
0
        }
2106
0
    }
2107
0
    return result;
2108
0
}
2109
2110
static PyObject *
2111
set_sub(PyObject *self, PyObject *other)
2112
12
{
2113
12
    if (!PyAnySet_Check(self) || !PyAnySet_Check(other))
2114
0
        Py_RETURN_NOTIMPLEMENTED;
2115
12
    PySetObject *so = _PySet_CAST(self);
2116
2117
12
    PyObject *rv;
2118
12
    Py_BEGIN_CRITICAL_SECTION2(so, other);
2119
12
    rv = set_difference(so, other);
2120
12
    Py_END_CRITICAL_SECTION2();
2121
12
    return rv;
2122
12
}
2123
2124
static PyObject *
2125
set_isub(PyObject *self, PyObject *other)
2126
0
{
2127
0
    if (!PyAnySet_Check(other))
2128
0
        Py_RETURN_NOTIMPLEMENTED;
2129
0
    PySetObject *so = _PySet_CAST(self);
2130
2131
0
    int rv;
2132
0
    Py_BEGIN_CRITICAL_SECTION2(so, other);
2133
0
    rv = set_difference_update_internal(so, other);
2134
0
    Py_END_CRITICAL_SECTION2();
2135
0
    if (rv < 0) {
2136
0
        return NULL;
2137
0
    }
2138
0
    return Py_NewRef(so);
2139
0
}
2140
2141
static int
2142
set_symmetric_difference_update_dict(PySetObject *so, PyObject *other)
2143
0
{
2144
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
2145
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(other);
2146
2147
0
    Py_ssize_t pos = 0;
2148
0
    PyObject *key, *value;
2149
0
    Py_hash_t hash;
2150
0
    while (_PyDict_Next(other, &pos, &key, &value, &hash)) {
2151
0
        Py_INCREF(key);
2152
0
        int rv = set_discard_entry(so, key, hash);
2153
0
        if (rv < 0) {
2154
0
            Py_DECREF(key);
2155
0
            return -1;
2156
0
        }
2157
0
        if (rv == DISCARD_NOTFOUND) {
2158
0
            if (set_add_entry(so, key, hash)) {
2159
0
                Py_DECREF(key);
2160
0
                return -1;
2161
0
            }
2162
0
        }
2163
0
        Py_DECREF(key);
2164
0
    }
2165
0
    return 0;
2166
0
}
2167
2168
static int
2169
set_symmetric_difference_update_set(PySetObject *so, PySetObject *other)
2170
0
{
2171
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(so);
2172
0
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(other);
2173
2174
0
    Py_ssize_t pos = 0;
2175
0
    setentry *entry;
2176
0
    while (set_next(other, &pos, &entry)) {
2177
0
        PyObject *key = Py_NewRef(entry->key);
2178
0
        Py_hash_t hash = entry->hash;
2179
0
        int rv = set_discard_entry(so, key, hash);
2180
0
        if (rv < 0) {
2181
0
            Py_DECREF(key);
2182
0
            return -1;
2183
0
        }
2184
0
        if (rv == DISCARD_NOTFOUND) {
2185
0
            if (set_add_entry(so, key, hash)) {
2186
0
                Py_DECREF(key);
2187
0
                return -1;
2188
0
            }
2189
0
        }
2190
0
        Py_DECREF(key);
2191
0
    }
2192
0
    return 0;
2193
0
}
2194
2195
/*[clinic input]
2196
@permit_long_summary
2197
set.symmetric_difference_update
2198
    so: setobject
2199
    other: object
2200
    /
2201
2202
Update the set, keeping only elements found in either set, but not in both.
2203
[clinic start generated code]*/
2204
2205
static PyObject *
2206
set_symmetric_difference_update_impl(PySetObject *so, PyObject *other)
2207
/*[clinic end generated code: output=79f80b4ee5da66c1 input=86a3dddac9bfb15e]*/
2208
0
{
2209
0
    if (Py_Is((PyObject *)so, other)) {
2210
0
        return set_clear((PyObject *)so, NULL);
2211
0
    }
2212
2213
0
    int rv;
2214
0
    if (PyDict_CheckExact(other)) {
2215
0
        Py_BEGIN_CRITICAL_SECTION2(so, other);
2216
0
        rv = set_symmetric_difference_update_dict(so, other);
2217
0
        Py_END_CRITICAL_SECTION2();
2218
0
    }
2219
0
    else if (PyAnySet_Check(other)) {
2220
0
        Py_BEGIN_CRITICAL_SECTION2(so, other);
2221
0
        rv = set_symmetric_difference_update_set(so, (PySetObject *)other);
2222
0
        Py_END_CRITICAL_SECTION2();
2223
0
    }
2224
0
    else {
2225
0
        PySetObject *otherset = (PySetObject *)make_new_set_basetype(Py_TYPE(so), other);
2226
0
        if (otherset == NULL) {
2227
0
            return NULL;
2228
0
        }
2229
2230
0
        Py_BEGIN_CRITICAL_SECTION(so);
2231
0
        rv = set_symmetric_difference_update_set(so, otherset);
2232
0
        Py_END_CRITICAL_SECTION();
2233
2234
0
        Py_DECREF(otherset);
2235
0
    }
2236
0
    if (rv < 0) {
2237
0
        return NULL;
2238
0
    }
2239
0
    Py_RETURN_NONE;
2240
0
}
2241
2242
/*[clinic input]
2243
@critical_section so other
2244
set.symmetric_difference
2245
    so: setobject
2246
    other: object
2247
    /
2248
2249
Return a new set with elements in either the set or other but not both.
2250
[clinic start generated code]*/
2251
2252
static PyObject *
2253
set_symmetric_difference_impl(PySetObject *so, PyObject *other)
2254
/*[clinic end generated code: output=270ee0b5d42b0797 input=624f6e7bbdf70db1]*/
2255
0
{
2256
0
    PySetObject *result = (PySetObject *)make_new_set_basetype(Py_TYPE(so), NULL);
2257
0
    if (result == NULL) {
2258
0
        return NULL;
2259
0
    }
2260
0
    if (set_update_lock_held(result, other) < 0) {
2261
0
        Py_DECREF(result);
2262
0
        return NULL;
2263
0
    }
2264
0
    if (set_symmetric_difference_update_set(result, so) < 0) {
2265
0
        Py_DECREF(result);
2266
0
        return NULL;
2267
0
    }
2268
0
    return (PyObject *)result;
2269
0
}
2270
2271
static PyObject *
2272
set_xor(PyObject *self, PyObject *other)
2273
0
{
2274
0
    if (!PyAnySet_Check(self) || !PyAnySet_Check(other))
2275
0
        Py_RETURN_NOTIMPLEMENTED;
2276
0
    PySetObject *so = _PySet_CAST(self);
2277
0
    return set_symmetric_difference((PyObject*)so, other);
2278
0
}
2279
2280
static PyObject *
2281
set_ixor(PyObject *self, PyObject *other)
2282
0
{
2283
0
    PyObject *result;
2284
2285
0
    if (!PyAnySet_Check(other))
2286
0
        Py_RETURN_NOTIMPLEMENTED;
2287
0
    PySetObject *so = _PySet_CAST(self);
2288
2289
0
    result = set_symmetric_difference_update((PyObject*)so, other);
2290
0
    if (result == NULL)
2291
0
        return NULL;
2292
0
    Py_DECREF(result);
2293
0
    return Py_NewRef(so);
2294
0
}
2295
2296
/*[clinic input]
2297
@critical_section so other
2298
set.issubset
2299
    so: setobject
2300
    other: object
2301
    /
2302
2303
Report whether another set contains this set.
2304
[clinic start generated code]*/
2305
2306
static PyObject *
2307
set_issubset_impl(PySetObject *so, PyObject *other)
2308
/*[clinic end generated code: output=b2b59d5f314555ce input=f2a4fd0f2537758b]*/
2309
118
{
2310
118
    setentry *entry;
2311
118
    Py_ssize_t pos = 0;
2312
118
    int rv;
2313
2314
118
    if (!PyAnySet_Check(other)) {
2315
0
        PyObject *tmp = set_intersection(so, other);
2316
0
        if (tmp == NULL) {
2317
0
            return NULL;
2318
0
        }
2319
0
        int result = (PySet_GET_SIZE(tmp) == PySet_GET_SIZE(so));
2320
0
        Py_DECREF(tmp);
2321
0
        return PyBool_FromLong(result);
2322
0
    }
2323
118
    if (PySet_GET_SIZE(so) > PySet_GET_SIZE(other))
2324
0
        Py_RETURN_FALSE;
2325
2326
532
    while (set_next(so, &pos, &entry)) {
2327
414
        PyObject *key = entry->key;
2328
414
        Py_INCREF(key);
2329
414
        rv = set_contains_entry((PySetObject *)other, key, entry->hash);
2330
414
        Py_DECREF(key);
2331
414
        if (rv < 0) {
2332
0
            return NULL;
2333
0
        }
2334
414
        if (!rv) {
2335
0
            Py_RETURN_FALSE;
2336
0
        }
2337
414
    }
2338
118
    Py_RETURN_TRUE;
2339
118
}
2340
2341
/*[clinic input]
2342
@critical_section so other
2343
set.issuperset
2344
    so: setobject
2345
    other: object
2346
    /
2347
2348
Report whether this set contains another set.
2349
[clinic start generated code]*/
2350
2351
static PyObject *
2352
set_issuperset_impl(PySetObject *so, PyObject *other)
2353
/*[clinic end generated code: output=ecf00ce552c09461 input=5f2e1f262e6e4ccc]*/
2354
5.88k
{
2355
5.88k
    if (PyAnySet_Check(other)) {
2356
0
        return set_issubset(other, (PyObject *)so);
2357
0
    }
2358
2359
5.88k
    PyObject *key, *it = PyObject_GetIter(other);
2360
5.88k
    if (it == NULL) {
2361
0
        return NULL;
2362
0
    }
2363
40.4k
    while ((key = PyIter_Next(it)) != NULL) {
2364
34.5k
        int rv = set_contains_key(so, key);
2365
34.5k
        Py_DECREF(key);
2366
34.5k
        if (rv < 0) {
2367
0
            Py_DECREF(it);
2368
0
            return NULL;
2369
0
        }
2370
34.5k
        if (!rv) {
2371
19
            Py_DECREF(it);
2372
19
            Py_RETURN_FALSE;
2373
19
        }
2374
34.5k
    }
2375
5.86k
    Py_DECREF(it);
2376
5.86k
    if (PyErr_Occurred()) {
2377
0
        return NULL;
2378
0
    }
2379
5.86k
    Py_RETURN_TRUE;
2380
5.86k
}
2381
2382
static PyObject *
2383
set_richcompare(PyObject *self, PyObject *w, int op)
2384
118
{
2385
118
    PySetObject *v = _PySet_CAST(self);
2386
118
    PyObject *r1;
2387
118
    int r2;
2388
2389
118
    if(!PyAnySet_Check(w))
2390
0
        Py_RETURN_NOTIMPLEMENTED;
2391
2392
118
    switch (op) {
2393
44
    case Py_EQ:
2394
44
        if (PySet_GET_SIZE(v) != PySet_GET_SIZE(w))
2395
0
            Py_RETURN_FALSE;
2396
44
        Py_hash_t v_hash = FT_ATOMIC_LOAD_SSIZE_RELAXED(v->hash);
2397
44
        Py_hash_t w_hash = FT_ATOMIC_LOAD_SSIZE_RELAXED(((PySetObject *)w)->hash);
2398
44
        if (v_hash != -1 && w_hash != -1 && v_hash != w_hash)
2399
0
            Py_RETURN_FALSE;
2400
44
        return set_issubset((PyObject*)v, w);
2401
0
    case Py_NE:
2402
0
        r1 = set_richcompare((PyObject*)v, w, Py_EQ);
2403
0
        if (r1 == NULL)
2404
0
            return NULL;
2405
0
        r2 = PyObject_IsTrue(r1);
2406
0
        Py_DECREF(r1);
2407
0
        if (r2 < 0)
2408
0
            return NULL;
2409
0
        return PyBool_FromLong(!r2);
2410
74
    case Py_LE:
2411
74
        return set_issubset((PyObject*)v, w);
2412
0
    case Py_GE:
2413
0
        return set_issuperset((PyObject*)v, w);
2414
0
    case Py_LT:
2415
0
        if (PySet_GET_SIZE(v) >= PySet_GET_SIZE(w))
2416
0
            Py_RETURN_FALSE;
2417
0
        return set_issubset((PyObject*)v, w);
2418
0
    case Py_GT:
2419
0
        if (PySet_GET_SIZE(v) <= PySet_GET_SIZE(w))
2420
0
            Py_RETURN_FALSE;
2421
0
        return set_issuperset((PyObject*)v, w);
2422
118
    }
2423
118
    Py_RETURN_NOTIMPLEMENTED;
2424
118
}
2425
2426
/*[clinic input]
2427
@critical_section
2428
set.add
2429
    so: setobject
2430
    object as key: object
2431
    /
2432
2433
Add an element to a set.
2434
2435
This has no effect if the element is already present.
2436
[clinic start generated code]*/
2437
2438
static PyObject *
2439
set_add_impl(PySetObject *so, PyObject *key)
2440
/*[clinic end generated code: output=4cc4a937f1425c96 input=03baf62cb0e66514]*/
2441
6.92M
{
2442
6.92M
    if (set_add_key(so, key))
2443
0
        return NULL;
2444
6.92M
    Py_RETURN_NONE;
2445
6.92M
}
2446
2447
int
2448
_PySet_Contains(PySetObject *so, PyObject *key)
2449
251M
{
2450
251M
    assert(so);
2451
2452
251M
    Py_hash_t hash = _PyObject_HashFast(key);
2453
251M
    if (hash == -1) {
2454
0
        if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError)) {
2455
0
            set_unhashable_type(key);
2456
0
            return -1;
2457
0
        }
2458
0
        PyErr_Clear();
2459
        // Note that 'key' could be a set() or frozenset() object.  Unlike most
2460
        // container types, set allows membership testing with a set key, even
2461
        // though it is not hashable.
2462
0
        Py_BEGIN_CRITICAL_SECTION(key);
2463
0
        hash = frozenset_hash_impl(key);
2464
0
        Py_END_CRITICAL_SECTION();
2465
0
    }
2466
251M
    return set_contains_entry(so, key, hash);
2467
251M
}
2468
2469
static int
2470
set_contains(PyObject *self, PyObject *key)
2471
604
{
2472
604
    PySetObject *so = _PySet_CAST(self);
2473
604
    return _PySet_Contains(so, key);
2474
604
}
2475
2476
/*[clinic input]
2477
@coexist
2478
set.__contains__
2479
    so: setobject
2480
    object as key: object
2481
    /
2482
2483
x.__contains__(y) <==> y in x.
2484
[clinic start generated code]*/
2485
2486
static PyObject *
2487
set___contains___impl(PySetObject *so, PyObject *key)
2488
/*[clinic end generated code: output=b44863d034b3c70e input=cf4c72db704e4cf0]*/
2489
20.6M
{
2490
20.6M
    long result;
2491
2492
20.6M
    result = _PySet_Contains(so, key);
2493
20.6M
    if (result < 0)
2494
0
        return NULL;
2495
20.6M
    return PyBool_FromLong(result);
2496
20.6M
}
2497
2498
/*[clinic input]
2499
@coexist
2500
frozenset.__contains__
2501
    so: setobject
2502
    object as key: object
2503
    /
2504
2505
x.__contains__(y) <==> y in x.
2506
[clinic start generated code]*/
2507
2508
static PyObject *
2509
frozenset___contains___impl(PySetObject *so, PyObject *key)
2510
/*[clinic end generated code: output=2301ed91bc3a6dd5 input=2f04922a98d8bab7]*/
2511
552
{
2512
552
    Py_hash_t hash = _PyObject_HashFast(key);
2513
552
    if (hash == -1) {
2514
0
        if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError)) {
2515
0
            set_unhashable_type(key);
2516
0
            return NULL;
2517
0
        }
2518
0
        PyErr_Clear();
2519
0
        Py_BEGIN_CRITICAL_SECTION(key);
2520
0
        hash = frozenset_hash_impl(key);
2521
0
        Py_END_CRITICAL_SECTION();
2522
0
    }
2523
552
    setentry *entry; // unused
2524
552
    int status = set_do_lookup(so, so->table, so->mask, key, hash, &entry,
2525
552
                           set_compare_frozenset);
2526
552
    if (status < 0)
2527
0
        return NULL;
2528
552
    return PyBool_FromLong(status);
2529
552
}
2530
2531
/*[clinic input]
2532
@critical_section
2533
set.remove
2534
    so: setobject
2535
    object as key: object
2536
    /
2537
2538
Remove an element from a set; it must be a member.
2539
2540
If the element is not a member, raise a KeyError.
2541
[clinic start generated code]*/
2542
2543
static PyObject *
2544
set_remove_impl(PySetObject *so, PyObject *key)
2545
/*[clinic end generated code: output=0b9134a2a2200363 input=893e1cb1df98227a]*/
2546
0
{
2547
0
    int rv;
2548
2549
0
    rv = set_discard_key(so, key);
2550
0
    if (rv < 0) {
2551
0
        if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError))
2552
0
            return NULL;
2553
0
        PyErr_Clear();
2554
0
        Py_hash_t hash;
2555
0
        Py_BEGIN_CRITICAL_SECTION(key);
2556
0
        hash = frozenset_hash_impl(key);
2557
0
        Py_END_CRITICAL_SECTION();
2558
0
        rv = set_discard_entry(so, key, hash);
2559
0
        if (rv < 0)
2560
0
            return NULL;
2561
0
    }
2562
2563
0
    if (rv == DISCARD_NOTFOUND) {
2564
0
        _PyErr_SetKeyError(key);
2565
0
        return NULL;
2566
0
    }
2567
0
    Py_RETURN_NONE;
2568
0
}
2569
2570
/*[clinic input]
2571
@critical_section
2572
set.discard
2573
    so: setobject
2574
    object as key: object
2575
    /
2576
2577
Remove an element from a set if it is a member.
2578
2579
Unlike set.remove(), the discard() method does not raise
2580
an exception when an element is missing from the set.
2581
[clinic start generated code]*/
2582
2583
static PyObject *
2584
set_discard_impl(PySetObject *so, PyObject *key)
2585
/*[clinic end generated code: output=eec3b687bf32759e input=861cb7fb69b4def0]*/
2586
0
{
2587
0
    int rv;
2588
2589
0
    rv = set_discard_key(so, key);
2590
0
    if (rv < 0) {
2591
0
        if (!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError))
2592
0
            return NULL;
2593
0
        PyErr_Clear();
2594
0
        Py_hash_t hash;
2595
0
        Py_BEGIN_CRITICAL_SECTION(key);
2596
0
        hash = frozenset_hash_impl(key);
2597
0
        Py_END_CRITICAL_SECTION();
2598
0
        rv = set_discard_entry(so, key, hash);
2599
0
        if (rv < 0)
2600
0
            return NULL;
2601
0
    }
2602
0
    Py_RETURN_NONE;
2603
0
}
2604
2605
/*[clinic input]
2606
@critical_section
2607
set.__reduce__
2608
    so: setobject
2609
2610
Return state information for pickling.
2611
[clinic start generated code]*/
2612
2613
static PyObject *
2614
set___reduce___impl(PySetObject *so)
2615
/*[clinic end generated code: output=9af7d0e029df87ee input=59405a4249e82f71]*/
2616
0
{
2617
0
    PyObject *keys=NULL, *args=NULL, *result=NULL, *state=NULL;
2618
2619
0
    keys = PySequence_List((PyObject *)so);
2620
0
    if (keys == NULL)
2621
0
        goto done;
2622
0
    args = PyTuple_Pack(1, keys);
2623
0
    if (args == NULL)
2624
0
        goto done;
2625
0
    state = _PyObject_GetState((PyObject *)so);
2626
0
    if (state == NULL)
2627
0
        goto done;
2628
0
    result = PyTuple_Pack(3, Py_TYPE(so), args, state);
2629
0
done:
2630
0
    Py_XDECREF(args);
2631
0
    Py_XDECREF(keys);
2632
0
    Py_XDECREF(state);
2633
0
    return result;
2634
0
}
2635
2636
/*[clinic input]
2637
@critical_section
2638
set.__sizeof__
2639
    so: setobject
2640
2641
S.__sizeof__() -> size of S in memory, in bytes.
2642
[clinic start generated code]*/
2643
2644
static PyObject *
2645
set___sizeof___impl(PySetObject *so)
2646
/*[clinic end generated code: output=4bfa3df7bd38ed88 input=09e1a09f168eaa23]*/
2647
0
{
2648
0
    size_t res = _PyObject_SIZE(Py_TYPE(so));
2649
0
    if (so->table != so->smalltable) {
2650
0
        res += ((size_t)so->mask + 1) * sizeof(setentry);
2651
0
    }
2652
0
    return PyLong_FromSize_t(res);
2653
0
}
2654
2655
static int
2656
set_init(PyObject *so, PyObject *args, PyObject *kwds)
2657
0
{
2658
0
    PySetObject *self = _PySet_CAST(so);
2659
0
    PyObject *iterable = NULL;
2660
2661
0
    if (!_PyArg_NoKeywords("set", kwds))
2662
0
        return -1;
2663
0
    if (!PyArg_UnpackTuple(args, Py_TYPE(self)->tp_name, 0, 1, &iterable))
2664
0
        return -1;
2665
2666
0
    if (_PyObject_IsUniquelyReferenced((PyObject *)self) && self->fill == 0) {
2667
0
        self->hash = -1;
2668
0
        if (iterable == NULL) {
2669
0
            return 0;
2670
0
        }
2671
0
        return set_update_local(self, iterable);
2672
0
    }
2673
0
    Py_BEGIN_CRITICAL_SECTION(self);
2674
0
    if (self->fill)
2675
0
        set_clear_internal((PyObject*)self);
2676
0
    self->hash = -1;
2677
0
    Py_END_CRITICAL_SECTION();
2678
2679
0
    if (iterable == NULL)
2680
0
        return 0;
2681
0
    return set_update_internal(self, iterable);
2682
0
}
2683
2684
static PyObject*
2685
set_vectorcall(PyObject *type, PyObject * const*args,
2686
               size_t nargsf, PyObject *kwnames)
2687
2.62M
{
2688
2.62M
    assert(PyType_Check(type));
2689
2690
2.62M
    if (!_PyArg_NoKwnames("set", kwnames)) {
2691
0
        return NULL;
2692
0
    }
2693
2694
2.62M
    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
2695
2.62M
    if (!_PyArg_CheckPositional("set", nargs, 0, 1)) {
2696
0
        return NULL;
2697
0
    }
2698
2699
2.62M
    if (nargs) {
2700
14.3k
        return make_new_set(_PyType_CAST(type), args[0]);
2701
14.3k
    }
2702
2703
2.61M
    return make_new_set(_PyType_CAST(type), NULL);
2704
2.62M
}
2705
2706
static PySequenceMethods set_as_sequence = {
2707
    set_len,                            /* sq_length */
2708
    0,                                  /* sq_concat */
2709
    0,                                  /* sq_repeat */
2710
    0,                                  /* sq_item */
2711
    0,                                  /* sq_slice */
2712
    0,                                  /* sq_ass_item */
2713
    0,                                  /* sq_ass_slice */
2714
    set_contains,                       /* sq_contains */
2715
};
2716
2717
/* set object ********************************************************/
2718
2719
static PyMethodDef set_methods[] = {
2720
    SET_ADD_METHODDEF
2721
    SET_CLEAR_METHODDEF
2722
    SET___CONTAINS___METHODDEF
2723
    SET_COPY_METHODDEF
2724
    SET_DISCARD_METHODDEF
2725
    SET_DIFFERENCE_MULTI_METHODDEF
2726
    SET_DIFFERENCE_UPDATE_METHODDEF
2727
    SET_INTERSECTION_MULTI_METHODDEF
2728
    SET_INTERSECTION_UPDATE_MULTI_METHODDEF
2729
    SET_ISDISJOINT_METHODDEF
2730
    SET_ISSUBSET_METHODDEF
2731
    SET_ISSUPERSET_METHODDEF
2732
    SET_POP_METHODDEF
2733
    SET___REDUCE___METHODDEF
2734
    SET_REMOVE_METHODDEF
2735
    SET___SIZEOF___METHODDEF
2736
    SET_SYMMETRIC_DIFFERENCE_METHODDEF
2737
    SET_SYMMETRIC_DIFFERENCE_UPDATE_METHODDEF
2738
    SET_UNION_METHODDEF
2739
    SET_UPDATE_METHODDEF
2740
    {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
2741
    {NULL,              NULL}   /* sentinel */
2742
};
2743
2744
static PyNumberMethods set_as_number = {
2745
    0,                                  /*nb_add*/
2746
    set_sub,                            /*nb_subtract*/
2747
    0,                                  /*nb_multiply*/
2748
    0,                                  /*nb_remainder*/
2749
    0,                                  /*nb_divmod*/
2750
    0,                                  /*nb_power*/
2751
    0,                                  /*nb_negative*/
2752
    0,                                  /*nb_positive*/
2753
    0,                                  /*nb_absolute*/
2754
    0,                                  /*nb_bool*/
2755
    0,                                  /*nb_invert*/
2756
    0,                                  /*nb_lshift*/
2757
    0,                                  /*nb_rshift*/
2758
    set_and,                            /*nb_and*/
2759
    set_xor,                            /*nb_xor*/
2760
    set_or,                             /*nb_or*/
2761
    0,                                  /*nb_int*/
2762
    0,                                  /*nb_reserved*/
2763
    0,                                  /*nb_float*/
2764
    0,                                  /*nb_inplace_add*/
2765
    set_isub,                           /*nb_inplace_subtract*/
2766
    0,                                  /*nb_inplace_multiply*/
2767
    0,                                  /*nb_inplace_remainder*/
2768
    0,                                  /*nb_inplace_power*/
2769
    0,                                  /*nb_inplace_lshift*/
2770
    0,                                  /*nb_inplace_rshift*/
2771
    set_iand,                           /*nb_inplace_and*/
2772
    set_ixor,                           /*nb_inplace_xor*/
2773
    set_ior,                            /*nb_inplace_or*/
2774
};
2775
2776
PyDoc_STRVAR(set_doc,
2777
"set(iterable=(), /)\n\
2778
--\n\
2779
\n\
2780
Build an unordered collection of unique elements.");
2781
2782
PyTypeObject PySet_Type = {
2783
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2784
    "set",                              /* tp_name */
2785
    sizeof(PySetObject),                /* tp_basicsize */
2786
    0,                                  /* tp_itemsize */
2787
    /* methods */
2788
    set_dealloc,                        /* tp_dealloc */
2789
    0,                                  /* tp_vectorcall_offset */
2790
    0,                                  /* tp_getattr */
2791
    0,                                  /* tp_setattr */
2792
    0,                                  /* tp_as_async */
2793
    set_repr,                           /* tp_repr */
2794
    &set_as_number,                     /* tp_as_number */
2795
    &set_as_sequence,                   /* tp_as_sequence */
2796
    0,                                  /* tp_as_mapping */
2797
    PyObject_HashNotImplemented,        /* tp_hash */
2798
    0,                                  /* tp_call */
2799
    0,                                  /* tp_str */
2800
    PyObject_GenericGetAttr,            /* tp_getattro */
2801
    0,                                  /* tp_setattro */
2802
    0,                                  /* tp_as_buffer */
2803
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
2804
        Py_TPFLAGS_BASETYPE |
2805
        _Py_TPFLAGS_MATCH_SELF,         /* tp_flags */
2806
    set_doc,                            /* tp_doc */
2807
    set_traverse,                       /* tp_traverse */
2808
    set_clear_internal,                 /* tp_clear */
2809
    set_richcompare,                    /* tp_richcompare */
2810
    offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */
2811
    set_iter,                           /* tp_iter */
2812
    0,                                  /* tp_iternext */
2813
    set_methods,                        /* tp_methods */
2814
    0,                                  /* tp_members */
2815
    0,                                  /* tp_getset */
2816
    0,                                  /* tp_base */
2817
    0,                                  /* tp_dict */
2818
    0,                                  /* tp_descr_get */
2819
    0,                                  /* tp_descr_set */
2820
    0,                                  /* tp_dictoffset */
2821
    set_init,                           /* tp_init */
2822
    PyType_GenericAlloc,                /* tp_alloc */
2823
    set_new,                            /* tp_new */
2824
    PyObject_GC_Del,                    /* tp_free */
2825
    .tp_vectorcall = set_vectorcall,
2826
    .tp_version_tag = _Py_TYPE_VERSION_SET,
2827
};
2828
2829
/* frozenset object ********************************************************/
2830
2831
2832
static PyMethodDef frozenset_methods[] = {
2833
    FROZENSET___CONTAINS___METHODDEF
2834
    FROZENSET_COPY_METHODDEF
2835
    SET_DIFFERENCE_MULTI_METHODDEF
2836
    SET_INTERSECTION_MULTI_METHODDEF
2837
    SET_ISDISJOINT_METHODDEF
2838
    SET_ISSUBSET_METHODDEF
2839
    SET_ISSUPERSET_METHODDEF
2840
    SET___REDUCE___METHODDEF
2841
    SET___SIZEOF___METHODDEF
2842
    SET_SYMMETRIC_DIFFERENCE_METHODDEF
2843
    SET_UNION_METHODDEF
2844
    {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
2845
    {NULL,              NULL}   /* sentinel */
2846
};
2847
2848
static PyNumberMethods frozenset_as_number = {
2849
    0,                                  /*nb_add*/
2850
    set_sub,                            /*nb_subtract*/
2851
    0,                                  /*nb_multiply*/
2852
    0,                                  /*nb_remainder*/
2853
    0,                                  /*nb_divmod*/
2854
    0,                                  /*nb_power*/
2855
    0,                                  /*nb_negative*/
2856
    0,                                  /*nb_positive*/
2857
    0,                                  /*nb_absolute*/
2858
    0,                                  /*nb_bool*/
2859
    0,                                  /*nb_invert*/
2860
    0,                                  /*nb_lshift*/
2861
    0,                                  /*nb_rshift*/
2862
    set_and,                            /*nb_and*/
2863
    set_xor,                            /*nb_xor*/
2864
    set_or,                             /*nb_or*/
2865
};
2866
2867
PyDoc_STRVAR(frozenset_doc,
2868
"frozenset(iterable=(), /)\n\
2869
--\n\
2870
\n\
2871
Build an immutable unordered collection of unique elements.");
2872
2873
PyTypeObject PyFrozenSet_Type = {
2874
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
2875
    "frozenset",                        /* tp_name */
2876
    sizeof(PySetObject),                /* tp_basicsize */
2877
    0,                                  /* tp_itemsize */
2878
    /* methods */
2879
    set_dealloc,                        /* tp_dealloc */
2880
    0,                                  /* tp_vectorcall_offset */
2881
    0,                                  /* tp_getattr */
2882
    0,                                  /* tp_setattr */
2883
    0,                                  /* tp_as_async */
2884
    set_repr,                           /* tp_repr */
2885
    &frozenset_as_number,               /* tp_as_number */
2886
    &set_as_sequence,                   /* tp_as_sequence */
2887
    0,                                  /* tp_as_mapping */
2888
    frozenset_hash,                     /* tp_hash */
2889
    0,                                  /* tp_call */
2890
    0,                                  /* tp_str */
2891
    PyObject_GenericGetAttr,            /* tp_getattro */
2892
    0,                                  /* tp_setattro */
2893
    0,                                  /* tp_as_buffer */
2894
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
2895
        Py_TPFLAGS_BASETYPE |
2896
        _Py_TPFLAGS_MATCH_SELF,         /* tp_flags */
2897
    frozenset_doc,                      /* tp_doc */
2898
    set_traverse,                       /* tp_traverse */
2899
    set_clear_internal,                 /* tp_clear */
2900
    set_richcompare,                    /* tp_richcompare */
2901
    offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */
2902
    set_iter,                           /* tp_iter */
2903
    0,                                  /* tp_iternext */
2904
    frozenset_methods,                  /* tp_methods */
2905
    0,                                  /* tp_members */
2906
    0,                                  /* tp_getset */
2907
    0,                                  /* tp_base */
2908
    0,                                  /* tp_dict */
2909
    0,                                  /* tp_descr_get */
2910
    0,                                  /* tp_descr_set */
2911
    0,                                  /* tp_dictoffset */
2912
    0,                                  /* tp_init */
2913
    PyType_GenericAlloc,                /* tp_alloc */
2914
    frozenset_new,                      /* tp_new */
2915
    PyObject_GC_Del,                    /* tp_free */
2916
    .tp_vectorcall = frozenset_vectorcall,
2917
    .tp_version_tag = _Py_TYPE_VERSION_FROZEN_SET,
2918
};
2919
2920
2921
/***** C API functions *************************************************/
2922
2923
PyObject *
2924
PySet_New(PyObject *iterable)
2925
131k
{
2926
131k
    return make_new_set(&PySet_Type, iterable);
2927
131k
}
2928
2929
PyObject *
2930
PyFrozenSet_New(PyObject *iterable)
2931
2.97k
{
2932
2.97k
    return make_new_set(&PyFrozenSet_Type, iterable);
2933
2.97k
}
2934
2935
Py_ssize_t
2936
PySet_Size(PyObject *anyset)
2937
148
{
2938
148
    if (!PyAnySet_Check(anyset)) {
2939
0
        PyErr_BadInternalCall();
2940
0
        return -1;
2941
0
    }
2942
148
    return set_len(anyset);
2943
148
}
2944
2945
int
2946
PySet_Clear(PyObject *set)
2947
333
{
2948
333
    if (!PySet_Check(set)) {
2949
0
        PyErr_BadInternalCall();
2950
0
        return -1;
2951
0
    }
2952
333
    (void)set_clear(set, NULL);
2953
333
    return 0;
2954
333
}
2955
2956
void
2957
_PySet_ClearInternal(PySetObject *so)
2958
0
{
2959
0
    (void)set_clear_internal((PyObject*)so);
2960
0
}
2961
2962
int
2963
PySet_Contains(PyObject *anyset, PyObject *key)
2964
185k
{
2965
185k
    if (!PyAnySet_Check(anyset)) {
2966
0
        PyErr_BadInternalCall();
2967
0
        return -1;
2968
0
    }
2969
185k
    if (PyFrozenSet_CheckExact(anyset)) {
2970
0
        return set_contains_key((PySetObject *)anyset, key);
2971
0
    }
2972
185k
    int rv;
2973
185k
    Py_BEGIN_CRITICAL_SECTION(anyset);
2974
185k
    rv = set_contains_key((PySetObject *)anyset, key);
2975
185k
    Py_END_CRITICAL_SECTION();
2976
185k
    return rv;
2977
185k
}
2978
2979
int
2980
PySet_Discard(PyObject *set, PyObject *key)
2981
86.6k
{
2982
86.6k
    if (!PySet_Check(set)) {
2983
0
        PyErr_BadInternalCall();
2984
0
        return -1;
2985
0
    }
2986
2987
86.6k
    int rv;
2988
86.6k
    Py_BEGIN_CRITICAL_SECTION(set);
2989
86.6k
    rv = set_discard_key((PySetObject *)set, key);
2990
86.6k
    Py_END_CRITICAL_SECTION();
2991
86.6k
    return rv;
2992
86.6k
}
2993
2994
int
2995
PySet_Add(PyObject *anyset, PyObject *key)
2996
57.3k
{
2997
57.3k
    if (PySet_Check(anyset)) {
2998
54.8k
        int rv;
2999
54.8k
        Py_BEGIN_CRITICAL_SECTION(anyset);
3000
54.8k
        rv = set_add_key((PySetObject *)anyset, key);
3001
54.8k
        Py_END_CRITICAL_SECTION();
3002
54.8k
        return rv;
3003
54.8k
    }
3004
3005
2.55k
    if (PyFrozenSet_Check(anyset) && _PyObject_IsUniquelyReferenced(anyset)) {
3006
        // We can only change frozensets if they are uniquely referenced. The
3007
        // API limits the usage of `PySet_Add` to "fill in the values of brand
3008
        // new frozensets before they are exposed to other code". In this case,
3009
        // this can be done without a lock.
3010
2.55k
        return set_add_key((PySetObject *)anyset, key);
3011
2.55k
    }
3012
3013
0
    PyErr_BadInternalCall();
3014
0
    return -1;
3015
2.55k
}
3016
3017
int
3018
_PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, Py_hash_t *hash)
3019
1.91k
{
3020
1.91k
    setentry *entry;
3021
3022
1.91k
    if (!PyAnySet_Check(set)) {
3023
0
        PyErr_BadInternalCall();
3024
0
        return -1;
3025
0
    }
3026
1.91k
    if (set_next((PySetObject *)set, pos, &entry) == 0)
3027
477
        return 0;
3028
1.43k
    *key = entry->key;
3029
1.43k
    *hash = entry->hash;
3030
1.43k
    return 1;
3031
1.91k
}
3032
3033
int
3034
_PySet_NextEntryRef(PyObject *set, Py_ssize_t *pos, PyObject **key, Py_hash_t *hash)
3035
110k
{
3036
110k
    setentry *entry;
3037
3038
110k
    if (!PyAnySet_Check(set)) {
3039
0
        PyErr_BadInternalCall();
3040
0
        return -1;
3041
0
    }
3042
110k
    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(set);
3043
110k
    if (set_next((PySetObject *)set, pos, &entry) == 0)
3044
19.1k
        return 0;
3045
91.5k
    *key = Py_NewRef(entry->key);
3046
91.5k
    *hash = entry->hash;
3047
91.5k
    return 1;
3048
110k
}
3049
3050
PyObject *
3051
PySet_Pop(PyObject *set)
3052
25
{
3053
25
    if (!PySet_Check(set)) {
3054
0
        PyErr_BadInternalCall();
3055
0
        return NULL;
3056
0
    }
3057
25
    return set_pop(set, NULL);
3058
25
}
3059
3060
int
3061
_PySet_Update(PyObject *set, PyObject *iterable)
3062
36
{
3063
36
    if (!PySet_Check(set)) {
3064
0
        PyErr_BadInternalCall();
3065
0
        return -1;
3066
0
    }
3067
36
    return set_update_internal((PySetObject *)set, iterable);
3068
36
}
3069
3070
/* Exported for the gdb plugin's benefit. */
3071
PyObject *_PySet_Dummy = dummy;
3072
3073
/***** Dummy Struct  *************************************************/
3074
3075
static PyObject *
3076
dummy_repr(PyObject *op)
3077
0
{
3078
0
    return PyUnicode_FromString("<dummy key>");
3079
0
}
3080
3081
static void _Py_NO_RETURN
3082
dummy_dealloc(PyObject* ignore)
3083
0
{
3084
0
    Py_FatalError("deallocating <dummy key>");
3085
0
}
3086
3087
static PyTypeObject _PySetDummy_Type = {
3088
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
3089
    "<dummy key> type",
3090
    0,
3091
    0,
3092
    dummy_dealloc,      /*tp_dealloc*/ /*never called*/
3093
    0,                  /*tp_vectorcall_offset*/
3094
    0,                  /*tp_getattr*/
3095
    0,                  /*tp_setattr*/
3096
    0,                  /*tp_as_async*/
3097
    dummy_repr,         /*tp_repr*/
3098
    0,                  /*tp_as_number*/
3099
    0,                  /*tp_as_sequence*/
3100
    0,                  /*tp_as_mapping*/
3101
    0,                  /*tp_hash */
3102
    0,                  /*tp_call */
3103
    0,                  /*tp_str */
3104
    0,                  /*tp_getattro */
3105
    0,                  /*tp_setattro */
3106
    0,                  /*tp_as_buffer */
3107
    Py_TPFLAGS_DEFAULT, /*tp_flags */
3108
};
3109
3110
static PyObject _dummy_struct = _PyObject_HEAD_INIT(&_PySetDummy_Type);