[Python-checkins] cpython (merge 3.6 -> default): Issue #28428: Rename _futures module to _asyncio. (merge from 3.6)

inada.naoki python-checkins at python.org
Sat Oct 15 02:41:17 EDT 2016


https://hg.python.org/cpython/rev/c2f3b7c56dff
changeset:   104505:c2f3b7c56dff
parent:      104502:98456ab88ab0
parent:      104504:9d06fdedae2b
user:        INADA Naoki <songofacandy at gmail.com>
date:        Sat Oct 15 15:41:05 2016 +0900
summary:
  Issue #28428: Rename _futures module to _asyncio. (merge from 3.6)

It will have more speedup functions or classes other than asyncio.Future.

files:
  Lib/asyncio/futures.py             |     6 +-
  Modules/Setup.dist                 |     2 +-
  Modules/_asynciomodule.c           |  1034 ++++++++++++++++
  Modules/_futuresmodule.c           |  1034 ----------------
  PCbuild/pythoncore.vcxproj         |     2 +-
  PCbuild/pythoncore.vcxproj.filters |     6 +-
  setup.py                           |     4 +-
  7 files changed, 1044 insertions(+), 1044 deletions(-)


diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py
--- a/Lib/asyncio/futures.py
+++ b/Lib/asyncio/futures.py
@@ -432,18 +432,18 @@
 
 
 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 --git a/Modules/Setup.dist b/Modules/Setup.dist
--- a/Modules/Setup.dist
+++ b/Modules/Setup.dist
@@ -181,7 +181,7 @@
 #_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 --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c
new file mode 100644
--- /dev/null
+++ b/Modules/_asynciomodule.c
@@ -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 --git a/Modules/_futuresmodule.c b/Modules/_futuresmodule.c
deleted file mode 100644
--- a/Modules/_futuresmodule.c
+++ /dev/null
@@ -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 --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj
--- a/PCbuild/pythoncore.vcxproj
+++ b/PCbuild/pythoncore.vcxproj
@@ -213,6 +213,7 @@
     <ClInclude Include="..\Python\wordcode_helpers.h" />
   </ItemGroup>
   <ItemGroup>
+    <ClCompile Include="..\Modules\_asynciomodule.c" />
     <ClCompile Include="..\Modules\_bisectmodule.c" />
     <ClCompile Include="..\Modules\_blake2\blake2module.c" />
     <ClCompile Include="..\Modules\_blake2\blake2b_impl.c" />
@@ -221,7 +222,6 @@
     <ClCompile Include="..\Modules\_collectionsmodule.c" />
     <ClCompile Include="..\Modules\_csv.c" />
     <ClCompile Include="..\Modules\_functoolsmodule.c" />
-    <ClCompile Include="..\Modules\_futuresmodule.c" />
     <ClCompile Include="..\Modules\_heapqmodule.c" />
     <ClCompile Include="..\Modules\_json.c" />
     <ClCompile Include="..\Modules\_localemodule.c" />
diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters
--- a/PCbuild/pythoncore.vcxproj.filters
+++ b/PCbuild/pythoncore.vcxproj.filters
@@ -446,6 +446,9 @@
     </ClInclude>
   </ItemGroup>
   <ItemGroup>
+    <ClCompile Include="..\Modules\_asynciomodule.c">
+      <Filter>Modules</Filter>
+    </ClCompile>
     <ClCompile Include="..\Modules\_bisectmodule.c">
       <Filter>Modules</Filter>
     </ClCompile>
@@ -470,9 +473,6 @@
     <ClCompile Include="..\Modules\_functoolsmodule.c">
       <Filter>Modules</Filter>
     </ClCompile>
-    <ClCompile Include="..\Modules\_futuresmodule.c">
-      <Filter>Modules</Filter>
-    </ClCompile>
     <ClCompile Include="..\Modules\_heapqmodule.c">
       <Filter>Modules</Filter>
     </ClCompile>
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -657,8 +657,8 @@
                                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

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list