Skip to content

Commit ab9f8b9

Browse files
vstinnerfasihahmad
authored andcommitted
bpo-40521: Make the empty frozenset per interpreter (pythonGH-21068)
Each interpreter now has its own empty frozenset singleton.
1 parent f58ee94 commit ab9f8b9

File tree

5 files changed

+24
-19
lines changed

5 files changed

+24
-19
lines changed

Include/internal/pycore_interp.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,8 @@ struct _is {
238238
/* Using a cache is very effective since typically only a single slice is
239239
created and then deleted again. */
240240
PySliceObject *slice_cache;
241+
// The empty frozenset is a singleton.
242+
PyObject *empty_frozenset;
241243

242244
struct _Py_tuple_state tuple;
243245
struct _Py_list_state list;

Include/internal/pycore_pylifecycle.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ extern void _PyFrame_Fini(PyThreadState *tstate);
6262
extern void _PyDict_Fini(PyThreadState *tstate);
6363
extern void _PyTuple_Fini(PyThreadState *tstate);
6464
extern void _PyList_Fini(PyThreadState *tstate);
65-
extern void _PySet_Fini(void);
65+
extern void _PySet_Fini(PyThreadState *tstate);
6666
extern void _PyBytes_Fini(void);
6767
extern void _PyFloat_Fini(PyThreadState *tstate);
6868
extern void _PySlice_Fini(PyThreadState *tstate);
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
The tuple free lists, the empty tuple singleton, the list free list, the float
2-
free list, the slice cache, the dict free lists, the frame free list, the
3-
asynchronous generator free lists, and the context free list are no longer
4-
shared by all interpreters: each interpreter now its has own free lists and
5-
caches.
1+
The tuple free lists, the empty tuple singleton, the list free list, the empty
2+
frozenset singleton, the float free list, the slice cache, the dict free lists,
3+
the frame free list, the asynchronous generator free lists, and the context
4+
free list are no longer shared by all interpreters: each interpreter now its
5+
has own free lists and caches.

Objects/setobject.c

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -975,12 +975,11 @@ make_new_set_basetype(PyTypeObject *type, PyObject *iterable)
975975
return make_new_set(type, iterable);
976976
}
977977

978-
/* The empty frozenset is a singleton */
979-
static PyObject *emptyfrozenset = NULL;
980-
981978
static PyObject *
982979
make_new_frozenset(PyTypeObject *type, PyObject *iterable)
983980
{
981+
PyObject *res;
982+
984983
if (type != &PyFrozenSet_Type) {
985984
return make_new_set(type, iterable);
986985
}
@@ -991,7 +990,7 @@ make_new_frozenset(PyTypeObject *type, PyObject *iterable)
991990
Py_INCREF(iterable);
992991
return iterable;
993992
}
994-
PyObject *res = make_new_set((PyTypeObject *)type, iterable);
993+
res = make_new_set((PyTypeObject *)type, iterable);
995994
if (res == NULL || PySet_GET_SIZE(res) != 0) {
996995
return res;
997996
}
@@ -1000,11 +999,17 @@ make_new_frozenset(PyTypeObject *type, PyObject *iterable)
1000999
}
10011000

10021001
// The empty frozenset is a singleton
1003-
if (emptyfrozenset == NULL) {
1004-
emptyfrozenset = make_new_set((PyTypeObject *)type, NULL);
1002+
PyInterpreterState *interp = _PyInterpreterState_GET();
1003+
res = interp->empty_frozenset;
1004+
if (res == NULL) {
1005+
interp->empty_frozenset = make_new_set((PyTypeObject *)type, NULL);
1006+
res = interp->empty_frozenset;
1007+
if (res == NULL) {
1008+
return NULL;
1009+
}
10051010
}
1006-
Py_XINCREF(emptyfrozenset);
1007-
return emptyfrozenset;
1011+
Py_INCREF(res);
1012+
return res;
10081013
}
10091014

10101015
static PyObject *
@@ -2300,9 +2305,9 @@ PySet_Add(PyObject *anyset, PyObject *key)
23002305
}
23012306

23022307
void
2303-
_PySet_Fini(void)
2308+
_PySet_Fini(PyThreadState *tstate)
23042309
{
2305-
Py_CLEAR(emptyfrozenset);
2310+
Py_CLEAR(tstate->interp->empty_frozenset);
23062311
}
23072312

23082313
int

Python/pylifecycle.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,9 +1255,7 @@ finalize_interp_types(PyThreadState *tstate, int is_main_interp)
12551255
_PyAsyncGen_Fini(tstate);
12561256
_PyContext_Fini(tstate);
12571257

1258-
if (is_main_interp) {
1259-
_PySet_Fini();
1260-
}
1258+
_PySet_Fini(tstate);
12611259
_PyDict_Fini(tstate);
12621260
_PyList_Fini(tstate);
12631261
_PyTuple_Fini(tstate);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy