cpython: f8815001a390 (original) (raw)
--- a/Lib/asyncio/futures.py +++ b/Lib/asyncio/futures.py @@ -120,6 +120,46 @@ def isfuture(obj): return getattr(obj, '_asyncio_future_blocking', None) is not None +def _format_callbacks(cb):
- if size == 1:
cb = format_cb(cb[0])[](#l1.17)
- elif size == 2:
cb = '{}, {}'.format(format_cb(cb[0]), format_cb(cb[1]))[](#l1.19)
- elif size > 2:
cb = '{}, <{} more>, {}'.format(format_cb(cb[0]),[](#l1.21)
size-2,[](#l1.22)
format_cb(cb[-1]))[](#l1.23)
- return 'cb=[%s]' % cb
+ + +def _future_repr_info(future):
(Future) -> str
- """helper function for Future.repr"""
- info = [future._state.lower()]
- if future._state == _FINISHED:
if future._exception is not None:[](#l1.32)
info.append('exception={!r}'.format(future._exception))[](#l1.33)
else:[](#l1.34)
# use reprlib to limit the length of the output, especially[](#l1.35)
# for very long strings[](#l1.36)
result = reprlib.repr(future._result)[](#l1.37)
info.append('result={}'.format(result))[](#l1.38)
- if future._callbacks:
info.append(_format_callbacks(future._callbacks))[](#l1.40)
- if future._source_traceback:
frame = future._source_traceback[-1][](#l1.42)
info.append('created at %s:%s' % (frame[0], frame[1]))[](#l1.43)
- return info
+ + class Future: """This class is almost compatible with concurrent.futures.Future. @@ -172,45 +212,10 @@ class Future: if self._loop.get_debug(): self._source_traceback = traceback.extract_stack(sys._getframe(1))
- def __format_callbacks(self):
cb = self._callbacks[](#l1.55)
size = len(cb)[](#l1.56)
if not size:[](#l1.57)
cb = ''[](#l1.58)
def format_cb(callback):[](#l1.60)
return events._format_callback_source(callback, ())[](#l1.61)
if size == 1:[](#l1.63)
cb = format_cb(cb[0])[](#l1.64)
elif size == 2:[](#l1.65)
cb = '{}, {}'.format(format_cb(cb[0]), format_cb(cb[1]))[](#l1.66)
elif size > 2:[](#l1.67)
cb = '{}, <{} more>, {}'.format(format_cb(cb[0]),[](#l1.68)
size-2,[](#l1.69)
format_cb(cb[-1]))[](#l1.70)
return 'cb=[%s]' % cb[](#l1.71)
- def _repr_info(self):
info = [self._state.lower()][](#l1.74)
if self._state == _FINISHED:[](#l1.75)
if self._exception is not None:[](#l1.76)
info.append('exception={!r}'.format(self._exception))[](#l1.77)
else:[](#l1.78)
# use reprlib to limit the length of the output, especially[](#l1.79)
# for very long strings[](#l1.80)
result = reprlib.repr(self._result)[](#l1.81)
info.append('result={}'.format(result))[](#l1.82)
if self._callbacks:[](#l1.83)
info.append(self.__format_callbacks())[](#l1.84)
if self._source_traceback:[](#l1.85)
frame = self._source_traceback[-1][](#l1.86)
info.append('created at %s:%s' % (frame[0], frame[1]))[](#l1.87)
return info[](#l1.88)
info = self._repr_info()[](#l1.92)
return '<%s %s>' % (self.__class__.__name__, ' '.join(info))[](#l1.93)
return '<%s %s>' % (self.__class__.__name__, ' '.join(self._repr_info()))[](#l1.94)
# On Python 3.3 and older, objects with a destructor part of a reference # cycle are never destroyed. It's not more the case on Python 3.4 thanks @@ -426,6 +431,21 @@ def _copy_future_state(source, dest): dest.set_result(result) +try:
- _futures._init_module(
traceback.extract_stack,[](#l1.108)
events.get_event_loop,[](#l1.109)
_future_repr_info,[](#l1.110)
InvalidStateError,[](#l1.111)
CancelledError)[](#l1.112)
+ + def _chain_future(source, destination): """Chain two futures so that when one completes, so does the other.
--- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ What's New in Python 3.7.0 alpha 1 Core and Builtins ----------------- +- Issue #26801: Added C implementation of asyncio.Future.
--- a/Modules/Setup.dist +++ b/Modules/Setup.dist @@ -181,6 +181,7 @@ faulthandler faulthandler.c #_datetime _datetimemodule.c # datetime accelerator #_bisect _bisectmodule.c # Bisection algorithms #_heapq _heapqmodule.c # Heap queue algorithm +#_futures _futuresmodule.c # Fast asyncio Future #unicodedata unicodedata.c # static Unicode character database
new file mode 100644 --- /dev/null +++ b/Modules/_futuresmodule.c @@ -0,0 +1,1034 @@ +#include "Python.h" +#include "structmember.h" + + +/* identifiers used from some functions / +_Py_IDENTIFIER(call_soon); + + +/ State of the _futures module */ +static int _futuremod_ready; +static PyObject *traceback_extract_stack; +static PyObject *asyncio_get_event_loop; +static PyObject *asyncio_repr_info_func; +static PyObject *asyncio_InvalidStateError; +static PyObject asyncio_CancelledError; + + +/ Get FutureIter from Future / +static PyObject new_future_iter(PyObject fut); + + +/ make sure module state is initialized and ready to be used. */ +static int +_FuturesMod_EnsureState(void) +{
- if (!_futuremod_ready) {
PyErr_SetString(PyExc_RuntimeError,[](#l4.31)
"_futures module wasn't properly initialized");[](#l4.32)
return -1;[](#l4.33)
- }
- return 0;
+} fut_state; + + +typedef struct {
- PyObject_HEAD
- PyObject *fut_loop;
- PyObject *fut_callbacks;
- PyObject *fut_exception;
- PyObject *fut_result;
- PyObject *fut_source_tb;
- fut_state fut_state;
- int fut_log_tb;
- int fut_blocking;
- PyObject *dict;
- PyObject *fut_weakreflist;
+} FutureObj; + + +static int +_schedule_callbacks(FutureObj *fut) +{
- if (fut->fut_callbacks == NULL) {
PyErr_SetString(PyExc_RuntimeError, "NULL callbacks");[](#l4.69)
return -1;[](#l4.70)
- }
- iters = PyList_GetSlice(fut->fut_callbacks, 0, len);
- if (iters == NULL) {
return -1;[](#l4.80)
- }
- if (PyList_SetSlice(fut->fut_callbacks, 0, len, NULL) < 0) {
Py_DECREF(iters);[](#l4.83)
return -1;[](#l4.84)
- }
- for (i = 0; i < len; i++) {
PyObject *handle = NULL;[](#l4.88)
PyObject *cb = PyList_GET_ITEM(iters, i);[](#l4.89)
handle = _PyObject_CallMethodId([](#l4.91)
fut->fut_loop, &PyId_call_soon, "OO", cb, fut, NULL);[](#l4.92)
if (handle == NULL) {[](#l4.94)
Py_DECREF(iters);[](#l4.95)
return -1;[](#l4.96)
}[](#l4.97)
else {[](#l4.98)
Py_DECREF(handle);[](#l4.99)
}[](#l4.100)
- }
+} + +static int +FutureObj_init(FutureObj *fut, PyObject *args, PyObject *kwds) +{
- static char *kwlist[] = {"loop", NULL};
- PyObject *loop = NULL;
- PyObject *res = NULL;
- _Py_IDENTIFIER(get_debug);
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|$O", kwlist, &loop)) {
return -1;[](#l4.120)
- }
- if (loop == NULL || loop == Py_None) {
loop = PyObject_CallObject(asyncio_get_event_loop, NULL);[](#l4.123)
if (loop == NULL) {[](#l4.124)
return -1;[](#l4.125)
}[](#l4.126)
- }
- else {
Py_INCREF(loop);[](#l4.129)
- }
- Py_CLEAR(fut->fut_loop);
- fut->fut_loop = loop;
- res = _PyObject_CallMethodId(fut->fut_loop, &PyId_get_debug, "()", NULL);
- if (res == NULL) {
return -1;[](#l4.136)
- }
- if (PyObject_IsTrue(res)) {
Py_CLEAR(res);[](#l4.139)
fut->fut_source_tb = PyObject_CallObject(traceback_extract_stack, NULL);[](#l4.140)
if (fut->fut_source_tb == NULL) {[](#l4.141)
return -1;[](#l4.142)
}[](#l4.143)
- }
- else {
Py_CLEAR(res);[](#l4.146)
- }
- fut->fut_callbacks = PyList_New(0);
- if (fut->fut_callbacks == NULL) {
return -1;[](#l4.151)
- }
- return 0;
+} + +static int +FutureObj_clear(FutureObj *fut) +{
- Py_CLEAR(fut->fut_loop);
- Py_CLEAR(fut->fut_callbacks);
- Py_CLEAR(fut->fut_result);
- Py_CLEAR(fut->fut_exception);
- Py_CLEAR(fut->fut_source_tb);
- Py_CLEAR(fut->dict);
- return 0;
+} + +static int +FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg) +{
- Py_VISIT(fut->fut_loop);
- Py_VISIT(fut->fut_callbacks);
- Py_VISIT(fut->fut_result);
- Py_VISIT(fut->fut_exception);
- Py_VISIT(fut->fut_source_tb);
- Py_VISIT(fut->dict);
- return 0;
+} + +PyDoc_STRVAR(pydoc_result,
- "Return the result this future represents.\n"
- "\n"
- "If the future has been cancelled, raises CancelledError. If the\n"
- "future's result isn't yet available, raises InvalidStateError. If\n"
- "the future is done and has an exception set, this exception is raised."
+); + +static PyObject * +FutureObj_result(FutureObj *fut, PyObject *arg) +{
- if (fut->fut_state == STATE_CANCELLED) {
PyErr_SetString(asyncio_CancelledError, "");[](#l4.192)
return NULL;[](#l4.193)
- }
- if (fut->fut_state != STATE_FINISHED) {
PyErr_SetString(asyncio_InvalidStateError, "Result is not ready.");[](#l4.197)
return NULL;[](#l4.198)
- }
- fut->fut_log_tb = 0;
- if (fut->fut_exception != NULL) {
PyObject *type = NULL;[](#l4.203)
type = PyExceptionInstance_Class(fut->fut_exception);[](#l4.204)
PyErr_SetObject(type, fut->fut_exception);[](#l4.205)
return NULL;[](#l4.206)
- }
+} + +PyDoc_STRVAR(pydoc_exception,
- "Return the exception that was set on this future.\n"
- "\n"
- "The exception (or None if no exception was set) is returned only if\n"
- "the future is done. If the future has been cancelled, raises\n"
- "CancelledError. If the future isn't done yet, raises\n"
- "InvalidStateError."
+); + +static PyObject * +FutureObj_exception(FutureObj *fut, PyObject *arg) +{
- if (fut->fut_state == STATE_CANCELLED) {
PyErr_SetString(asyncio_CancelledError, "");[](#l4.230)
return NULL;[](#l4.231)
- }
- if (fut->fut_state != STATE_FINISHED) {
PyErr_SetString(asyncio_InvalidStateError, "Result is not ready.");[](#l4.235)
return NULL;[](#l4.236)
- }
- if (fut->fut_exception != NULL) {
fut->fut_log_tb = 0;[](#l4.240)
Py_INCREF(fut->fut_exception);[](#l4.241)
return fut->fut_exception;[](#l4.242)
- }
+} + +PyDoc_STRVAR(pydoc_set_result,
- "Mark the future done and set its result.\n"
- "\n"
- "If the future is already done when this method is called, raises\n"
- "InvalidStateError."
+); + +static PyObject * +FutureObj_set_result(FutureObj *fut, PyObject *res) +{
- if (fut->fut_state != STATE_PENDING) {
PyErr_SetString(asyncio_InvalidStateError, "invalid state");[](#l4.263)
return NULL;[](#l4.264)
- }
+} + +PyDoc_STRVAR(pydoc_set_exception,
- "Mark the future done and set an exception.\n"
- "\n"
- "If the future is already done when this method is called, raises\n"
- "InvalidStateError."
+); + +static PyObject * +FutureObj_set_exception(FutureObj *fut, PyObject *exc) +{
- if (fut->fut_state != STATE_PENDING) {
PyErr_SetString(asyncio_InvalidStateError, "invalid state");[](#l4.294)
return NULL;[](#l4.295)
- }
- if (PyExceptionClass_Check(exc)) {
exc_val = PyObject_CallObject(exc, NULL);[](#l4.299)
if (exc_val == NULL) {[](#l4.300)
return NULL;[](#l4.301)
}[](#l4.302)
- }
- else {
exc_val = exc;[](#l4.305)
Py_INCREF(exc_val);[](#l4.306)
- }
- if (!PyExceptionInstance_Check(exc_val)) {
Py_DECREF(exc_val);[](#l4.309)
PyErr_SetString(PyExc_TypeError, "invalid exception object");[](#l4.310)
return NULL;[](#l4.311)
- }
- if ((PyObject*)Py_TYPE(exc_val) == PyExc_StopIteration) {
Py_DECREF(exc_val);[](#l4.314)
PyErr_SetString(PyExc_TypeError,[](#l4.315)
"StopIteration interacts badly with generators "[](#l4.316)
"and cannot be raised into a Future");[](#l4.317)
return NULL;[](#l4.318)
- }
+} + +PyDoc_STRVAR(pydoc_add_done_callback,
- "Add a callback to be run when the future becomes done.\n"
- "\n"
- "The callback is called with a single argument - the future object. If\n"
- "the future is already done when this is called, the callback is\n"
- "scheduled with call_soon.";
+); + +static PyObject * +FutureObj_add_done_callback(FutureObj *fut, PyObject *arg) +{
- if (fut->fut_state != STATE_PENDING) {
PyObject *handle = _PyObject_CallMethodId([](#l4.344)
fut->fut_loop, &PyId_call_soon, "OO", arg, fut, NULL);[](#l4.345)
if (handle == NULL) {[](#l4.347)
return NULL;[](#l4.348)
}[](#l4.349)
else {[](#l4.350)
Py_DECREF(handle);[](#l4.351)
}[](#l4.352)
- }
- else {
int err = PyList_Append(fut->fut_callbacks, arg);[](#l4.355)
if (err != 0) {[](#l4.356)
return NULL;[](#l4.357)
}[](#l4.358)
- }
- Py_RETURN_NONE;
+} + +PyDoc_STRVAR(pydoc_remove_done_callback,
- "Remove all instances of a callback from the "call when done" list.\n"
- "\n"
- "Returns the number of callbacks removed."
+); + +static PyObject * +FutureObj_remove_done_callback(FutureObj *fut, PyObject *arg) +{
- len = PyList_GET_SIZE(fut->fut_callbacks);
- if (len == 0) {
return PyLong_FromSsize_t(0);[](#l4.377)
- }
- for (i = 0; i < len; i++) {
int ret;[](#l4.386)
PyObject *item = PyList_GET_ITEM(fut->fut_callbacks, i);[](#l4.387)
if ((ret = PyObject_RichCompareBool(arg, item, Py_EQ)) < 0) {[](#l4.389)
goto fail;[](#l4.390)
}[](#l4.391)
if (ret == 0) {[](#l4.392)
Py_INCREF(item);[](#l4.393)
PyList_SET_ITEM(newlist, j, item);[](#l4.394)
j++;[](#l4.395)
}[](#l4.396)
- }
- if (PyList_SetSlice(newlist, j, len, NULL) < 0) {
goto fail;[](#l4.400)
- }
- if (PyList_SetSlice(fut->fut_callbacks, 0, len, newlist) < 0) {
goto fail;[](#l4.403)
- }
- Py_DECREF(newlist);
- return PyLong_FromSsize_t(len - j);
+} + +PyDoc_STRVAR(pydoc_cancel,
- "Cancel the future and schedule callbacks.\n"
- "\n"
- "If the future is already done or cancelled, return False. Otherwise,\n"
- "change the future's state to cancelled, schedule the callbacks and\n"
- "return True."
+); + +static PyObject * +FutureObj_cancel(FutureObj *fut, PyObject *arg) +{
- if (fut->fut_state != STATE_PENDING) {
Py_RETURN_FALSE;[](#l4.425)
- }
- fut->fut_state = STATE_CANCELLED;
+} + +PyDoc_STRVAR(pydoc_cancelled, "Return True if the future was cancelled."); + +static PyObject * +FutureObj_cancelled(FutureObj *fut, PyObject *arg) +{
- if (fut->fut_state == STATE_CANCELLED) {
Py_RETURN_TRUE;[](#l4.442)
- }
- else {
Py_RETURN_FALSE;[](#l4.445)
- }
+} + +PyDoc_STRVAR(pydoc_done,
- "Return True if the future is done.\n"
- "\n"
- "Done means either that a result / exception are available, or that the\n"
- "future was cancelled."
+); + +static PyObject * +FutureObj_done(FutureObj *fut, PyObject *arg) +{
- if (fut->fut_state == STATE_PENDING) {
Py_RETURN_FALSE;[](#l4.460)
- }
- else {
Py_RETURN_TRUE;[](#l4.463)
- }
+} + +static PyObject * +FutureObj_get_blocking(FutureObj *fut) +{
+} + +static int +FutureObj_set_blocking(FutureObj *fut, PyObject *val) +{
- int is_true = PyObject_IsTrue(val);
- if (is_true < 0) {
return -1;[](#l4.483)
- }
- fut->fut_blocking = is_true;
- return 0;
+} + +static PyObject * +FutureObj_get_log_traceback(FutureObj *fut) +{
+} + +static PyObject * +FutureObj_get_loop(FutureObj *fut) +{
- if (fut->fut_loop == NULL) {
Py_RETURN_NONE;[](#l4.504)
- }
- Py_INCREF(fut->fut_loop);
- return fut->fut_loop;
+} + +static PyObject * +FutureObj_get_callbacks(FutureObj *fut) +{
- if (fut->fut_callbacks == NULL) {
Py_RETURN_NONE;[](#l4.514)
- }
- Py_INCREF(fut->fut_callbacks);
- return fut->fut_callbacks;
+} + +static PyObject * +FutureObj_get_result(FutureObj *fut) +{
- if (fut->fut_result == NULL) {
Py_RETURN_NONE;[](#l4.524)
- }
- Py_INCREF(fut->fut_result);
- return fut->fut_result;
+} + +static PyObject * +FutureObj_get_exception(FutureObj *fut) +{
- if (fut->fut_exception == NULL) {
Py_RETURN_NONE;[](#l4.534)
- }
- Py_INCREF(fut->fut_exception);
- return fut->fut_exception;
+} + +static PyObject * +FutureObj_get_source_traceback(FutureObj *fut) +{
- if (fut->fut_source_tb == NULL) {
Py_RETURN_NONE;[](#l4.544)
- }
- Py_INCREF(fut->fut_source_tb);
- return fut->fut_source_tb;
+} + +static PyObject * +FutureObj_get_state(FutureObj *fut) +{
- switch (fut->fut_state) {
- case STATE_PENDING:
ret = _PyUnicode_FromId(&PyId_PENDING);[](#l4.560)
break;[](#l4.561)
- case STATE_CANCELLED:
ret = _PyUnicode_FromId(&PyId_CANCELLED);[](#l4.563)
break;[](#l4.564)
- case STATE_FINISHED:
ret = _PyUnicode_FromId(&PyId_FINISHED);[](#l4.566)
break;[](#l4.567)
- default:
assert (0);[](#l4.569)
- }
- Py_INCREF(ret);
- return ret;
+} + +static PyObject* +FutureObj__repr_info(FutureObj *fut) +{
- if (asyncio_repr_info_func == NULL) {
return PyList_New(0);[](#l4.579)
- }
- return PyObject_CallFunctionObjArgs(asyncio_repr_info_func, fut, NULL);
+} + +static PyObject * +FutureObj_repr(FutureObj *fut) +{
- PyObject *_repr_info = _PyUnicode_FromId(&PyId__repr_info); // borrowed
- if (_repr_info == NULL) {
return NULL;[](#l4.591)
- }
- PyObject rinfo = PyObject_CallMethodObjArgs((PyObject)fut, _repr_info,
NULL);[](#l4.595)
- if (rinfo == NULL) {
return NULL;[](#l4.597)
- }
- PyObject *sp = PyUnicode_FromString(" ");
- if (sp == NULL) {
Py_DECREF(rinfo);[](#l4.602)
return NULL;[](#l4.603)
- }
- PyObject *rinfo_s = PyUnicode_Join(sp, rinfo);
- Py_DECREF(sp);
- Py_DECREF(rinfo);
- if (rinfo_s == NULL) {
return NULL;[](#l4.610)
- }
- PyObject *rstr = NULL;
- PyObject type_name = PyObject_GetAttrString((PyObject)Py_TYPE(fut),
"__name__");[](#l4.615)
- if (type_name != NULL) {
rstr = PyUnicode_FromFormat("<%S %S>", type_name, rinfo_s);[](#l4.617)
Py_DECREF(type_name);[](#l4.618)
- }
- Py_DECREF(rinfo_s);
- return rstr;
+} + +static void +FutureObj_finalize(FutureObj *fut) +{
- _Py_IDENTIFIER(call_exception_handler);
- _Py_IDENTIFIER(message);
- _Py_IDENTIFIER(exception);
- _Py_IDENTIFIER(future);
- _Py_IDENTIFIER(source_traceback);
- if (!fut->fut_log_tb) {
return;[](#l4.634)
- }
- assert(fut->fut_exception != NULL);
- fut->fut_log_tb = 0;;
- PyObject *error_type, *error_value, *error_traceback;
- /* Save the current exception, if any. */
- PyErr_Fetch(&error_type, &error_value, &error_traceback);
- PyObject *context = NULL;
- PyObject *type_name = NULL;
- PyObject *message = NULL;
- PyObject *func = NULL;
- PyObject *res = NULL;
- type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut), "name");
- if (type_name == NULL) {
goto finally;[](#l4.656)
- }
- message = PyUnicode_FromFormat(
"%S exception was never retrieved", type_name);[](#l4.660)
- if (message == NULL) {
goto finally;[](#l4.662)
- }
- if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
_PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||[](#l4.666)
_PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {[](#l4.667)
goto finally;[](#l4.668)
- }
- if (fut->fut_source_tb != NULL) {
if (_PyDict_SetItemId(context, &PyId_source_traceback,[](#l4.671)
fut->fut_source_tb) < 0) {[](#l4.672)
goto finally;[](#l4.673)
}[](#l4.674)
- }
- func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
- if (func != NULL) {
res = _PyObject_CallArg1(func, context);[](#l4.679)
if (res == NULL) {[](#l4.680)
PyErr_WriteUnraisable(func);[](#l4.681)
}[](#l4.682)
- }
+} + + +static PyAsyncMethods FutureType_as_async = {
+}; + +static PyMethodDef FutureType_methods[] = {
- {"_repr_info", (PyCFunction)FutureObj__repr_info, METH_NOARGS, NULL},
- {"add_done_callback",
(PyCFunction)FutureObj_add_done_callback,[](#l4.706)
METH_O, pydoc_add_done_callback},[](#l4.707)
- {"remove_done_callback",
(PyCFunction)FutureObj_remove_done_callback,[](#l4.709)
METH_O, pydoc_remove_done_callback},[](#l4.710)
- {"set_result",
(PyCFunction)FutureObj_set_result, METH_O, pydoc_set_result},[](#l4.712)
- {"set_exception",
(PyCFunction)FutureObj_set_exception, METH_O, pydoc_set_exception},[](#l4.714)
- {"cancel", (PyCFunction)FutureObj_cancel, METH_NOARGS, pydoc_cancel},
- {"cancelled",
(PyCFunction)FutureObj_cancelled, METH_NOARGS, pydoc_cancelled},[](#l4.717)
- {"done", (PyCFunction)FutureObj_done, METH_NOARGS, pydoc_done},
- {"result", (PyCFunction)FutureObj_result, METH_NOARGS, pydoc_result},
- {"exception",
(PyCFunction)FutureObj_exception, METH_NOARGS, pydoc_exception},[](#l4.721)
- {NULL, NULL} /* Sentinel */
+}; + +static PyGetSetDef FutureType_getsetlist[] = {
- {"_state", (getter)FutureObj_get_state, NULL, NULL},
- {"_asyncio_future_blocking", (getter)FutureObj_get_blocking,
(setter)FutureObj_set_blocking, NULL},[](#l4.728)
- {"_loop", (getter)FutureObj_get_loop, NULL, NULL},
- {"_callbacks", (getter)FutureObj_get_callbacks, NULL, NULL},
- {"_result", (getter)FutureObj_get_result, NULL, NULL},
- {"_exception", (getter)FutureObj_get_exception, NULL, NULL},
- {"_log_traceback", (getter)FutureObj_get_log_traceback, NULL, NULL},
- {"_source_traceback", (getter)FutureObj_get_source_traceback, NULL, NULL},
- {NULL} /* Sentinel */
+}; + +static void FutureObj_dealloc(PyObject *self); + +static PyTypeObject FutureType = {
- PyVarObject_HEAD_INIT(0, 0)
- "_futures.Future",
- sizeof(FutureObj), /* tp_basicsize */
- .tp_dealloc = FutureObj_dealloc,
- .tp_as_async = &FutureType_as_async,
- .tp_repr = (reprfunc)FutureObj_repr,
- .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE
| Py_TPFLAGS_HAVE_FINALIZE,[](#l4.748)
- .tp_doc = "Fast asyncio.Future implementation.",
- .tp_traverse = (traverseproc)FutureObj_traverse,
- .tp_clear = (inquiry)FutureObj_clear,
- .tp_weaklistoffset = offsetof(FutureObj, fut_weakreflist),
- .tp_iter = (getiterfunc)new_future_iter,
- .tp_methods = FutureType_methods,
- .tp_getset = FutureType_getsetlist,
- .tp_dictoffset = offsetof(FutureObj, dict),
- .tp_init = (initproc)FutureObj_init,
- .tp_new = PyType_GenericNew,
- .tp_finalize = (destructor)FutureObj_finalize,
+}; + +static void +FutureObj_dealloc(PyObject *self) +{
- if (Py_TYPE(fut) == &FutureType) {
/* When fut is subclass of Future, finalizer is called from[](#l4.768)
* subtype_dealloc.[](#l4.769)
*/[](#l4.770)
if (PyObject_CallFinalizerFromDealloc(self) < 0) {[](#l4.771)
// resurrected.[](#l4.772)
return;[](#l4.773)
}[](#l4.774)
- }
+} + + +/*********************** Future Iterator **************************/ + +typedef struct {
+} futureiterobject; + +static void +FutureIter_dealloc(futureiterobject *it) +{
+} + +static PyObject * +FutureIter_iternext(futureiterobject *it) +{
- if (fut->fut_state == STATE_PENDING) {
if (!fut->fut_blocking) {[](#l4.812)
fut->fut_blocking = 1;[](#l4.813)
Py_INCREF(fut);[](#l4.814)
return (PyObject *)fut;[](#l4.815)
}[](#l4.816)
PyErr_Format(PyExc_AssertionError,[](#l4.817)
"yield from wasn't used with future");[](#l4.818)
return NULL;[](#l4.819)
- }
- res = FutureObj_result(fut, NULL);
- if (res != NULL) {
// normal result[](#l4.824)
PyErr_SetObject(PyExc_StopIteration, res);[](#l4.825)
Py_DECREF(res);[](#l4.826)
- }
+} + +static PyObject * +FutureIter_send(futureiterobject *self, PyObject *arg) +{
- if (arg != Py_None) {
PyErr_Format(PyExc_TypeError,[](#l4.838)
"can't send non-None value to a FutureIter");[](#l4.839)
return NULL;[](#l4.840)
- }
- return FutureIter_iternext(self);
+} + +static PyObject * +FutureIter_throw(futureiterobject *self, PyObject *args) +{
- PyObject *type=NULL, *val=NULL, *tb=NULL;
- if (!PyArg_ParseTuple(args, "O|OO", &type, &val, &tb))
return NULL;[](#l4.850)
- if (tb != NULL) {
PyErr_Restore(type, val, tb);[](#l4.862)
- }
- else if (val != NULL) {
PyErr_SetObject(type, val);[](#l4.865)
- }
- else {
if (PyExceptionClass_Check(type)) {[](#l4.868)
val = PyObject_CallObject(type, NULL);[](#l4.869)
}[](#l4.870)
else {[](#l4.871)
val = type;[](#l4.872)
assert (PyExceptionInstance_Check(val));[](#l4.873)
type = (PyObject*)Py_TYPE(val);[](#l4.874)
assert (PyExceptionClass_Check(type));[](#l4.875)
}[](#l4.876)
PyErr_SetObject(type, val);[](#l4.877)
- }
- return FutureIter_iternext(self);
+} + +static PyObject * +FutureIter_close(futureiterobject *self, PyObject *arg) +{
+} + +static int +FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg) +{
+} + +static PyMethodDef FutureIter_methods[] = {
- {"send", (PyCFunction)FutureIter_send, METH_O, NULL},
- {"throw", (PyCFunction)FutureIter_throw, METH_VARARGS, NULL},
- {"close", (PyCFunction)FutureIter_close, METH_NOARGS, NULL},
- {NULL, NULL} /* Sentinel */
+}; + +static PyTypeObject FutureIterType = {
- PyVarObject_HEAD_INIT(0, 0)
- "_futures.FutureIter",
- sizeof(futureiterobject), /* tp_basicsize */
- 0, /* tp_itemsize */
- (destructor)FutureIter_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_as_async */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
- 0, /* tp_doc */
- (traverseproc)FutureIter_traverse, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- PyObject_SelfIter, /* tp_iter */
- (iternextfunc)FutureIter_iternext, /* tp_iternext */
- FutureIter_methods, /* tp_methods */
- 0, /* tp_members */
+}; + +static PyObject * +new_future_iter(PyObject *fut) +{
- if (!PyObject_TypeCheck(fut, &FutureType)) {
PyErr_BadInternalCall();[](#l4.941)
return NULL;[](#l4.942)
- }
- it = PyObject_GC_New(futureiterobject, &FutureIterType);
- if (it == NULL) {
return NULL;[](#l4.946)
- }
- Py_INCREF(fut);
- it->future = (FutureObj*)fut;
- _PyObject_GC_TRACK(it);
- return (PyObject*)it;
+} + +/*********************** Module **************************/ + +PyDoc_STRVAR(module_doc, "Fast asyncio.Future implementation.\n"); + +PyObject * +_init_module(PyObject *self, PyObject *args) +{
- PyObject *extract_stack;
- PyObject *get_event_loop;
- PyObject *repr_info_func;
- PyObject *invalidStateError;
- PyObject *cancelledError;
- if (!PyArg_UnpackTuple(args, "_init_module", 5, 5,
&extract_stack,[](#l4.968)
&get_event_loop,[](#l4.969)
&repr_info_func,[](#l4.970)
&invalidStateError,[](#l4.971)
&cancelledError)) {[](#l4.972)
return NULL;[](#l4.973)
- }
+} + + +static struct PyMethodDef futuresmod_methods[] = {
+}; + + +static struct PyModuleDef _futuresmodule = {
- PyModuleDef_HEAD_INIT, /* m_base */
- "_futures", /* m_name */
- module_doc, /* m_doc */
- -1, /* m_size */
- futuresmod_methods, /* m_methods */
- NULL, /* m_slots */
- NULL, /* m_traverse */
- NULL, /* m_clear */
- NULL, /* m_free */
+}; + + +PyMODINIT_FUNC +PyInit__futures(void) +{
- if (PyType_Ready(&FutureType) < 0) {
return NULL;[](#l4.1020)
- }
- if (PyType_Ready(&FutureIterType) < 0) {
return NULL;[](#l4.1023)
- }
- Py_INCREF(&FutureType);
- if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
Py_DECREF(&FutureType);[](#l4.1033)
return NULL;[](#l4.1034)
- }
--- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -221,6 +221,7 @@
--- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -470,6 +470,9 @@ Modules
--- a/setup.py +++ b/setup.py @@ -657,6 +657,8 @@ class PyBuildExt(build_ext): depends=['unicodedata_db.h', 'unicodename_db.h']) ) # _opcode module exts.append( Extension('_opcode', ['_opcode.c']) )
# Fast asyncio Future implementation[](#l7.7)
exts.append( Extension("_futures", ["_futuresmodule.c"]) )[](#l7.8)
# Modules with some UNIX dependencies -- on by default: # (If you have a really backward UNIX, select and socket may not be