@@ -1878,8 +1878,9 @@ _release_xidata(void *arg)
1878
1878
_PyCrossInterpreterData * data = (_PyCrossInterpreterData * )arg ;
1879
1879
if (data -> free != NULL ) {
1880
1880
data -> free (data -> data );
1881
+ data -> data = NULL ;
1881
1882
}
1882
- Py_XDECREF (data -> obj );
1883
+ Py_CLEAR (data -> obj );
1883
1884
}
1884
1885
1885
1886
static void
@@ -1899,6 +1900,8 @@ _call_in_interpreter(struct _gilstate_runtime_state *gilstate,
1899
1900
save_tstate = _PyThreadState_Swap (gilstate , tstate );
1900
1901
}
1901
1902
1903
+ // XXX Once the GIL is per-interpreter, this should be called with the
1904
+ // calling interpreter's GIL released and the target interpreter's held.
1902
1905
func (arg );
1903
1906
1904
1907
// Switch back.
@@ -1943,21 +1946,73 @@ _PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *data)
1943
1946
crossinterpdatafunc. It would be simpler and more efficient. */
1944
1947
1945
1948
static int
1946
- _register_xidata (struct _xidregistry * xidregistry , PyTypeObject * cls ,
1949
+ _xidregistry_add_type (struct _xidregistry * xidregistry , PyTypeObject * cls ,
1947
1950
crossinterpdatafunc getdata )
1948
1951
{
1949
1952
// Note that we effectively replace already registered classes
1950
1953
// rather than failing.
1951
1954
struct _xidregitem * newhead = PyMem_RawMalloc (sizeof (struct _xidregitem ));
1952
- if (newhead == NULL )
1955
+ if (newhead == NULL ) {
1953
1956
return -1 ;
1954
- newhead -> cls = cls ;
1957
+ }
1958
+ // XXX Assign a callback to clear the entry from the registry?
1959
+ newhead -> cls = PyWeakref_NewRef ((PyObject * )cls , NULL );
1960
+ if (newhead -> cls == NULL ) {
1961
+ PyMem_RawFree (newhead );
1962
+ return -1 ;
1963
+ }
1955
1964
newhead -> getdata = getdata ;
1965
+ newhead -> prev = NULL ;
1956
1966
newhead -> next = xidregistry -> head ;
1967
+ if (newhead -> next != NULL ) {
1968
+ newhead -> next -> prev = newhead ;
1969
+ }
1957
1970
xidregistry -> head = newhead ;
1958
1971
return 0 ;
1959
1972
}
1960
1973
1974
+ static struct _xidregitem *
1975
+ _xidregistry_remove_entry (struct _xidregistry * xidregistry ,
1976
+ struct _xidregitem * entry )
1977
+ {
1978
+ struct _xidregitem * next = entry -> next ;
1979
+ if (entry -> prev != NULL ) {
1980
+ assert (entry -> prev -> next == entry );
1981
+ entry -> prev -> next = next ;
1982
+ }
1983
+ else {
1984
+ assert (xidregistry -> head == entry );
1985
+ xidregistry -> head = next ;
1986
+ }
1987
+ if (next != NULL ) {
1988
+ next -> prev = entry -> prev ;
1989
+ }
1990
+ Py_DECREF (entry -> cls );
1991
+ PyMem_RawFree (entry );
1992
+ return next ;
1993
+ }
1994
+
1995
+ static struct _xidregitem *
1996
+ _xidregistry_find_type (struct _xidregistry * xidregistry , PyTypeObject * cls )
1997
+ {
1998
+ struct _xidregitem * cur = xidregistry -> head ;
1999
+ while (cur != NULL ) {
2000
+ PyObject * registered = PyWeakref_GetObject (cur -> cls );
2001
+ if (registered == Py_None ) {
2002
+ // The weakly ref'ed object was freed.
2003
+ cur = _xidregistry_remove_entry (xidregistry , cur );
2004
+ }
2005
+ else {
2006
+ assert (PyType_Check (registered ));
2007
+ if (registered == (PyObject * )cls ) {
2008
+ return cur ;
2009
+ }
2010
+ cur = cur -> next ;
2011
+ }
2012
+ }
2013
+ return NULL ;
2014
+ }
2015
+
1961
2016
static void _register_builtins_for_crossinterpreter_data (struct _xidregistry * xidregistry );
1962
2017
1963
2018
int
@@ -1973,19 +2028,32 @@ _PyCrossInterpreterData_RegisterClass(PyTypeObject *cls,
1973
2028
return -1 ;
1974
2029
}
1975
2030
1976
- // Make sure the class isn't ever deallocated.
1977
- Py_INCREF ((PyObject * )cls );
1978
-
1979
2031
struct _xidregistry * xidregistry = & _PyRuntime .xidregistry ;
1980
2032
PyThread_acquire_lock (xidregistry -> mutex , WAIT_LOCK );
1981
2033
if (xidregistry -> head == NULL ) {
1982
2034
_register_builtins_for_crossinterpreter_data (xidregistry );
1983
2035
}
1984
- int res = _register_xidata (xidregistry , cls , getdata );
2036
+ int res = _xidregistry_add_type (xidregistry , cls , getdata );
1985
2037
PyThread_release_lock (xidregistry -> mutex );
1986
2038
return res ;
1987
2039
}
1988
2040
2041
+ int
2042
+ _PyCrossInterpreterData_UnregisterClass (PyTypeObject * cls )
2043
+ {
2044
+ int res = 0 ;
2045
+ struct _xidregistry * xidregistry = & _PyRuntime .xidregistry ;
2046
+ PyThread_acquire_lock (xidregistry -> mutex , WAIT_LOCK );
2047
+ struct _xidregitem * matched = _xidregistry_find_type (xidregistry , cls );
2048
+ if (matched != NULL ) {
2049
+ (void )_xidregistry_remove_entry (xidregistry , matched );
2050
+ res = 1 ;
2051
+ }
2052
+ PyThread_release_lock (xidregistry -> mutex );
2053
+ return res ;
2054
+ }
2055
+
2056
+
1989
2057
/* Cross-interpreter objects are looked up by exact match on the class.
1990
2058
We can reassess this policy when we move from a global registry to a
1991
2059
tp_* slot. */
@@ -1995,22 +2063,15 @@ _PyCrossInterpreterData_Lookup(PyObject *obj)
1995
2063
{
1996
2064
struct _xidregistry * xidregistry = & _PyRuntime .xidregistry ;
1997
2065
PyObject * cls = PyObject_Type (obj );
1998
- crossinterpdatafunc getdata = NULL ;
1999
2066
PyThread_acquire_lock (xidregistry -> mutex , WAIT_LOCK );
2000
- struct _xidregitem * cur = xidregistry -> head ;
2001
- if (cur == NULL ) {
2067
+ if (xidregistry -> head == NULL ) {
2002
2068
_register_builtins_for_crossinterpreter_data (xidregistry );
2003
- cur = xidregistry -> head ;
2004
- }
2005
- for (; cur != NULL ; cur = cur -> next ) {
2006
- if (cur -> cls == (PyTypeObject * )cls ) {
2007
- getdata = cur -> getdata ;
2008
- break ;
2009
- }
2010
2069
}
2070
+ struct _xidregitem * matched = _xidregistry_find_type (xidregistry ,
2071
+ (PyTypeObject * )cls );
2011
2072
Py_DECREF (cls );
2012
2073
PyThread_release_lock (xidregistry -> mutex );
2013
- return getdata ;
2074
+ return matched != NULL ? matched -> getdata : NULL ;
2014
2075
}
2015
2076
2016
2077
/* cross-interpreter data for builtin types */
@@ -2116,22 +2177,22 @@ static void
2116
2177
_register_builtins_for_crossinterpreter_data (struct _xidregistry * xidregistry )
2117
2178
{
2118
2179
// None
2119
- if (_register_xidata (xidregistry , (PyTypeObject * )PyObject_Type (Py_None ), _none_shared ) != 0 ) {
2180
+ if (_xidregistry_add_type (xidregistry , (PyTypeObject * )PyObject_Type (Py_None ), _none_shared ) != 0 ) {
2120
2181
Py_FatalError ("could not register None for cross-interpreter sharing" );
2121
2182
}
2122
2183
2123
2184
// int
2124
- if (_register_xidata (xidregistry , & PyLong_Type , _long_shared ) != 0 ) {
2185
+ if (_xidregistry_add_type (xidregistry , & PyLong_Type , _long_shared ) != 0 ) {
2125
2186
Py_FatalError ("could not register int for cross-interpreter sharing" );
2126
2187
}
2127
2188
2128
2189
// bytes
2129
- if (_register_xidata (xidregistry , & PyBytes_Type , _bytes_shared ) != 0 ) {
2190
+ if (_xidregistry_add_type (xidregistry , & PyBytes_Type , _bytes_shared ) != 0 ) {
2130
2191
Py_FatalError ("could not register bytes for cross-interpreter sharing" );
2131
2192
}
2132
2193
2133
2194
// str
2134
- if (_register_xidata (xidregistry , & PyUnicode_Type , _str_shared ) != 0 ) {
2195
+ if (_xidregistry_add_type (xidregistry , & PyUnicode_Type , _str_shared ) != 0 ) {
2135
2196
Py_FatalError ("could not register str for cross-interpreter sharing" );
2136
2197
}
2137
2198
}
0 commit comments