@@ -713,6 +713,99 @@ _bool_shared(PyThreadState *tstate, PyObject *obj,
713
713
return 0 ;
714
714
}
715
715
716
+ struct _shared_tuple_data {
717
+ Py_ssize_t len ;
718
+ _PyCrossInterpreterData * * data ;
719
+ };
720
+
721
+ static PyObject *
722
+ _new_tuple_object (_PyCrossInterpreterData * data )
723
+ {
724
+ struct _shared_tuple_data * shared = (struct _shared_tuple_data * )(data -> data );
725
+ PyObject * tuple = PyTuple_New (shared -> len );
726
+ if (tuple == NULL ) {
727
+ return NULL ;
728
+ }
729
+
730
+ for (Py_ssize_t i = 0 ; i < shared -> len ; i ++ ) {
731
+ PyObject * item = _PyCrossInterpreterData_NewObject (shared -> data [i ]);
732
+ if (item == NULL ){
733
+ Py_DECREF (tuple );
734
+ return NULL ;
735
+ }
736
+ PyTuple_SET_ITEM (tuple , i , item );
737
+ }
738
+ return tuple ;
739
+ }
740
+
741
+ static void
742
+ _tuple_shared_free (void * data )
743
+ {
744
+ struct _shared_tuple_data * shared = (struct _shared_tuple_data * )(data );
745
+ #ifndef NDEBUG
746
+ int64_t interpid = PyInterpreterState_GetID (_PyInterpreterState_GET ());
747
+ #endif
748
+ for (Py_ssize_t i = 0 ; i < shared -> len ; i ++ ) {
749
+ if (shared -> data [i ] != NULL ) {
750
+ assert (shared -> data [i ]-> interpid == interpid );
751
+ _PyCrossInterpreterData_Release (shared -> data [i ]);
752
+ PyMem_RawFree (shared -> data [i ]);
753
+ shared -> data [i ] = NULL ;
754
+ }
755
+ }
756
+ PyMem_Free (shared -> data );
757
+ PyMem_RawFree (shared );
758
+ }
759
+
760
+ static int
761
+ _tuple_shared (PyThreadState * tstate , PyObject * obj ,
762
+ _PyCrossInterpreterData * data )
763
+ {
764
+ Py_ssize_t len = PyTuple_GET_SIZE (obj );
765
+ if (len < 0 ) {
766
+ return -1 ;
767
+ }
768
+ struct _shared_tuple_data * shared = PyMem_RawMalloc (sizeof (struct _shared_tuple_data ));
769
+ if (shared == NULL ){
770
+ PyErr_NoMemory ();
771
+ return -1 ;
772
+ }
773
+
774
+ shared -> len = len ;
775
+ shared -> data = (_PyCrossInterpreterData * * ) PyMem_Calloc (shared -> len , sizeof (_PyCrossInterpreterData * ));
776
+ if (shared -> data == NULL ) {
777
+ PyErr_NoMemory ();
778
+ return -1 ;
779
+ }
780
+
781
+ for (Py_ssize_t i = 0 ; i < shared -> len ; i ++ ) {
782
+ _PyCrossInterpreterData * data = _PyCrossInterpreterData_New ();
783
+ if (data == NULL ) {
784
+ goto error ; // PyErr_NoMemory already set
785
+ }
786
+ PyObject * item = PyTuple_GET_ITEM (obj , i );
787
+
788
+ int res = -1 ;
789
+ if (!_Py_EnterRecursiveCallTstate (tstate , " while sharing a tuple" )) {
790
+ res = _PyObject_GetCrossInterpreterData (item , data );
791
+ _Py_LeaveRecursiveCallTstate (tstate );
792
+ }
793
+ if (res < 0 ) {
794
+ PyMem_RawFree (data );
795
+ goto error ;
796
+ }
797
+ shared -> data [i ] = data ;
798
+ }
799
+ _PyCrossInterpreterData_Init (
800
+ data , tstate -> interp , shared , obj , _new_tuple_object );
801
+ data -> free = _tuple_shared_free ;
802
+ return 0 ;
803
+
804
+ error :
805
+ _tuple_shared_free (shared );
806
+ return -1 ;
807
+ }
808
+
716
809
static void
717
810
_register_builtins_for_crossinterpreter_data (struct _xidregistry * xidregistry )
718
811
{
@@ -745,6 +838,11 @@ _register_builtins_for_crossinterpreter_data(struct _xidregistry *xidregistry)
745
838
if (_xidregistry_add_type (xidregistry , & PyFloat_Type , _float_shared ) != 0 ) {
746
839
Py_FatalError ("could not register float for cross-interpreter sharing" );
747
840
}
841
+
842
+ // tuple
843
+ if (_xidregistry_add_type (xidregistry , & PyTuple_Type , _tuple_shared ) != 0 ) {
844
+ Py_FatalError ("could not register tuple for cross-interpreter sharing" );
845
+ }
748
846
}
749
847
750
848
/* registry lifecycle */
0 commit comments