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