diff -r 86a1905ea28d Lib/asyncio/futures.py
--- a/Lib/asyncio/futures.py Wed Oct 12 20:16:05 2016 +0200
+++ b/Lib/asyncio/futures.py Thu Oct 13 21:10:34 2016 +0900
@@ -432,18 +432,18 @@ def _copy_future_state(source, dest):
try:
- import _futures
+ import _asyncio
except ImportError:
pass
else:
- _futures._init_module(
+ _asyncio._init_module(
traceback.extract_stack,
events.get_event_loop,
_future_repr_info,
InvalidStateError,
CancelledError)
- Future = _futures.Future
+ Future = _asyncio.Future
def _chain_future(source, destination):
diff -r 86a1905ea28d Modules/Setup.dist
--- a/Modules/Setup.dist Wed Oct 12 20:16:05 2016 +0200
+++ b/Modules/Setup.dist Thu Oct 13 21:10:34 2016 +0900
@@ -181,7 +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
+#_asyncio _asynciomodule.c # Fast asyncio Future
#unicodedata unicodedata.c # static Unicode character database
diff -r 86a1905ea28d Modules/_asynciomodule.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Modules/_asynciomodule.c Thu Oct 13 21:10:34 2016 +0900
@@ -0,0 +1,1034 @@
+#include "Python.h"
+#include "structmember.h"
+
+
+/* identifiers used from some functions */
+_Py_IDENTIFIER(call_soon);
+
+
+/* State of the _asyncio module */
+static int _asynciomod_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
+_AsyncioMod_EnsureState(void)
+{
+ if (!_asynciomod_ready) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "_asyncio module wasn't properly initialized");
+ return -1;
+ }
+ return 0;
+}
+
+
+typedef enum {
+ STATE_PENDING,
+ STATE_CANCELLED,
+ STATE_FINISHED
+} 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)
+{
+ Py_ssize_t len;
+ PyObject* iters;
+ int i;
+
+ if (fut->fut_callbacks == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "NULL callbacks");
+ return -1;
+ }
+
+ len = PyList_GET_SIZE(fut->fut_callbacks);
+ if (len == 0) {
+ return 0;
+ }
+
+ iters = PyList_GetSlice(fut->fut_callbacks, 0, len);
+ if (iters == NULL) {
+ return -1;
+ }
+ if (PyList_SetSlice(fut->fut_callbacks, 0, len, NULL) < 0) {
+ Py_DECREF(iters);
+ return -1;
+ }
+
+ for (i = 0; i < len; i++) {
+ PyObject *handle = NULL;
+ PyObject *cb = PyList_GET_ITEM(iters, i);
+
+ handle = _PyObject_CallMethodId(
+ fut->fut_loop, &PyId_call_soon, "OO", cb, fut, NULL);
+
+ if (handle == NULL) {
+ Py_DECREF(iters);
+ return -1;
+ }
+ else {
+ Py_DECREF(handle);
+ }
+ }
+
+ Py_DECREF(iters);
+ return 0;
+}
+
+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 (_AsyncioMod_EnsureState()) {
+ return -1;
+ }
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|$O", kwlist, &loop)) {
+ return -1;
+ }
+ if (loop == NULL || loop == Py_None) {
+ loop = PyObject_CallObject(asyncio_get_event_loop, NULL);
+ if (loop == NULL) {
+ return -1;
+ }
+ }
+ else {
+ Py_INCREF(loop);
+ }
+ Py_CLEAR(fut->fut_loop);
+ fut->fut_loop = loop;
+
+ res = _PyObject_CallMethodId(fut->fut_loop, &PyId_get_debug, "()", NULL);
+ if (res == NULL) {
+ return -1;
+ }
+ if (PyObject_IsTrue(res)) {
+ Py_CLEAR(res);
+ fut->fut_source_tb = PyObject_CallObject(traceback_extract_stack, NULL);
+ if (fut->fut_source_tb == NULL) {
+ return -1;
+ }
+ }
+ else {
+ Py_CLEAR(res);
+ }
+
+ fut->fut_callbacks = PyList_New(0);
+ if (fut->fut_callbacks == NULL) {
+ return -1;
+ }
+ 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, "");
+ return NULL;
+ }
+
+ if (fut->fut_state != STATE_FINISHED) {
+ PyErr_SetString(asyncio_InvalidStateError, "Result is not ready.");
+ return NULL;
+ }
+
+ fut->fut_log_tb = 0;
+ if (fut->fut_exception != NULL) {
+ PyObject *type = NULL;
+ type = PyExceptionInstance_Class(fut->fut_exception);
+ PyErr_SetObject(type, fut->fut_exception);
+ return NULL;
+ }
+
+ Py_INCREF(fut->fut_result);
+ return fut->fut_result;
+}
+
+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 (_AsyncioMod_EnsureState()) {
+ return NULL;
+ }
+
+ if (fut->fut_state == STATE_CANCELLED) {
+ PyErr_SetString(asyncio_CancelledError, "");
+ return NULL;
+ }
+
+ if (fut->fut_state != STATE_FINISHED) {
+ PyErr_SetString(asyncio_InvalidStateError, "Result is not ready.");
+ return NULL;
+ }
+
+ if (fut->fut_exception != NULL) {
+ fut->fut_log_tb = 0;
+ Py_INCREF(fut->fut_exception);
+ return fut->fut_exception;
+ }
+
+ Py_RETURN_NONE;
+}
+
+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 (_AsyncioMod_EnsureState()) {
+ return NULL;
+ }
+
+ if (fut->fut_state != STATE_PENDING) {
+ PyErr_SetString(asyncio_InvalidStateError, "invalid state");
+ return NULL;
+ }
+
+ Py_INCREF(res);
+ fut->fut_result = res;
+ fut->fut_state = STATE_FINISHED;
+
+ if (_schedule_callbacks(fut) == -1) {
+ return NULL;
+ }
+ Py_RETURN_NONE;
+}
+
+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)
+{
+ PyObject *exc_val = NULL;
+
+ if (_AsyncioMod_EnsureState()) {
+ return NULL;
+ }
+
+ if (fut->fut_state != STATE_PENDING) {
+ PyErr_SetString(asyncio_InvalidStateError, "invalid state");
+ return NULL;
+ }
+
+ if (PyExceptionClass_Check(exc)) {
+ exc_val = PyObject_CallObject(exc, NULL);
+ if (exc_val == NULL) {
+ return NULL;
+ }
+ }
+ else {
+ exc_val = exc;
+ Py_INCREF(exc_val);
+ }
+ if (!PyExceptionInstance_Check(exc_val)) {
+ Py_DECREF(exc_val);
+ PyErr_SetString(PyExc_TypeError, "invalid exception object");
+ return NULL;
+ }
+ if ((PyObject*)Py_TYPE(exc_val) == PyExc_StopIteration) {
+ Py_DECREF(exc_val);
+ PyErr_SetString(PyExc_TypeError,
+ "StopIteration interacts badly with generators "
+ "and cannot be raised into a Future");
+ return NULL;
+ }
+
+ fut->fut_exception = exc_val;
+ fut->fut_state = STATE_FINISHED;
+
+ if (_schedule_callbacks(fut) == -1) {
+ return NULL;
+ }
+
+ fut->fut_log_tb = 1;
+ Py_RETURN_NONE;
+}
+
+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(
+ fut->fut_loop, &PyId_call_soon, "OO", arg, fut, NULL);
+
+ if (handle == NULL) {
+ return NULL;
+ }
+ else {
+ Py_DECREF(handle);
+ }
+ }
+ else {
+ int err = PyList_Append(fut->fut_callbacks, arg);
+ if (err != 0) {
+ return NULL;
+ }
+ }
+ 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)
+{
+ PyObject *newlist;
+ Py_ssize_t len, i, j=0;
+
+ len = PyList_GET_SIZE(fut->fut_callbacks);
+ if (len == 0) {
+ return PyLong_FromSsize_t(0);
+ }
+
+ newlist = PyList_New(len);
+ if (newlist == NULL) {
+ return NULL;
+ }
+
+ for (i = 0; i < len; i++) {
+ int ret;
+ PyObject *item = PyList_GET_ITEM(fut->fut_callbacks, i);
+
+ if ((ret = PyObject_RichCompareBool(arg, item, Py_EQ)) < 0) {
+ goto fail;
+ }
+ if (ret == 0) {
+ Py_INCREF(item);
+ PyList_SET_ITEM(newlist, j, item);
+ j++;
+ }
+ }
+
+ if (PyList_SetSlice(newlist, j, len, NULL) < 0) {
+ goto fail;
+ }
+ if (PyList_SetSlice(fut->fut_callbacks, 0, len, newlist) < 0) {
+ goto fail;
+ }
+ Py_DECREF(newlist);
+ return PyLong_FromSsize_t(len - j);
+
+fail:
+ Py_DECREF(newlist);
+ return NULL;
+}
+
+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;
+ }
+ fut->fut_state = STATE_CANCELLED;
+
+ if (_schedule_callbacks(fut) == -1) {
+ return NULL;
+ }
+
+ Py_RETURN_TRUE;
+}
+
+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;
+ }
+ else {
+ Py_RETURN_FALSE;
+ }
+}
+
+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;
+ }
+ else {
+ Py_RETURN_TRUE;
+ }
+}
+
+static PyObject *
+FutureObj_get_blocking(FutureObj *fut)
+{
+ if (fut->fut_blocking) {
+ Py_RETURN_TRUE;
+ }
+ else {
+ Py_RETURN_FALSE;
+ }
+}
+
+static int
+FutureObj_set_blocking(FutureObj *fut, PyObject *val)
+{
+ int is_true = PyObject_IsTrue(val);
+ if (is_true < 0) {
+ return -1;
+ }
+ fut->fut_blocking = is_true;
+ return 0;
+}
+
+static PyObject *
+FutureObj_get_log_traceback(FutureObj *fut)
+{
+ if (fut->fut_log_tb) {
+ Py_RETURN_TRUE;
+ }
+ else {
+ Py_RETURN_FALSE;
+ }
+}
+
+static PyObject *
+FutureObj_get_loop(FutureObj *fut)
+{
+ if (fut->fut_loop == NULL) {
+ Py_RETURN_NONE;
+ }
+ Py_INCREF(fut->fut_loop);
+ return fut->fut_loop;
+}
+
+static PyObject *
+FutureObj_get_callbacks(FutureObj *fut)
+{
+ if (fut->fut_callbacks == NULL) {
+ Py_RETURN_NONE;
+ }
+ Py_INCREF(fut->fut_callbacks);
+ return fut->fut_callbacks;
+}
+
+static PyObject *
+FutureObj_get_result(FutureObj *fut)
+{
+ if (fut->fut_result == NULL) {
+ Py_RETURN_NONE;
+ }
+ Py_INCREF(fut->fut_result);
+ return fut->fut_result;
+}
+
+static PyObject *
+FutureObj_get_exception(FutureObj *fut)
+{
+ if (fut->fut_exception == NULL) {
+ Py_RETURN_NONE;
+ }
+ 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;
+ }
+ Py_INCREF(fut->fut_source_tb);
+ return fut->fut_source_tb;
+}
+
+static PyObject *
+FutureObj_get_state(FutureObj *fut)
+{
+ _Py_IDENTIFIER(PENDING);
+ _Py_IDENTIFIER(CANCELLED);
+ _Py_IDENTIFIER(FINISHED);
+ PyObject *ret = NULL;
+
+ switch (fut->fut_state) {
+ case STATE_PENDING:
+ ret = _PyUnicode_FromId(&PyId_PENDING);
+ break;
+ case STATE_CANCELLED:
+ ret = _PyUnicode_FromId(&PyId_CANCELLED);
+ break;
+ case STATE_FINISHED:
+ ret = _PyUnicode_FromId(&PyId_FINISHED);
+ break;
+ default:
+ assert (0);
+ }
+ Py_INCREF(ret);
+ return ret;
+}
+
+static PyObject*
+FutureObj__repr_info(FutureObj *fut)
+{
+ if (asyncio_repr_info_func == NULL) {
+ return PyList_New(0);
+ }
+ return PyObject_CallFunctionObjArgs(asyncio_repr_info_func, fut, NULL);
+}
+
+static PyObject *
+FutureObj_repr(FutureObj *fut)
+{
+ _Py_IDENTIFIER(_repr_info);
+
+ PyObject *_repr_info = _PyUnicode_FromId(&PyId__repr_info); // borrowed
+ if (_repr_info == NULL) {
+ return NULL;
+ }
+
+ PyObject *rinfo = PyObject_CallMethodObjArgs((PyObject*)fut, _repr_info,
+ NULL);
+ if (rinfo == NULL) {
+ return NULL;
+ }
+
+ PyObject *sp = PyUnicode_FromString(" ");
+ if (sp == NULL) {
+ Py_DECREF(rinfo);
+ return NULL;
+ }
+
+ PyObject *rinfo_s = PyUnicode_Join(sp, rinfo);
+ Py_DECREF(sp);
+ Py_DECREF(rinfo);
+ if (rinfo_s == NULL) {
+ return NULL;
+ }
+
+ PyObject *rstr = NULL;
+ PyObject *type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut),
+ "__name__");
+ if (type_name != NULL) {
+ rstr = PyUnicode_FromFormat("<%S %S>", type_name, rinfo_s);
+ Py_DECREF(type_name);
+ }
+ 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;
+ }
+ 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;
+
+ context = PyDict_New();
+ if (context == NULL) {
+ goto finally;
+ }
+
+ type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut), "__name__");
+ if (type_name == NULL) {
+ goto finally;
+ }
+
+ message = PyUnicode_FromFormat(
+ "%S exception was never retrieved", type_name);
+ if (message == NULL) {
+ goto finally;
+ }
+
+ if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
+ _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
+ _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
+ goto finally;
+ }
+ if (fut->fut_source_tb != NULL) {
+ if (_PyDict_SetItemId(context, &PyId_source_traceback,
+ fut->fut_source_tb) < 0) {
+ goto finally;
+ }
+ }
+
+ func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
+ if (func != NULL) {
+ res = _PyObject_CallArg1(func, context);
+ if (res == NULL) {
+ PyErr_WriteUnraisable(func);
+ }
+ }
+
+finally:
+ Py_CLEAR(context);
+ Py_CLEAR(type_name);
+ Py_CLEAR(message);
+ Py_CLEAR(func);
+ Py_CLEAR(res);
+
+ /* Restore the saved exception. */
+ PyErr_Restore(error_type, error_value, error_traceback);
+}
+
+
+static PyAsyncMethods FutureType_as_async = {
+ (unaryfunc)new_future_iter, /* am_await */
+ 0, /* am_aiter */
+ 0 /* am_anext */
+};
+
+static PyMethodDef FutureType_methods[] = {
+ {"_repr_info", (PyCFunction)FutureObj__repr_info, METH_NOARGS, NULL},
+ {"add_done_callback",
+ (PyCFunction)FutureObj_add_done_callback,
+ METH_O, pydoc_add_done_callback},
+ {"remove_done_callback",
+ (PyCFunction)FutureObj_remove_done_callback,
+ METH_O, pydoc_remove_done_callback},
+ {"set_result",
+ (PyCFunction)FutureObj_set_result, METH_O, pydoc_set_result},
+ {"set_exception",
+ (PyCFunction)FutureObj_set_exception, METH_O, pydoc_set_exception},
+ {"cancel", (PyCFunction)FutureObj_cancel, METH_NOARGS, pydoc_cancel},
+ {"cancelled",
+ (PyCFunction)FutureObj_cancelled, METH_NOARGS, pydoc_cancelled},
+ {"done", (PyCFunction)FutureObj_done, METH_NOARGS, pydoc_done},
+ {"result", (PyCFunction)FutureObj_result, METH_NOARGS, pydoc_result},
+ {"exception",
+ (PyCFunction)FutureObj_exception, METH_NOARGS, pydoc_exception},
+ {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},
+ {"_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)
+ "_asyncio.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,
+ .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)
+{
+ FutureObj *fut = (FutureObj *)self;
+
+ if (Py_TYPE(fut) == &FutureType) {
+ /* When fut is subclass of Future, finalizer is called from
+ * subtype_dealloc.
+ */
+ if (PyObject_CallFinalizerFromDealloc(self) < 0) {
+ // resurrected.
+ return;
+ }
+ }
+
+ if (fut->fut_weakreflist != NULL) {
+ PyObject_ClearWeakRefs(self);
+ }
+
+ FutureObj_clear(fut);
+ Py_TYPE(fut)->tp_free(fut);
+}
+
+
+/*********************** Future Iterator **************************/
+
+typedef struct {
+ PyObject_HEAD
+ FutureObj *future;
+} futureiterobject;
+
+static void
+FutureIter_dealloc(futureiterobject *it)
+{
+ _PyObject_GC_UNTRACK(it);
+ Py_XDECREF(it->future);
+ PyObject_GC_Del(it);
+}
+
+static PyObject *
+FutureIter_iternext(futureiterobject *it)
+{
+ PyObject *res;
+ FutureObj *fut = it->future;
+
+ if (fut == NULL) {
+ return NULL;
+ }
+
+ if (fut->fut_state == STATE_PENDING) {
+ if (!fut->fut_blocking) {
+ fut->fut_blocking = 1;
+ Py_INCREF(fut);
+ return (PyObject *)fut;
+ }
+ PyErr_Format(PyExc_AssertionError,
+ "yield from wasn't used with future");
+ return NULL;
+ }
+
+ res = FutureObj_result(fut, NULL);
+ if (res != NULL) {
+ // normal result
+ PyErr_SetObject(PyExc_StopIteration, res);
+ Py_DECREF(res);
+ }
+
+ it->future = NULL;
+ Py_DECREF(fut);
+ return NULL;
+}
+
+static PyObject *
+FutureIter_send(futureiterobject *self, PyObject *arg)
+{
+ if (arg != Py_None) {
+ PyErr_Format(PyExc_TypeError,
+ "can't send non-None value to a FutureIter");
+ return NULL;
+ }
+ 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;
+
+ if (val == Py_None) {
+ val = NULL;
+ }
+ if (tb == Py_None) {
+ tb = NULL;
+ }
+
+ Py_CLEAR(self->future);
+
+ if (tb != NULL) {
+ PyErr_Restore(type, val, tb);
+ }
+ else if (val != NULL) {
+ PyErr_SetObject(type, val);
+ }
+ else {
+ if (PyExceptionClass_Check(type)) {
+ val = PyObject_CallObject(type, NULL);
+ }
+ else {
+ val = type;
+ assert (PyExceptionInstance_Check(val));
+ type = (PyObject*)Py_TYPE(val);
+ assert (PyExceptionClass_Check(type));
+ }
+ PyErr_SetObject(type, val);
+ }
+ return FutureIter_iternext(self);
+}
+
+static PyObject *
+FutureIter_close(futureiterobject *self, PyObject *arg)
+{
+ Py_CLEAR(self->future);
+ Py_RETURN_NONE;
+}
+
+static int
+FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
+{
+ Py_VISIT(it->future);
+ return 0;
+}
+
+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)
+ "_asyncio.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)
+{
+ futureiterobject *it;
+
+ if (!PyObject_TypeCheck(fut, &FutureType)) {
+ PyErr_BadInternalCall();
+ return NULL;
+ }
+ it = PyObject_GC_New(futureiterobject, &FutureIterType);
+ if (it == NULL) {
+ return NULL;
+ }
+ Py_INCREF(fut);
+ it->future = (FutureObj*)fut;
+ PyObject_GC_Track(it);
+ return (PyObject*)it;
+}
+
+/*********************** Module **************************/
+
+PyDoc_STRVAR(module_doc, "asyncio speedups.\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,
+ &get_event_loop,
+ &repr_info_func,
+ &invalidStateError,
+ &cancelledError)) {
+ return NULL;
+ }
+
+ Py_INCREF(extract_stack);
+ Py_XSETREF(traceback_extract_stack, extract_stack);
+
+ Py_INCREF(get_event_loop);
+ Py_XSETREF(asyncio_get_event_loop, get_event_loop);
+
+ Py_INCREF(repr_info_func);
+ Py_XSETREF(asyncio_repr_info_func, repr_info_func);
+
+ Py_INCREF(invalidStateError);
+ Py_XSETREF(asyncio_InvalidStateError, invalidStateError);
+
+ Py_INCREF(cancelledError);
+ Py_XSETREF(asyncio_CancelledError, cancelledError);
+
+ _asynciomod_ready = 1;
+
+ Py_RETURN_NONE;
+}
+
+
+static struct PyMethodDef asynciomod_methods[] = {
+ {"_init_module", _init_module, METH_VARARGS, NULL},
+ {NULL, NULL}
+};
+
+
+static struct PyModuleDef _asynciomodule = {
+ PyModuleDef_HEAD_INIT, /* m_base */
+ "_asyncio", /* m_name */
+ module_doc, /* m_doc */
+ -1, /* m_size */
+ asynciomod_methods, /* m_methods */
+ NULL, /* m_slots */
+ NULL, /* m_traverse */
+ NULL, /* m_clear */
+ NULL, /* m_free */
+};
+
+
+PyMODINIT_FUNC
+PyInit__asyncio(void)
+{
+ if (PyType_Ready(&FutureType) < 0) {
+ return NULL;
+ }
+ if (PyType_Ready(&FutureIterType) < 0) {
+ return NULL;
+ }
+
+ PyObject *m = PyModule_Create(&_asynciomodule);
+ if (m == NULL) {
+ return NULL;
+ }
+
+ Py_INCREF(&FutureType);
+ if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
+ Py_DECREF(&FutureType);
+ return NULL;
+ }
+
+ return m;
+}
diff -r 86a1905ea28d Modules/_futuresmodule.c
--- a/Modules/_futuresmodule.c Wed Oct 12 20:16:05 2016 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1034 +0,0 @@
-#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,
- "_futures module wasn't properly initialized");
- return -1;
- }
- return 0;
-}
-
-
-typedef enum {
- STATE_PENDING,
- STATE_CANCELLED,
- STATE_FINISHED
-} 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)
-{
- Py_ssize_t len;
- PyObject* iters;
- int i;
-
- if (fut->fut_callbacks == NULL) {
- PyErr_SetString(PyExc_RuntimeError, "NULL callbacks");
- return -1;
- }
-
- len = PyList_GET_SIZE(fut->fut_callbacks);
- if (len == 0) {
- return 0;
- }
-
- iters = PyList_GetSlice(fut->fut_callbacks, 0, len);
- if (iters == NULL) {
- return -1;
- }
- if (PyList_SetSlice(fut->fut_callbacks, 0, len, NULL) < 0) {
- Py_DECREF(iters);
- return -1;
- }
-
- for (i = 0; i < len; i++) {
- PyObject *handle = NULL;
- PyObject *cb = PyList_GET_ITEM(iters, i);
-
- handle = _PyObject_CallMethodId(
- fut->fut_loop, &PyId_call_soon, "OO", cb, fut, NULL);
-
- if (handle == NULL) {
- Py_DECREF(iters);
- return -1;
- }
- else {
- Py_DECREF(handle);
- }
- }
-
- Py_DECREF(iters);
- return 0;
-}
-
-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 (_FuturesMod_EnsureState()) {
- return -1;
- }
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|$O", kwlist, &loop)) {
- return -1;
- }
- if (loop == NULL || loop == Py_None) {
- loop = PyObject_CallObject(asyncio_get_event_loop, NULL);
- if (loop == NULL) {
- return -1;
- }
- }
- else {
- Py_INCREF(loop);
- }
- Py_CLEAR(fut->fut_loop);
- fut->fut_loop = loop;
-
- res = _PyObject_CallMethodId(fut->fut_loop, &PyId_get_debug, "()", NULL);
- if (res == NULL) {
- return -1;
- }
- if (PyObject_IsTrue(res)) {
- Py_CLEAR(res);
- fut->fut_source_tb = PyObject_CallObject(traceback_extract_stack, NULL);
- if (fut->fut_source_tb == NULL) {
- return -1;
- }
- }
- else {
- Py_CLEAR(res);
- }
-
- fut->fut_callbacks = PyList_New(0);
- if (fut->fut_callbacks == NULL) {
- return -1;
- }
- 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, "");
- return NULL;
- }
-
- if (fut->fut_state != STATE_FINISHED) {
- PyErr_SetString(asyncio_InvalidStateError, "Result is not ready.");
- return NULL;
- }
-
- fut->fut_log_tb = 0;
- if (fut->fut_exception != NULL) {
- PyObject *type = NULL;
- type = PyExceptionInstance_Class(fut->fut_exception);
- PyErr_SetObject(type, fut->fut_exception);
- return NULL;
- }
-
- Py_INCREF(fut->fut_result);
- return fut->fut_result;
-}
-
-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 (_FuturesMod_EnsureState()) {
- return NULL;
- }
-
- if (fut->fut_state == STATE_CANCELLED) {
- PyErr_SetString(asyncio_CancelledError, "");
- return NULL;
- }
-
- if (fut->fut_state != STATE_FINISHED) {
- PyErr_SetString(asyncio_InvalidStateError, "Result is not ready.");
- return NULL;
- }
-
- if (fut->fut_exception != NULL) {
- fut->fut_log_tb = 0;
- Py_INCREF(fut->fut_exception);
- return fut->fut_exception;
- }
-
- Py_RETURN_NONE;
-}
-
-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 (_FuturesMod_EnsureState()) {
- return NULL;
- }
-
- if (fut->fut_state != STATE_PENDING) {
- PyErr_SetString(asyncio_InvalidStateError, "invalid state");
- return NULL;
- }
-
- Py_INCREF(res);
- fut->fut_result = res;
- fut->fut_state = STATE_FINISHED;
-
- if (_schedule_callbacks(fut) == -1) {
- return NULL;
- }
- Py_RETURN_NONE;
-}
-
-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)
-{
- PyObject *exc_val = NULL;
-
- if (_FuturesMod_EnsureState()) {
- return NULL;
- }
-
- if (fut->fut_state != STATE_PENDING) {
- PyErr_SetString(asyncio_InvalidStateError, "invalid state");
- return NULL;
- }
-
- if (PyExceptionClass_Check(exc)) {
- exc_val = PyObject_CallObject(exc, NULL);
- if (exc_val == NULL) {
- return NULL;
- }
- }
- else {
- exc_val = exc;
- Py_INCREF(exc_val);
- }
- if (!PyExceptionInstance_Check(exc_val)) {
- Py_DECREF(exc_val);
- PyErr_SetString(PyExc_TypeError, "invalid exception object");
- return NULL;
- }
- if ((PyObject*)Py_TYPE(exc_val) == PyExc_StopIteration) {
- Py_DECREF(exc_val);
- PyErr_SetString(PyExc_TypeError,
- "StopIteration interacts badly with generators "
- "and cannot be raised into a Future");
- return NULL;
- }
-
- fut->fut_exception = exc_val;
- fut->fut_state = STATE_FINISHED;
-
- if (_schedule_callbacks(fut) == -1) {
- return NULL;
- }
-
- fut->fut_log_tb = 1;
- Py_RETURN_NONE;
-}
-
-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(
- fut->fut_loop, &PyId_call_soon, "OO", arg, fut, NULL);
-
- if (handle == NULL) {
- return NULL;
- }
- else {
- Py_DECREF(handle);
- }
- }
- else {
- int err = PyList_Append(fut->fut_callbacks, arg);
- if (err != 0) {
- return NULL;
- }
- }
- 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)
-{
- PyObject *newlist;
- Py_ssize_t len, i, j=0;
-
- len = PyList_GET_SIZE(fut->fut_callbacks);
- if (len == 0) {
- return PyLong_FromSsize_t(0);
- }
-
- newlist = PyList_New(len);
- if (newlist == NULL) {
- return NULL;
- }
-
- for (i = 0; i < len; i++) {
- int ret;
- PyObject *item = PyList_GET_ITEM(fut->fut_callbacks, i);
-
- if ((ret = PyObject_RichCompareBool(arg, item, Py_EQ)) < 0) {
- goto fail;
- }
- if (ret == 0) {
- Py_INCREF(item);
- PyList_SET_ITEM(newlist, j, item);
- j++;
- }
- }
-
- if (PyList_SetSlice(newlist, j, len, NULL) < 0) {
- goto fail;
- }
- if (PyList_SetSlice(fut->fut_callbacks, 0, len, newlist) < 0) {
- goto fail;
- }
- Py_DECREF(newlist);
- return PyLong_FromSsize_t(len - j);
-
-fail:
- Py_DECREF(newlist);
- return NULL;
-}
-
-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;
- }
- fut->fut_state = STATE_CANCELLED;
-
- if (_schedule_callbacks(fut) == -1) {
- return NULL;
- }
-
- Py_RETURN_TRUE;
-}
-
-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;
- }
- else {
- Py_RETURN_FALSE;
- }
-}
-
-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;
- }
- else {
- Py_RETURN_TRUE;
- }
-}
-
-static PyObject *
-FutureObj_get_blocking(FutureObj *fut)
-{
- if (fut->fut_blocking) {
- Py_RETURN_TRUE;
- }
- else {
- Py_RETURN_FALSE;
- }
-}
-
-static int
-FutureObj_set_blocking(FutureObj *fut, PyObject *val)
-{
- int is_true = PyObject_IsTrue(val);
- if (is_true < 0) {
- return -1;
- }
- fut->fut_blocking = is_true;
- return 0;
-}
-
-static PyObject *
-FutureObj_get_log_traceback(FutureObj *fut)
-{
- if (fut->fut_log_tb) {
- Py_RETURN_TRUE;
- }
- else {
- Py_RETURN_FALSE;
- }
-}
-
-static PyObject *
-FutureObj_get_loop(FutureObj *fut)
-{
- if (fut->fut_loop == NULL) {
- Py_RETURN_NONE;
- }
- Py_INCREF(fut->fut_loop);
- return fut->fut_loop;
-}
-
-static PyObject *
-FutureObj_get_callbacks(FutureObj *fut)
-{
- if (fut->fut_callbacks == NULL) {
- Py_RETURN_NONE;
- }
- Py_INCREF(fut->fut_callbacks);
- return fut->fut_callbacks;
-}
-
-static PyObject *
-FutureObj_get_result(FutureObj *fut)
-{
- if (fut->fut_result == NULL) {
- Py_RETURN_NONE;
- }
- Py_INCREF(fut->fut_result);
- return fut->fut_result;
-}
-
-static PyObject *
-FutureObj_get_exception(FutureObj *fut)
-{
- if (fut->fut_exception == NULL) {
- Py_RETURN_NONE;
- }
- 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;
- }
- Py_INCREF(fut->fut_source_tb);
- return fut->fut_source_tb;
-}
-
-static PyObject *
-FutureObj_get_state(FutureObj *fut)
-{
- _Py_IDENTIFIER(PENDING);
- _Py_IDENTIFIER(CANCELLED);
- _Py_IDENTIFIER(FINISHED);
- PyObject *ret = NULL;
-
- switch (fut->fut_state) {
- case STATE_PENDING:
- ret = _PyUnicode_FromId(&PyId_PENDING);
- break;
- case STATE_CANCELLED:
- ret = _PyUnicode_FromId(&PyId_CANCELLED);
- break;
- case STATE_FINISHED:
- ret = _PyUnicode_FromId(&PyId_FINISHED);
- break;
- default:
- assert (0);
- }
- Py_INCREF(ret);
- return ret;
-}
-
-static PyObject*
-FutureObj__repr_info(FutureObj *fut)
-{
- if (asyncio_repr_info_func == NULL) {
- return PyList_New(0);
- }
- return PyObject_CallFunctionObjArgs(asyncio_repr_info_func, fut, NULL);
-}
-
-static PyObject *
-FutureObj_repr(FutureObj *fut)
-{
- _Py_IDENTIFIER(_repr_info);
-
- PyObject *_repr_info = _PyUnicode_FromId(&PyId__repr_info); // borrowed
- if (_repr_info == NULL) {
- return NULL;
- }
-
- PyObject *rinfo = PyObject_CallMethodObjArgs((PyObject*)fut, _repr_info,
- NULL);
- if (rinfo == NULL) {
- return NULL;
- }
-
- PyObject *sp = PyUnicode_FromString(" ");
- if (sp == NULL) {
- Py_DECREF(rinfo);
- return NULL;
- }
-
- PyObject *rinfo_s = PyUnicode_Join(sp, rinfo);
- Py_DECREF(sp);
- Py_DECREF(rinfo);
- if (rinfo_s == NULL) {
- return NULL;
- }
-
- PyObject *rstr = NULL;
- PyObject *type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut),
- "__name__");
- if (type_name != NULL) {
- rstr = PyUnicode_FromFormat("<%S %S>", type_name, rinfo_s);
- Py_DECREF(type_name);
- }
- 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;
- }
- 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;
-
- context = PyDict_New();
- if (context == NULL) {
- goto finally;
- }
-
- type_name = PyObject_GetAttrString((PyObject*)Py_TYPE(fut), "__name__");
- if (type_name == NULL) {
- goto finally;
- }
-
- message = PyUnicode_FromFormat(
- "%S exception was never retrieved", type_name);
- if (message == NULL) {
- goto finally;
- }
-
- if (_PyDict_SetItemId(context, &PyId_message, message) < 0 ||
- _PyDict_SetItemId(context, &PyId_exception, fut->fut_exception) < 0 ||
- _PyDict_SetItemId(context, &PyId_future, (PyObject*)fut) < 0) {
- goto finally;
- }
- if (fut->fut_source_tb != NULL) {
- if (_PyDict_SetItemId(context, &PyId_source_traceback,
- fut->fut_source_tb) < 0) {
- goto finally;
- }
- }
-
- func = _PyObject_GetAttrId(fut->fut_loop, &PyId_call_exception_handler);
- if (func != NULL) {
- res = _PyObject_CallArg1(func, context);
- if (res == NULL) {
- PyErr_WriteUnraisable(func);
- }
- }
-
-finally:
- Py_CLEAR(context);
- Py_CLEAR(type_name);
- Py_CLEAR(message);
- Py_CLEAR(func);
- Py_CLEAR(res);
-
- /* Restore the saved exception. */
- PyErr_Restore(error_type, error_value, error_traceback);
-}
-
-
-static PyAsyncMethods FutureType_as_async = {
- (unaryfunc)new_future_iter, /* am_await */
- 0, /* am_aiter */
- 0 /* am_anext */
-};
-
-static PyMethodDef FutureType_methods[] = {
- {"_repr_info", (PyCFunction)FutureObj__repr_info, METH_NOARGS, NULL},
- {"add_done_callback",
- (PyCFunction)FutureObj_add_done_callback,
- METH_O, pydoc_add_done_callback},
- {"remove_done_callback",
- (PyCFunction)FutureObj_remove_done_callback,
- METH_O, pydoc_remove_done_callback},
- {"set_result",
- (PyCFunction)FutureObj_set_result, METH_O, pydoc_set_result},
- {"set_exception",
- (PyCFunction)FutureObj_set_exception, METH_O, pydoc_set_exception},
- {"cancel", (PyCFunction)FutureObj_cancel, METH_NOARGS, pydoc_cancel},
- {"cancelled",
- (PyCFunction)FutureObj_cancelled, METH_NOARGS, pydoc_cancelled},
- {"done", (PyCFunction)FutureObj_done, METH_NOARGS, pydoc_done},
- {"result", (PyCFunction)FutureObj_result, METH_NOARGS, pydoc_result},
- {"exception",
- (PyCFunction)FutureObj_exception, METH_NOARGS, pydoc_exception},
- {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},
- {"_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,
- .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)
-{
- FutureObj *fut = (FutureObj *)self;
-
- if (Py_TYPE(fut) == &FutureType) {
- /* When fut is subclass of Future, finalizer is called from
- * subtype_dealloc.
- */
- if (PyObject_CallFinalizerFromDealloc(self) < 0) {
- // resurrected.
- return;
- }
- }
-
- if (fut->fut_weakreflist != NULL) {
- PyObject_ClearWeakRefs(self);
- }
-
- FutureObj_clear(fut);
- Py_TYPE(fut)->tp_free(fut);
-}
-
-
-/*********************** Future Iterator **************************/
-
-typedef struct {
- PyObject_HEAD
- FutureObj *future;
-} futureiterobject;
-
-static void
-FutureIter_dealloc(futureiterobject *it)
-{
- _PyObject_GC_UNTRACK(it);
- Py_XDECREF(it->future);
- PyObject_GC_Del(it);
-}
-
-static PyObject *
-FutureIter_iternext(futureiterobject *it)
-{
- PyObject *res;
- FutureObj *fut = it->future;
-
- if (fut == NULL) {
- return NULL;
- }
-
- if (fut->fut_state == STATE_PENDING) {
- if (!fut->fut_blocking) {
- fut->fut_blocking = 1;
- Py_INCREF(fut);
- return (PyObject *)fut;
- }
- PyErr_Format(PyExc_AssertionError,
- "yield from wasn't used with future");
- return NULL;
- }
-
- res = FutureObj_result(fut, NULL);
- if (res != NULL) {
- // normal result
- PyErr_SetObject(PyExc_StopIteration, res);
- Py_DECREF(res);
- }
-
- it->future = NULL;
- Py_DECREF(fut);
- return NULL;
-}
-
-static PyObject *
-FutureIter_send(futureiterobject *self, PyObject *arg)
-{
- if (arg != Py_None) {
- PyErr_Format(PyExc_TypeError,
- "can't send non-None value to a FutureIter");
- return NULL;
- }
- 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;
-
- if (val == Py_None) {
- val = NULL;
- }
- if (tb == Py_None) {
- tb = NULL;
- }
-
- Py_CLEAR(self->future);
-
- if (tb != NULL) {
- PyErr_Restore(type, val, tb);
- }
- else if (val != NULL) {
- PyErr_SetObject(type, val);
- }
- else {
- if (PyExceptionClass_Check(type)) {
- val = PyObject_CallObject(type, NULL);
- }
- else {
- val = type;
- assert (PyExceptionInstance_Check(val));
- type = (PyObject*)Py_TYPE(val);
- assert (PyExceptionClass_Check(type));
- }
- PyErr_SetObject(type, val);
- }
- return FutureIter_iternext(self);
-}
-
-static PyObject *
-FutureIter_close(futureiterobject *self, PyObject *arg)
-{
- Py_CLEAR(self->future);
- Py_RETURN_NONE;
-}
-
-static int
-FutureIter_traverse(futureiterobject *it, visitproc visit, void *arg)
-{
- Py_VISIT(it->future);
- return 0;
-}
-
-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)
-{
- futureiterobject *it;
-
- if (!PyObject_TypeCheck(fut, &FutureType)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- it = PyObject_GC_New(futureiterobject, &FutureIterType);
- if (it == NULL) {
- return NULL;
- }
- 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,
- &get_event_loop,
- &repr_info_func,
- &invalidStateError,
- &cancelledError)) {
- return NULL;
- }
-
- Py_INCREF(extract_stack);
- Py_XSETREF(traceback_extract_stack, extract_stack);
-
- Py_INCREF(get_event_loop);
- Py_XSETREF(asyncio_get_event_loop, get_event_loop);
-
- Py_INCREF(repr_info_func);
- Py_XSETREF(asyncio_repr_info_func, repr_info_func);
-
- Py_INCREF(invalidStateError);
- Py_XSETREF(asyncio_InvalidStateError, invalidStateError);
-
- Py_INCREF(cancelledError);
- Py_XSETREF(asyncio_CancelledError, cancelledError);
-
- _futuremod_ready = 1;
-
- Py_RETURN_NONE;
-}
-
-
-static struct PyMethodDef futuresmod_methods[] = {
- {"_init_module", _init_module, METH_VARARGS, NULL},
- {NULL, NULL}
-};
-
-
-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;
- }
- if (PyType_Ready(&FutureIterType) < 0) {
- return NULL;
- }
-
- PyObject *m = PyModule_Create(&_futuresmodule);
- if (m == NULL) {
- return NULL;
- }
-
- Py_INCREF(&FutureType);
- if (PyModule_AddObject(m, "Future", (PyObject *)&FutureType) < 0) {
- Py_DECREF(&FutureType);
- return NULL;
- }
-
- return m;
-}
diff -r 86a1905ea28d PCbuild/pythoncore.vcxproj
--- a/PCbuild/pythoncore.vcxproj Wed Oct 12 20:16:05 2016 +0200
+++ b/PCbuild/pythoncore.vcxproj Thu Oct 13 21:10:34 2016 +0900
@@ -213,6 +213,7 @@
+
@@ -221,7 +222,6 @@
-
diff -r 86a1905ea28d PCbuild/pythoncore.vcxproj.filters
--- a/PCbuild/pythoncore.vcxproj.filters Wed Oct 12 20:16:05 2016 +0200
+++ b/PCbuild/pythoncore.vcxproj.filters Thu Oct 13 21:10:34 2016 +0900
@@ -446,6 +446,9 @@
+
+ Modules
+
Modules
@@ -470,9 +473,6 @@
Modules
-
- Modules
-
Modules
diff -r 86a1905ea28d setup.py
--- a/setup.py Wed Oct 12 20:16:05 2016 +0200
+++ b/setup.py Thu Oct 13 21:10:34 2016 +0900
@@ -656,8 +656,8 @@ class PyBuildExt(build_ext):
depends=['unicodedata_db.h', 'unicodename_db.h']) )
# _opcode module
exts.append( Extension('_opcode', ['_opcode.c']) )
- # Fast asyncio Future implementation
- exts.append( Extension("_futures", ["_futuresmodule.c"]) )
+ # asyncio speedups
+ exts.append( Extension("_asyncio", ["_asynciomodule.c"]) )
# Modules with some UNIX dependencies -- on by default:
# (If you have a really backward UNIX, select and socket may not be