mirror of
https://github.com/python/cpython.git
synced 2025-11-01 10:45:30 +00:00
bpo-38880: List interpreters associated with a channel end (GH-17323)
This PR adds the functionality requested by https://github.com/ericsnowcurrently/multi-core-python/issues/52. Automerge-Triggered-By: @ericsnowcurrently
This commit is contained in:
parent
49f70db83e
commit
f7bbf58aa9
4 changed files with 282 additions and 6 deletions
|
|
@ -538,7 +538,7 @@ _channelend_find(_channelend *first, int64_t interp, _channelend **pprev)
|
|||
|
||||
typedef struct _channelassociations {
|
||||
// Note that the list entries are never removed for interpreter
|
||||
// for which the channel is closed. This should be a problem in
|
||||
// for which the channel is closed. This should not be a problem in
|
||||
// practice. Also, a channel isn't automatically closed when an
|
||||
// interpreter is destroyed.
|
||||
int64_t numsendopen;
|
||||
|
|
@ -1179,11 +1179,6 @@ _channels_list_all(_channels *channels, int64_t *count)
|
|||
{
|
||||
int64_t *cids = NULL;
|
||||
PyThread_acquire_lock(channels->mutex, WAIT_LOCK);
|
||||
int64_t numopen = channels->numopen;
|
||||
if (numopen >= PY_SSIZE_T_MAX) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "too many channels open");
|
||||
goto done;
|
||||
}
|
||||
int64_t *ids = PyMem_NEW(int64_t, (Py_ssize_t)(channels->numopen));
|
||||
if (ids == NULL) {
|
||||
goto done;
|
||||
|
|
@ -1392,6 +1387,24 @@ _channel_close(_channels *channels, int64_t id, int end, int force)
|
|||
return _channels_close(channels, id, NULL, end, force);
|
||||
}
|
||||
|
||||
static int
|
||||
_channel_is_associated(_channels *channels, int64_t cid, int64_t interp,
|
||||
int send)
|
||||
{
|
||||
_PyChannelState *chan = _channels_lookup(channels, cid, NULL);
|
||||
if (chan == NULL) {
|
||||
return -1;
|
||||
} else if (send && chan->closing != NULL) {
|
||||
PyErr_Format(ChannelClosedError, "channel %" PRId64 " closed", cid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
_channelend *end = _channelend_find(send ? chan->ends->send : chan->ends->recv,
|
||||
interp, NULL);
|
||||
|
||||
return (end != NULL && end->open);
|
||||
}
|
||||
|
||||
/* ChannelID class */
|
||||
|
||||
static PyTypeObject ChannelIDtype;
|
||||
|
|
@ -2323,6 +2336,68 @@ PyDoc_STRVAR(channel_list_all_doc,
|
|||
\n\
|
||||
Return the list of all IDs for active channels.");
|
||||
|
||||
static PyObject *
|
||||
channel_list_interpreters(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
static char *kwlist[] = {"cid", "send", NULL};
|
||||
int64_t cid; /* Channel ID */
|
||||
int send = 0; /* Send or receive end? */
|
||||
int64_t id;
|
||||
PyObject *ids, *id_obj;
|
||||
PyInterpreterState *interp;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(
|
||||
args, kwds, "O&$p:channel_list_interpreters",
|
||||
kwlist, channel_id_converter, &cid, &send)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ids = PyList_New(0);
|
||||
if (ids == NULL) {
|
||||
goto except;
|
||||
}
|
||||
|
||||
interp = PyInterpreterState_Head();
|
||||
while (interp != NULL) {
|
||||
id = PyInterpreterState_GetID(interp);
|
||||
assert(id >= 0);
|
||||
int res = _channel_is_associated(&_globals.channels, cid, id, send);
|
||||
if (res < 0) {
|
||||
goto except;
|
||||
}
|
||||
if (res) {
|
||||
id_obj = _PyInterpreterState_GetIDObject(interp);
|
||||
if (id_obj == NULL) {
|
||||
goto except;
|
||||
}
|
||||
res = PyList_Insert(ids, 0, id_obj);
|
||||
Py_DECREF(id_obj);
|
||||
if (res < 0) {
|
||||
goto except;
|
||||
}
|
||||
}
|
||||
interp = PyInterpreterState_Next(interp);
|
||||
}
|
||||
|
||||
goto finally;
|
||||
|
||||
except:
|
||||
Py_XDECREF(ids);
|
||||
ids = NULL;
|
||||
|
||||
finally:
|
||||
return ids;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(channel_list_interpreters_doc,
|
||||
"channel_list_interpreters(cid, *, send) -> [id]\n\
|
||||
\n\
|
||||
Return the list of all interpreter IDs associated with an end of the channel.\n\
|
||||
\n\
|
||||
The 'send' argument should be a boolean indicating whether to use the send or\n\
|
||||
receive end.");
|
||||
|
||||
|
||||
static PyObject *
|
||||
channel_send(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
|
|
@ -2493,6 +2568,8 @@ static PyMethodDef module_functions[] = {
|
|||
METH_VARARGS | METH_KEYWORDS, channel_destroy_doc},
|
||||
{"channel_list_all", channel_list_all,
|
||||
METH_NOARGS, channel_list_all_doc},
|
||||
{"channel_list_interpreters", (PyCFunction)(void(*)(void))channel_list_interpreters,
|
||||
METH_VARARGS | METH_KEYWORDS, channel_list_interpreters_doc},
|
||||
{"channel_send", (PyCFunction)(void(*)(void))channel_send,
|
||||
METH_VARARGS | METH_KEYWORDS, channel_send_doc},
|
||||
{"channel_recv", (PyCFunction)(void(*)(void))channel_recv,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue