17db96d56Sopenharmony_ci 27db96d56Sopenharmony_ci/* interpreters module */ 37db96d56Sopenharmony_ci/* low-level access to interpreter primitives */ 47db96d56Sopenharmony_ci#ifndef Py_BUILD_CORE_BUILTIN 57db96d56Sopenharmony_ci# define Py_BUILD_CORE_MODULE 1 67db96d56Sopenharmony_ci#endif 77db96d56Sopenharmony_ci 87db96d56Sopenharmony_ci#include "Python.h" 97db96d56Sopenharmony_ci#include "pycore_frame.h" 107db96d56Sopenharmony_ci#include "pycore_pystate.h" // _PyThreadState_GET() 117db96d56Sopenharmony_ci#include "pycore_interpreteridobject.h" 127db96d56Sopenharmony_ci 137db96d56Sopenharmony_ci 147db96d56Sopenharmony_cistatic char * 157db96d56Sopenharmony_ci_copy_raw_string(PyObject *strobj) 167db96d56Sopenharmony_ci{ 177db96d56Sopenharmony_ci const char *str = PyUnicode_AsUTF8(strobj); 187db96d56Sopenharmony_ci if (str == NULL) { 197db96d56Sopenharmony_ci return NULL; 207db96d56Sopenharmony_ci } 217db96d56Sopenharmony_ci char *copied = PyMem_Malloc(strlen(str)+1); 227db96d56Sopenharmony_ci if (copied == NULL) { 237db96d56Sopenharmony_ci PyErr_NoMemory(); 247db96d56Sopenharmony_ci return NULL; 257db96d56Sopenharmony_ci } 267db96d56Sopenharmony_ci strcpy(copied, str); 277db96d56Sopenharmony_ci return copied; 287db96d56Sopenharmony_ci} 297db96d56Sopenharmony_ci 307db96d56Sopenharmony_cistatic PyInterpreterState * 317db96d56Sopenharmony_ci_get_current(void) 327db96d56Sopenharmony_ci{ 337db96d56Sopenharmony_ci // PyInterpreterState_Get() aborts if lookup fails, so don't need 347db96d56Sopenharmony_ci // to check the result for NULL. 357db96d56Sopenharmony_ci return PyInterpreterState_Get(); 367db96d56Sopenharmony_ci} 377db96d56Sopenharmony_ci 387db96d56Sopenharmony_ci 397db96d56Sopenharmony_ci/* data-sharing-specific code ***********************************************/ 407db96d56Sopenharmony_ci 417db96d56Sopenharmony_cistruct _sharednsitem { 427db96d56Sopenharmony_ci char *name; 437db96d56Sopenharmony_ci _PyCrossInterpreterData data; 447db96d56Sopenharmony_ci}; 457db96d56Sopenharmony_ci 467db96d56Sopenharmony_cistatic void _sharednsitem_clear(struct _sharednsitem *); // forward 477db96d56Sopenharmony_ci 487db96d56Sopenharmony_cistatic int 497db96d56Sopenharmony_ci_sharednsitem_init(struct _sharednsitem *item, PyObject *key, PyObject *value) 507db96d56Sopenharmony_ci{ 517db96d56Sopenharmony_ci item->name = _copy_raw_string(key); 527db96d56Sopenharmony_ci if (item->name == NULL) { 537db96d56Sopenharmony_ci return -1; 547db96d56Sopenharmony_ci } 557db96d56Sopenharmony_ci if (_PyObject_GetCrossInterpreterData(value, &item->data) != 0) { 567db96d56Sopenharmony_ci _sharednsitem_clear(item); 577db96d56Sopenharmony_ci return -1; 587db96d56Sopenharmony_ci } 597db96d56Sopenharmony_ci return 0; 607db96d56Sopenharmony_ci} 617db96d56Sopenharmony_ci 627db96d56Sopenharmony_cistatic void 637db96d56Sopenharmony_ci_sharednsitem_clear(struct _sharednsitem *item) 647db96d56Sopenharmony_ci{ 657db96d56Sopenharmony_ci if (item->name != NULL) { 667db96d56Sopenharmony_ci PyMem_Free(item->name); 677db96d56Sopenharmony_ci item->name = NULL; 687db96d56Sopenharmony_ci } 697db96d56Sopenharmony_ci _PyCrossInterpreterData_Release(&item->data); 707db96d56Sopenharmony_ci} 717db96d56Sopenharmony_ci 727db96d56Sopenharmony_cistatic int 737db96d56Sopenharmony_ci_sharednsitem_apply(struct _sharednsitem *item, PyObject *ns) 747db96d56Sopenharmony_ci{ 757db96d56Sopenharmony_ci PyObject *name = PyUnicode_FromString(item->name); 767db96d56Sopenharmony_ci if (name == NULL) { 777db96d56Sopenharmony_ci return -1; 787db96d56Sopenharmony_ci } 797db96d56Sopenharmony_ci PyObject *value = _PyCrossInterpreterData_NewObject(&item->data); 807db96d56Sopenharmony_ci if (value == NULL) { 817db96d56Sopenharmony_ci Py_DECREF(name); 827db96d56Sopenharmony_ci return -1; 837db96d56Sopenharmony_ci } 847db96d56Sopenharmony_ci int res = PyDict_SetItem(ns, name, value); 857db96d56Sopenharmony_ci Py_DECREF(name); 867db96d56Sopenharmony_ci Py_DECREF(value); 877db96d56Sopenharmony_ci return res; 887db96d56Sopenharmony_ci} 897db96d56Sopenharmony_ci 907db96d56Sopenharmony_citypedef struct _sharedns { 917db96d56Sopenharmony_ci Py_ssize_t len; 927db96d56Sopenharmony_ci struct _sharednsitem* items; 937db96d56Sopenharmony_ci} _sharedns; 947db96d56Sopenharmony_ci 957db96d56Sopenharmony_cistatic _sharedns * 967db96d56Sopenharmony_ci_sharedns_new(Py_ssize_t len) 977db96d56Sopenharmony_ci{ 987db96d56Sopenharmony_ci _sharedns *shared = PyMem_NEW(_sharedns, 1); 997db96d56Sopenharmony_ci if (shared == NULL) { 1007db96d56Sopenharmony_ci PyErr_NoMemory(); 1017db96d56Sopenharmony_ci return NULL; 1027db96d56Sopenharmony_ci } 1037db96d56Sopenharmony_ci shared->len = len; 1047db96d56Sopenharmony_ci shared->items = PyMem_NEW(struct _sharednsitem, len); 1057db96d56Sopenharmony_ci if (shared->items == NULL) { 1067db96d56Sopenharmony_ci PyErr_NoMemory(); 1077db96d56Sopenharmony_ci PyMem_Free(shared); 1087db96d56Sopenharmony_ci return NULL; 1097db96d56Sopenharmony_ci } 1107db96d56Sopenharmony_ci return shared; 1117db96d56Sopenharmony_ci} 1127db96d56Sopenharmony_ci 1137db96d56Sopenharmony_cistatic void 1147db96d56Sopenharmony_ci_sharedns_free(_sharedns *shared) 1157db96d56Sopenharmony_ci{ 1167db96d56Sopenharmony_ci for (Py_ssize_t i=0; i < shared->len; i++) { 1177db96d56Sopenharmony_ci _sharednsitem_clear(&shared->items[i]); 1187db96d56Sopenharmony_ci } 1197db96d56Sopenharmony_ci PyMem_Free(shared->items); 1207db96d56Sopenharmony_ci PyMem_Free(shared); 1217db96d56Sopenharmony_ci} 1227db96d56Sopenharmony_ci 1237db96d56Sopenharmony_cistatic _sharedns * 1247db96d56Sopenharmony_ci_get_shared_ns(PyObject *shareable) 1257db96d56Sopenharmony_ci{ 1267db96d56Sopenharmony_ci if (shareable == NULL || shareable == Py_None) { 1277db96d56Sopenharmony_ci return NULL; 1287db96d56Sopenharmony_ci } 1297db96d56Sopenharmony_ci Py_ssize_t len = PyDict_Size(shareable); 1307db96d56Sopenharmony_ci if (len == 0) { 1317db96d56Sopenharmony_ci return NULL; 1327db96d56Sopenharmony_ci } 1337db96d56Sopenharmony_ci 1347db96d56Sopenharmony_ci _sharedns *shared = _sharedns_new(len); 1357db96d56Sopenharmony_ci if (shared == NULL) { 1367db96d56Sopenharmony_ci return NULL; 1377db96d56Sopenharmony_ci } 1387db96d56Sopenharmony_ci Py_ssize_t pos = 0; 1397db96d56Sopenharmony_ci for (Py_ssize_t i=0; i < len; i++) { 1407db96d56Sopenharmony_ci PyObject *key, *value; 1417db96d56Sopenharmony_ci if (PyDict_Next(shareable, &pos, &key, &value) == 0) { 1427db96d56Sopenharmony_ci break; 1437db96d56Sopenharmony_ci } 1447db96d56Sopenharmony_ci if (_sharednsitem_init(&shared->items[i], key, value) != 0) { 1457db96d56Sopenharmony_ci break; 1467db96d56Sopenharmony_ci } 1477db96d56Sopenharmony_ci } 1487db96d56Sopenharmony_ci if (PyErr_Occurred()) { 1497db96d56Sopenharmony_ci _sharedns_free(shared); 1507db96d56Sopenharmony_ci return NULL; 1517db96d56Sopenharmony_ci } 1527db96d56Sopenharmony_ci return shared; 1537db96d56Sopenharmony_ci} 1547db96d56Sopenharmony_ci 1557db96d56Sopenharmony_cistatic int 1567db96d56Sopenharmony_ci_sharedns_apply(_sharedns *shared, PyObject *ns) 1577db96d56Sopenharmony_ci{ 1587db96d56Sopenharmony_ci for (Py_ssize_t i=0; i < shared->len; i++) { 1597db96d56Sopenharmony_ci if (_sharednsitem_apply(&shared->items[i], ns) != 0) { 1607db96d56Sopenharmony_ci return -1; 1617db96d56Sopenharmony_ci } 1627db96d56Sopenharmony_ci } 1637db96d56Sopenharmony_ci return 0; 1647db96d56Sopenharmony_ci} 1657db96d56Sopenharmony_ci 1667db96d56Sopenharmony_ci// Ultimately we'd like to preserve enough information about the 1677db96d56Sopenharmony_ci// exception and traceback that we could re-constitute (or at least 1687db96d56Sopenharmony_ci// simulate, a la traceback.TracebackException), and even chain, a copy 1697db96d56Sopenharmony_ci// of the exception in the calling interpreter. 1707db96d56Sopenharmony_ci 1717db96d56Sopenharmony_citypedef struct _sharedexception { 1727db96d56Sopenharmony_ci char *name; 1737db96d56Sopenharmony_ci char *msg; 1747db96d56Sopenharmony_ci} _sharedexception; 1757db96d56Sopenharmony_ci 1767db96d56Sopenharmony_cistatic _sharedexception * 1777db96d56Sopenharmony_ci_sharedexception_new(void) 1787db96d56Sopenharmony_ci{ 1797db96d56Sopenharmony_ci _sharedexception *err = PyMem_NEW(_sharedexception, 1); 1807db96d56Sopenharmony_ci if (err == NULL) { 1817db96d56Sopenharmony_ci PyErr_NoMemory(); 1827db96d56Sopenharmony_ci return NULL; 1837db96d56Sopenharmony_ci } 1847db96d56Sopenharmony_ci err->name = NULL; 1857db96d56Sopenharmony_ci err->msg = NULL; 1867db96d56Sopenharmony_ci return err; 1877db96d56Sopenharmony_ci} 1887db96d56Sopenharmony_ci 1897db96d56Sopenharmony_cistatic void 1907db96d56Sopenharmony_ci_sharedexception_clear(_sharedexception *exc) 1917db96d56Sopenharmony_ci{ 1927db96d56Sopenharmony_ci if (exc->name != NULL) { 1937db96d56Sopenharmony_ci PyMem_Free(exc->name); 1947db96d56Sopenharmony_ci } 1957db96d56Sopenharmony_ci if (exc->msg != NULL) { 1967db96d56Sopenharmony_ci PyMem_Free(exc->msg); 1977db96d56Sopenharmony_ci } 1987db96d56Sopenharmony_ci} 1997db96d56Sopenharmony_ci 2007db96d56Sopenharmony_cistatic void 2017db96d56Sopenharmony_ci_sharedexception_free(_sharedexception *exc) 2027db96d56Sopenharmony_ci{ 2037db96d56Sopenharmony_ci _sharedexception_clear(exc); 2047db96d56Sopenharmony_ci PyMem_Free(exc); 2057db96d56Sopenharmony_ci} 2067db96d56Sopenharmony_ci 2077db96d56Sopenharmony_cistatic _sharedexception * 2087db96d56Sopenharmony_ci_sharedexception_bind(PyObject *exctype, PyObject *exc, PyObject *tb) 2097db96d56Sopenharmony_ci{ 2107db96d56Sopenharmony_ci assert(exctype != NULL); 2117db96d56Sopenharmony_ci char *failure = NULL; 2127db96d56Sopenharmony_ci 2137db96d56Sopenharmony_ci _sharedexception *err = _sharedexception_new(); 2147db96d56Sopenharmony_ci if (err == NULL) { 2157db96d56Sopenharmony_ci goto finally; 2167db96d56Sopenharmony_ci } 2177db96d56Sopenharmony_ci 2187db96d56Sopenharmony_ci PyObject *name = PyUnicode_FromFormat("%S", exctype); 2197db96d56Sopenharmony_ci if (name == NULL) { 2207db96d56Sopenharmony_ci failure = "unable to format exception type name"; 2217db96d56Sopenharmony_ci goto finally; 2227db96d56Sopenharmony_ci } 2237db96d56Sopenharmony_ci err->name = _copy_raw_string(name); 2247db96d56Sopenharmony_ci Py_DECREF(name); 2257db96d56Sopenharmony_ci if (err->name == NULL) { 2267db96d56Sopenharmony_ci if (PyErr_ExceptionMatches(PyExc_MemoryError)) { 2277db96d56Sopenharmony_ci failure = "out of memory copying exception type name"; 2287db96d56Sopenharmony_ci } else { 2297db96d56Sopenharmony_ci failure = "unable to encode and copy exception type name"; 2307db96d56Sopenharmony_ci } 2317db96d56Sopenharmony_ci goto finally; 2327db96d56Sopenharmony_ci } 2337db96d56Sopenharmony_ci 2347db96d56Sopenharmony_ci if (exc != NULL) { 2357db96d56Sopenharmony_ci PyObject *msg = PyUnicode_FromFormat("%S", exc); 2367db96d56Sopenharmony_ci if (msg == NULL) { 2377db96d56Sopenharmony_ci failure = "unable to format exception message"; 2387db96d56Sopenharmony_ci goto finally; 2397db96d56Sopenharmony_ci } 2407db96d56Sopenharmony_ci err->msg = _copy_raw_string(msg); 2417db96d56Sopenharmony_ci Py_DECREF(msg); 2427db96d56Sopenharmony_ci if (err->msg == NULL) { 2437db96d56Sopenharmony_ci if (PyErr_ExceptionMatches(PyExc_MemoryError)) { 2447db96d56Sopenharmony_ci failure = "out of memory copying exception message"; 2457db96d56Sopenharmony_ci } else { 2467db96d56Sopenharmony_ci failure = "unable to encode and copy exception message"; 2477db96d56Sopenharmony_ci } 2487db96d56Sopenharmony_ci goto finally; 2497db96d56Sopenharmony_ci } 2507db96d56Sopenharmony_ci } 2517db96d56Sopenharmony_ci 2527db96d56Sopenharmony_cifinally: 2537db96d56Sopenharmony_ci if (failure != NULL) { 2547db96d56Sopenharmony_ci PyErr_Clear(); 2557db96d56Sopenharmony_ci if (err->name != NULL) { 2567db96d56Sopenharmony_ci PyMem_Free(err->name); 2577db96d56Sopenharmony_ci err->name = NULL; 2587db96d56Sopenharmony_ci } 2597db96d56Sopenharmony_ci err->msg = failure; 2607db96d56Sopenharmony_ci } 2617db96d56Sopenharmony_ci return err; 2627db96d56Sopenharmony_ci} 2637db96d56Sopenharmony_ci 2647db96d56Sopenharmony_cistatic void 2657db96d56Sopenharmony_ci_sharedexception_apply(_sharedexception *exc, PyObject *wrapperclass) 2667db96d56Sopenharmony_ci{ 2677db96d56Sopenharmony_ci if (exc->name != NULL) { 2687db96d56Sopenharmony_ci if (exc->msg != NULL) { 2697db96d56Sopenharmony_ci PyErr_Format(wrapperclass, "%s: %s", exc->name, exc->msg); 2707db96d56Sopenharmony_ci } 2717db96d56Sopenharmony_ci else { 2727db96d56Sopenharmony_ci PyErr_SetString(wrapperclass, exc->name); 2737db96d56Sopenharmony_ci } 2747db96d56Sopenharmony_ci } 2757db96d56Sopenharmony_ci else if (exc->msg != NULL) { 2767db96d56Sopenharmony_ci PyErr_SetString(wrapperclass, exc->msg); 2777db96d56Sopenharmony_ci } 2787db96d56Sopenharmony_ci else { 2797db96d56Sopenharmony_ci PyErr_SetNone(wrapperclass); 2807db96d56Sopenharmony_ci } 2817db96d56Sopenharmony_ci} 2827db96d56Sopenharmony_ci 2837db96d56Sopenharmony_ci 2847db96d56Sopenharmony_ci/* channel-specific code ****************************************************/ 2857db96d56Sopenharmony_ci 2867db96d56Sopenharmony_ci#define CHANNEL_SEND 1 2877db96d56Sopenharmony_ci#define CHANNEL_BOTH 0 2887db96d56Sopenharmony_ci#define CHANNEL_RECV -1 2897db96d56Sopenharmony_ci 2907db96d56Sopenharmony_cistatic PyObject *ChannelError; 2917db96d56Sopenharmony_cistatic PyObject *ChannelNotFoundError; 2927db96d56Sopenharmony_cistatic PyObject *ChannelClosedError; 2937db96d56Sopenharmony_cistatic PyObject *ChannelEmptyError; 2947db96d56Sopenharmony_cistatic PyObject *ChannelNotEmptyError; 2957db96d56Sopenharmony_ci 2967db96d56Sopenharmony_cistatic int 2977db96d56Sopenharmony_cichannel_exceptions_init(PyObject *ns) 2987db96d56Sopenharmony_ci{ 2997db96d56Sopenharmony_ci // XXX Move the exceptions into per-module memory? 3007db96d56Sopenharmony_ci 3017db96d56Sopenharmony_ci // A channel-related operation failed. 3027db96d56Sopenharmony_ci ChannelError = PyErr_NewException("_xxsubinterpreters.ChannelError", 3037db96d56Sopenharmony_ci PyExc_RuntimeError, NULL); 3047db96d56Sopenharmony_ci if (ChannelError == NULL) { 3057db96d56Sopenharmony_ci return -1; 3067db96d56Sopenharmony_ci } 3077db96d56Sopenharmony_ci if (PyDict_SetItemString(ns, "ChannelError", ChannelError) != 0) { 3087db96d56Sopenharmony_ci return -1; 3097db96d56Sopenharmony_ci } 3107db96d56Sopenharmony_ci 3117db96d56Sopenharmony_ci // An operation tried to use a channel that doesn't exist. 3127db96d56Sopenharmony_ci ChannelNotFoundError = PyErr_NewException( 3137db96d56Sopenharmony_ci "_xxsubinterpreters.ChannelNotFoundError", ChannelError, NULL); 3147db96d56Sopenharmony_ci if (ChannelNotFoundError == NULL) { 3157db96d56Sopenharmony_ci return -1; 3167db96d56Sopenharmony_ci } 3177db96d56Sopenharmony_ci if (PyDict_SetItemString(ns, "ChannelNotFoundError", ChannelNotFoundError) != 0) { 3187db96d56Sopenharmony_ci return -1; 3197db96d56Sopenharmony_ci } 3207db96d56Sopenharmony_ci 3217db96d56Sopenharmony_ci // An operation tried to use a closed channel. 3227db96d56Sopenharmony_ci ChannelClosedError = PyErr_NewException( 3237db96d56Sopenharmony_ci "_xxsubinterpreters.ChannelClosedError", ChannelError, NULL); 3247db96d56Sopenharmony_ci if (ChannelClosedError == NULL) { 3257db96d56Sopenharmony_ci return -1; 3267db96d56Sopenharmony_ci } 3277db96d56Sopenharmony_ci if (PyDict_SetItemString(ns, "ChannelClosedError", ChannelClosedError) != 0) { 3287db96d56Sopenharmony_ci return -1; 3297db96d56Sopenharmony_ci } 3307db96d56Sopenharmony_ci 3317db96d56Sopenharmony_ci // An operation tried to pop from an empty channel. 3327db96d56Sopenharmony_ci ChannelEmptyError = PyErr_NewException( 3337db96d56Sopenharmony_ci "_xxsubinterpreters.ChannelEmptyError", ChannelError, NULL); 3347db96d56Sopenharmony_ci if (ChannelEmptyError == NULL) { 3357db96d56Sopenharmony_ci return -1; 3367db96d56Sopenharmony_ci } 3377db96d56Sopenharmony_ci if (PyDict_SetItemString(ns, "ChannelEmptyError", ChannelEmptyError) != 0) { 3387db96d56Sopenharmony_ci return -1; 3397db96d56Sopenharmony_ci } 3407db96d56Sopenharmony_ci 3417db96d56Sopenharmony_ci // An operation tried to close a non-empty channel. 3427db96d56Sopenharmony_ci ChannelNotEmptyError = PyErr_NewException( 3437db96d56Sopenharmony_ci "_xxsubinterpreters.ChannelNotEmptyError", ChannelError, NULL); 3447db96d56Sopenharmony_ci if (ChannelNotEmptyError == NULL) { 3457db96d56Sopenharmony_ci return -1; 3467db96d56Sopenharmony_ci } 3477db96d56Sopenharmony_ci if (PyDict_SetItemString(ns, "ChannelNotEmptyError", ChannelNotEmptyError) != 0) { 3487db96d56Sopenharmony_ci return -1; 3497db96d56Sopenharmony_ci } 3507db96d56Sopenharmony_ci 3517db96d56Sopenharmony_ci return 0; 3527db96d56Sopenharmony_ci} 3537db96d56Sopenharmony_ci 3547db96d56Sopenharmony_ci/* the channel queue */ 3557db96d56Sopenharmony_ci 3567db96d56Sopenharmony_cistruct _channelitem; 3577db96d56Sopenharmony_ci 3587db96d56Sopenharmony_citypedef struct _channelitem { 3597db96d56Sopenharmony_ci _PyCrossInterpreterData *data; 3607db96d56Sopenharmony_ci struct _channelitem *next; 3617db96d56Sopenharmony_ci} _channelitem; 3627db96d56Sopenharmony_ci 3637db96d56Sopenharmony_cistatic _channelitem * 3647db96d56Sopenharmony_ci_channelitem_new(void) 3657db96d56Sopenharmony_ci{ 3667db96d56Sopenharmony_ci _channelitem *item = PyMem_NEW(_channelitem, 1); 3677db96d56Sopenharmony_ci if (item == NULL) { 3687db96d56Sopenharmony_ci PyErr_NoMemory(); 3697db96d56Sopenharmony_ci return NULL; 3707db96d56Sopenharmony_ci } 3717db96d56Sopenharmony_ci item->data = NULL; 3727db96d56Sopenharmony_ci item->next = NULL; 3737db96d56Sopenharmony_ci return item; 3747db96d56Sopenharmony_ci} 3757db96d56Sopenharmony_ci 3767db96d56Sopenharmony_cistatic void 3777db96d56Sopenharmony_ci_channelitem_clear(_channelitem *item) 3787db96d56Sopenharmony_ci{ 3797db96d56Sopenharmony_ci if (item->data != NULL) { 3807db96d56Sopenharmony_ci _PyCrossInterpreterData_Release(item->data); 3817db96d56Sopenharmony_ci PyMem_Free(item->data); 3827db96d56Sopenharmony_ci item->data = NULL; 3837db96d56Sopenharmony_ci } 3847db96d56Sopenharmony_ci item->next = NULL; 3857db96d56Sopenharmony_ci} 3867db96d56Sopenharmony_ci 3877db96d56Sopenharmony_cistatic void 3887db96d56Sopenharmony_ci_channelitem_free(_channelitem *item) 3897db96d56Sopenharmony_ci{ 3907db96d56Sopenharmony_ci _channelitem_clear(item); 3917db96d56Sopenharmony_ci PyMem_Free(item); 3927db96d56Sopenharmony_ci} 3937db96d56Sopenharmony_ci 3947db96d56Sopenharmony_cistatic void 3957db96d56Sopenharmony_ci_channelitem_free_all(_channelitem *item) 3967db96d56Sopenharmony_ci{ 3977db96d56Sopenharmony_ci while (item != NULL) { 3987db96d56Sopenharmony_ci _channelitem *last = item; 3997db96d56Sopenharmony_ci item = item->next; 4007db96d56Sopenharmony_ci _channelitem_free(last); 4017db96d56Sopenharmony_ci } 4027db96d56Sopenharmony_ci} 4037db96d56Sopenharmony_ci 4047db96d56Sopenharmony_cistatic _PyCrossInterpreterData * 4057db96d56Sopenharmony_ci_channelitem_popped(_channelitem *item) 4067db96d56Sopenharmony_ci{ 4077db96d56Sopenharmony_ci _PyCrossInterpreterData *data = item->data; 4087db96d56Sopenharmony_ci item->data = NULL; 4097db96d56Sopenharmony_ci _channelitem_free(item); 4107db96d56Sopenharmony_ci return data; 4117db96d56Sopenharmony_ci} 4127db96d56Sopenharmony_ci 4137db96d56Sopenharmony_citypedef struct _channelqueue { 4147db96d56Sopenharmony_ci int64_t count; 4157db96d56Sopenharmony_ci _channelitem *first; 4167db96d56Sopenharmony_ci _channelitem *last; 4177db96d56Sopenharmony_ci} _channelqueue; 4187db96d56Sopenharmony_ci 4197db96d56Sopenharmony_cistatic _channelqueue * 4207db96d56Sopenharmony_ci_channelqueue_new(void) 4217db96d56Sopenharmony_ci{ 4227db96d56Sopenharmony_ci _channelqueue *queue = PyMem_NEW(_channelqueue, 1); 4237db96d56Sopenharmony_ci if (queue == NULL) { 4247db96d56Sopenharmony_ci PyErr_NoMemory(); 4257db96d56Sopenharmony_ci return NULL; 4267db96d56Sopenharmony_ci } 4277db96d56Sopenharmony_ci queue->count = 0; 4287db96d56Sopenharmony_ci queue->first = NULL; 4297db96d56Sopenharmony_ci queue->last = NULL; 4307db96d56Sopenharmony_ci return queue; 4317db96d56Sopenharmony_ci} 4327db96d56Sopenharmony_ci 4337db96d56Sopenharmony_cistatic void 4347db96d56Sopenharmony_ci_channelqueue_clear(_channelqueue *queue) 4357db96d56Sopenharmony_ci{ 4367db96d56Sopenharmony_ci _channelitem_free_all(queue->first); 4377db96d56Sopenharmony_ci queue->count = 0; 4387db96d56Sopenharmony_ci queue->first = NULL; 4397db96d56Sopenharmony_ci queue->last = NULL; 4407db96d56Sopenharmony_ci} 4417db96d56Sopenharmony_ci 4427db96d56Sopenharmony_cistatic void 4437db96d56Sopenharmony_ci_channelqueue_free(_channelqueue *queue) 4447db96d56Sopenharmony_ci{ 4457db96d56Sopenharmony_ci _channelqueue_clear(queue); 4467db96d56Sopenharmony_ci PyMem_Free(queue); 4477db96d56Sopenharmony_ci} 4487db96d56Sopenharmony_ci 4497db96d56Sopenharmony_cistatic int 4507db96d56Sopenharmony_ci_channelqueue_put(_channelqueue *queue, _PyCrossInterpreterData *data) 4517db96d56Sopenharmony_ci{ 4527db96d56Sopenharmony_ci _channelitem *item = _channelitem_new(); 4537db96d56Sopenharmony_ci if (item == NULL) { 4547db96d56Sopenharmony_ci return -1; 4557db96d56Sopenharmony_ci } 4567db96d56Sopenharmony_ci item->data = data; 4577db96d56Sopenharmony_ci 4587db96d56Sopenharmony_ci queue->count += 1; 4597db96d56Sopenharmony_ci if (queue->first == NULL) { 4607db96d56Sopenharmony_ci queue->first = item; 4617db96d56Sopenharmony_ci } 4627db96d56Sopenharmony_ci else { 4637db96d56Sopenharmony_ci queue->last->next = item; 4647db96d56Sopenharmony_ci } 4657db96d56Sopenharmony_ci queue->last = item; 4667db96d56Sopenharmony_ci return 0; 4677db96d56Sopenharmony_ci} 4687db96d56Sopenharmony_ci 4697db96d56Sopenharmony_cistatic _PyCrossInterpreterData * 4707db96d56Sopenharmony_ci_channelqueue_get(_channelqueue *queue) 4717db96d56Sopenharmony_ci{ 4727db96d56Sopenharmony_ci _channelitem *item = queue->first; 4737db96d56Sopenharmony_ci if (item == NULL) { 4747db96d56Sopenharmony_ci return NULL; 4757db96d56Sopenharmony_ci } 4767db96d56Sopenharmony_ci queue->first = item->next; 4777db96d56Sopenharmony_ci if (queue->last == item) { 4787db96d56Sopenharmony_ci queue->last = NULL; 4797db96d56Sopenharmony_ci } 4807db96d56Sopenharmony_ci queue->count -= 1; 4817db96d56Sopenharmony_ci 4827db96d56Sopenharmony_ci return _channelitem_popped(item); 4837db96d56Sopenharmony_ci} 4847db96d56Sopenharmony_ci 4857db96d56Sopenharmony_ci/* channel-interpreter associations */ 4867db96d56Sopenharmony_ci 4877db96d56Sopenharmony_cistruct _channelend; 4887db96d56Sopenharmony_ci 4897db96d56Sopenharmony_citypedef struct _channelend { 4907db96d56Sopenharmony_ci struct _channelend *next; 4917db96d56Sopenharmony_ci int64_t interp; 4927db96d56Sopenharmony_ci int open; 4937db96d56Sopenharmony_ci} _channelend; 4947db96d56Sopenharmony_ci 4957db96d56Sopenharmony_cistatic _channelend * 4967db96d56Sopenharmony_ci_channelend_new(int64_t interp) 4977db96d56Sopenharmony_ci{ 4987db96d56Sopenharmony_ci _channelend *end = PyMem_NEW(_channelend, 1); 4997db96d56Sopenharmony_ci if (end == NULL) { 5007db96d56Sopenharmony_ci PyErr_NoMemory(); 5017db96d56Sopenharmony_ci return NULL; 5027db96d56Sopenharmony_ci } 5037db96d56Sopenharmony_ci end->next = NULL; 5047db96d56Sopenharmony_ci end->interp = interp; 5057db96d56Sopenharmony_ci end->open = 1; 5067db96d56Sopenharmony_ci return end; 5077db96d56Sopenharmony_ci} 5087db96d56Sopenharmony_ci 5097db96d56Sopenharmony_cistatic void 5107db96d56Sopenharmony_ci_channelend_free(_channelend *end) 5117db96d56Sopenharmony_ci{ 5127db96d56Sopenharmony_ci PyMem_Free(end); 5137db96d56Sopenharmony_ci} 5147db96d56Sopenharmony_ci 5157db96d56Sopenharmony_cistatic void 5167db96d56Sopenharmony_ci_channelend_free_all(_channelend *end) 5177db96d56Sopenharmony_ci{ 5187db96d56Sopenharmony_ci while (end != NULL) { 5197db96d56Sopenharmony_ci _channelend *last = end; 5207db96d56Sopenharmony_ci end = end->next; 5217db96d56Sopenharmony_ci _channelend_free(last); 5227db96d56Sopenharmony_ci } 5237db96d56Sopenharmony_ci} 5247db96d56Sopenharmony_ci 5257db96d56Sopenharmony_cistatic _channelend * 5267db96d56Sopenharmony_ci_channelend_find(_channelend *first, int64_t interp, _channelend **pprev) 5277db96d56Sopenharmony_ci{ 5287db96d56Sopenharmony_ci _channelend *prev = NULL; 5297db96d56Sopenharmony_ci _channelend *end = first; 5307db96d56Sopenharmony_ci while (end != NULL) { 5317db96d56Sopenharmony_ci if (end->interp == interp) { 5327db96d56Sopenharmony_ci break; 5337db96d56Sopenharmony_ci } 5347db96d56Sopenharmony_ci prev = end; 5357db96d56Sopenharmony_ci end = end->next; 5367db96d56Sopenharmony_ci } 5377db96d56Sopenharmony_ci if (pprev != NULL) { 5387db96d56Sopenharmony_ci *pprev = prev; 5397db96d56Sopenharmony_ci } 5407db96d56Sopenharmony_ci return end; 5417db96d56Sopenharmony_ci} 5427db96d56Sopenharmony_ci 5437db96d56Sopenharmony_citypedef struct _channelassociations { 5447db96d56Sopenharmony_ci // Note that the list entries are never removed for interpreter 5457db96d56Sopenharmony_ci // for which the channel is closed. This should not be a problem in 5467db96d56Sopenharmony_ci // practice. Also, a channel isn't automatically closed when an 5477db96d56Sopenharmony_ci // interpreter is destroyed. 5487db96d56Sopenharmony_ci int64_t numsendopen; 5497db96d56Sopenharmony_ci int64_t numrecvopen; 5507db96d56Sopenharmony_ci _channelend *send; 5517db96d56Sopenharmony_ci _channelend *recv; 5527db96d56Sopenharmony_ci} _channelends; 5537db96d56Sopenharmony_ci 5547db96d56Sopenharmony_cistatic _channelends * 5557db96d56Sopenharmony_ci_channelends_new(void) 5567db96d56Sopenharmony_ci{ 5577db96d56Sopenharmony_ci _channelends *ends = PyMem_NEW(_channelends, 1); 5587db96d56Sopenharmony_ci if (ends== NULL) { 5597db96d56Sopenharmony_ci return NULL; 5607db96d56Sopenharmony_ci } 5617db96d56Sopenharmony_ci ends->numsendopen = 0; 5627db96d56Sopenharmony_ci ends->numrecvopen = 0; 5637db96d56Sopenharmony_ci ends->send = NULL; 5647db96d56Sopenharmony_ci ends->recv = NULL; 5657db96d56Sopenharmony_ci return ends; 5667db96d56Sopenharmony_ci} 5677db96d56Sopenharmony_ci 5687db96d56Sopenharmony_cistatic void 5697db96d56Sopenharmony_ci_channelends_clear(_channelends *ends) 5707db96d56Sopenharmony_ci{ 5717db96d56Sopenharmony_ci _channelend_free_all(ends->send); 5727db96d56Sopenharmony_ci ends->send = NULL; 5737db96d56Sopenharmony_ci ends->numsendopen = 0; 5747db96d56Sopenharmony_ci 5757db96d56Sopenharmony_ci _channelend_free_all(ends->recv); 5767db96d56Sopenharmony_ci ends->recv = NULL; 5777db96d56Sopenharmony_ci ends->numrecvopen = 0; 5787db96d56Sopenharmony_ci} 5797db96d56Sopenharmony_ci 5807db96d56Sopenharmony_cistatic void 5817db96d56Sopenharmony_ci_channelends_free(_channelends *ends) 5827db96d56Sopenharmony_ci{ 5837db96d56Sopenharmony_ci _channelends_clear(ends); 5847db96d56Sopenharmony_ci PyMem_Free(ends); 5857db96d56Sopenharmony_ci} 5867db96d56Sopenharmony_ci 5877db96d56Sopenharmony_cistatic _channelend * 5887db96d56Sopenharmony_ci_channelends_add(_channelends *ends, _channelend *prev, int64_t interp, 5897db96d56Sopenharmony_ci int send) 5907db96d56Sopenharmony_ci{ 5917db96d56Sopenharmony_ci _channelend *end = _channelend_new(interp); 5927db96d56Sopenharmony_ci if (end == NULL) { 5937db96d56Sopenharmony_ci return NULL; 5947db96d56Sopenharmony_ci } 5957db96d56Sopenharmony_ci 5967db96d56Sopenharmony_ci if (prev == NULL) { 5977db96d56Sopenharmony_ci if (send) { 5987db96d56Sopenharmony_ci ends->send = end; 5997db96d56Sopenharmony_ci } 6007db96d56Sopenharmony_ci else { 6017db96d56Sopenharmony_ci ends->recv = end; 6027db96d56Sopenharmony_ci } 6037db96d56Sopenharmony_ci } 6047db96d56Sopenharmony_ci else { 6057db96d56Sopenharmony_ci prev->next = end; 6067db96d56Sopenharmony_ci } 6077db96d56Sopenharmony_ci if (send) { 6087db96d56Sopenharmony_ci ends->numsendopen += 1; 6097db96d56Sopenharmony_ci } 6107db96d56Sopenharmony_ci else { 6117db96d56Sopenharmony_ci ends->numrecvopen += 1; 6127db96d56Sopenharmony_ci } 6137db96d56Sopenharmony_ci return end; 6147db96d56Sopenharmony_ci} 6157db96d56Sopenharmony_ci 6167db96d56Sopenharmony_cistatic int 6177db96d56Sopenharmony_ci_channelends_associate(_channelends *ends, int64_t interp, int send) 6187db96d56Sopenharmony_ci{ 6197db96d56Sopenharmony_ci _channelend *prev; 6207db96d56Sopenharmony_ci _channelend *end = _channelend_find(send ? ends->send : ends->recv, 6217db96d56Sopenharmony_ci interp, &prev); 6227db96d56Sopenharmony_ci if (end != NULL) { 6237db96d56Sopenharmony_ci if (!end->open) { 6247db96d56Sopenharmony_ci PyErr_SetString(ChannelClosedError, "channel already closed"); 6257db96d56Sopenharmony_ci return -1; 6267db96d56Sopenharmony_ci } 6277db96d56Sopenharmony_ci // already associated 6287db96d56Sopenharmony_ci return 0; 6297db96d56Sopenharmony_ci } 6307db96d56Sopenharmony_ci if (_channelends_add(ends, prev, interp, send) == NULL) { 6317db96d56Sopenharmony_ci return -1; 6327db96d56Sopenharmony_ci } 6337db96d56Sopenharmony_ci return 0; 6347db96d56Sopenharmony_ci} 6357db96d56Sopenharmony_ci 6367db96d56Sopenharmony_cistatic int 6377db96d56Sopenharmony_ci_channelends_is_open(_channelends *ends) 6387db96d56Sopenharmony_ci{ 6397db96d56Sopenharmony_ci if (ends->numsendopen != 0 || ends->numrecvopen != 0) { 6407db96d56Sopenharmony_ci return 1; 6417db96d56Sopenharmony_ci } 6427db96d56Sopenharmony_ci if (ends->send == NULL && ends->recv == NULL) { 6437db96d56Sopenharmony_ci return 1; 6447db96d56Sopenharmony_ci } 6457db96d56Sopenharmony_ci return 0; 6467db96d56Sopenharmony_ci} 6477db96d56Sopenharmony_ci 6487db96d56Sopenharmony_cistatic void 6497db96d56Sopenharmony_ci_channelends_close_end(_channelends *ends, _channelend *end, int send) 6507db96d56Sopenharmony_ci{ 6517db96d56Sopenharmony_ci end->open = 0; 6527db96d56Sopenharmony_ci if (send) { 6537db96d56Sopenharmony_ci ends->numsendopen -= 1; 6547db96d56Sopenharmony_ci } 6557db96d56Sopenharmony_ci else { 6567db96d56Sopenharmony_ci ends->numrecvopen -= 1; 6577db96d56Sopenharmony_ci } 6587db96d56Sopenharmony_ci} 6597db96d56Sopenharmony_ci 6607db96d56Sopenharmony_cistatic int 6617db96d56Sopenharmony_ci_channelends_close_interpreter(_channelends *ends, int64_t interp, int which) 6627db96d56Sopenharmony_ci{ 6637db96d56Sopenharmony_ci _channelend *prev; 6647db96d56Sopenharmony_ci _channelend *end; 6657db96d56Sopenharmony_ci if (which >= 0) { // send/both 6667db96d56Sopenharmony_ci end = _channelend_find(ends->send, interp, &prev); 6677db96d56Sopenharmony_ci if (end == NULL) { 6687db96d56Sopenharmony_ci // never associated so add it 6697db96d56Sopenharmony_ci end = _channelends_add(ends, prev, interp, 1); 6707db96d56Sopenharmony_ci if (end == NULL) { 6717db96d56Sopenharmony_ci return -1; 6727db96d56Sopenharmony_ci } 6737db96d56Sopenharmony_ci } 6747db96d56Sopenharmony_ci _channelends_close_end(ends, end, 1); 6757db96d56Sopenharmony_ci } 6767db96d56Sopenharmony_ci if (which <= 0) { // recv/both 6777db96d56Sopenharmony_ci end = _channelend_find(ends->recv, interp, &prev); 6787db96d56Sopenharmony_ci if (end == NULL) { 6797db96d56Sopenharmony_ci // never associated so add it 6807db96d56Sopenharmony_ci end = _channelends_add(ends, prev, interp, 0); 6817db96d56Sopenharmony_ci if (end == NULL) { 6827db96d56Sopenharmony_ci return -1; 6837db96d56Sopenharmony_ci } 6847db96d56Sopenharmony_ci } 6857db96d56Sopenharmony_ci _channelends_close_end(ends, end, 0); 6867db96d56Sopenharmony_ci } 6877db96d56Sopenharmony_ci return 0; 6887db96d56Sopenharmony_ci} 6897db96d56Sopenharmony_ci 6907db96d56Sopenharmony_cistatic void 6917db96d56Sopenharmony_ci_channelends_close_all(_channelends *ends, int which, int force) 6927db96d56Sopenharmony_ci{ 6937db96d56Sopenharmony_ci // XXX Handle the ends. 6947db96d56Sopenharmony_ci // XXX Handle force is True. 6957db96d56Sopenharmony_ci 6967db96d56Sopenharmony_ci // Ensure all the "send"-associated interpreters are closed. 6977db96d56Sopenharmony_ci _channelend *end; 6987db96d56Sopenharmony_ci for (end = ends->send; end != NULL; end = end->next) { 6997db96d56Sopenharmony_ci _channelends_close_end(ends, end, 1); 7007db96d56Sopenharmony_ci } 7017db96d56Sopenharmony_ci 7027db96d56Sopenharmony_ci // Ensure all the "recv"-associated interpreters are closed. 7037db96d56Sopenharmony_ci for (end = ends->recv; end != NULL; end = end->next) { 7047db96d56Sopenharmony_ci _channelends_close_end(ends, end, 0); 7057db96d56Sopenharmony_ci } 7067db96d56Sopenharmony_ci} 7077db96d56Sopenharmony_ci 7087db96d56Sopenharmony_ci/* channels */ 7097db96d56Sopenharmony_ci 7107db96d56Sopenharmony_cistruct _channel; 7117db96d56Sopenharmony_cistruct _channel_closing; 7127db96d56Sopenharmony_cistatic void _channel_clear_closing(struct _channel *); 7137db96d56Sopenharmony_cistatic void _channel_finish_closing(struct _channel *); 7147db96d56Sopenharmony_ci 7157db96d56Sopenharmony_citypedef struct _channel { 7167db96d56Sopenharmony_ci PyThread_type_lock mutex; 7177db96d56Sopenharmony_ci _channelqueue *queue; 7187db96d56Sopenharmony_ci _channelends *ends; 7197db96d56Sopenharmony_ci int open; 7207db96d56Sopenharmony_ci struct _channel_closing *closing; 7217db96d56Sopenharmony_ci} _PyChannelState; 7227db96d56Sopenharmony_ci 7237db96d56Sopenharmony_cistatic _PyChannelState * 7247db96d56Sopenharmony_ci_channel_new(void) 7257db96d56Sopenharmony_ci{ 7267db96d56Sopenharmony_ci _PyChannelState *chan = PyMem_NEW(_PyChannelState, 1); 7277db96d56Sopenharmony_ci if (chan == NULL) { 7287db96d56Sopenharmony_ci return NULL; 7297db96d56Sopenharmony_ci } 7307db96d56Sopenharmony_ci chan->mutex = PyThread_allocate_lock(); 7317db96d56Sopenharmony_ci if (chan->mutex == NULL) { 7327db96d56Sopenharmony_ci PyMem_Free(chan); 7337db96d56Sopenharmony_ci PyErr_SetString(ChannelError, 7347db96d56Sopenharmony_ci "can't initialize mutex for new channel"); 7357db96d56Sopenharmony_ci return NULL; 7367db96d56Sopenharmony_ci } 7377db96d56Sopenharmony_ci chan->queue = _channelqueue_new(); 7387db96d56Sopenharmony_ci if (chan->queue == NULL) { 7397db96d56Sopenharmony_ci PyMem_Free(chan); 7407db96d56Sopenharmony_ci return NULL; 7417db96d56Sopenharmony_ci } 7427db96d56Sopenharmony_ci chan->ends = _channelends_new(); 7437db96d56Sopenharmony_ci if (chan->ends == NULL) { 7447db96d56Sopenharmony_ci _channelqueue_free(chan->queue); 7457db96d56Sopenharmony_ci PyMem_Free(chan); 7467db96d56Sopenharmony_ci return NULL; 7477db96d56Sopenharmony_ci } 7487db96d56Sopenharmony_ci chan->open = 1; 7497db96d56Sopenharmony_ci chan->closing = NULL; 7507db96d56Sopenharmony_ci return chan; 7517db96d56Sopenharmony_ci} 7527db96d56Sopenharmony_ci 7537db96d56Sopenharmony_cistatic void 7547db96d56Sopenharmony_ci_channel_free(_PyChannelState *chan) 7557db96d56Sopenharmony_ci{ 7567db96d56Sopenharmony_ci _channel_clear_closing(chan); 7577db96d56Sopenharmony_ci PyThread_acquire_lock(chan->mutex, WAIT_LOCK); 7587db96d56Sopenharmony_ci _channelqueue_free(chan->queue); 7597db96d56Sopenharmony_ci _channelends_free(chan->ends); 7607db96d56Sopenharmony_ci PyThread_release_lock(chan->mutex); 7617db96d56Sopenharmony_ci 7627db96d56Sopenharmony_ci PyThread_free_lock(chan->mutex); 7637db96d56Sopenharmony_ci PyMem_Free(chan); 7647db96d56Sopenharmony_ci} 7657db96d56Sopenharmony_ci 7667db96d56Sopenharmony_cistatic int 7677db96d56Sopenharmony_ci_channel_add(_PyChannelState *chan, int64_t interp, 7687db96d56Sopenharmony_ci _PyCrossInterpreterData *data) 7697db96d56Sopenharmony_ci{ 7707db96d56Sopenharmony_ci int res = -1; 7717db96d56Sopenharmony_ci PyThread_acquire_lock(chan->mutex, WAIT_LOCK); 7727db96d56Sopenharmony_ci 7737db96d56Sopenharmony_ci if (!chan->open) { 7747db96d56Sopenharmony_ci PyErr_SetString(ChannelClosedError, "channel closed"); 7757db96d56Sopenharmony_ci goto done; 7767db96d56Sopenharmony_ci } 7777db96d56Sopenharmony_ci if (_channelends_associate(chan->ends, interp, 1) != 0) { 7787db96d56Sopenharmony_ci goto done; 7797db96d56Sopenharmony_ci } 7807db96d56Sopenharmony_ci 7817db96d56Sopenharmony_ci if (_channelqueue_put(chan->queue, data) != 0) { 7827db96d56Sopenharmony_ci goto done; 7837db96d56Sopenharmony_ci } 7847db96d56Sopenharmony_ci 7857db96d56Sopenharmony_ci res = 0; 7867db96d56Sopenharmony_cidone: 7877db96d56Sopenharmony_ci PyThread_release_lock(chan->mutex); 7887db96d56Sopenharmony_ci return res; 7897db96d56Sopenharmony_ci} 7907db96d56Sopenharmony_ci 7917db96d56Sopenharmony_cistatic _PyCrossInterpreterData * 7927db96d56Sopenharmony_ci_channel_next(_PyChannelState *chan, int64_t interp) 7937db96d56Sopenharmony_ci{ 7947db96d56Sopenharmony_ci _PyCrossInterpreterData *data = NULL; 7957db96d56Sopenharmony_ci PyThread_acquire_lock(chan->mutex, WAIT_LOCK); 7967db96d56Sopenharmony_ci 7977db96d56Sopenharmony_ci if (!chan->open) { 7987db96d56Sopenharmony_ci PyErr_SetString(ChannelClosedError, "channel closed"); 7997db96d56Sopenharmony_ci goto done; 8007db96d56Sopenharmony_ci } 8017db96d56Sopenharmony_ci if (_channelends_associate(chan->ends, interp, 0) != 0) { 8027db96d56Sopenharmony_ci goto done; 8037db96d56Sopenharmony_ci } 8047db96d56Sopenharmony_ci 8057db96d56Sopenharmony_ci data = _channelqueue_get(chan->queue); 8067db96d56Sopenharmony_ci if (data == NULL && !PyErr_Occurred() && chan->closing != NULL) { 8077db96d56Sopenharmony_ci chan->open = 0; 8087db96d56Sopenharmony_ci } 8097db96d56Sopenharmony_ci 8107db96d56Sopenharmony_cidone: 8117db96d56Sopenharmony_ci PyThread_release_lock(chan->mutex); 8127db96d56Sopenharmony_ci if (chan->queue->count == 0) { 8137db96d56Sopenharmony_ci _channel_finish_closing(chan); 8147db96d56Sopenharmony_ci } 8157db96d56Sopenharmony_ci return data; 8167db96d56Sopenharmony_ci} 8177db96d56Sopenharmony_ci 8187db96d56Sopenharmony_cistatic int 8197db96d56Sopenharmony_ci_channel_close_interpreter(_PyChannelState *chan, int64_t interp, int end) 8207db96d56Sopenharmony_ci{ 8217db96d56Sopenharmony_ci PyThread_acquire_lock(chan->mutex, WAIT_LOCK); 8227db96d56Sopenharmony_ci 8237db96d56Sopenharmony_ci int res = -1; 8247db96d56Sopenharmony_ci if (!chan->open) { 8257db96d56Sopenharmony_ci PyErr_SetString(ChannelClosedError, "channel already closed"); 8267db96d56Sopenharmony_ci goto done; 8277db96d56Sopenharmony_ci } 8287db96d56Sopenharmony_ci 8297db96d56Sopenharmony_ci if (_channelends_close_interpreter(chan->ends, interp, end) != 0) { 8307db96d56Sopenharmony_ci goto done; 8317db96d56Sopenharmony_ci } 8327db96d56Sopenharmony_ci chan->open = _channelends_is_open(chan->ends); 8337db96d56Sopenharmony_ci 8347db96d56Sopenharmony_ci res = 0; 8357db96d56Sopenharmony_cidone: 8367db96d56Sopenharmony_ci PyThread_release_lock(chan->mutex); 8377db96d56Sopenharmony_ci return res; 8387db96d56Sopenharmony_ci} 8397db96d56Sopenharmony_ci 8407db96d56Sopenharmony_cistatic int 8417db96d56Sopenharmony_ci_channel_close_all(_PyChannelState *chan, int end, int force) 8427db96d56Sopenharmony_ci{ 8437db96d56Sopenharmony_ci int res = -1; 8447db96d56Sopenharmony_ci PyThread_acquire_lock(chan->mutex, WAIT_LOCK); 8457db96d56Sopenharmony_ci 8467db96d56Sopenharmony_ci if (!chan->open) { 8477db96d56Sopenharmony_ci PyErr_SetString(ChannelClosedError, "channel already closed"); 8487db96d56Sopenharmony_ci goto done; 8497db96d56Sopenharmony_ci } 8507db96d56Sopenharmony_ci 8517db96d56Sopenharmony_ci if (!force && chan->queue->count > 0) { 8527db96d56Sopenharmony_ci PyErr_SetString(ChannelNotEmptyError, 8537db96d56Sopenharmony_ci "may not be closed if not empty (try force=True)"); 8547db96d56Sopenharmony_ci goto done; 8557db96d56Sopenharmony_ci } 8567db96d56Sopenharmony_ci 8577db96d56Sopenharmony_ci chan->open = 0; 8587db96d56Sopenharmony_ci 8597db96d56Sopenharmony_ci // We *could* also just leave these in place, since we've marked 8607db96d56Sopenharmony_ci // the channel as closed already. 8617db96d56Sopenharmony_ci _channelends_close_all(chan->ends, end, force); 8627db96d56Sopenharmony_ci 8637db96d56Sopenharmony_ci res = 0; 8647db96d56Sopenharmony_cidone: 8657db96d56Sopenharmony_ci PyThread_release_lock(chan->mutex); 8667db96d56Sopenharmony_ci return res; 8677db96d56Sopenharmony_ci} 8687db96d56Sopenharmony_ci 8697db96d56Sopenharmony_ci/* the set of channels */ 8707db96d56Sopenharmony_ci 8717db96d56Sopenharmony_cistruct _channelref; 8727db96d56Sopenharmony_ci 8737db96d56Sopenharmony_citypedef struct _channelref { 8747db96d56Sopenharmony_ci int64_t id; 8757db96d56Sopenharmony_ci _PyChannelState *chan; 8767db96d56Sopenharmony_ci struct _channelref *next; 8777db96d56Sopenharmony_ci Py_ssize_t objcount; 8787db96d56Sopenharmony_ci} _channelref; 8797db96d56Sopenharmony_ci 8807db96d56Sopenharmony_cistatic _channelref * 8817db96d56Sopenharmony_ci_channelref_new(int64_t id, _PyChannelState *chan) 8827db96d56Sopenharmony_ci{ 8837db96d56Sopenharmony_ci _channelref *ref = PyMem_NEW(_channelref, 1); 8847db96d56Sopenharmony_ci if (ref == NULL) { 8857db96d56Sopenharmony_ci return NULL; 8867db96d56Sopenharmony_ci } 8877db96d56Sopenharmony_ci ref->id = id; 8887db96d56Sopenharmony_ci ref->chan = chan; 8897db96d56Sopenharmony_ci ref->next = NULL; 8907db96d56Sopenharmony_ci ref->objcount = 0; 8917db96d56Sopenharmony_ci return ref; 8927db96d56Sopenharmony_ci} 8937db96d56Sopenharmony_ci 8947db96d56Sopenharmony_ci//static void 8957db96d56Sopenharmony_ci//_channelref_clear(_channelref *ref) 8967db96d56Sopenharmony_ci//{ 8977db96d56Sopenharmony_ci// ref->id = -1; 8987db96d56Sopenharmony_ci// ref->chan = NULL; 8997db96d56Sopenharmony_ci// ref->next = NULL; 9007db96d56Sopenharmony_ci// ref->objcount = 0; 9017db96d56Sopenharmony_ci//} 9027db96d56Sopenharmony_ci 9037db96d56Sopenharmony_cistatic void 9047db96d56Sopenharmony_ci_channelref_free(_channelref *ref) 9057db96d56Sopenharmony_ci{ 9067db96d56Sopenharmony_ci if (ref->chan != NULL) { 9077db96d56Sopenharmony_ci _channel_clear_closing(ref->chan); 9087db96d56Sopenharmony_ci } 9097db96d56Sopenharmony_ci //_channelref_clear(ref); 9107db96d56Sopenharmony_ci PyMem_Free(ref); 9117db96d56Sopenharmony_ci} 9127db96d56Sopenharmony_ci 9137db96d56Sopenharmony_cistatic _channelref * 9147db96d56Sopenharmony_ci_channelref_find(_channelref *first, int64_t id, _channelref **pprev) 9157db96d56Sopenharmony_ci{ 9167db96d56Sopenharmony_ci _channelref *prev = NULL; 9177db96d56Sopenharmony_ci _channelref *ref = first; 9187db96d56Sopenharmony_ci while (ref != NULL) { 9197db96d56Sopenharmony_ci if (ref->id == id) { 9207db96d56Sopenharmony_ci break; 9217db96d56Sopenharmony_ci } 9227db96d56Sopenharmony_ci prev = ref; 9237db96d56Sopenharmony_ci ref = ref->next; 9247db96d56Sopenharmony_ci } 9257db96d56Sopenharmony_ci if (pprev != NULL) { 9267db96d56Sopenharmony_ci *pprev = prev; 9277db96d56Sopenharmony_ci } 9287db96d56Sopenharmony_ci return ref; 9297db96d56Sopenharmony_ci} 9307db96d56Sopenharmony_ci 9317db96d56Sopenharmony_citypedef struct _channels { 9327db96d56Sopenharmony_ci PyThread_type_lock mutex; 9337db96d56Sopenharmony_ci _channelref *head; 9347db96d56Sopenharmony_ci int64_t numopen; 9357db96d56Sopenharmony_ci int64_t next_id; 9367db96d56Sopenharmony_ci} _channels; 9377db96d56Sopenharmony_ci 9387db96d56Sopenharmony_cistatic int 9397db96d56Sopenharmony_ci_channels_init(_channels *channels) 9407db96d56Sopenharmony_ci{ 9417db96d56Sopenharmony_ci if (channels->mutex == NULL) { 9427db96d56Sopenharmony_ci channels->mutex = PyThread_allocate_lock(); 9437db96d56Sopenharmony_ci if (channels->mutex == NULL) { 9447db96d56Sopenharmony_ci PyErr_SetString(ChannelError, 9457db96d56Sopenharmony_ci "can't initialize mutex for channel management"); 9467db96d56Sopenharmony_ci return -1; 9477db96d56Sopenharmony_ci } 9487db96d56Sopenharmony_ci } 9497db96d56Sopenharmony_ci channels->head = NULL; 9507db96d56Sopenharmony_ci channels->numopen = 0; 9517db96d56Sopenharmony_ci channels->next_id = 0; 9527db96d56Sopenharmony_ci return 0; 9537db96d56Sopenharmony_ci} 9547db96d56Sopenharmony_ci 9557db96d56Sopenharmony_cistatic int64_t 9567db96d56Sopenharmony_ci_channels_next_id(_channels *channels) // needs lock 9577db96d56Sopenharmony_ci{ 9587db96d56Sopenharmony_ci int64_t id = channels->next_id; 9597db96d56Sopenharmony_ci if (id < 0) { 9607db96d56Sopenharmony_ci /* overflow */ 9617db96d56Sopenharmony_ci PyErr_SetString(ChannelError, 9627db96d56Sopenharmony_ci "failed to get a channel ID"); 9637db96d56Sopenharmony_ci return -1; 9647db96d56Sopenharmony_ci } 9657db96d56Sopenharmony_ci channels->next_id += 1; 9667db96d56Sopenharmony_ci return id; 9677db96d56Sopenharmony_ci} 9687db96d56Sopenharmony_ci 9697db96d56Sopenharmony_cistatic _PyChannelState * 9707db96d56Sopenharmony_ci_channels_lookup(_channels *channels, int64_t id, PyThread_type_lock *pmutex) 9717db96d56Sopenharmony_ci{ 9727db96d56Sopenharmony_ci _PyChannelState *chan = NULL; 9737db96d56Sopenharmony_ci PyThread_acquire_lock(channels->mutex, WAIT_LOCK); 9747db96d56Sopenharmony_ci if (pmutex != NULL) { 9757db96d56Sopenharmony_ci *pmutex = NULL; 9767db96d56Sopenharmony_ci } 9777db96d56Sopenharmony_ci 9787db96d56Sopenharmony_ci _channelref *ref = _channelref_find(channels->head, id, NULL); 9797db96d56Sopenharmony_ci if (ref == NULL) { 9807db96d56Sopenharmony_ci PyErr_Format(ChannelNotFoundError, "channel %" PRId64 " not found", id); 9817db96d56Sopenharmony_ci goto done; 9827db96d56Sopenharmony_ci } 9837db96d56Sopenharmony_ci if (ref->chan == NULL || !ref->chan->open) { 9847db96d56Sopenharmony_ci PyErr_Format(ChannelClosedError, "channel %" PRId64 " closed", id); 9857db96d56Sopenharmony_ci goto done; 9867db96d56Sopenharmony_ci } 9877db96d56Sopenharmony_ci 9887db96d56Sopenharmony_ci if (pmutex != NULL) { 9897db96d56Sopenharmony_ci // The mutex will be closed by the caller. 9907db96d56Sopenharmony_ci *pmutex = channels->mutex; 9917db96d56Sopenharmony_ci } 9927db96d56Sopenharmony_ci 9937db96d56Sopenharmony_ci chan = ref->chan; 9947db96d56Sopenharmony_cidone: 9957db96d56Sopenharmony_ci if (pmutex == NULL || *pmutex == NULL) { 9967db96d56Sopenharmony_ci PyThread_release_lock(channels->mutex); 9977db96d56Sopenharmony_ci } 9987db96d56Sopenharmony_ci return chan; 9997db96d56Sopenharmony_ci} 10007db96d56Sopenharmony_ci 10017db96d56Sopenharmony_cistatic int64_t 10027db96d56Sopenharmony_ci_channels_add(_channels *channels, _PyChannelState *chan) 10037db96d56Sopenharmony_ci{ 10047db96d56Sopenharmony_ci int64_t cid = -1; 10057db96d56Sopenharmony_ci PyThread_acquire_lock(channels->mutex, WAIT_LOCK); 10067db96d56Sopenharmony_ci 10077db96d56Sopenharmony_ci // Create a new ref. 10087db96d56Sopenharmony_ci int64_t id = _channels_next_id(channels); 10097db96d56Sopenharmony_ci if (id < 0) { 10107db96d56Sopenharmony_ci goto done; 10117db96d56Sopenharmony_ci } 10127db96d56Sopenharmony_ci _channelref *ref = _channelref_new(id, chan); 10137db96d56Sopenharmony_ci if (ref == NULL) { 10147db96d56Sopenharmony_ci goto done; 10157db96d56Sopenharmony_ci } 10167db96d56Sopenharmony_ci 10177db96d56Sopenharmony_ci // Add it to the list. 10187db96d56Sopenharmony_ci // We assume that the channel is a new one (not already in the list). 10197db96d56Sopenharmony_ci ref->next = channels->head; 10207db96d56Sopenharmony_ci channels->head = ref; 10217db96d56Sopenharmony_ci channels->numopen += 1; 10227db96d56Sopenharmony_ci 10237db96d56Sopenharmony_ci cid = id; 10247db96d56Sopenharmony_cidone: 10257db96d56Sopenharmony_ci PyThread_release_lock(channels->mutex); 10267db96d56Sopenharmony_ci return cid; 10277db96d56Sopenharmony_ci} 10287db96d56Sopenharmony_ci 10297db96d56Sopenharmony_ci/* forward */ 10307db96d56Sopenharmony_cistatic int _channel_set_closing(struct _channelref *, PyThread_type_lock); 10317db96d56Sopenharmony_ci 10327db96d56Sopenharmony_cistatic int 10337db96d56Sopenharmony_ci_channels_close(_channels *channels, int64_t cid, _PyChannelState **pchan, 10347db96d56Sopenharmony_ci int end, int force) 10357db96d56Sopenharmony_ci{ 10367db96d56Sopenharmony_ci int res = -1; 10377db96d56Sopenharmony_ci PyThread_acquire_lock(channels->mutex, WAIT_LOCK); 10387db96d56Sopenharmony_ci if (pchan != NULL) { 10397db96d56Sopenharmony_ci *pchan = NULL; 10407db96d56Sopenharmony_ci } 10417db96d56Sopenharmony_ci 10427db96d56Sopenharmony_ci _channelref *ref = _channelref_find(channels->head, cid, NULL); 10437db96d56Sopenharmony_ci if (ref == NULL) { 10447db96d56Sopenharmony_ci PyErr_Format(ChannelNotFoundError, "channel %" PRId64 " not found", cid); 10457db96d56Sopenharmony_ci goto done; 10467db96d56Sopenharmony_ci } 10477db96d56Sopenharmony_ci 10487db96d56Sopenharmony_ci if (ref->chan == NULL) { 10497db96d56Sopenharmony_ci PyErr_Format(ChannelClosedError, "channel %" PRId64 " closed", cid); 10507db96d56Sopenharmony_ci goto done; 10517db96d56Sopenharmony_ci } 10527db96d56Sopenharmony_ci else if (!force && end == CHANNEL_SEND && ref->chan->closing != NULL) { 10537db96d56Sopenharmony_ci PyErr_Format(ChannelClosedError, "channel %" PRId64 " closed", cid); 10547db96d56Sopenharmony_ci goto done; 10557db96d56Sopenharmony_ci } 10567db96d56Sopenharmony_ci else { 10577db96d56Sopenharmony_ci if (_channel_close_all(ref->chan, end, force) != 0) { 10587db96d56Sopenharmony_ci if (end == CHANNEL_SEND && 10597db96d56Sopenharmony_ci PyErr_ExceptionMatches(ChannelNotEmptyError)) { 10607db96d56Sopenharmony_ci if (ref->chan->closing != NULL) { 10617db96d56Sopenharmony_ci PyErr_Format(ChannelClosedError, 10627db96d56Sopenharmony_ci "channel %" PRId64 " closed", cid); 10637db96d56Sopenharmony_ci goto done; 10647db96d56Sopenharmony_ci } 10657db96d56Sopenharmony_ci // Mark the channel as closing and return. The channel 10667db96d56Sopenharmony_ci // will be cleaned up in _channel_next(). 10677db96d56Sopenharmony_ci PyErr_Clear(); 10687db96d56Sopenharmony_ci if (_channel_set_closing(ref, channels->mutex) != 0) { 10697db96d56Sopenharmony_ci goto done; 10707db96d56Sopenharmony_ci } 10717db96d56Sopenharmony_ci if (pchan != NULL) { 10727db96d56Sopenharmony_ci *pchan = ref->chan; 10737db96d56Sopenharmony_ci } 10747db96d56Sopenharmony_ci res = 0; 10757db96d56Sopenharmony_ci } 10767db96d56Sopenharmony_ci goto done; 10777db96d56Sopenharmony_ci } 10787db96d56Sopenharmony_ci if (pchan != NULL) { 10797db96d56Sopenharmony_ci *pchan = ref->chan; 10807db96d56Sopenharmony_ci } 10817db96d56Sopenharmony_ci else { 10827db96d56Sopenharmony_ci _channel_free(ref->chan); 10837db96d56Sopenharmony_ci } 10847db96d56Sopenharmony_ci ref->chan = NULL; 10857db96d56Sopenharmony_ci } 10867db96d56Sopenharmony_ci 10877db96d56Sopenharmony_ci res = 0; 10887db96d56Sopenharmony_cidone: 10897db96d56Sopenharmony_ci PyThread_release_lock(channels->mutex); 10907db96d56Sopenharmony_ci return res; 10917db96d56Sopenharmony_ci} 10927db96d56Sopenharmony_ci 10937db96d56Sopenharmony_cistatic void 10947db96d56Sopenharmony_ci_channels_remove_ref(_channels *channels, _channelref *ref, _channelref *prev, 10957db96d56Sopenharmony_ci _PyChannelState **pchan) 10967db96d56Sopenharmony_ci{ 10977db96d56Sopenharmony_ci if (ref == channels->head) { 10987db96d56Sopenharmony_ci channels->head = ref->next; 10997db96d56Sopenharmony_ci } 11007db96d56Sopenharmony_ci else { 11017db96d56Sopenharmony_ci prev->next = ref->next; 11027db96d56Sopenharmony_ci } 11037db96d56Sopenharmony_ci channels->numopen -= 1; 11047db96d56Sopenharmony_ci 11057db96d56Sopenharmony_ci if (pchan != NULL) { 11067db96d56Sopenharmony_ci *pchan = ref->chan; 11077db96d56Sopenharmony_ci } 11087db96d56Sopenharmony_ci _channelref_free(ref); 11097db96d56Sopenharmony_ci} 11107db96d56Sopenharmony_ci 11117db96d56Sopenharmony_cistatic int 11127db96d56Sopenharmony_ci_channels_remove(_channels *channels, int64_t id, _PyChannelState **pchan) 11137db96d56Sopenharmony_ci{ 11147db96d56Sopenharmony_ci int res = -1; 11157db96d56Sopenharmony_ci PyThread_acquire_lock(channels->mutex, WAIT_LOCK); 11167db96d56Sopenharmony_ci 11177db96d56Sopenharmony_ci if (pchan != NULL) { 11187db96d56Sopenharmony_ci *pchan = NULL; 11197db96d56Sopenharmony_ci } 11207db96d56Sopenharmony_ci 11217db96d56Sopenharmony_ci _channelref *prev = NULL; 11227db96d56Sopenharmony_ci _channelref *ref = _channelref_find(channels->head, id, &prev); 11237db96d56Sopenharmony_ci if (ref == NULL) { 11247db96d56Sopenharmony_ci PyErr_Format(ChannelNotFoundError, "channel %" PRId64 " not found", id); 11257db96d56Sopenharmony_ci goto done; 11267db96d56Sopenharmony_ci } 11277db96d56Sopenharmony_ci 11287db96d56Sopenharmony_ci _channels_remove_ref(channels, ref, prev, pchan); 11297db96d56Sopenharmony_ci 11307db96d56Sopenharmony_ci res = 0; 11317db96d56Sopenharmony_cidone: 11327db96d56Sopenharmony_ci PyThread_release_lock(channels->mutex); 11337db96d56Sopenharmony_ci return res; 11347db96d56Sopenharmony_ci} 11357db96d56Sopenharmony_ci 11367db96d56Sopenharmony_cistatic int 11377db96d56Sopenharmony_ci_channels_add_id_object(_channels *channels, int64_t id) 11387db96d56Sopenharmony_ci{ 11397db96d56Sopenharmony_ci int res = -1; 11407db96d56Sopenharmony_ci PyThread_acquire_lock(channels->mutex, WAIT_LOCK); 11417db96d56Sopenharmony_ci 11427db96d56Sopenharmony_ci _channelref *ref = _channelref_find(channels->head, id, NULL); 11437db96d56Sopenharmony_ci if (ref == NULL) { 11447db96d56Sopenharmony_ci PyErr_Format(ChannelNotFoundError, "channel %" PRId64 " not found", id); 11457db96d56Sopenharmony_ci goto done; 11467db96d56Sopenharmony_ci } 11477db96d56Sopenharmony_ci ref->objcount += 1; 11487db96d56Sopenharmony_ci 11497db96d56Sopenharmony_ci res = 0; 11507db96d56Sopenharmony_cidone: 11517db96d56Sopenharmony_ci PyThread_release_lock(channels->mutex); 11527db96d56Sopenharmony_ci return res; 11537db96d56Sopenharmony_ci} 11547db96d56Sopenharmony_ci 11557db96d56Sopenharmony_cistatic void 11567db96d56Sopenharmony_ci_channels_drop_id_object(_channels *channels, int64_t id) 11577db96d56Sopenharmony_ci{ 11587db96d56Sopenharmony_ci PyThread_acquire_lock(channels->mutex, WAIT_LOCK); 11597db96d56Sopenharmony_ci 11607db96d56Sopenharmony_ci _channelref *prev = NULL; 11617db96d56Sopenharmony_ci _channelref *ref = _channelref_find(channels->head, id, &prev); 11627db96d56Sopenharmony_ci if (ref == NULL) { 11637db96d56Sopenharmony_ci // Already destroyed. 11647db96d56Sopenharmony_ci goto done; 11657db96d56Sopenharmony_ci } 11667db96d56Sopenharmony_ci ref->objcount -= 1; 11677db96d56Sopenharmony_ci 11687db96d56Sopenharmony_ci // Destroy if no longer used. 11697db96d56Sopenharmony_ci if (ref->objcount == 0) { 11707db96d56Sopenharmony_ci _PyChannelState *chan = NULL; 11717db96d56Sopenharmony_ci _channels_remove_ref(channels, ref, prev, &chan); 11727db96d56Sopenharmony_ci if (chan != NULL) { 11737db96d56Sopenharmony_ci _channel_free(chan); 11747db96d56Sopenharmony_ci } 11757db96d56Sopenharmony_ci } 11767db96d56Sopenharmony_ci 11777db96d56Sopenharmony_cidone: 11787db96d56Sopenharmony_ci PyThread_release_lock(channels->mutex); 11797db96d56Sopenharmony_ci} 11807db96d56Sopenharmony_ci 11817db96d56Sopenharmony_cistatic int64_t * 11827db96d56Sopenharmony_ci_channels_list_all(_channels *channels, int64_t *count) 11837db96d56Sopenharmony_ci{ 11847db96d56Sopenharmony_ci int64_t *cids = NULL; 11857db96d56Sopenharmony_ci PyThread_acquire_lock(channels->mutex, WAIT_LOCK); 11867db96d56Sopenharmony_ci int64_t *ids = PyMem_NEW(int64_t, (Py_ssize_t)(channels->numopen)); 11877db96d56Sopenharmony_ci if (ids == NULL) { 11887db96d56Sopenharmony_ci goto done; 11897db96d56Sopenharmony_ci } 11907db96d56Sopenharmony_ci _channelref *ref = channels->head; 11917db96d56Sopenharmony_ci for (int64_t i=0; ref != NULL; ref = ref->next, i++) { 11927db96d56Sopenharmony_ci ids[i] = ref->id; 11937db96d56Sopenharmony_ci } 11947db96d56Sopenharmony_ci *count = channels->numopen; 11957db96d56Sopenharmony_ci 11967db96d56Sopenharmony_ci cids = ids; 11977db96d56Sopenharmony_cidone: 11987db96d56Sopenharmony_ci PyThread_release_lock(channels->mutex); 11997db96d56Sopenharmony_ci return cids; 12007db96d56Sopenharmony_ci} 12017db96d56Sopenharmony_ci 12027db96d56Sopenharmony_ci/* support for closing non-empty channels */ 12037db96d56Sopenharmony_ci 12047db96d56Sopenharmony_cistruct _channel_closing { 12057db96d56Sopenharmony_ci struct _channelref *ref; 12067db96d56Sopenharmony_ci}; 12077db96d56Sopenharmony_ci 12087db96d56Sopenharmony_cistatic int 12097db96d56Sopenharmony_ci_channel_set_closing(struct _channelref *ref, PyThread_type_lock mutex) { 12107db96d56Sopenharmony_ci struct _channel *chan = ref->chan; 12117db96d56Sopenharmony_ci if (chan == NULL) { 12127db96d56Sopenharmony_ci // already closed 12137db96d56Sopenharmony_ci return 0; 12147db96d56Sopenharmony_ci } 12157db96d56Sopenharmony_ci int res = -1; 12167db96d56Sopenharmony_ci PyThread_acquire_lock(chan->mutex, WAIT_LOCK); 12177db96d56Sopenharmony_ci if (chan->closing != NULL) { 12187db96d56Sopenharmony_ci PyErr_SetString(ChannelClosedError, "channel closed"); 12197db96d56Sopenharmony_ci goto done; 12207db96d56Sopenharmony_ci } 12217db96d56Sopenharmony_ci chan->closing = PyMem_NEW(struct _channel_closing, 1); 12227db96d56Sopenharmony_ci if (chan->closing == NULL) { 12237db96d56Sopenharmony_ci goto done; 12247db96d56Sopenharmony_ci } 12257db96d56Sopenharmony_ci chan->closing->ref = ref; 12267db96d56Sopenharmony_ci 12277db96d56Sopenharmony_ci res = 0; 12287db96d56Sopenharmony_cidone: 12297db96d56Sopenharmony_ci PyThread_release_lock(chan->mutex); 12307db96d56Sopenharmony_ci return res; 12317db96d56Sopenharmony_ci} 12327db96d56Sopenharmony_ci 12337db96d56Sopenharmony_cistatic void 12347db96d56Sopenharmony_ci_channel_clear_closing(struct _channel *chan) { 12357db96d56Sopenharmony_ci PyThread_acquire_lock(chan->mutex, WAIT_LOCK); 12367db96d56Sopenharmony_ci if (chan->closing != NULL) { 12377db96d56Sopenharmony_ci PyMem_Free(chan->closing); 12387db96d56Sopenharmony_ci chan->closing = NULL; 12397db96d56Sopenharmony_ci } 12407db96d56Sopenharmony_ci PyThread_release_lock(chan->mutex); 12417db96d56Sopenharmony_ci} 12427db96d56Sopenharmony_ci 12437db96d56Sopenharmony_cistatic void 12447db96d56Sopenharmony_ci_channel_finish_closing(struct _channel *chan) { 12457db96d56Sopenharmony_ci struct _channel_closing *closing = chan->closing; 12467db96d56Sopenharmony_ci if (closing == NULL) { 12477db96d56Sopenharmony_ci return; 12487db96d56Sopenharmony_ci } 12497db96d56Sopenharmony_ci _channelref *ref = closing->ref; 12507db96d56Sopenharmony_ci _channel_clear_closing(chan); 12517db96d56Sopenharmony_ci // Do the things that would have been done in _channels_close(). 12527db96d56Sopenharmony_ci ref->chan = NULL; 12537db96d56Sopenharmony_ci _channel_free(chan); 12547db96d56Sopenharmony_ci} 12557db96d56Sopenharmony_ci 12567db96d56Sopenharmony_ci/* "high"-level channel-related functions */ 12577db96d56Sopenharmony_ci 12587db96d56Sopenharmony_cistatic int64_t 12597db96d56Sopenharmony_ci_channel_create(_channels *channels) 12607db96d56Sopenharmony_ci{ 12617db96d56Sopenharmony_ci _PyChannelState *chan = _channel_new(); 12627db96d56Sopenharmony_ci if (chan == NULL) { 12637db96d56Sopenharmony_ci return -1; 12647db96d56Sopenharmony_ci } 12657db96d56Sopenharmony_ci int64_t id = _channels_add(channels, chan); 12667db96d56Sopenharmony_ci if (id < 0) { 12677db96d56Sopenharmony_ci _channel_free(chan); 12687db96d56Sopenharmony_ci return -1; 12697db96d56Sopenharmony_ci } 12707db96d56Sopenharmony_ci return id; 12717db96d56Sopenharmony_ci} 12727db96d56Sopenharmony_ci 12737db96d56Sopenharmony_cistatic int 12747db96d56Sopenharmony_ci_channel_destroy(_channels *channels, int64_t id) 12757db96d56Sopenharmony_ci{ 12767db96d56Sopenharmony_ci _PyChannelState *chan = NULL; 12777db96d56Sopenharmony_ci if (_channels_remove(channels, id, &chan) != 0) { 12787db96d56Sopenharmony_ci return -1; 12797db96d56Sopenharmony_ci } 12807db96d56Sopenharmony_ci if (chan != NULL) { 12817db96d56Sopenharmony_ci _channel_free(chan); 12827db96d56Sopenharmony_ci } 12837db96d56Sopenharmony_ci return 0; 12847db96d56Sopenharmony_ci} 12857db96d56Sopenharmony_ci 12867db96d56Sopenharmony_cistatic int 12877db96d56Sopenharmony_ci_channel_send(_channels *channels, int64_t id, PyObject *obj) 12887db96d56Sopenharmony_ci{ 12897db96d56Sopenharmony_ci PyInterpreterState *interp = _get_current(); 12907db96d56Sopenharmony_ci if (interp == NULL) { 12917db96d56Sopenharmony_ci return -1; 12927db96d56Sopenharmony_ci } 12937db96d56Sopenharmony_ci 12947db96d56Sopenharmony_ci // Look up the channel. 12957db96d56Sopenharmony_ci PyThread_type_lock mutex = NULL; 12967db96d56Sopenharmony_ci _PyChannelState *chan = _channels_lookup(channels, id, &mutex); 12977db96d56Sopenharmony_ci if (chan == NULL) { 12987db96d56Sopenharmony_ci return -1; 12997db96d56Sopenharmony_ci } 13007db96d56Sopenharmony_ci // Past this point we are responsible for releasing the mutex. 13017db96d56Sopenharmony_ci 13027db96d56Sopenharmony_ci if (chan->closing != NULL) { 13037db96d56Sopenharmony_ci PyErr_Format(ChannelClosedError, "channel %" PRId64 " closed", id); 13047db96d56Sopenharmony_ci PyThread_release_lock(mutex); 13057db96d56Sopenharmony_ci return -1; 13067db96d56Sopenharmony_ci } 13077db96d56Sopenharmony_ci 13087db96d56Sopenharmony_ci // Convert the object to cross-interpreter data. 13097db96d56Sopenharmony_ci _PyCrossInterpreterData *data = PyMem_NEW(_PyCrossInterpreterData, 1); 13107db96d56Sopenharmony_ci if (data == NULL) { 13117db96d56Sopenharmony_ci PyThread_release_lock(mutex); 13127db96d56Sopenharmony_ci return -1; 13137db96d56Sopenharmony_ci } 13147db96d56Sopenharmony_ci if (_PyObject_GetCrossInterpreterData(obj, data) != 0) { 13157db96d56Sopenharmony_ci PyThread_release_lock(mutex); 13167db96d56Sopenharmony_ci PyMem_Free(data); 13177db96d56Sopenharmony_ci return -1; 13187db96d56Sopenharmony_ci } 13197db96d56Sopenharmony_ci 13207db96d56Sopenharmony_ci // Add the data to the channel. 13217db96d56Sopenharmony_ci int res = _channel_add(chan, PyInterpreterState_GetID(interp), data); 13227db96d56Sopenharmony_ci PyThread_release_lock(mutex); 13237db96d56Sopenharmony_ci if (res != 0) { 13247db96d56Sopenharmony_ci _PyCrossInterpreterData_Release(data); 13257db96d56Sopenharmony_ci PyMem_Free(data); 13267db96d56Sopenharmony_ci return -1; 13277db96d56Sopenharmony_ci } 13287db96d56Sopenharmony_ci 13297db96d56Sopenharmony_ci return 0; 13307db96d56Sopenharmony_ci} 13317db96d56Sopenharmony_ci 13327db96d56Sopenharmony_cistatic PyObject * 13337db96d56Sopenharmony_ci_channel_recv(_channels *channels, int64_t id) 13347db96d56Sopenharmony_ci{ 13357db96d56Sopenharmony_ci PyInterpreterState *interp = _get_current(); 13367db96d56Sopenharmony_ci if (interp == NULL) { 13377db96d56Sopenharmony_ci return NULL; 13387db96d56Sopenharmony_ci } 13397db96d56Sopenharmony_ci 13407db96d56Sopenharmony_ci // Look up the channel. 13417db96d56Sopenharmony_ci PyThread_type_lock mutex = NULL; 13427db96d56Sopenharmony_ci _PyChannelState *chan = _channels_lookup(channels, id, &mutex); 13437db96d56Sopenharmony_ci if (chan == NULL) { 13447db96d56Sopenharmony_ci return NULL; 13457db96d56Sopenharmony_ci } 13467db96d56Sopenharmony_ci // Past this point we are responsible for releasing the mutex. 13477db96d56Sopenharmony_ci 13487db96d56Sopenharmony_ci // Pop off the next item from the channel. 13497db96d56Sopenharmony_ci _PyCrossInterpreterData *data = _channel_next(chan, PyInterpreterState_GetID(interp)); 13507db96d56Sopenharmony_ci PyThread_release_lock(mutex); 13517db96d56Sopenharmony_ci if (data == NULL) { 13527db96d56Sopenharmony_ci return NULL; 13537db96d56Sopenharmony_ci } 13547db96d56Sopenharmony_ci 13557db96d56Sopenharmony_ci // Convert the data back to an object. 13567db96d56Sopenharmony_ci PyObject *obj = _PyCrossInterpreterData_NewObject(data); 13577db96d56Sopenharmony_ci _PyCrossInterpreterData_Release(data); 13587db96d56Sopenharmony_ci PyMem_Free(data); 13597db96d56Sopenharmony_ci if (obj == NULL) { 13607db96d56Sopenharmony_ci return NULL; 13617db96d56Sopenharmony_ci } 13627db96d56Sopenharmony_ci 13637db96d56Sopenharmony_ci return obj; 13647db96d56Sopenharmony_ci} 13657db96d56Sopenharmony_ci 13667db96d56Sopenharmony_cistatic int 13677db96d56Sopenharmony_ci_channel_drop(_channels *channels, int64_t id, int send, int recv) 13687db96d56Sopenharmony_ci{ 13697db96d56Sopenharmony_ci PyInterpreterState *interp = _get_current(); 13707db96d56Sopenharmony_ci if (interp == NULL) { 13717db96d56Sopenharmony_ci return -1; 13727db96d56Sopenharmony_ci } 13737db96d56Sopenharmony_ci 13747db96d56Sopenharmony_ci // Look up the channel. 13757db96d56Sopenharmony_ci PyThread_type_lock mutex = NULL; 13767db96d56Sopenharmony_ci _PyChannelState *chan = _channels_lookup(channels, id, &mutex); 13777db96d56Sopenharmony_ci if (chan == NULL) { 13787db96d56Sopenharmony_ci return -1; 13797db96d56Sopenharmony_ci } 13807db96d56Sopenharmony_ci // Past this point we are responsible for releasing the mutex. 13817db96d56Sopenharmony_ci 13827db96d56Sopenharmony_ci // Close one or both of the two ends. 13837db96d56Sopenharmony_ci int res = _channel_close_interpreter(chan, PyInterpreterState_GetID(interp), send-recv); 13847db96d56Sopenharmony_ci PyThread_release_lock(mutex); 13857db96d56Sopenharmony_ci return res; 13867db96d56Sopenharmony_ci} 13877db96d56Sopenharmony_ci 13887db96d56Sopenharmony_cistatic int 13897db96d56Sopenharmony_ci_channel_close(_channels *channels, int64_t id, int end, int force) 13907db96d56Sopenharmony_ci{ 13917db96d56Sopenharmony_ci return _channels_close(channels, id, NULL, end, force); 13927db96d56Sopenharmony_ci} 13937db96d56Sopenharmony_ci 13947db96d56Sopenharmony_cistatic int 13957db96d56Sopenharmony_ci_channel_is_associated(_channels *channels, int64_t cid, int64_t interp, 13967db96d56Sopenharmony_ci int send) 13977db96d56Sopenharmony_ci{ 13987db96d56Sopenharmony_ci _PyChannelState *chan = _channels_lookup(channels, cid, NULL); 13997db96d56Sopenharmony_ci if (chan == NULL) { 14007db96d56Sopenharmony_ci return -1; 14017db96d56Sopenharmony_ci } else if (send && chan->closing != NULL) { 14027db96d56Sopenharmony_ci PyErr_Format(ChannelClosedError, "channel %" PRId64 " closed", cid); 14037db96d56Sopenharmony_ci return -1; 14047db96d56Sopenharmony_ci } 14057db96d56Sopenharmony_ci 14067db96d56Sopenharmony_ci _channelend *end = _channelend_find(send ? chan->ends->send : chan->ends->recv, 14077db96d56Sopenharmony_ci interp, NULL); 14087db96d56Sopenharmony_ci 14097db96d56Sopenharmony_ci return (end != NULL && end->open); 14107db96d56Sopenharmony_ci} 14117db96d56Sopenharmony_ci 14127db96d56Sopenharmony_ci/* ChannelID class */ 14137db96d56Sopenharmony_ci 14147db96d56Sopenharmony_cistatic PyTypeObject ChannelIDtype; 14157db96d56Sopenharmony_ci 14167db96d56Sopenharmony_citypedef struct channelid { 14177db96d56Sopenharmony_ci PyObject_HEAD 14187db96d56Sopenharmony_ci int64_t id; 14197db96d56Sopenharmony_ci int end; 14207db96d56Sopenharmony_ci int resolve; 14217db96d56Sopenharmony_ci _channels *channels; 14227db96d56Sopenharmony_ci} channelid; 14237db96d56Sopenharmony_ci 14247db96d56Sopenharmony_cistatic int 14257db96d56Sopenharmony_cichannel_id_converter(PyObject *arg, void *ptr) 14267db96d56Sopenharmony_ci{ 14277db96d56Sopenharmony_ci int64_t cid; 14287db96d56Sopenharmony_ci if (PyObject_TypeCheck(arg, &ChannelIDtype)) { 14297db96d56Sopenharmony_ci cid = ((channelid *)arg)->id; 14307db96d56Sopenharmony_ci } 14317db96d56Sopenharmony_ci else if (PyIndex_Check(arg)) { 14327db96d56Sopenharmony_ci cid = PyLong_AsLongLong(arg); 14337db96d56Sopenharmony_ci if (cid == -1 && PyErr_Occurred()) { 14347db96d56Sopenharmony_ci return 0; 14357db96d56Sopenharmony_ci } 14367db96d56Sopenharmony_ci if (cid < 0) { 14377db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, 14387db96d56Sopenharmony_ci "channel ID must be a non-negative int, got %R", arg); 14397db96d56Sopenharmony_ci return 0; 14407db96d56Sopenharmony_ci } 14417db96d56Sopenharmony_ci } 14427db96d56Sopenharmony_ci else { 14437db96d56Sopenharmony_ci PyErr_Format(PyExc_TypeError, 14447db96d56Sopenharmony_ci "channel ID must be an int, got %.100s", 14457db96d56Sopenharmony_ci Py_TYPE(arg)->tp_name); 14467db96d56Sopenharmony_ci return 0; 14477db96d56Sopenharmony_ci } 14487db96d56Sopenharmony_ci *(int64_t *)ptr = cid; 14497db96d56Sopenharmony_ci return 1; 14507db96d56Sopenharmony_ci} 14517db96d56Sopenharmony_ci 14527db96d56Sopenharmony_cistatic channelid * 14537db96d56Sopenharmony_cinewchannelid(PyTypeObject *cls, int64_t cid, int end, _channels *channels, 14547db96d56Sopenharmony_ci int force, int resolve) 14557db96d56Sopenharmony_ci{ 14567db96d56Sopenharmony_ci channelid *self = PyObject_New(channelid, cls); 14577db96d56Sopenharmony_ci if (self == NULL) { 14587db96d56Sopenharmony_ci return NULL; 14597db96d56Sopenharmony_ci } 14607db96d56Sopenharmony_ci self->id = cid; 14617db96d56Sopenharmony_ci self->end = end; 14627db96d56Sopenharmony_ci self->resolve = resolve; 14637db96d56Sopenharmony_ci self->channels = channels; 14647db96d56Sopenharmony_ci 14657db96d56Sopenharmony_ci if (_channels_add_id_object(channels, cid) != 0) { 14667db96d56Sopenharmony_ci if (force && PyErr_ExceptionMatches(ChannelNotFoundError)) { 14677db96d56Sopenharmony_ci PyErr_Clear(); 14687db96d56Sopenharmony_ci } 14697db96d56Sopenharmony_ci else { 14707db96d56Sopenharmony_ci Py_DECREF((PyObject *)self); 14717db96d56Sopenharmony_ci return NULL; 14727db96d56Sopenharmony_ci } 14737db96d56Sopenharmony_ci } 14747db96d56Sopenharmony_ci 14757db96d56Sopenharmony_ci return self; 14767db96d56Sopenharmony_ci} 14777db96d56Sopenharmony_ci 14787db96d56Sopenharmony_cistatic _channels * _global_channels(void); 14797db96d56Sopenharmony_ci 14807db96d56Sopenharmony_cistatic PyObject * 14817db96d56Sopenharmony_cichannelid_new(PyTypeObject *cls, PyObject *args, PyObject *kwds) 14827db96d56Sopenharmony_ci{ 14837db96d56Sopenharmony_ci static char *kwlist[] = {"id", "send", "recv", "force", "_resolve", NULL}; 14847db96d56Sopenharmony_ci int64_t cid; 14857db96d56Sopenharmony_ci int send = -1; 14867db96d56Sopenharmony_ci int recv = -1; 14877db96d56Sopenharmony_ci int force = 0; 14887db96d56Sopenharmony_ci int resolve = 0; 14897db96d56Sopenharmony_ci if (!PyArg_ParseTupleAndKeywords(args, kwds, 14907db96d56Sopenharmony_ci "O&|$pppp:ChannelID.__new__", kwlist, 14917db96d56Sopenharmony_ci channel_id_converter, &cid, &send, &recv, &force, &resolve)) 14927db96d56Sopenharmony_ci return NULL; 14937db96d56Sopenharmony_ci 14947db96d56Sopenharmony_ci // Handle "send" and "recv". 14957db96d56Sopenharmony_ci if (send == 0 && recv == 0) { 14967db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 14977db96d56Sopenharmony_ci "'send' and 'recv' cannot both be False"); 14987db96d56Sopenharmony_ci return NULL; 14997db96d56Sopenharmony_ci } 15007db96d56Sopenharmony_ci 15017db96d56Sopenharmony_ci int end = 0; 15027db96d56Sopenharmony_ci if (send == 1) { 15037db96d56Sopenharmony_ci if (recv == 0 || recv == -1) { 15047db96d56Sopenharmony_ci end = CHANNEL_SEND; 15057db96d56Sopenharmony_ci } 15067db96d56Sopenharmony_ci } 15077db96d56Sopenharmony_ci else if (recv == 1) { 15087db96d56Sopenharmony_ci end = CHANNEL_RECV; 15097db96d56Sopenharmony_ci } 15107db96d56Sopenharmony_ci 15117db96d56Sopenharmony_ci return (PyObject *)newchannelid(cls, cid, end, _global_channels(), 15127db96d56Sopenharmony_ci force, resolve); 15137db96d56Sopenharmony_ci} 15147db96d56Sopenharmony_ci 15157db96d56Sopenharmony_cistatic void 15167db96d56Sopenharmony_cichannelid_dealloc(PyObject *v) 15177db96d56Sopenharmony_ci{ 15187db96d56Sopenharmony_ci int64_t cid = ((channelid *)v)->id; 15197db96d56Sopenharmony_ci _channels *channels = ((channelid *)v)->channels; 15207db96d56Sopenharmony_ci Py_TYPE(v)->tp_free(v); 15217db96d56Sopenharmony_ci 15227db96d56Sopenharmony_ci _channels_drop_id_object(channels, cid); 15237db96d56Sopenharmony_ci} 15247db96d56Sopenharmony_ci 15257db96d56Sopenharmony_cistatic PyObject * 15267db96d56Sopenharmony_cichannelid_repr(PyObject *self) 15277db96d56Sopenharmony_ci{ 15287db96d56Sopenharmony_ci PyTypeObject *type = Py_TYPE(self); 15297db96d56Sopenharmony_ci const char *name = _PyType_Name(type); 15307db96d56Sopenharmony_ci 15317db96d56Sopenharmony_ci channelid *cid = (channelid *)self; 15327db96d56Sopenharmony_ci const char *fmt; 15337db96d56Sopenharmony_ci if (cid->end == CHANNEL_SEND) { 15347db96d56Sopenharmony_ci fmt = "%s(%" PRId64 ", send=True)"; 15357db96d56Sopenharmony_ci } 15367db96d56Sopenharmony_ci else if (cid->end == CHANNEL_RECV) { 15377db96d56Sopenharmony_ci fmt = "%s(%" PRId64 ", recv=True)"; 15387db96d56Sopenharmony_ci } 15397db96d56Sopenharmony_ci else { 15407db96d56Sopenharmony_ci fmt = "%s(%" PRId64 ")"; 15417db96d56Sopenharmony_ci } 15427db96d56Sopenharmony_ci return PyUnicode_FromFormat(fmt, name, cid->id); 15437db96d56Sopenharmony_ci} 15447db96d56Sopenharmony_ci 15457db96d56Sopenharmony_cistatic PyObject * 15467db96d56Sopenharmony_cichannelid_str(PyObject *self) 15477db96d56Sopenharmony_ci{ 15487db96d56Sopenharmony_ci channelid *cid = (channelid *)self; 15497db96d56Sopenharmony_ci return PyUnicode_FromFormat("%" PRId64 "", cid->id); 15507db96d56Sopenharmony_ci} 15517db96d56Sopenharmony_ci 15527db96d56Sopenharmony_cistatic PyObject * 15537db96d56Sopenharmony_cichannelid_int(PyObject *self) 15547db96d56Sopenharmony_ci{ 15557db96d56Sopenharmony_ci channelid *cid = (channelid *)self; 15567db96d56Sopenharmony_ci return PyLong_FromLongLong(cid->id); 15577db96d56Sopenharmony_ci} 15587db96d56Sopenharmony_ci 15597db96d56Sopenharmony_cistatic PyNumberMethods channelid_as_number = { 15607db96d56Sopenharmony_ci 0, /* nb_add */ 15617db96d56Sopenharmony_ci 0, /* nb_subtract */ 15627db96d56Sopenharmony_ci 0, /* nb_multiply */ 15637db96d56Sopenharmony_ci 0, /* nb_remainder */ 15647db96d56Sopenharmony_ci 0, /* nb_divmod */ 15657db96d56Sopenharmony_ci 0, /* nb_power */ 15667db96d56Sopenharmony_ci 0, /* nb_negative */ 15677db96d56Sopenharmony_ci 0, /* nb_positive */ 15687db96d56Sopenharmony_ci 0, /* nb_absolute */ 15697db96d56Sopenharmony_ci 0, /* nb_bool */ 15707db96d56Sopenharmony_ci 0, /* nb_invert */ 15717db96d56Sopenharmony_ci 0, /* nb_lshift */ 15727db96d56Sopenharmony_ci 0, /* nb_rshift */ 15737db96d56Sopenharmony_ci 0, /* nb_and */ 15747db96d56Sopenharmony_ci 0, /* nb_xor */ 15757db96d56Sopenharmony_ci 0, /* nb_or */ 15767db96d56Sopenharmony_ci (unaryfunc)channelid_int, /* nb_int */ 15777db96d56Sopenharmony_ci 0, /* nb_reserved */ 15787db96d56Sopenharmony_ci 0, /* nb_float */ 15797db96d56Sopenharmony_ci 15807db96d56Sopenharmony_ci 0, /* nb_inplace_add */ 15817db96d56Sopenharmony_ci 0, /* nb_inplace_subtract */ 15827db96d56Sopenharmony_ci 0, /* nb_inplace_multiply */ 15837db96d56Sopenharmony_ci 0, /* nb_inplace_remainder */ 15847db96d56Sopenharmony_ci 0, /* nb_inplace_power */ 15857db96d56Sopenharmony_ci 0, /* nb_inplace_lshift */ 15867db96d56Sopenharmony_ci 0, /* nb_inplace_rshift */ 15877db96d56Sopenharmony_ci 0, /* nb_inplace_and */ 15887db96d56Sopenharmony_ci 0, /* nb_inplace_xor */ 15897db96d56Sopenharmony_ci 0, /* nb_inplace_or */ 15907db96d56Sopenharmony_ci 15917db96d56Sopenharmony_ci 0, /* nb_floor_divide */ 15927db96d56Sopenharmony_ci 0, /* nb_true_divide */ 15937db96d56Sopenharmony_ci 0, /* nb_inplace_floor_divide */ 15947db96d56Sopenharmony_ci 0, /* nb_inplace_true_divide */ 15957db96d56Sopenharmony_ci 15967db96d56Sopenharmony_ci (unaryfunc)channelid_int, /* nb_index */ 15977db96d56Sopenharmony_ci}; 15987db96d56Sopenharmony_ci 15997db96d56Sopenharmony_cistatic Py_hash_t 16007db96d56Sopenharmony_cichannelid_hash(PyObject *self) 16017db96d56Sopenharmony_ci{ 16027db96d56Sopenharmony_ci channelid *cid = (channelid *)self; 16037db96d56Sopenharmony_ci PyObject *id = PyLong_FromLongLong(cid->id); 16047db96d56Sopenharmony_ci if (id == NULL) { 16057db96d56Sopenharmony_ci return -1; 16067db96d56Sopenharmony_ci } 16077db96d56Sopenharmony_ci Py_hash_t hash = PyObject_Hash(id); 16087db96d56Sopenharmony_ci Py_DECREF(id); 16097db96d56Sopenharmony_ci return hash; 16107db96d56Sopenharmony_ci} 16117db96d56Sopenharmony_ci 16127db96d56Sopenharmony_cistatic PyObject * 16137db96d56Sopenharmony_cichannelid_richcompare(PyObject *self, PyObject *other, int op) 16147db96d56Sopenharmony_ci{ 16157db96d56Sopenharmony_ci if (op != Py_EQ && op != Py_NE) { 16167db96d56Sopenharmony_ci Py_RETURN_NOTIMPLEMENTED; 16177db96d56Sopenharmony_ci } 16187db96d56Sopenharmony_ci 16197db96d56Sopenharmony_ci if (!PyObject_TypeCheck(self, &ChannelIDtype)) { 16207db96d56Sopenharmony_ci Py_RETURN_NOTIMPLEMENTED; 16217db96d56Sopenharmony_ci } 16227db96d56Sopenharmony_ci 16237db96d56Sopenharmony_ci channelid *cid = (channelid *)self; 16247db96d56Sopenharmony_ci int equal; 16257db96d56Sopenharmony_ci if (PyObject_TypeCheck(other, &ChannelIDtype)) { 16267db96d56Sopenharmony_ci channelid *othercid = (channelid *)other; 16277db96d56Sopenharmony_ci equal = (cid->end == othercid->end) && (cid->id == othercid->id); 16287db96d56Sopenharmony_ci } 16297db96d56Sopenharmony_ci else if (PyLong_Check(other)) { 16307db96d56Sopenharmony_ci /* Fast path */ 16317db96d56Sopenharmony_ci int overflow; 16327db96d56Sopenharmony_ci long long othercid = PyLong_AsLongLongAndOverflow(other, &overflow); 16337db96d56Sopenharmony_ci if (othercid == -1 && PyErr_Occurred()) { 16347db96d56Sopenharmony_ci return NULL; 16357db96d56Sopenharmony_ci } 16367db96d56Sopenharmony_ci equal = !overflow && (othercid >= 0) && (cid->id == othercid); 16377db96d56Sopenharmony_ci } 16387db96d56Sopenharmony_ci else if (PyNumber_Check(other)) { 16397db96d56Sopenharmony_ci PyObject *pyid = PyLong_FromLongLong(cid->id); 16407db96d56Sopenharmony_ci if (pyid == NULL) { 16417db96d56Sopenharmony_ci return NULL; 16427db96d56Sopenharmony_ci } 16437db96d56Sopenharmony_ci PyObject *res = PyObject_RichCompare(pyid, other, op); 16447db96d56Sopenharmony_ci Py_DECREF(pyid); 16457db96d56Sopenharmony_ci return res; 16467db96d56Sopenharmony_ci } 16477db96d56Sopenharmony_ci else { 16487db96d56Sopenharmony_ci Py_RETURN_NOTIMPLEMENTED; 16497db96d56Sopenharmony_ci } 16507db96d56Sopenharmony_ci 16517db96d56Sopenharmony_ci if ((op == Py_EQ && equal) || (op == Py_NE && !equal)) { 16527db96d56Sopenharmony_ci Py_RETURN_TRUE; 16537db96d56Sopenharmony_ci } 16547db96d56Sopenharmony_ci Py_RETURN_FALSE; 16557db96d56Sopenharmony_ci} 16567db96d56Sopenharmony_ci 16577db96d56Sopenharmony_cistatic PyObject * 16587db96d56Sopenharmony_ci_channel_from_cid(PyObject *cid, int end) 16597db96d56Sopenharmony_ci{ 16607db96d56Sopenharmony_ci PyObject *highlevel = PyImport_ImportModule("interpreters"); 16617db96d56Sopenharmony_ci if (highlevel == NULL) { 16627db96d56Sopenharmony_ci PyErr_Clear(); 16637db96d56Sopenharmony_ci highlevel = PyImport_ImportModule("test.support.interpreters"); 16647db96d56Sopenharmony_ci if (highlevel == NULL) { 16657db96d56Sopenharmony_ci return NULL; 16667db96d56Sopenharmony_ci } 16677db96d56Sopenharmony_ci } 16687db96d56Sopenharmony_ci const char *clsname = (end == CHANNEL_RECV) ? "RecvChannel" : 16697db96d56Sopenharmony_ci "SendChannel"; 16707db96d56Sopenharmony_ci PyObject *cls = PyObject_GetAttrString(highlevel, clsname); 16717db96d56Sopenharmony_ci Py_DECREF(highlevel); 16727db96d56Sopenharmony_ci if (cls == NULL) { 16737db96d56Sopenharmony_ci return NULL; 16747db96d56Sopenharmony_ci } 16757db96d56Sopenharmony_ci PyObject *chan = PyObject_CallFunctionObjArgs(cls, cid, NULL); 16767db96d56Sopenharmony_ci Py_DECREF(cls); 16777db96d56Sopenharmony_ci if (chan == NULL) { 16787db96d56Sopenharmony_ci return NULL; 16797db96d56Sopenharmony_ci } 16807db96d56Sopenharmony_ci return chan; 16817db96d56Sopenharmony_ci} 16827db96d56Sopenharmony_ci 16837db96d56Sopenharmony_cistruct _channelid_xid { 16847db96d56Sopenharmony_ci int64_t id; 16857db96d56Sopenharmony_ci int end; 16867db96d56Sopenharmony_ci int resolve; 16877db96d56Sopenharmony_ci}; 16887db96d56Sopenharmony_ci 16897db96d56Sopenharmony_cistatic PyObject * 16907db96d56Sopenharmony_ci_channelid_from_xid(_PyCrossInterpreterData *data) 16917db96d56Sopenharmony_ci{ 16927db96d56Sopenharmony_ci struct _channelid_xid *xid = (struct _channelid_xid *)data->data; 16937db96d56Sopenharmony_ci // Note that we do not preserve the "resolve" flag. 16947db96d56Sopenharmony_ci PyObject *cid = (PyObject *)newchannelid(&ChannelIDtype, xid->id, xid->end, 16957db96d56Sopenharmony_ci _global_channels(), 0, 0); 16967db96d56Sopenharmony_ci if (xid->end == 0) { 16977db96d56Sopenharmony_ci return cid; 16987db96d56Sopenharmony_ci } 16997db96d56Sopenharmony_ci if (!xid->resolve) { 17007db96d56Sopenharmony_ci return cid; 17017db96d56Sopenharmony_ci } 17027db96d56Sopenharmony_ci 17037db96d56Sopenharmony_ci /* Try returning a high-level channel end but fall back to the ID. */ 17047db96d56Sopenharmony_ci PyObject *chan = _channel_from_cid(cid, xid->end); 17057db96d56Sopenharmony_ci if (chan == NULL) { 17067db96d56Sopenharmony_ci PyErr_Clear(); 17077db96d56Sopenharmony_ci return cid; 17087db96d56Sopenharmony_ci } 17097db96d56Sopenharmony_ci Py_DECREF(cid); 17107db96d56Sopenharmony_ci return chan; 17117db96d56Sopenharmony_ci} 17127db96d56Sopenharmony_ci 17137db96d56Sopenharmony_cistatic int 17147db96d56Sopenharmony_ci_channelid_shared(PyObject *obj, _PyCrossInterpreterData *data) 17157db96d56Sopenharmony_ci{ 17167db96d56Sopenharmony_ci struct _channelid_xid *xid = PyMem_NEW(struct _channelid_xid, 1); 17177db96d56Sopenharmony_ci if (xid == NULL) { 17187db96d56Sopenharmony_ci return -1; 17197db96d56Sopenharmony_ci } 17207db96d56Sopenharmony_ci xid->id = ((channelid *)obj)->id; 17217db96d56Sopenharmony_ci xid->end = ((channelid *)obj)->end; 17227db96d56Sopenharmony_ci xid->resolve = ((channelid *)obj)->resolve; 17237db96d56Sopenharmony_ci 17247db96d56Sopenharmony_ci data->data = xid; 17257db96d56Sopenharmony_ci Py_INCREF(obj); 17267db96d56Sopenharmony_ci data->obj = obj; 17277db96d56Sopenharmony_ci data->new_object = _channelid_from_xid; 17287db96d56Sopenharmony_ci data->free = PyMem_Free; 17297db96d56Sopenharmony_ci return 0; 17307db96d56Sopenharmony_ci} 17317db96d56Sopenharmony_ci 17327db96d56Sopenharmony_cistatic PyObject * 17337db96d56Sopenharmony_cichannelid_end(PyObject *self, void *end) 17347db96d56Sopenharmony_ci{ 17357db96d56Sopenharmony_ci int force = 1; 17367db96d56Sopenharmony_ci channelid *cid = (channelid *)self; 17377db96d56Sopenharmony_ci if (end != NULL) { 17387db96d56Sopenharmony_ci return (PyObject *)newchannelid(Py_TYPE(self), cid->id, *(int *)end, 17397db96d56Sopenharmony_ci cid->channels, force, cid->resolve); 17407db96d56Sopenharmony_ci } 17417db96d56Sopenharmony_ci 17427db96d56Sopenharmony_ci if (cid->end == CHANNEL_SEND) { 17437db96d56Sopenharmony_ci return PyUnicode_InternFromString("send"); 17447db96d56Sopenharmony_ci } 17457db96d56Sopenharmony_ci if (cid->end == CHANNEL_RECV) { 17467db96d56Sopenharmony_ci return PyUnicode_InternFromString("recv"); 17477db96d56Sopenharmony_ci } 17487db96d56Sopenharmony_ci return PyUnicode_InternFromString("both"); 17497db96d56Sopenharmony_ci} 17507db96d56Sopenharmony_ci 17517db96d56Sopenharmony_cistatic int _channelid_end_send = CHANNEL_SEND; 17527db96d56Sopenharmony_cistatic int _channelid_end_recv = CHANNEL_RECV; 17537db96d56Sopenharmony_ci 17547db96d56Sopenharmony_cistatic PyGetSetDef channelid_getsets[] = { 17557db96d56Sopenharmony_ci {"end", (getter)channelid_end, NULL, 17567db96d56Sopenharmony_ci PyDoc_STR("'send', 'recv', or 'both'")}, 17577db96d56Sopenharmony_ci {"send", (getter)channelid_end, NULL, 17587db96d56Sopenharmony_ci PyDoc_STR("the 'send' end of the channel"), &_channelid_end_send}, 17597db96d56Sopenharmony_ci {"recv", (getter)channelid_end, NULL, 17607db96d56Sopenharmony_ci PyDoc_STR("the 'recv' end of the channel"), &_channelid_end_recv}, 17617db96d56Sopenharmony_ci {NULL} 17627db96d56Sopenharmony_ci}; 17637db96d56Sopenharmony_ci 17647db96d56Sopenharmony_ciPyDoc_STRVAR(channelid_doc, 17657db96d56Sopenharmony_ci"A channel ID identifies a channel and may be used as an int."); 17667db96d56Sopenharmony_ci 17677db96d56Sopenharmony_cistatic PyTypeObject ChannelIDtype = { 17687db96d56Sopenharmony_ci PyVarObject_HEAD_INIT(&PyType_Type, 0) 17697db96d56Sopenharmony_ci "_xxsubinterpreters.ChannelID", /* tp_name */ 17707db96d56Sopenharmony_ci sizeof(channelid), /* tp_basicsize */ 17717db96d56Sopenharmony_ci 0, /* tp_itemsize */ 17727db96d56Sopenharmony_ci (destructor)channelid_dealloc, /* tp_dealloc */ 17737db96d56Sopenharmony_ci 0, /* tp_vectorcall_offset */ 17747db96d56Sopenharmony_ci 0, /* tp_getattr */ 17757db96d56Sopenharmony_ci 0, /* tp_setattr */ 17767db96d56Sopenharmony_ci 0, /* tp_as_async */ 17777db96d56Sopenharmony_ci (reprfunc)channelid_repr, /* tp_repr */ 17787db96d56Sopenharmony_ci &channelid_as_number, /* tp_as_number */ 17797db96d56Sopenharmony_ci 0, /* tp_as_sequence */ 17807db96d56Sopenharmony_ci 0, /* tp_as_mapping */ 17817db96d56Sopenharmony_ci channelid_hash, /* tp_hash */ 17827db96d56Sopenharmony_ci 0, /* tp_call */ 17837db96d56Sopenharmony_ci (reprfunc)channelid_str, /* tp_str */ 17847db96d56Sopenharmony_ci 0, /* tp_getattro */ 17857db96d56Sopenharmony_ci 0, /* tp_setattro */ 17867db96d56Sopenharmony_ci 0, /* tp_as_buffer */ 17877db96d56Sopenharmony_ci // Use Py_TPFLAGS_DISALLOW_INSTANTIATION so the type cannot be instantiated 17887db96d56Sopenharmony_ci // from Python code. We do this because there is a strong relationship 17897db96d56Sopenharmony_ci // between channel IDs and the channel lifecycle, so this limitation avoids 17907db96d56Sopenharmony_ci // related complications. Use the _channel_id() function instead. 17917db96d56Sopenharmony_ci Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE 17927db96d56Sopenharmony_ci | Py_TPFLAGS_DISALLOW_INSTANTIATION, /* tp_flags */ 17937db96d56Sopenharmony_ci channelid_doc, /* tp_doc */ 17947db96d56Sopenharmony_ci 0, /* tp_traverse */ 17957db96d56Sopenharmony_ci 0, /* tp_clear */ 17967db96d56Sopenharmony_ci channelid_richcompare, /* tp_richcompare */ 17977db96d56Sopenharmony_ci 0, /* tp_weaklistoffset */ 17987db96d56Sopenharmony_ci 0, /* tp_iter */ 17997db96d56Sopenharmony_ci 0, /* tp_iternext */ 18007db96d56Sopenharmony_ci 0, /* tp_methods */ 18017db96d56Sopenharmony_ci 0, /* tp_members */ 18027db96d56Sopenharmony_ci channelid_getsets, /* tp_getset */ 18037db96d56Sopenharmony_ci}; 18047db96d56Sopenharmony_ci 18057db96d56Sopenharmony_ci 18067db96d56Sopenharmony_ci/* interpreter-specific code ************************************************/ 18077db96d56Sopenharmony_ci 18087db96d56Sopenharmony_cistatic PyObject * RunFailedError = NULL; 18097db96d56Sopenharmony_ci 18107db96d56Sopenharmony_cistatic int 18117db96d56Sopenharmony_ciinterp_exceptions_init(PyObject *ns) 18127db96d56Sopenharmony_ci{ 18137db96d56Sopenharmony_ci // XXX Move the exceptions into per-module memory? 18147db96d56Sopenharmony_ci 18157db96d56Sopenharmony_ci if (RunFailedError == NULL) { 18167db96d56Sopenharmony_ci // An uncaught exception came out of interp_run_string(). 18177db96d56Sopenharmony_ci RunFailedError = PyErr_NewException("_xxsubinterpreters.RunFailedError", 18187db96d56Sopenharmony_ci PyExc_RuntimeError, NULL); 18197db96d56Sopenharmony_ci if (RunFailedError == NULL) { 18207db96d56Sopenharmony_ci return -1; 18217db96d56Sopenharmony_ci } 18227db96d56Sopenharmony_ci if (PyDict_SetItemString(ns, "RunFailedError", RunFailedError) != 0) { 18237db96d56Sopenharmony_ci return -1; 18247db96d56Sopenharmony_ci } 18257db96d56Sopenharmony_ci } 18267db96d56Sopenharmony_ci 18277db96d56Sopenharmony_ci return 0; 18287db96d56Sopenharmony_ci} 18297db96d56Sopenharmony_ci 18307db96d56Sopenharmony_cistatic int 18317db96d56Sopenharmony_ci_is_running(PyInterpreterState *interp) 18327db96d56Sopenharmony_ci{ 18337db96d56Sopenharmony_ci PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); 18347db96d56Sopenharmony_ci if (PyThreadState_Next(tstate) != NULL) { 18357db96d56Sopenharmony_ci PyErr_SetString(PyExc_RuntimeError, 18367db96d56Sopenharmony_ci "interpreter has more than one thread"); 18377db96d56Sopenharmony_ci return -1; 18387db96d56Sopenharmony_ci } 18397db96d56Sopenharmony_ci 18407db96d56Sopenharmony_ci assert(!PyErr_Occurred()); 18417db96d56Sopenharmony_ci _PyInterpreterFrame *frame = tstate->cframe->current_frame; 18427db96d56Sopenharmony_ci if (frame == NULL) { 18437db96d56Sopenharmony_ci return 0; 18447db96d56Sopenharmony_ci } 18457db96d56Sopenharmony_ci return 1; 18467db96d56Sopenharmony_ci} 18477db96d56Sopenharmony_ci 18487db96d56Sopenharmony_cistatic int 18497db96d56Sopenharmony_ci_ensure_not_running(PyInterpreterState *interp) 18507db96d56Sopenharmony_ci{ 18517db96d56Sopenharmony_ci int is_running = _is_running(interp); 18527db96d56Sopenharmony_ci if (is_running < 0) { 18537db96d56Sopenharmony_ci return -1; 18547db96d56Sopenharmony_ci } 18557db96d56Sopenharmony_ci if (is_running) { 18567db96d56Sopenharmony_ci PyErr_Format(PyExc_RuntimeError, "interpreter already running"); 18577db96d56Sopenharmony_ci return -1; 18587db96d56Sopenharmony_ci } 18597db96d56Sopenharmony_ci return 0; 18607db96d56Sopenharmony_ci} 18617db96d56Sopenharmony_ci 18627db96d56Sopenharmony_cistatic int 18637db96d56Sopenharmony_ci_run_script(PyInterpreterState *interp, const char *codestr, 18647db96d56Sopenharmony_ci _sharedns *shared, _sharedexception **exc) 18657db96d56Sopenharmony_ci{ 18667db96d56Sopenharmony_ci PyObject *exctype = NULL; 18677db96d56Sopenharmony_ci PyObject *excval = NULL; 18687db96d56Sopenharmony_ci PyObject *tb = NULL; 18697db96d56Sopenharmony_ci 18707db96d56Sopenharmony_ci PyObject *main_mod = _PyInterpreterState_GetMainModule(interp); 18717db96d56Sopenharmony_ci if (main_mod == NULL) { 18727db96d56Sopenharmony_ci goto error; 18737db96d56Sopenharmony_ci } 18747db96d56Sopenharmony_ci PyObject *ns = PyModule_GetDict(main_mod); // borrowed 18757db96d56Sopenharmony_ci Py_DECREF(main_mod); 18767db96d56Sopenharmony_ci if (ns == NULL) { 18777db96d56Sopenharmony_ci goto error; 18787db96d56Sopenharmony_ci } 18797db96d56Sopenharmony_ci Py_INCREF(ns); 18807db96d56Sopenharmony_ci 18817db96d56Sopenharmony_ci // Apply the cross-interpreter data. 18827db96d56Sopenharmony_ci if (shared != NULL) { 18837db96d56Sopenharmony_ci if (_sharedns_apply(shared, ns) != 0) { 18847db96d56Sopenharmony_ci Py_DECREF(ns); 18857db96d56Sopenharmony_ci goto error; 18867db96d56Sopenharmony_ci } 18877db96d56Sopenharmony_ci } 18887db96d56Sopenharmony_ci 18897db96d56Sopenharmony_ci // Run the string (see PyRun_SimpleStringFlags). 18907db96d56Sopenharmony_ci PyObject *result = PyRun_StringFlags(codestr, Py_file_input, ns, ns, NULL); 18917db96d56Sopenharmony_ci Py_DECREF(ns); 18927db96d56Sopenharmony_ci if (result == NULL) { 18937db96d56Sopenharmony_ci goto error; 18947db96d56Sopenharmony_ci } 18957db96d56Sopenharmony_ci else { 18967db96d56Sopenharmony_ci Py_DECREF(result); // We throw away the result. 18977db96d56Sopenharmony_ci } 18987db96d56Sopenharmony_ci 18997db96d56Sopenharmony_ci *exc = NULL; 19007db96d56Sopenharmony_ci return 0; 19017db96d56Sopenharmony_ci 19027db96d56Sopenharmony_cierror: 19037db96d56Sopenharmony_ci PyErr_Fetch(&exctype, &excval, &tb); 19047db96d56Sopenharmony_ci 19057db96d56Sopenharmony_ci _sharedexception *sharedexc = _sharedexception_bind(exctype, excval, tb); 19067db96d56Sopenharmony_ci Py_XDECREF(exctype); 19077db96d56Sopenharmony_ci Py_XDECREF(excval); 19087db96d56Sopenharmony_ci Py_XDECREF(tb); 19097db96d56Sopenharmony_ci if (sharedexc == NULL) { 19107db96d56Sopenharmony_ci fprintf(stderr, "RunFailedError: script raised an uncaught exception"); 19117db96d56Sopenharmony_ci PyErr_Clear(); 19127db96d56Sopenharmony_ci sharedexc = NULL; 19137db96d56Sopenharmony_ci } 19147db96d56Sopenharmony_ci else { 19157db96d56Sopenharmony_ci assert(!PyErr_Occurred()); 19167db96d56Sopenharmony_ci } 19177db96d56Sopenharmony_ci *exc = sharedexc; 19187db96d56Sopenharmony_ci return -1; 19197db96d56Sopenharmony_ci} 19207db96d56Sopenharmony_ci 19217db96d56Sopenharmony_cistatic int 19227db96d56Sopenharmony_ci_run_script_in_interpreter(PyInterpreterState *interp, const char *codestr, 19237db96d56Sopenharmony_ci PyObject *shareables) 19247db96d56Sopenharmony_ci{ 19257db96d56Sopenharmony_ci if (_ensure_not_running(interp) < 0) { 19267db96d56Sopenharmony_ci return -1; 19277db96d56Sopenharmony_ci } 19287db96d56Sopenharmony_ci 19297db96d56Sopenharmony_ci _sharedns *shared = _get_shared_ns(shareables); 19307db96d56Sopenharmony_ci if (shared == NULL && PyErr_Occurred()) { 19317db96d56Sopenharmony_ci return -1; 19327db96d56Sopenharmony_ci } 19337db96d56Sopenharmony_ci 19347db96d56Sopenharmony_ci // Switch to interpreter. 19357db96d56Sopenharmony_ci PyThreadState *save_tstate = NULL; 19367db96d56Sopenharmony_ci if (interp != PyInterpreterState_Get()) { 19377db96d56Sopenharmony_ci // XXX Using the "head" thread isn't strictly correct. 19387db96d56Sopenharmony_ci PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); 19397db96d56Sopenharmony_ci // XXX Possible GILState issues? 19407db96d56Sopenharmony_ci save_tstate = PyThreadState_Swap(tstate); 19417db96d56Sopenharmony_ci } 19427db96d56Sopenharmony_ci 19437db96d56Sopenharmony_ci // Run the script. 19447db96d56Sopenharmony_ci _sharedexception *exc = NULL; 19457db96d56Sopenharmony_ci int result = _run_script(interp, codestr, shared, &exc); 19467db96d56Sopenharmony_ci 19477db96d56Sopenharmony_ci // Switch back. 19487db96d56Sopenharmony_ci if (save_tstate != NULL) { 19497db96d56Sopenharmony_ci PyThreadState_Swap(save_tstate); 19507db96d56Sopenharmony_ci } 19517db96d56Sopenharmony_ci 19527db96d56Sopenharmony_ci // Propagate any exception out to the caller. 19537db96d56Sopenharmony_ci if (exc != NULL) { 19547db96d56Sopenharmony_ci _sharedexception_apply(exc, RunFailedError); 19557db96d56Sopenharmony_ci _sharedexception_free(exc); 19567db96d56Sopenharmony_ci } 19577db96d56Sopenharmony_ci else if (result != 0) { 19587db96d56Sopenharmony_ci // We were unable to allocate a shared exception. 19597db96d56Sopenharmony_ci PyErr_NoMemory(); 19607db96d56Sopenharmony_ci } 19617db96d56Sopenharmony_ci 19627db96d56Sopenharmony_ci if (shared != NULL) { 19637db96d56Sopenharmony_ci _sharedns_free(shared); 19647db96d56Sopenharmony_ci } 19657db96d56Sopenharmony_ci 19667db96d56Sopenharmony_ci return result; 19677db96d56Sopenharmony_ci} 19687db96d56Sopenharmony_ci 19697db96d56Sopenharmony_ci 19707db96d56Sopenharmony_ci/* module level code ********************************************************/ 19717db96d56Sopenharmony_ci 19727db96d56Sopenharmony_ci/* globals is the process-global state for the module. It holds all 19737db96d56Sopenharmony_ci the data that we need to share between interpreters, so it cannot 19747db96d56Sopenharmony_ci hold PyObject values. */ 19757db96d56Sopenharmony_cistatic struct globals { 19767db96d56Sopenharmony_ci _channels channels; 19777db96d56Sopenharmony_ci} _globals = {{0}}; 19787db96d56Sopenharmony_ci 19797db96d56Sopenharmony_cistatic int 19807db96d56Sopenharmony_ci_init_globals(void) 19817db96d56Sopenharmony_ci{ 19827db96d56Sopenharmony_ci if (_channels_init(&_globals.channels) != 0) { 19837db96d56Sopenharmony_ci return -1; 19847db96d56Sopenharmony_ci } 19857db96d56Sopenharmony_ci return 0; 19867db96d56Sopenharmony_ci} 19877db96d56Sopenharmony_ci 19887db96d56Sopenharmony_cistatic _channels * 19897db96d56Sopenharmony_ci_global_channels(void) { 19907db96d56Sopenharmony_ci return &_globals.channels; 19917db96d56Sopenharmony_ci} 19927db96d56Sopenharmony_ci 19937db96d56Sopenharmony_cistatic PyObject * 19947db96d56Sopenharmony_ciinterp_create(PyObject *self, PyObject *args, PyObject *kwds) 19957db96d56Sopenharmony_ci{ 19967db96d56Sopenharmony_ci 19977db96d56Sopenharmony_ci static char *kwlist[] = {"isolated", NULL}; 19987db96d56Sopenharmony_ci int isolated = 1; 19997db96d56Sopenharmony_ci if (!PyArg_ParseTupleAndKeywords(args, kwds, "|$i:create", kwlist, 20007db96d56Sopenharmony_ci &isolated)) { 20017db96d56Sopenharmony_ci return NULL; 20027db96d56Sopenharmony_ci } 20037db96d56Sopenharmony_ci 20047db96d56Sopenharmony_ci // Create and initialize the new interpreter. 20057db96d56Sopenharmony_ci PyThreadState *save_tstate = _PyThreadState_GET(); 20067db96d56Sopenharmony_ci // XXX Possible GILState issues? 20077db96d56Sopenharmony_ci PyThreadState *tstate = _Py_NewInterpreter(isolated); 20087db96d56Sopenharmony_ci PyThreadState_Swap(save_tstate); 20097db96d56Sopenharmony_ci if (tstate == NULL) { 20107db96d56Sopenharmony_ci /* Since no new thread state was created, there is no exception to 20117db96d56Sopenharmony_ci propagate; raise a fresh one after swapping in the old thread 20127db96d56Sopenharmony_ci state. */ 20137db96d56Sopenharmony_ci PyErr_SetString(PyExc_RuntimeError, "interpreter creation failed"); 20147db96d56Sopenharmony_ci return NULL; 20157db96d56Sopenharmony_ci } 20167db96d56Sopenharmony_ci PyInterpreterState *interp = PyThreadState_GetInterpreter(tstate); 20177db96d56Sopenharmony_ci PyObject *idobj = _PyInterpreterState_GetIDObject(interp); 20187db96d56Sopenharmony_ci if (idobj == NULL) { 20197db96d56Sopenharmony_ci // XXX Possible GILState issues? 20207db96d56Sopenharmony_ci save_tstate = PyThreadState_Swap(tstate); 20217db96d56Sopenharmony_ci Py_EndInterpreter(tstate); 20227db96d56Sopenharmony_ci PyThreadState_Swap(save_tstate); 20237db96d56Sopenharmony_ci return NULL; 20247db96d56Sopenharmony_ci } 20257db96d56Sopenharmony_ci _PyInterpreterState_RequireIDRef(interp, 1); 20267db96d56Sopenharmony_ci return idobj; 20277db96d56Sopenharmony_ci} 20287db96d56Sopenharmony_ci 20297db96d56Sopenharmony_ciPyDoc_STRVAR(create_doc, 20307db96d56Sopenharmony_ci"create() -> ID\n\ 20317db96d56Sopenharmony_ci\n\ 20327db96d56Sopenharmony_ciCreate a new interpreter and return a unique generated ID."); 20337db96d56Sopenharmony_ci 20347db96d56Sopenharmony_ci 20357db96d56Sopenharmony_cistatic PyObject * 20367db96d56Sopenharmony_ciinterp_destroy(PyObject *self, PyObject *args, PyObject *kwds) 20377db96d56Sopenharmony_ci{ 20387db96d56Sopenharmony_ci static char *kwlist[] = {"id", NULL}; 20397db96d56Sopenharmony_ci PyObject *id; 20407db96d56Sopenharmony_ci // XXX Use "L" for id? 20417db96d56Sopenharmony_ci if (!PyArg_ParseTupleAndKeywords(args, kwds, 20427db96d56Sopenharmony_ci "O:destroy", kwlist, &id)) { 20437db96d56Sopenharmony_ci return NULL; 20447db96d56Sopenharmony_ci } 20457db96d56Sopenharmony_ci 20467db96d56Sopenharmony_ci // Look up the interpreter. 20477db96d56Sopenharmony_ci PyInterpreterState *interp = _PyInterpreterID_LookUp(id); 20487db96d56Sopenharmony_ci if (interp == NULL) { 20497db96d56Sopenharmony_ci return NULL; 20507db96d56Sopenharmony_ci } 20517db96d56Sopenharmony_ci 20527db96d56Sopenharmony_ci // Ensure we don't try to destroy the current interpreter. 20537db96d56Sopenharmony_ci PyInterpreterState *current = _get_current(); 20547db96d56Sopenharmony_ci if (current == NULL) { 20557db96d56Sopenharmony_ci return NULL; 20567db96d56Sopenharmony_ci } 20577db96d56Sopenharmony_ci if (interp == current) { 20587db96d56Sopenharmony_ci PyErr_SetString(PyExc_RuntimeError, 20597db96d56Sopenharmony_ci "cannot destroy the current interpreter"); 20607db96d56Sopenharmony_ci return NULL; 20617db96d56Sopenharmony_ci } 20627db96d56Sopenharmony_ci 20637db96d56Sopenharmony_ci // Ensure the interpreter isn't running. 20647db96d56Sopenharmony_ci /* XXX We *could* support destroying a running interpreter but 20657db96d56Sopenharmony_ci aren't going to worry about it for now. */ 20667db96d56Sopenharmony_ci if (_ensure_not_running(interp) < 0) { 20677db96d56Sopenharmony_ci return NULL; 20687db96d56Sopenharmony_ci } 20697db96d56Sopenharmony_ci 20707db96d56Sopenharmony_ci // Destroy the interpreter. 20717db96d56Sopenharmony_ci PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); 20727db96d56Sopenharmony_ci // XXX Possible GILState issues? 20737db96d56Sopenharmony_ci PyThreadState *save_tstate = PyThreadState_Swap(tstate); 20747db96d56Sopenharmony_ci Py_EndInterpreter(tstate); 20757db96d56Sopenharmony_ci PyThreadState_Swap(save_tstate); 20767db96d56Sopenharmony_ci 20777db96d56Sopenharmony_ci Py_RETURN_NONE; 20787db96d56Sopenharmony_ci} 20797db96d56Sopenharmony_ci 20807db96d56Sopenharmony_ciPyDoc_STRVAR(destroy_doc, 20817db96d56Sopenharmony_ci"destroy(id)\n\ 20827db96d56Sopenharmony_ci\n\ 20837db96d56Sopenharmony_ciDestroy the identified interpreter.\n\ 20847db96d56Sopenharmony_ci\n\ 20857db96d56Sopenharmony_ciAttempting to destroy the current interpreter results in a RuntimeError.\n\ 20867db96d56Sopenharmony_ciSo does an unrecognized ID."); 20877db96d56Sopenharmony_ci 20887db96d56Sopenharmony_ci 20897db96d56Sopenharmony_cistatic PyObject * 20907db96d56Sopenharmony_ciinterp_list_all(PyObject *self, PyObject *Py_UNUSED(ignored)) 20917db96d56Sopenharmony_ci{ 20927db96d56Sopenharmony_ci PyObject *ids, *id; 20937db96d56Sopenharmony_ci PyInterpreterState *interp; 20947db96d56Sopenharmony_ci 20957db96d56Sopenharmony_ci ids = PyList_New(0); 20967db96d56Sopenharmony_ci if (ids == NULL) { 20977db96d56Sopenharmony_ci return NULL; 20987db96d56Sopenharmony_ci } 20997db96d56Sopenharmony_ci 21007db96d56Sopenharmony_ci interp = PyInterpreterState_Head(); 21017db96d56Sopenharmony_ci while (interp != NULL) { 21027db96d56Sopenharmony_ci id = _PyInterpreterState_GetIDObject(interp); 21037db96d56Sopenharmony_ci if (id == NULL) { 21047db96d56Sopenharmony_ci Py_DECREF(ids); 21057db96d56Sopenharmony_ci return NULL; 21067db96d56Sopenharmony_ci } 21077db96d56Sopenharmony_ci // insert at front of list 21087db96d56Sopenharmony_ci int res = PyList_Insert(ids, 0, id); 21097db96d56Sopenharmony_ci Py_DECREF(id); 21107db96d56Sopenharmony_ci if (res < 0) { 21117db96d56Sopenharmony_ci Py_DECREF(ids); 21127db96d56Sopenharmony_ci return NULL; 21137db96d56Sopenharmony_ci } 21147db96d56Sopenharmony_ci 21157db96d56Sopenharmony_ci interp = PyInterpreterState_Next(interp); 21167db96d56Sopenharmony_ci } 21177db96d56Sopenharmony_ci 21187db96d56Sopenharmony_ci return ids; 21197db96d56Sopenharmony_ci} 21207db96d56Sopenharmony_ci 21217db96d56Sopenharmony_ciPyDoc_STRVAR(list_all_doc, 21227db96d56Sopenharmony_ci"list_all() -> [ID]\n\ 21237db96d56Sopenharmony_ci\n\ 21247db96d56Sopenharmony_ciReturn a list containing the ID of every existing interpreter."); 21257db96d56Sopenharmony_ci 21267db96d56Sopenharmony_ci 21277db96d56Sopenharmony_cistatic PyObject * 21287db96d56Sopenharmony_ciinterp_get_current(PyObject *self, PyObject *Py_UNUSED(ignored)) 21297db96d56Sopenharmony_ci{ 21307db96d56Sopenharmony_ci PyInterpreterState *interp =_get_current(); 21317db96d56Sopenharmony_ci if (interp == NULL) { 21327db96d56Sopenharmony_ci return NULL; 21337db96d56Sopenharmony_ci } 21347db96d56Sopenharmony_ci return _PyInterpreterState_GetIDObject(interp); 21357db96d56Sopenharmony_ci} 21367db96d56Sopenharmony_ci 21377db96d56Sopenharmony_ciPyDoc_STRVAR(get_current_doc, 21387db96d56Sopenharmony_ci"get_current() -> ID\n\ 21397db96d56Sopenharmony_ci\n\ 21407db96d56Sopenharmony_ciReturn the ID of current interpreter."); 21417db96d56Sopenharmony_ci 21427db96d56Sopenharmony_ci 21437db96d56Sopenharmony_cistatic PyObject * 21447db96d56Sopenharmony_ciinterp_get_main(PyObject *self, PyObject *Py_UNUSED(ignored)) 21457db96d56Sopenharmony_ci{ 21467db96d56Sopenharmony_ci // Currently, 0 is always the main interpreter. 21477db96d56Sopenharmony_ci int64_t id = 0; 21487db96d56Sopenharmony_ci return _PyInterpreterID_New(id); 21497db96d56Sopenharmony_ci} 21507db96d56Sopenharmony_ci 21517db96d56Sopenharmony_ciPyDoc_STRVAR(get_main_doc, 21527db96d56Sopenharmony_ci"get_main() -> ID\n\ 21537db96d56Sopenharmony_ci\n\ 21547db96d56Sopenharmony_ciReturn the ID of main interpreter."); 21557db96d56Sopenharmony_ci 21567db96d56Sopenharmony_ci 21577db96d56Sopenharmony_cistatic PyObject * 21587db96d56Sopenharmony_ciinterp_run_string(PyObject *self, PyObject *args, PyObject *kwds) 21597db96d56Sopenharmony_ci{ 21607db96d56Sopenharmony_ci static char *kwlist[] = {"id", "script", "shared", NULL}; 21617db96d56Sopenharmony_ci PyObject *id, *code; 21627db96d56Sopenharmony_ci PyObject *shared = NULL; 21637db96d56Sopenharmony_ci if (!PyArg_ParseTupleAndKeywords(args, kwds, 21647db96d56Sopenharmony_ci "OU|O:run_string", kwlist, 21657db96d56Sopenharmony_ci &id, &code, &shared)) { 21667db96d56Sopenharmony_ci return NULL; 21677db96d56Sopenharmony_ci } 21687db96d56Sopenharmony_ci 21697db96d56Sopenharmony_ci // Look up the interpreter. 21707db96d56Sopenharmony_ci PyInterpreterState *interp = _PyInterpreterID_LookUp(id); 21717db96d56Sopenharmony_ci if (interp == NULL) { 21727db96d56Sopenharmony_ci return NULL; 21737db96d56Sopenharmony_ci } 21747db96d56Sopenharmony_ci 21757db96d56Sopenharmony_ci // Extract code. 21767db96d56Sopenharmony_ci Py_ssize_t size; 21777db96d56Sopenharmony_ci const char *codestr = PyUnicode_AsUTF8AndSize(code, &size); 21787db96d56Sopenharmony_ci if (codestr == NULL) { 21797db96d56Sopenharmony_ci return NULL; 21807db96d56Sopenharmony_ci } 21817db96d56Sopenharmony_ci if (strlen(codestr) != (size_t)size) { 21827db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 21837db96d56Sopenharmony_ci "source code string cannot contain null bytes"); 21847db96d56Sopenharmony_ci return NULL; 21857db96d56Sopenharmony_ci } 21867db96d56Sopenharmony_ci 21877db96d56Sopenharmony_ci // Run the code in the interpreter. 21887db96d56Sopenharmony_ci if (_run_script_in_interpreter(interp, codestr, shared) != 0) { 21897db96d56Sopenharmony_ci return NULL; 21907db96d56Sopenharmony_ci } 21917db96d56Sopenharmony_ci Py_RETURN_NONE; 21927db96d56Sopenharmony_ci} 21937db96d56Sopenharmony_ci 21947db96d56Sopenharmony_ciPyDoc_STRVAR(run_string_doc, 21957db96d56Sopenharmony_ci"run_string(id, script, shared)\n\ 21967db96d56Sopenharmony_ci\n\ 21977db96d56Sopenharmony_ciExecute the provided string in the identified interpreter.\n\ 21987db96d56Sopenharmony_ci\n\ 21997db96d56Sopenharmony_ciSee PyRun_SimpleStrings."); 22007db96d56Sopenharmony_ci 22017db96d56Sopenharmony_ci 22027db96d56Sopenharmony_cistatic PyObject * 22037db96d56Sopenharmony_ciobject_is_shareable(PyObject *self, PyObject *args, PyObject *kwds) 22047db96d56Sopenharmony_ci{ 22057db96d56Sopenharmony_ci static char *kwlist[] = {"obj", NULL}; 22067db96d56Sopenharmony_ci PyObject *obj; 22077db96d56Sopenharmony_ci if (!PyArg_ParseTupleAndKeywords(args, kwds, 22087db96d56Sopenharmony_ci "O:is_shareable", kwlist, &obj)) { 22097db96d56Sopenharmony_ci return NULL; 22107db96d56Sopenharmony_ci } 22117db96d56Sopenharmony_ci 22127db96d56Sopenharmony_ci if (_PyObject_CheckCrossInterpreterData(obj) == 0) { 22137db96d56Sopenharmony_ci Py_RETURN_TRUE; 22147db96d56Sopenharmony_ci } 22157db96d56Sopenharmony_ci PyErr_Clear(); 22167db96d56Sopenharmony_ci Py_RETURN_FALSE; 22177db96d56Sopenharmony_ci} 22187db96d56Sopenharmony_ci 22197db96d56Sopenharmony_ciPyDoc_STRVAR(is_shareable_doc, 22207db96d56Sopenharmony_ci"is_shareable(obj) -> bool\n\ 22217db96d56Sopenharmony_ci\n\ 22227db96d56Sopenharmony_ciReturn True if the object's data may be shared between interpreters and\n\ 22237db96d56Sopenharmony_ciFalse otherwise."); 22247db96d56Sopenharmony_ci 22257db96d56Sopenharmony_ci 22267db96d56Sopenharmony_cistatic PyObject * 22277db96d56Sopenharmony_ciinterp_is_running(PyObject *self, PyObject *args, PyObject *kwds) 22287db96d56Sopenharmony_ci{ 22297db96d56Sopenharmony_ci static char *kwlist[] = {"id", NULL}; 22307db96d56Sopenharmony_ci PyObject *id; 22317db96d56Sopenharmony_ci if (!PyArg_ParseTupleAndKeywords(args, kwds, 22327db96d56Sopenharmony_ci "O:is_running", kwlist, &id)) { 22337db96d56Sopenharmony_ci return NULL; 22347db96d56Sopenharmony_ci } 22357db96d56Sopenharmony_ci 22367db96d56Sopenharmony_ci PyInterpreterState *interp = _PyInterpreterID_LookUp(id); 22377db96d56Sopenharmony_ci if (interp == NULL) { 22387db96d56Sopenharmony_ci return NULL; 22397db96d56Sopenharmony_ci } 22407db96d56Sopenharmony_ci int is_running = _is_running(interp); 22417db96d56Sopenharmony_ci if (is_running < 0) { 22427db96d56Sopenharmony_ci return NULL; 22437db96d56Sopenharmony_ci } 22447db96d56Sopenharmony_ci if (is_running) { 22457db96d56Sopenharmony_ci Py_RETURN_TRUE; 22467db96d56Sopenharmony_ci } 22477db96d56Sopenharmony_ci Py_RETURN_FALSE; 22487db96d56Sopenharmony_ci} 22497db96d56Sopenharmony_ci 22507db96d56Sopenharmony_ciPyDoc_STRVAR(is_running_doc, 22517db96d56Sopenharmony_ci"is_running(id) -> bool\n\ 22527db96d56Sopenharmony_ci\n\ 22537db96d56Sopenharmony_ciReturn whether or not the identified interpreter is running."); 22547db96d56Sopenharmony_ci 22557db96d56Sopenharmony_cistatic PyObject * 22567db96d56Sopenharmony_cichannel_create(PyObject *self, PyObject *Py_UNUSED(ignored)) 22577db96d56Sopenharmony_ci{ 22587db96d56Sopenharmony_ci int64_t cid = _channel_create(&_globals.channels); 22597db96d56Sopenharmony_ci if (cid < 0) { 22607db96d56Sopenharmony_ci return NULL; 22617db96d56Sopenharmony_ci } 22627db96d56Sopenharmony_ci PyObject *id = (PyObject *)newchannelid(&ChannelIDtype, cid, 0, 22637db96d56Sopenharmony_ci &_globals.channels, 0, 0); 22647db96d56Sopenharmony_ci if (id == NULL) { 22657db96d56Sopenharmony_ci if (_channel_destroy(&_globals.channels, cid) != 0) { 22667db96d56Sopenharmony_ci // XXX issue a warning? 22677db96d56Sopenharmony_ci } 22687db96d56Sopenharmony_ci return NULL; 22697db96d56Sopenharmony_ci } 22707db96d56Sopenharmony_ci assert(((channelid *)id)->channels != NULL); 22717db96d56Sopenharmony_ci return id; 22727db96d56Sopenharmony_ci} 22737db96d56Sopenharmony_ci 22747db96d56Sopenharmony_ciPyDoc_STRVAR(channel_create_doc, 22757db96d56Sopenharmony_ci"channel_create() -> cid\n\ 22767db96d56Sopenharmony_ci\n\ 22777db96d56Sopenharmony_ciCreate a new cross-interpreter channel and return a unique generated ID."); 22787db96d56Sopenharmony_ci 22797db96d56Sopenharmony_cistatic PyObject * 22807db96d56Sopenharmony_cichannel_destroy(PyObject *self, PyObject *args, PyObject *kwds) 22817db96d56Sopenharmony_ci{ 22827db96d56Sopenharmony_ci static char *kwlist[] = {"cid", NULL}; 22837db96d56Sopenharmony_ci int64_t cid; 22847db96d56Sopenharmony_ci if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&:channel_destroy", kwlist, 22857db96d56Sopenharmony_ci channel_id_converter, &cid)) { 22867db96d56Sopenharmony_ci return NULL; 22877db96d56Sopenharmony_ci } 22887db96d56Sopenharmony_ci 22897db96d56Sopenharmony_ci if (_channel_destroy(&_globals.channels, cid) != 0) { 22907db96d56Sopenharmony_ci return NULL; 22917db96d56Sopenharmony_ci } 22927db96d56Sopenharmony_ci Py_RETURN_NONE; 22937db96d56Sopenharmony_ci} 22947db96d56Sopenharmony_ci 22957db96d56Sopenharmony_ciPyDoc_STRVAR(channel_destroy_doc, 22967db96d56Sopenharmony_ci"channel_destroy(cid)\n\ 22977db96d56Sopenharmony_ci\n\ 22987db96d56Sopenharmony_ciClose and finalize the channel. Afterward attempts to use the channel\n\ 22997db96d56Sopenharmony_ciwill behave as though it never existed."); 23007db96d56Sopenharmony_ci 23017db96d56Sopenharmony_cistatic PyObject * 23027db96d56Sopenharmony_cichannel_list_all(PyObject *self, PyObject *Py_UNUSED(ignored)) 23037db96d56Sopenharmony_ci{ 23047db96d56Sopenharmony_ci int64_t count = 0; 23057db96d56Sopenharmony_ci int64_t *cids = _channels_list_all(&_globals.channels, &count); 23067db96d56Sopenharmony_ci if (cids == NULL) { 23077db96d56Sopenharmony_ci if (count == 0) { 23087db96d56Sopenharmony_ci return PyList_New(0); 23097db96d56Sopenharmony_ci } 23107db96d56Sopenharmony_ci return NULL; 23117db96d56Sopenharmony_ci } 23127db96d56Sopenharmony_ci PyObject *ids = PyList_New((Py_ssize_t)count); 23137db96d56Sopenharmony_ci if (ids == NULL) { 23147db96d56Sopenharmony_ci goto finally; 23157db96d56Sopenharmony_ci } 23167db96d56Sopenharmony_ci int64_t *cur = cids; 23177db96d56Sopenharmony_ci for (int64_t i=0; i < count; cur++, i++) { 23187db96d56Sopenharmony_ci PyObject *id = (PyObject *)newchannelid(&ChannelIDtype, *cur, 0, 23197db96d56Sopenharmony_ci &_globals.channels, 0, 0); 23207db96d56Sopenharmony_ci if (id == NULL) { 23217db96d56Sopenharmony_ci Py_DECREF(ids); 23227db96d56Sopenharmony_ci ids = NULL; 23237db96d56Sopenharmony_ci break; 23247db96d56Sopenharmony_ci } 23257db96d56Sopenharmony_ci PyList_SET_ITEM(ids, i, id); 23267db96d56Sopenharmony_ci } 23277db96d56Sopenharmony_ci 23287db96d56Sopenharmony_cifinally: 23297db96d56Sopenharmony_ci PyMem_Free(cids); 23307db96d56Sopenharmony_ci return ids; 23317db96d56Sopenharmony_ci} 23327db96d56Sopenharmony_ci 23337db96d56Sopenharmony_ciPyDoc_STRVAR(channel_list_all_doc, 23347db96d56Sopenharmony_ci"channel_list_all() -> [cid]\n\ 23357db96d56Sopenharmony_ci\n\ 23367db96d56Sopenharmony_ciReturn the list of all IDs for active channels."); 23377db96d56Sopenharmony_ci 23387db96d56Sopenharmony_cistatic PyObject * 23397db96d56Sopenharmony_cichannel_list_interpreters(PyObject *self, PyObject *args, PyObject *kwds) 23407db96d56Sopenharmony_ci{ 23417db96d56Sopenharmony_ci static char *kwlist[] = {"cid", "send", NULL}; 23427db96d56Sopenharmony_ci int64_t cid; /* Channel ID */ 23437db96d56Sopenharmony_ci int send = 0; /* Send or receive end? */ 23447db96d56Sopenharmony_ci int64_t id; 23457db96d56Sopenharmony_ci PyObject *ids, *id_obj; 23467db96d56Sopenharmony_ci PyInterpreterState *interp; 23477db96d56Sopenharmony_ci 23487db96d56Sopenharmony_ci if (!PyArg_ParseTupleAndKeywords( 23497db96d56Sopenharmony_ci args, kwds, "O&$p:channel_list_interpreters", 23507db96d56Sopenharmony_ci kwlist, channel_id_converter, &cid, &send)) { 23517db96d56Sopenharmony_ci return NULL; 23527db96d56Sopenharmony_ci } 23537db96d56Sopenharmony_ci 23547db96d56Sopenharmony_ci ids = PyList_New(0); 23557db96d56Sopenharmony_ci if (ids == NULL) { 23567db96d56Sopenharmony_ci goto except; 23577db96d56Sopenharmony_ci } 23587db96d56Sopenharmony_ci 23597db96d56Sopenharmony_ci interp = PyInterpreterState_Head(); 23607db96d56Sopenharmony_ci while (interp != NULL) { 23617db96d56Sopenharmony_ci id = PyInterpreterState_GetID(interp); 23627db96d56Sopenharmony_ci assert(id >= 0); 23637db96d56Sopenharmony_ci int res = _channel_is_associated(&_globals.channels, cid, id, send); 23647db96d56Sopenharmony_ci if (res < 0) { 23657db96d56Sopenharmony_ci goto except; 23667db96d56Sopenharmony_ci } 23677db96d56Sopenharmony_ci if (res) { 23687db96d56Sopenharmony_ci id_obj = _PyInterpreterState_GetIDObject(interp); 23697db96d56Sopenharmony_ci if (id_obj == NULL) { 23707db96d56Sopenharmony_ci goto except; 23717db96d56Sopenharmony_ci } 23727db96d56Sopenharmony_ci res = PyList_Insert(ids, 0, id_obj); 23737db96d56Sopenharmony_ci Py_DECREF(id_obj); 23747db96d56Sopenharmony_ci if (res < 0) { 23757db96d56Sopenharmony_ci goto except; 23767db96d56Sopenharmony_ci } 23777db96d56Sopenharmony_ci } 23787db96d56Sopenharmony_ci interp = PyInterpreterState_Next(interp); 23797db96d56Sopenharmony_ci } 23807db96d56Sopenharmony_ci 23817db96d56Sopenharmony_ci goto finally; 23827db96d56Sopenharmony_ci 23837db96d56Sopenharmony_ciexcept: 23847db96d56Sopenharmony_ci Py_XDECREF(ids); 23857db96d56Sopenharmony_ci ids = NULL; 23867db96d56Sopenharmony_ci 23877db96d56Sopenharmony_cifinally: 23887db96d56Sopenharmony_ci return ids; 23897db96d56Sopenharmony_ci} 23907db96d56Sopenharmony_ci 23917db96d56Sopenharmony_ciPyDoc_STRVAR(channel_list_interpreters_doc, 23927db96d56Sopenharmony_ci"channel_list_interpreters(cid, *, send) -> [id]\n\ 23937db96d56Sopenharmony_ci\n\ 23947db96d56Sopenharmony_ciReturn the list of all interpreter IDs associated with an end of the channel.\n\ 23957db96d56Sopenharmony_ci\n\ 23967db96d56Sopenharmony_ciThe 'send' argument should be a boolean indicating whether to use the send or\n\ 23977db96d56Sopenharmony_cireceive end."); 23987db96d56Sopenharmony_ci 23997db96d56Sopenharmony_ci 24007db96d56Sopenharmony_cistatic PyObject * 24017db96d56Sopenharmony_cichannel_send(PyObject *self, PyObject *args, PyObject *kwds) 24027db96d56Sopenharmony_ci{ 24037db96d56Sopenharmony_ci static char *kwlist[] = {"cid", "obj", NULL}; 24047db96d56Sopenharmony_ci int64_t cid; 24057db96d56Sopenharmony_ci PyObject *obj; 24067db96d56Sopenharmony_ci if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&O:channel_send", kwlist, 24077db96d56Sopenharmony_ci channel_id_converter, &cid, &obj)) { 24087db96d56Sopenharmony_ci return NULL; 24097db96d56Sopenharmony_ci } 24107db96d56Sopenharmony_ci 24117db96d56Sopenharmony_ci if (_channel_send(&_globals.channels, cid, obj) != 0) { 24127db96d56Sopenharmony_ci return NULL; 24137db96d56Sopenharmony_ci } 24147db96d56Sopenharmony_ci Py_RETURN_NONE; 24157db96d56Sopenharmony_ci} 24167db96d56Sopenharmony_ci 24177db96d56Sopenharmony_ciPyDoc_STRVAR(channel_send_doc, 24187db96d56Sopenharmony_ci"channel_send(cid, obj)\n\ 24197db96d56Sopenharmony_ci\n\ 24207db96d56Sopenharmony_ciAdd the object's data to the channel's queue."); 24217db96d56Sopenharmony_ci 24227db96d56Sopenharmony_cistatic PyObject * 24237db96d56Sopenharmony_cichannel_recv(PyObject *self, PyObject *args, PyObject *kwds) 24247db96d56Sopenharmony_ci{ 24257db96d56Sopenharmony_ci static char *kwlist[] = {"cid", "default", NULL}; 24267db96d56Sopenharmony_ci int64_t cid; 24277db96d56Sopenharmony_ci PyObject *dflt = NULL; 24287db96d56Sopenharmony_ci if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|O:channel_recv", kwlist, 24297db96d56Sopenharmony_ci channel_id_converter, &cid, &dflt)) { 24307db96d56Sopenharmony_ci return NULL; 24317db96d56Sopenharmony_ci } 24327db96d56Sopenharmony_ci Py_XINCREF(dflt); 24337db96d56Sopenharmony_ci 24347db96d56Sopenharmony_ci PyObject *obj = _channel_recv(&_globals.channels, cid); 24357db96d56Sopenharmony_ci if (obj != NULL) { 24367db96d56Sopenharmony_ci Py_XDECREF(dflt); 24377db96d56Sopenharmony_ci return obj; 24387db96d56Sopenharmony_ci } else if (PyErr_Occurred()) { 24397db96d56Sopenharmony_ci Py_XDECREF(dflt); 24407db96d56Sopenharmony_ci return NULL; 24417db96d56Sopenharmony_ci } else if (dflt != NULL) { 24427db96d56Sopenharmony_ci return dflt; 24437db96d56Sopenharmony_ci } else { 24447db96d56Sopenharmony_ci PyErr_Format(ChannelEmptyError, "channel %" PRId64 " is empty", cid); 24457db96d56Sopenharmony_ci return NULL; 24467db96d56Sopenharmony_ci } 24477db96d56Sopenharmony_ci} 24487db96d56Sopenharmony_ci 24497db96d56Sopenharmony_ciPyDoc_STRVAR(channel_recv_doc, 24507db96d56Sopenharmony_ci"channel_recv(cid, [default]) -> obj\n\ 24517db96d56Sopenharmony_ci\n\ 24527db96d56Sopenharmony_ciReturn a new object from the data at the front of the channel's queue.\n\ 24537db96d56Sopenharmony_ci\n\ 24547db96d56Sopenharmony_ciIf there is nothing to receive then raise ChannelEmptyError, unless\n\ 24557db96d56Sopenharmony_cia default value is provided. In that case return it."); 24567db96d56Sopenharmony_ci 24577db96d56Sopenharmony_cistatic PyObject * 24587db96d56Sopenharmony_cichannel_close(PyObject *self, PyObject *args, PyObject *kwds) 24597db96d56Sopenharmony_ci{ 24607db96d56Sopenharmony_ci static char *kwlist[] = {"cid", "send", "recv", "force", NULL}; 24617db96d56Sopenharmony_ci int64_t cid; 24627db96d56Sopenharmony_ci int send = 0; 24637db96d56Sopenharmony_ci int recv = 0; 24647db96d56Sopenharmony_ci int force = 0; 24657db96d56Sopenharmony_ci if (!PyArg_ParseTupleAndKeywords(args, kwds, 24667db96d56Sopenharmony_ci "O&|$ppp:channel_close", kwlist, 24677db96d56Sopenharmony_ci channel_id_converter, &cid, &send, &recv, &force)) { 24687db96d56Sopenharmony_ci return NULL; 24697db96d56Sopenharmony_ci } 24707db96d56Sopenharmony_ci 24717db96d56Sopenharmony_ci if (_channel_close(&_globals.channels, cid, send-recv, force) != 0) { 24727db96d56Sopenharmony_ci return NULL; 24737db96d56Sopenharmony_ci } 24747db96d56Sopenharmony_ci Py_RETURN_NONE; 24757db96d56Sopenharmony_ci} 24767db96d56Sopenharmony_ci 24777db96d56Sopenharmony_ciPyDoc_STRVAR(channel_close_doc, 24787db96d56Sopenharmony_ci"channel_close(cid, *, send=None, recv=None, force=False)\n\ 24797db96d56Sopenharmony_ci\n\ 24807db96d56Sopenharmony_ciClose the channel for all interpreters.\n\ 24817db96d56Sopenharmony_ci\n\ 24827db96d56Sopenharmony_ciIf the channel is empty then the keyword args are ignored and both\n\ 24837db96d56Sopenharmony_ciends are immediately closed. Otherwise, if 'force' is True then\n\ 24847db96d56Sopenharmony_ciall queued items are released and both ends are immediately\n\ 24857db96d56Sopenharmony_ciclosed.\n\ 24867db96d56Sopenharmony_ci\n\ 24877db96d56Sopenharmony_ciIf the channel is not empty *and* 'force' is False then following\n\ 24887db96d56Sopenharmony_cihappens:\n\ 24897db96d56Sopenharmony_ci\n\ 24907db96d56Sopenharmony_ci * recv is True (regardless of send):\n\ 24917db96d56Sopenharmony_ci - raise ChannelNotEmptyError\n\ 24927db96d56Sopenharmony_ci * recv is None and send is None:\n\ 24937db96d56Sopenharmony_ci - raise ChannelNotEmptyError\n\ 24947db96d56Sopenharmony_ci * send is True and recv is not True:\n\ 24957db96d56Sopenharmony_ci - fully close the 'send' end\n\ 24967db96d56Sopenharmony_ci - close the 'recv' end to interpreters not already receiving\n\ 24977db96d56Sopenharmony_ci - fully close it once empty\n\ 24987db96d56Sopenharmony_ci\n\ 24997db96d56Sopenharmony_ciClosing an already closed channel results in a ChannelClosedError.\n\ 25007db96d56Sopenharmony_ci\n\ 25017db96d56Sopenharmony_ciOnce the channel's ID has no more ref counts in any interpreter\n\ 25027db96d56Sopenharmony_cithe channel will be destroyed."); 25037db96d56Sopenharmony_ci 25047db96d56Sopenharmony_cistatic PyObject * 25057db96d56Sopenharmony_cichannel_release(PyObject *self, PyObject *args, PyObject *kwds) 25067db96d56Sopenharmony_ci{ 25077db96d56Sopenharmony_ci // Note that only the current interpreter is affected. 25087db96d56Sopenharmony_ci static char *kwlist[] = {"cid", "send", "recv", "force", NULL}; 25097db96d56Sopenharmony_ci int64_t cid; 25107db96d56Sopenharmony_ci int send = 0; 25117db96d56Sopenharmony_ci int recv = 0; 25127db96d56Sopenharmony_ci int force = 0; 25137db96d56Sopenharmony_ci if (!PyArg_ParseTupleAndKeywords(args, kwds, 25147db96d56Sopenharmony_ci "O&|$ppp:channel_release", kwlist, 25157db96d56Sopenharmony_ci channel_id_converter, &cid, &send, &recv, &force)) { 25167db96d56Sopenharmony_ci return NULL; 25177db96d56Sopenharmony_ci } 25187db96d56Sopenharmony_ci if (send == 0 && recv == 0) { 25197db96d56Sopenharmony_ci send = 1; 25207db96d56Sopenharmony_ci recv = 1; 25217db96d56Sopenharmony_ci } 25227db96d56Sopenharmony_ci 25237db96d56Sopenharmony_ci // XXX Handle force is True. 25247db96d56Sopenharmony_ci // XXX Fix implicit release. 25257db96d56Sopenharmony_ci 25267db96d56Sopenharmony_ci if (_channel_drop(&_globals.channels, cid, send, recv) != 0) { 25277db96d56Sopenharmony_ci return NULL; 25287db96d56Sopenharmony_ci } 25297db96d56Sopenharmony_ci Py_RETURN_NONE; 25307db96d56Sopenharmony_ci} 25317db96d56Sopenharmony_ci 25327db96d56Sopenharmony_ciPyDoc_STRVAR(channel_release_doc, 25337db96d56Sopenharmony_ci"channel_release(cid, *, send=None, recv=None, force=True)\n\ 25347db96d56Sopenharmony_ci\n\ 25357db96d56Sopenharmony_ciClose the channel for the current interpreter. 'send' and 'recv'\n\ 25367db96d56Sopenharmony_ci(bool) may be used to indicate the ends to close. By default both\n\ 25377db96d56Sopenharmony_ciends are closed. Closing an already closed end is a noop."); 25387db96d56Sopenharmony_ci 25397db96d56Sopenharmony_cistatic PyObject * 25407db96d56Sopenharmony_cichannel__channel_id(PyObject *self, PyObject *args, PyObject *kwds) 25417db96d56Sopenharmony_ci{ 25427db96d56Sopenharmony_ci return channelid_new(&ChannelIDtype, args, kwds); 25437db96d56Sopenharmony_ci} 25447db96d56Sopenharmony_ci 25457db96d56Sopenharmony_cistatic PyMethodDef module_functions[] = { 25467db96d56Sopenharmony_ci {"create", _PyCFunction_CAST(interp_create), 25477db96d56Sopenharmony_ci METH_VARARGS | METH_KEYWORDS, create_doc}, 25487db96d56Sopenharmony_ci {"destroy", _PyCFunction_CAST(interp_destroy), 25497db96d56Sopenharmony_ci METH_VARARGS | METH_KEYWORDS, destroy_doc}, 25507db96d56Sopenharmony_ci {"list_all", interp_list_all, 25517db96d56Sopenharmony_ci METH_NOARGS, list_all_doc}, 25527db96d56Sopenharmony_ci {"get_current", interp_get_current, 25537db96d56Sopenharmony_ci METH_NOARGS, get_current_doc}, 25547db96d56Sopenharmony_ci {"get_main", interp_get_main, 25557db96d56Sopenharmony_ci METH_NOARGS, get_main_doc}, 25567db96d56Sopenharmony_ci {"is_running", _PyCFunction_CAST(interp_is_running), 25577db96d56Sopenharmony_ci METH_VARARGS | METH_KEYWORDS, is_running_doc}, 25587db96d56Sopenharmony_ci {"run_string", _PyCFunction_CAST(interp_run_string), 25597db96d56Sopenharmony_ci METH_VARARGS | METH_KEYWORDS, run_string_doc}, 25607db96d56Sopenharmony_ci 25617db96d56Sopenharmony_ci {"is_shareable", _PyCFunction_CAST(object_is_shareable), 25627db96d56Sopenharmony_ci METH_VARARGS | METH_KEYWORDS, is_shareable_doc}, 25637db96d56Sopenharmony_ci 25647db96d56Sopenharmony_ci {"channel_create", channel_create, 25657db96d56Sopenharmony_ci METH_NOARGS, channel_create_doc}, 25667db96d56Sopenharmony_ci {"channel_destroy", _PyCFunction_CAST(channel_destroy), 25677db96d56Sopenharmony_ci METH_VARARGS | METH_KEYWORDS, channel_destroy_doc}, 25687db96d56Sopenharmony_ci {"channel_list_all", channel_list_all, 25697db96d56Sopenharmony_ci METH_NOARGS, channel_list_all_doc}, 25707db96d56Sopenharmony_ci {"channel_list_interpreters", _PyCFunction_CAST(channel_list_interpreters), 25717db96d56Sopenharmony_ci METH_VARARGS | METH_KEYWORDS, channel_list_interpreters_doc}, 25727db96d56Sopenharmony_ci {"channel_send", _PyCFunction_CAST(channel_send), 25737db96d56Sopenharmony_ci METH_VARARGS | METH_KEYWORDS, channel_send_doc}, 25747db96d56Sopenharmony_ci {"channel_recv", _PyCFunction_CAST(channel_recv), 25757db96d56Sopenharmony_ci METH_VARARGS | METH_KEYWORDS, channel_recv_doc}, 25767db96d56Sopenharmony_ci {"channel_close", _PyCFunction_CAST(channel_close), 25777db96d56Sopenharmony_ci METH_VARARGS | METH_KEYWORDS, channel_close_doc}, 25787db96d56Sopenharmony_ci {"channel_release", _PyCFunction_CAST(channel_release), 25797db96d56Sopenharmony_ci METH_VARARGS | METH_KEYWORDS, channel_release_doc}, 25807db96d56Sopenharmony_ci {"_channel_id", _PyCFunction_CAST(channel__channel_id), 25817db96d56Sopenharmony_ci METH_VARARGS | METH_KEYWORDS, NULL}, 25827db96d56Sopenharmony_ci 25837db96d56Sopenharmony_ci {NULL, NULL} /* sentinel */ 25847db96d56Sopenharmony_ci}; 25857db96d56Sopenharmony_ci 25867db96d56Sopenharmony_ci 25877db96d56Sopenharmony_ci/* initialization function */ 25887db96d56Sopenharmony_ci 25897db96d56Sopenharmony_ciPyDoc_STRVAR(module_doc, 25907db96d56Sopenharmony_ci"This module provides primitive operations to manage Python interpreters.\n\ 25917db96d56Sopenharmony_ciThe 'interpreters' module provides a more convenient interface."); 25927db96d56Sopenharmony_ci 25937db96d56Sopenharmony_cistatic struct PyModuleDef interpretersmodule = { 25947db96d56Sopenharmony_ci PyModuleDef_HEAD_INIT, 25957db96d56Sopenharmony_ci "_xxsubinterpreters", /* m_name */ 25967db96d56Sopenharmony_ci module_doc, /* m_doc */ 25977db96d56Sopenharmony_ci -1, /* m_size */ 25987db96d56Sopenharmony_ci module_functions, /* m_methods */ 25997db96d56Sopenharmony_ci NULL, /* m_slots */ 26007db96d56Sopenharmony_ci NULL, /* m_traverse */ 26017db96d56Sopenharmony_ci NULL, /* m_clear */ 26027db96d56Sopenharmony_ci NULL /* m_free */ 26037db96d56Sopenharmony_ci}; 26047db96d56Sopenharmony_ci 26057db96d56Sopenharmony_ci 26067db96d56Sopenharmony_ciPyMODINIT_FUNC 26077db96d56Sopenharmony_ciPyInit__xxsubinterpreters(void) 26087db96d56Sopenharmony_ci{ 26097db96d56Sopenharmony_ci if (_init_globals() != 0) { 26107db96d56Sopenharmony_ci return NULL; 26117db96d56Sopenharmony_ci } 26127db96d56Sopenharmony_ci 26137db96d56Sopenharmony_ci /* Initialize types */ 26147db96d56Sopenharmony_ci if (PyType_Ready(&ChannelIDtype) != 0) { 26157db96d56Sopenharmony_ci return NULL; 26167db96d56Sopenharmony_ci } 26177db96d56Sopenharmony_ci 26187db96d56Sopenharmony_ci /* Create the module */ 26197db96d56Sopenharmony_ci PyObject *module = PyModule_Create(&interpretersmodule); 26207db96d56Sopenharmony_ci if (module == NULL) { 26217db96d56Sopenharmony_ci return NULL; 26227db96d56Sopenharmony_ci } 26237db96d56Sopenharmony_ci 26247db96d56Sopenharmony_ci /* Add exception types */ 26257db96d56Sopenharmony_ci PyObject *ns = PyModule_GetDict(module); // borrowed 26267db96d56Sopenharmony_ci if (interp_exceptions_init(ns) != 0) { 26277db96d56Sopenharmony_ci return NULL; 26287db96d56Sopenharmony_ci } 26297db96d56Sopenharmony_ci if (channel_exceptions_init(ns) != 0) { 26307db96d56Sopenharmony_ci return NULL; 26317db96d56Sopenharmony_ci } 26327db96d56Sopenharmony_ci 26337db96d56Sopenharmony_ci /* Add other types */ 26347db96d56Sopenharmony_ci Py_INCREF(&ChannelIDtype); 26357db96d56Sopenharmony_ci if (PyDict_SetItemString(ns, "ChannelID", (PyObject *)&ChannelIDtype) != 0) { 26367db96d56Sopenharmony_ci return NULL; 26377db96d56Sopenharmony_ci } 26387db96d56Sopenharmony_ci Py_INCREF(&_PyInterpreterID_Type); 26397db96d56Sopenharmony_ci if (PyDict_SetItemString(ns, "InterpreterID", (PyObject *)&_PyInterpreterID_Type) != 0) { 26407db96d56Sopenharmony_ci return NULL; 26417db96d56Sopenharmony_ci } 26427db96d56Sopenharmony_ci 26437db96d56Sopenharmony_ci if (_PyCrossInterpreterData_RegisterClass(&ChannelIDtype, _channelid_shared)) { 26447db96d56Sopenharmony_ci return NULL; 26457db96d56Sopenharmony_ci } 26467db96d56Sopenharmony_ci 26477db96d56Sopenharmony_ci return module; 26487db96d56Sopenharmony_ci} 2649