diff options
author | Eric Snow <ericsnowcurrently@gmail.com> | 2020-04-28 23:11:32 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-28 23:11:32 (GMT) |
commit | 5e8c691594d68925213d36296ce7c4b3e90bcb1d (patch) | |
tree | 1b93ee2c24dd9944396aa98ba232f0db4e2893c1 /Modules | |
parent | 6d86a2331e6b64a2ae80c1a21f81baa5a71ac594 (diff) | |
download | cpython-5e8c691594d68925213d36296ce7c4b3e90bcb1d.zip cpython-5e8c691594d68925213d36296ce7c4b3e90bcb1d.tar.gz cpython-5e8c691594d68925213d36296ce7c4b3e90bcb1d.tar.bz2 |
bpo-32604: Add support for a "default" arg in channel_recv(). (GH-19770)
This allows the caller to avoid creation of an exception when the channel is empty (just like `dict.get()` works). `ChannelEmptyError` is still raised if no default is provided.
Automerge-Triggered-By: @ericsnowcurrently
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_xxsubinterpretersmodule.c | 36 |
1 files changed, 25 insertions, 11 deletions
diff --git a/Modules/_xxsubinterpretersmodule.c b/Modules/_xxsubinterpretersmodule.c index fa35e14..2ee8d07 100644 --- a/Modules/_xxsubinterpretersmodule.c +++ b/Modules/_xxsubinterpretersmodule.c @@ -1350,19 +1350,16 @@ _channel_recv(_channels *channels, int64_t id) _PyCrossInterpreterData *data = _channel_next(chan, PyInterpreterState_GetID(interp)); PyThread_release_lock(mutex); if (data == NULL) { - if (!PyErr_Occurred()) { - PyErr_Format(ChannelEmptyError, "channel %" PRId64 " is empty", id); - } return NULL; } // Convert the data back to an object. PyObject *obj = _PyCrossInterpreterData_NewObject(data); + _PyCrossInterpreterData_Release(data); + PyMem_Free(data); if (obj == NULL) { return NULL; } - _PyCrossInterpreterData_Release(data); - PyMem_Free(data); return obj; } @@ -2351,20 +2348,37 @@ Add the object's data to the channel's queue."); static PyObject * channel_recv(PyObject *self, PyObject *args, PyObject *kwds) { - static char *kwlist[] = {"cid", NULL}; + static char *kwlist[] = {"cid", "default", NULL}; int64_t cid; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&:channel_recv", kwlist, - channel_id_converter, &cid)) { + PyObject *dflt = NULL; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|O:channel_recv", kwlist, + channel_id_converter, &cid, &dflt)) { return NULL; } + Py_XINCREF(dflt); - return _channel_recv(&_globals.channels, cid); + PyObject *obj = _channel_recv(&_globals.channels, cid); + if (obj != NULL) { + Py_XDECREF(dflt); + return obj; + } else if (PyErr_Occurred()) { + Py_XDECREF(dflt); + return NULL; + } else if (dflt != NULL) { + return dflt; + } else { + PyErr_Format(ChannelEmptyError, "channel %" PRId64 " is empty", cid); + return NULL; + } } PyDoc_STRVAR(channel_recv_doc, -"channel_recv(cid) -> obj\n\ +"channel_recv(cid, [default]) -> obj\n\ +\n\ +Return a new object from the data at the front of the channel's queue.\n\ \n\ -Return a new object from the data at the from of the channel's queue."); +If there is nothing to receive then raise ChannelEmptyError, unless\n\ +a default value is provided. In that case return it."); static PyObject * channel_close(PyObject *self, PyObject *args, PyObject *kwds) |