diff -r 8ee02ec9b634 Lib/asyncio/futures.py --- a/Lib/asyncio/futures.py Sat Jan 09 23:56:40 2016 -0800 +++ b/Lib/asyncio/futures.py Mon Jan 11 12:19:13 2016 -0500 @@ -110,50 +110,7 @@ self.loop.call_exception_handler({'message': msg}) -class Future: - """This class is *almost* compatible with concurrent.futures.Future. - - Differences: - - - result() and exception() do not take a timeout argument and - raise an exception when the future isn't done yet. - - - Callbacks registered with add_done_callback() are always called - via the event loop's call_soon_threadsafe(). - - - This class is not compatible with the wait() and as_completed() - methods in the concurrent.futures package. - - (In Python 3.4 or later we may be able to unify the implementations.) - """ - - # Class variables serving as defaults for instance variables. - _state = _PENDING - _result = None - _exception = None - _loop = None - _source_traceback = None - - _blocking = False # proper use of future (yield vs yield from) - - _log_traceback = False # Used for Python 3.4 and later - _tb_logger = None # Used for Python 3.3 only - - def __init__(self, *, loop=None): - """Initialize the future. - - The optional event_loop argument allows to explicitly set the event - loop object used by the future. If it's not provided, the future uses - the default event loop. - """ - if loop is None: - self._loop = events.get_event_loop() - else: - self._loop = loop - self._callbacks = [] - if self._loop.get_debug(): - self._source_traceback = traceback.extract_stack(sys._getframe(1)) - +class _BaseFuture: def __format_callbacks(self): cb = self._callbacks size = len(cb) @@ -214,6 +171,51 @@ context['source_traceback'] = self._source_traceback self._loop.call_exception_handler(context) + +class Future(_BaseFuture): + """This class is *almost* compatible with concurrent.futures.Future. + + Differences: + + - result() and exception() do not take a timeout argument and + raise an exception when the future isn't done yet. + + - Callbacks registered with add_done_callback() are always called + via the event loop's call_soon_threadsafe(). + + - This class is not compatible with the wait() and as_completed() + methods in the concurrent.futures package. + + (In Python 3.4 or later we may be able to unify the implementations.) + """ + + # Class variables serving as defaults for instance variables. + _state = _PENDING + _result = None + _exception = None + _loop = None + _source_traceback = None + + _blocking = False # proper use of future (yield vs yield from) + + _log_traceback = False # Used for Python 3.4 and later + _tb_logger = None # Used for Python 3.3 only + + def __init__(self, *, loop=None): + """Initialize the future. + + The optional event_loop argument allows to explicitly set the event + loop object used by the future. If it's not provided, the future uses + the default event loop. + """ + if loop is None: + self._loop = events.get_event_loop() + else: + self._loop = loop + self._callbacks = [] + if self._loop.get_debug(): + self._source_traceback = traceback.extract_stack(sys._getframe(1)) + def cancel(self): """Cancel the future and schedule callbacks. @@ -405,6 +407,23 @@ dest.set_result(result) +try: + import _futures +except ImportError: + pass +else: + # class Future(_futures.Future, _BaseFuture): + # pass + + Future = _futures.Future + + _futures._init_module( + traceback.extract_stack, + events.get_event_loop, + InvalidStateError, + CancelledError) + + def _chain_future(source, destination): """Chain two futures so that when one completes, so does the other. diff -r 8ee02ec9b634 Lib/asyncio/tasks.py --- a/Lib/asyncio/tasks.py Sat Jan 09 23:56:40 2016 -0800 +++ b/Lib/asyncio/tasks.py Mon Jan 11 12:19:13 2016 -0500 @@ -80,7 +80,7 @@ # On Python 3.3 or older, objects with a destructor that are part of a # reference cycle are never destroyed. That's not the case any more on # Python 3.4 thanks to the PEP 442. - if compat.PY34: + if compat.PY34 and 0: def __del__(self): if self._state == futures._PENDING and self._log_destroy_pending: context = { @@ -90,7 +90,7 @@ if self._source_traceback: context['source_traceback'] = self._source_traceback self._loop.call_exception_handler(context) - futures.Future.__del__(self) + super().__del__() def _repr_info(self): info = super()._repr_info() diff -r 8ee02ec9b634 Modules/Setup.dist --- a/Modules/Setup.dist Sat Jan 09 23:56:40 2016 -0800 +++ b/Modules/Setup.dist Mon Jan 11 12:19:13 2016 -0500 @@ -180,6 +180,7 @@ #_datetime _datetimemodule.c # datetime accelerator #_bisect _bisectmodule.c # Bisection algorithms #_heapq _heapqmodule.c # Heap queue algorithm +#_futures _futuresmodule.c # Fast asyncio Future #unicodedata unicodedata.c # static Unicode character database diff -r 8ee02ec9b634 Modules/_futuresmodule.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Modules/_futuresmodule.c Mon Jan 11 12:19:13 2016 -0500 @@ -0,0 +1,742 @@ +#include "Python.h" +#include "structmember.h" + +/* +TODO + +1. expose read-only '_state' prop +2. add _init_futuresmod +3. This isn't a Future class; it's a BaseFuture +*/ + + +/* State of the _futures module */ +typedef struct { + int ready; + + PyObject *traceback_extract_stack; + PyObject *asyncio_get_event_loop; + PyObject *asyncio_InvalidStateError; + PyObject *asyncio_CancelledError; +} FuturesModState; + + +/* Forward declaration of the _futures module definition. */ +static struct PyModuleDef _futuresmodule; + + +/* Given a module object, get its per-module state. */ +static FuturesModState * +_FuturesMod_GetState(PyObject *module) +{ + return (FuturesModState *) PyModule_GetState(module); +} + + +/* Find the module instance imported in the currently running sub-interpreter + and get the module's state. */ +static FuturesModState * +_FuturesMod_GetGlobalState(void) +{ + PyObject *m = PyState_FindModule(&_futuresmodule); + if (m == NULL) + return NULL; + return _FuturesMod_GetState(m); +} + + +/* Get the global module state and make sure it's initialized + and ready to be used. */ +static FuturesModState * +_FuturesMod_EnsureState(void) +{ + FuturesModState *st = _FuturesMod_GetGlobalState(); + + if (st == NULL) + goto error; + + if (!st->ready) + goto error; + + return st; + + error: + PyErr_SetString(PyExc_RuntimeError, + "_futures module wasn't properly initialized"); + return NULL; +} + + +/* Clear the given _futures module state. */ +static void +_FuturesMod_ClearState(FuturesModState *st) +{ + st->ready = 0; + Py_CLEAR(st->traceback_extract_stack); + Py_CLEAR(st->asyncio_get_event_loop); + Py_CLEAR(st->asyncio_InvalidStateError); + Py_CLEAR(st->asyncio_CancelledError); +} + + +/* Initialize the given pickle module state. */ +static int +_FuturesMod_InitState(PyObject *module) +{ + FuturesModState *st; + + st = _FuturesMod_GetState(module); + if (st == NULL) + return -1; + + st->ready = 0; + st->traceback_extract_stack = NULL; + st->asyncio_get_event_loop = NULL; + st->asyncio_InvalidStateError = NULL; + st->asyncio_CancelledError = NULL; + return 0; +} + + +typedef enum { + STATE_PENDING, + STATE_CANCELLED, + STATE_FINISHED +} fut_state; + + +typedef struct { + PyObject_HEAD + FuturesModState *fut_modstate; + 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; + _Py_IDENTIFIER(call_soon); + + 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 PyObject * +FutureObj_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + FuturesModState *st; + FutureObj *fut; + + st = _FuturesMod_EnsureState(); + if (st == NULL) + return NULL; + + fut = PyObject_GC_New(FutureObj, type); + if (fut == NULL) + return NULL; + + fut->dict = NULL; + + fut->fut_modstate = st; + fut->fut_state = STATE_PENDING; + fut->fut_log_tb = 0; + fut->fut_blocking = 0; + fut->fut_exception = NULL; + fut->fut_result = NULL; + fut->fut_loop = NULL; + fut->fut_callbacks = NULL; + fut->fut_weakreflist = NULL; + fut->fut_source_tb = NULL; + + PyObject_GC_Track(fut); + return (PyObject *)fut; +} + +static int +FutureObj_init(FutureObj *fut, PyObject *args, PyObject *kwds) +{ + static char *kwlist[] = {"loop", NULL}; + PyObject *loop = NULL; + PyObject *res = NULL; + _Py_IDENTIFIER(get_debug); + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &loop)) + return -1; + if (loop == NULL || loop == Py_None) { + Py_CLEAR(loop); + loop = PyObject_CallObject(fut->fut_modstate->asyncio_get_event_loop, + NULL); + if (loop == NULL) + return -1; + } else { + Py_INCREF(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); + PyObject *arg_tuple = PyTuple_New(0); + fut->fut_source_tb = PyObject_Call( + fut->fut_modstate->traceback_extract_stack, + arg_tuple, NULL); + Py_CLEAR(arg_tuple); + 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 void +FutureObj_dealloc(FutureObj *fut) +{ + PyObject_GC_UnTrack(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); + + if (fut->fut_weakreflist != NULL) + PyObject_ClearWeakRefs((PyObject *)fut); + + fut->fut_modstate = NULL; +} + +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->dict); + Py_VISIT(fut->fut_source_tb); + return 0; +} + +static PyObject * +FutureObj_result(FutureObj *fut, PyObject *arg) +{ + if (fut->fut_state == STATE_CANCELLED) { + PyErr_SetString(fut->fut_modstate->asyncio_CancelledError, ""); + return NULL; + } + + if (fut->fut_state != STATE_FINISHED) { + PyErr_SetString(fut->fut_modstate->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; +} + +static PyObject * +FutureObj_exception(FutureObj *fut, PyObject *arg) +{ + FuturesModState *st; + + st = _FuturesMod_EnsureState(); + if (st == NULL) + return NULL; + + if (fut->fut_state == STATE_CANCELLED) { + PyErr_SetString(fut->fut_modstate->asyncio_CancelledError, ""); + return NULL; + } + + if (fut->fut_state != STATE_FINISHED) { + PyErr_SetString(fut->fut_modstate->asyncio_InvalidStateError, + "Result is not ready."); + return NULL; + } + + if (fut->fut_exception != NULL) { + Py_INCREF(fut->fut_exception); + return fut->fut_exception; + } + + Py_RETURN_NONE; +} + +static PyObject * +FutureObj_set_result(FutureObj *fut, PyObject *res) +{ + FuturesModState *st; + + st = _FuturesMod_EnsureState(); + if (st == NULL) + return NULL; + + if (fut->fut_state != STATE_PENDING) { + PyErr_SetString(fut->fut_modstate->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; +} + +static PyObject * +FutureObj_set_exception(FutureObj *fut, PyObject *exc) +{ + FuturesModState *st; + + st = _FuturesMod_EnsureState(); + if (st == NULL) + return NULL; + + if (fut->fut_state != STATE_PENDING) { + PyErr_SetString(fut->fut_modstate->asyncio_InvalidStateError, + "invalid state"); + return NULL; + } + + PyObject *exc_val = NULL; + if (PyExceptionClass_Check(exc)) { + exc_val = PyObject_CallObject(exc, NULL); + if (exc_val == NULL) + return NULL; + } + if (exc_val == NULL) { + 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; + } + + 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; +} + +static PyObject * +FutureObj_await(FutureObj *fut) +{ + Py_INCREF(fut); + return (PyObject *)fut; +} + +static PyObject * +FutureObj_iternext(FutureObj *fut) +{ + PyObject *res; + + 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) + return NULL; + + // normal result + PyErr_SetObject(PyExc_StopIteration, res); + Py_DECREF(res); + + return NULL; +} + +static PyObject * +FutureObj_add_done_callback(FutureObj *fut, PyObject *arg) +{ + PyObject *handle; + _Py_IDENTIFIER(call_soon); + + if (fut->fut_state != STATE_PENDING) { + 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; +} + +static PyObject * +FutureObj_remove_done_callback(FutureObj *fut, PyObject *arg) +{ + /* XXX */ + Py_ssize_t len; + len = PyList_GET_SIZE(fut->fut_callbacks); + + if (len) { + if (PyList_SetSlice(fut->fut_callbacks, 0, len, NULL) < 0) { + return NULL; + } + } + + Py_RETURN_NONE; +} + +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; +} + +static PyObject * +FutureObj_cancelled(FutureObj *fut, PyObject *arg) +{ + if (fut->fut_state == STATE_CANCELLED) { + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } +} + +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) +{ + if (PyObject_IsTrue(val)) { + fut->fut_blocking = 1; + } else { + fut->fut_blocking = 0; + } + return 0; +} + +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_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) +{ + if (fut->fut_state == STATE_PENDING) + return PyUnicode_FromString("PENDING"); + + if (fut->fut_state == STATE_CANCELLED) + return PyUnicode_FromString("CANCELLED"); + + assert(fut->fut_state == STATE_FINISHED); + return PyUnicode_FromString("FINISHED"); +} + +static PyAsyncMethods FutureType_as_async = { + (unaryfunc)FutureObj_await, /* am_await */ + 0, /* am_aiter */ + 0 /* am_anext */ +}; + +static PyMethodDef FutureType_methods[] = { + {"add_done_callback", (PyCFunction)FutureObj_add_done_callback, + METH_O, NULL}, + {"remove_done_callback", (PyCFunction)FutureObj_remove_done_callback, + METH_O, NULL}, + {"set_result", (PyCFunction)FutureObj_set_result, METH_O, NULL}, + {"set_exception", (PyCFunction)FutureObj_set_exception, METH_O, NULL}, + {"cancel", (PyCFunction)FutureObj_cancel, METH_NOARGS, NULL}, + {"cancelled", (PyCFunction)FutureObj_cancelled, METH_NOARGS, NULL}, + {"done", (PyCFunction)FutureObj_done, METH_NOARGS, NULL}, + {"result", (PyCFunction)FutureObj_result, METH_NOARGS, NULL}, + {"exception", (PyCFunction)FutureObj_exception, METH_NOARGS, NULL}, + {NULL, NULL} /* Sentinel */ +}; + +static PyGetSetDef FutureType_getsetlist[] = { + {"_blocking", (getter)FutureObj_get_blocking, + (setter)FutureObj_set_blocking, NULL}, + {"_loop", (getter)FutureObj_get_loop, NULL, NULL}, + {"_exception", (getter)FutureObj_get_exception, NULL, NULL}, + {"_source_traceback", (getter)FutureObj_get_source_traceback, NULL, NULL}, + {"_state", (getter)FutureObj_get_state, NULL, NULL}, + {NULL} /* Sentinel */ +}; + +static PyTypeObject FutureType = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "asyncio.Future", + sizeof(FutureObj), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)FutureObj_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + &FutureType_as_async, /* 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 + | Py_TPFLAGS_BASETYPE, /* tp_flags */ + "Fast asyncio.Future implementation.", /* tp_doc */ + (traverseproc)FutureObj_traverse, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + offsetof(FutureObj, fut_weakreflist), /* tp_weaklistoffset */ + PyObject_SelfIter, /* tp_iter */ + (iternextfunc)FutureObj_iternext, /* tp_iternext */ + FutureType_methods, /* tp_methods */ + 0, /* tp_members */ + FutureType_getsetlist, /* tp_getset */ + 0, + 0, + 0, + 0, + offsetof(FutureObj, dict), /* tp_dictoffset */ + (initproc)FutureObj_init, /* tp_init */ + 0, /* tp_alloc */ + FutureObj_new, /* tp_new */ + PyObject_GC_Del, /* tp_free */ +}; + + +PyDoc_STRVAR(module_doc, "Fast asyncio.Future implementation.\n"); + + +PyObject * +_init_module(PyObject *self, PyObject *args) +{ + FuturesModState *st; + + PyObject *traceback_extract_stack; + PyObject *asyncio_get_event_loop; + PyObject *asyncio_InvalidStateError; + PyObject *asyncio_CancelledError; + + if (!PyArg_UnpackTuple(args, "_init_module", 4, 4, + &traceback_extract_stack, + &asyncio_get_event_loop, + &asyncio_InvalidStateError, + &asyncio_CancelledError)) + return NULL; + + st = _FuturesMod_GetGlobalState(); + assert(st != NULL); + + Py_INCREF(traceback_extract_stack); + st->traceback_extract_stack = traceback_extract_stack; + + Py_INCREF(asyncio_get_event_loop); + st->asyncio_get_event_loop = asyncio_get_event_loop; + + Py_INCREF(asyncio_InvalidStateError); + st->asyncio_InvalidStateError = asyncio_InvalidStateError; + + Py_INCREF(asyncio_CancelledError); + st->asyncio_CancelledError = asyncio_CancelledError; + + st->ready = 1; + + Py_RETURN_NONE; +} + + +static void +futuresmod_free(PyObject *m) +{ + _FuturesMod_ClearState(_FuturesMod_GetState(m)); +} + + +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 */ + sizeof(FuturesModState), /* m_size */ + futuresmod_methods, /* m_methods */ + NULL, /* m_slots */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + (freefunc)futuresmod_free /* m_free */ +}; + + +PyMODINIT_FUNC +PyInit__futures(void) +{ + PyObject *m; + + m = PyState_FindModule(&_futuresmodule); + if (m) { + Py_INCREF(m); + return m; + } + + if (PyType_Ready(&FutureType) < 0) + return NULL; + + 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; + } + + if (_FuturesMod_InitState(m) < 0) + return NULL; + + return m; +} diff -r 8ee02ec9b634 PCbuild/pythoncore.vcxproj --- a/PCbuild/pythoncore.vcxproj Sat Jan 09 23:56:40 2016 -0800 +++ b/PCbuild/pythoncore.vcxproj Mon Jan 11 12:19:13 2016 -0500 @@ -217,6 +217,7 @@ + @@ -417,4 +418,4 @@ - \ No newline at end of file + diff -r 8ee02ec9b634 PCbuild/pythoncore.vcxproj.filters --- a/PCbuild/pythoncore.vcxproj.filters Sat Jan 09 23:56:40 2016 -0800 +++ b/PCbuild/pythoncore.vcxproj.filters Mon Jan 11 12:19:13 2016 -0500 @@ -455,6 +455,9 @@ Modules + + Modules + Modules @@ -980,4 +983,4 @@ Resource Files - \ No newline at end of file + diff -r 8ee02ec9b634 setup.py --- a/setup.py Sat Jan 09 23:56:40 2016 -0800 +++ b/setup.py Mon Jan 11 12:19:13 2016 -0500 @@ -628,6 +628,8 @@ exts.append( Extension('unicodedata', ['unicodedata.c']) ) # _opcode module exts.append( Extension('_opcode', ['_opcode.c']) ) + # Fast asyncio Future implementation + exts.append( Extension("_futures", ["_futuresmodule.c"]) ) # Modules with some UNIX dependencies -- on by default: # (If you have a really backward UNIX, select and socket may not be