@@ -3,12 +3,8 @@ from collections import defaultdict
3
3
cimport cython
4
4
from cpython.object cimport PyObject
5
5
from cpython.pyport cimport PY_SSIZE_T_MAX
6
- from cpython.ref cimport Py_DECREF
7
6
from cpython.slice cimport PySlice_GetIndicesEx
8
- from cpython.weakref cimport (
9
- PyWeakref_GetRef,
10
- PyWeakref_NewRef,
11
- )
7
+ from cpython.weakref cimport PyWeakref_NewRef
12
8
from cython cimport Py_ssize_t
13
9
14
10
import numpy as np
@@ -30,6 +26,14 @@ from pandas._libs.util cimport (
30
26
is_integer_object,
31
27
)
32
28
29
+ include " free_threading_config.pxi"
30
+
31
+ IF CYTHON_COMPATIBLE_WITH_FREE_THREADING:
32
+ from cpython.weakref cimport PyWeakref_GetRef
33
+ from cpython.ref cimport Py_DECREF
34
+ ELSE :
35
+ from cpython.weakref cimport PyWeakref_GetObject
36
+
33
37
34
38
cdef extern from " Python.h" :
35
39
PyObject* Py_None
@@ -909,24 +913,35 @@ cdef class BlockValuesRefs:
909
913
# if force=False. Clearing for every insertion causes slowdowns if
910
914
# all these objects stay alive, e.g. df.items() for wide DataFrames
911
915
# see GH#55245 and GH#55008
912
- cdef PyObject* pobj
913
- cdef bint status
916
+ IF CYTHON_COMPATIBLE_WITH_FREE_THREADING:
917
+ cdef PyObject* pobj
918
+ cdef bint status
914
919
915
920
if force or len (self .referenced_blocks) > self .clear_counter:
916
- new_referenced_blocks = []
917
- for ref in self .referenced_blocks:
918
- status = PyWeakref_GetRef(ref, & pobj)
919
- if status == 1 :
920
- new_referenced_blocks.append(ref)
921
- Py_DECREF(< object > pobj)
922
- self .referenced_blocks = new_referenced_blocks
921
+ IF CYTHON_COMPATIBLE_WITH_FREE_THREADING:
922
+ new_referenced_blocks = []
923
+ for ref in self .referenced_blocks:
924
+ status = PyWeakref_GetRef(ref, & pobj)
925
+ if status == 1 :
926
+ new_referenced_blocks.append(ref)
927
+ Py_DECREF(< object > pobj)
928
+ self .referenced_blocks = new_referenced_blocks
929
+ ELSE :
930
+ self .referenced_blocks = [
931
+ ref for ref in self .referenced_blocks
932
+ if PyWeakref_GetObject(ref) != Py_None
933
+ ]
923
934
924
935
nr_of_refs = len (self .referenced_blocks)
925
936
if nr_of_refs < self .clear_counter // 2 :
926
937
self .clear_counter = max (self .clear_counter // 2 , 500 )
927
938
elif nr_of_refs > self .clear_counter:
928
939
self .clear_counter = max (self .clear_counter * 2 , nr_of_refs)
929
940
941
+ cpdef _add_reference_maybe_locked(self , Block blk):
942
+ self ._clear_dead_references()
943
+ self .referenced_blocks.append(PyWeakref_NewRef(blk, None ))
944
+
930
945
cpdef add_reference(self , Block blk):
931
946
""" Adds a new reference to our reference collection.
932
947
@@ -935,9 +950,15 @@ cdef class BlockValuesRefs:
935
950
blk : Block
936
951
The block that the new references should point to.
937
952
"""
938
- with cython.critical_section(self ):
939
- self ._clear_dead_references()
940
- self .referenced_blocks.append(PyWeakref_NewRef(blk, None ))
953
+ IF CYTHON_COMPATIBLE_WITH_FREE_THREADING:
954
+ with cython.critical_section(self ):
955
+ self ._add_reference_maybe_locked(blk)
956
+ ELSE :
957
+ self ._add_reference_maybe_locked(blk)
958
+
959
+ def _add_index_reference_maybe_locked (self , index: object ) -> None:
960
+ self._clear_dead_references()
961
+ self.referenced_blocks.append(PyWeakref_NewRef(index , None ))
941
962
942
963
def add_index_reference(self , index: object ) -> None:
943
964
"""Adds a new reference to our reference collection when creating an index.
@@ -947,9 +968,16 @@ cdef class BlockValuesRefs:
947
968
index : Index
948
969
The index that the new reference should point to.
949
970
"""
950
- with cython.critical_section(self ):
951
- self ._clear_dead_references()
952
- self .referenced_blocks.append(PyWeakref_NewRef(index, None ))
971
+ IF CYTHON_COMPATIBLE_WITH_FREE_THREADING:
972
+ with cython.critical_section(self ):
973
+ self ._add_index_reference_maybe_locked(index)
974
+ ELSE :
975
+ self ._add_index_reference_maybe_locked(index)
976
+
977
+ def _has_reference_maybe_locked (self ) -> bool:
978
+ self._clear_dead_references(force = True )
979
+ # Checking for more references than block pointing to itself
980
+ return len(self.referenced_blocks ) > 1
953
981
954
982
def has_reference(self ) -> bool:
955
983
"""Checks if block has foreign references.
@@ -961,8 +989,8 @@ cdef class BlockValuesRefs:
961
989
-------
962
990
bool
963
991
"""
964
- with cython.critical_section( self ) :
965
- self ._clear_dead_references( force = True )
966
- # Checking for more references than block pointing to itself
967
- has_reference = len ( self .referenced_blocks) > 1
968
- return has_reference
992
+ IF CYTHON_COMPATIBLE_WITH_FREE_THREADING :
993
+ with cython.critical_section( self ):
994
+ return self ._has_reference_maybe_locked()
995
+ ELSE :
996
+ return self ._has_reference_maybe_locked()
0 commit comments