Issue #28544: Implement asyncio.Task in C.

This implementation provides additional 10-20% speed boost for
asyncio programs.

The patch also fixes _asynciomodule.c to use Arguments Clinic, and
makes '_schedule_callbacks' an overridable method (as it was in 3.5).
diff --git a/Lib/asyncio/base_events.py b/Lib/asyncio/base_events.py
index 5880061..cc9994d 100644
--- a/Lib/asyncio/base_events.py
+++ b/Lib/asyncio/base_events.py
@@ -57,7 +57,7 @@
 
 def _format_handle(handle):
     cb = handle._callback
-    if inspect.ismethod(cb) and isinstance(cb.__self__, tasks.Task):
+    if isinstance(getattr(cb, '__self__', None), tasks.Task):
         # format the task
         return repr(cb.__self__)
     else:
diff --git a/Lib/asyncio/base_futures.py b/Lib/asyncio/base_futures.py
new file mode 100644
index 0000000..64f7845
--- /dev/null
+++ b/Lib/asyncio/base_futures.py
@@ -0,0 +1,70 @@
+__all__ = []
+
+import concurrent.futures._base
+import reprlib
+
+from . import events
+
+Error = concurrent.futures._base.Error
+CancelledError = concurrent.futures.CancelledError
+TimeoutError = concurrent.futures.TimeoutError
+
+
+class InvalidStateError(Error):
+    """The operation is not allowed in this state."""
+
+
+# States for Future.
+_PENDING = 'PENDING'
+_CANCELLED = 'CANCELLED'
+_FINISHED = 'FINISHED'
+
+
+def isfuture(obj):
+    """Check for a Future.
+
+    This returns True when obj is a Future instance or is advertising
+    itself as duck-type compatible by setting _asyncio_future_blocking.
+    See comment in Future for more details.
+    """
+    return getattr(obj, '_asyncio_future_blocking', None) is not None
+
+
+def _format_callbacks(cb):
+    """helper function for Future.__repr__"""
+    size = len(cb)
+    if not size:
+        cb = ''
+
+    def format_cb(callback):
+        return events._format_callback_source(callback, ())
+
+    if size == 1:
+        cb = format_cb(cb[0])
+    elif size == 2:
+        cb = '{}, {}'.format(format_cb(cb[0]), format_cb(cb[1]))
+    elif size > 2:
+        cb = '{}, <{} more>, {}'.format(format_cb(cb[0]),
+                                        size - 2,
+                                        format_cb(cb[-1]))
+    return 'cb=[%s]' % cb
+
+
+def _future_repr_info(future):
+    # (Future) -> str
+    """helper function for Future.__repr__"""
+    info = [future._state.lower()]
+    if future._state == _FINISHED:
+        if future._exception is not None:
+            info.append('exception={!r}'.format(future._exception))
+        else:
+            # use reprlib to limit the length of the output, especially
+            # for very long strings
+            result = reprlib.repr(future._result)
+            info.append('result={}'.format(result))
+    if future._callbacks:
+        info.append(_format_callbacks(future._callbacks))
+    if future._source_traceback:
+        frame = future._source_traceback[-1]
+        info.append('created at %s:%s' % (frame[0], frame[1]))
+    return info
diff --git a/Lib/asyncio/base_tasks.py b/Lib/asyncio/base_tasks.py
new file mode 100644
index 0000000..5f34434
--- /dev/null
+++ b/Lib/asyncio/base_tasks.py
@@ -0,0 +1,76 @@
+import linecache
+import traceback
+
+from . import base_futures
+from . import coroutines
+
+
+def _task_repr_info(task):
+    info = base_futures._future_repr_info(task)
+
+    if task._must_cancel:
+        # replace status
+        info[0] = 'cancelling'
+
+    coro = coroutines._format_coroutine(task._coro)
+    info.insert(1, 'coro=<%s>' % coro)
+
+    if task._fut_waiter is not None:
+        info.insert(2, 'wait_for=%r' % task._fut_waiter)
+    return info
+
+
+def _task_get_stack(task, limit):
+    frames = []
+    try:
+        # 'async def' coroutines
+        f = task._coro.cr_frame
+    except AttributeError:
+        f = task._coro.gi_frame
+    if f is not None:
+        while f is not None:
+            if limit is not None:
+                if limit <= 0:
+                    break
+                limit -= 1
+            frames.append(f)
+            f = f.f_back
+        frames.reverse()
+    elif task._exception is not None:
+        tb = task._exception.__traceback__
+        while tb is not None:
+            if limit is not None:
+                if limit <= 0:
+                    break
+                limit -= 1
+            frames.append(tb.tb_frame)
+            tb = tb.tb_next
+    return frames
+
+
+def _task_print_stack(task, limit, file):
+    extracted_list = []
+    checked = set()
+    for f in task.get_stack(limit=limit):
+        lineno = f.f_lineno
+        co = f.f_code
+        filename = co.co_filename
+        name = co.co_name
+        if filename not in checked:
+            checked.add(filename)
+            linecache.checkcache(filename)
+        line = linecache.getline(filename, lineno, f.f_globals)
+        extracted_list.append((filename, lineno, name, line))
+    exc = task._exception
+    if not extracted_list:
+        print('No stack for %r' % task, file=file)
+    elif exc is not None:
+        print('Traceback for %r (most recent call last):' % task,
+              file=file)
+    else:
+        print('Stack for %r (most recent call last):' % task,
+              file=file)
+    traceback.print_list(extracted_list, file=file)
+    if exc is not None:
+        for line in traceback.format_exception_only(exc.__class__, exc):
+            print(line, file=file, end='')
diff --git a/Lib/asyncio/coroutines.py b/Lib/asyncio/coroutines.py
index 1db7030..167c1e4 100644
--- a/Lib/asyncio/coroutines.py
+++ b/Lib/asyncio/coroutines.py
@@ -11,7 +11,7 @@
 
 from . import compat
 from . import events
-from . import futures
+from . import base_futures
 from .log import logger
 
 
@@ -204,7 +204,7 @@
         @functools.wraps(func)
         def coro(*args, **kw):
             res = func(*args, **kw)
-            if (futures.isfuture(res) or inspect.isgenerator(res) or
+            if (base_futures.isfuture(res) or inspect.isgenerator(res) or
                 isinstance(res, CoroWrapper)):
                 res = yield from res
             elif _AwaitableABC is not None:
diff --git a/Lib/asyncio/futures.py b/Lib/asyncio/futures.py
index b571130..d11d289 100644
--- a/Lib/asyncio/futures.py
+++ b/Lib/asyncio/futures.py
@@ -1,35 +1,32 @@
 """A Future class similar to the one in PEP 3148."""
 
-__all__ = ['CancelledError', 'TimeoutError',
-           'InvalidStateError',
-           'Future', 'wrap_future', 'isfuture'
-           ]
+__all__ = ['CancelledError', 'TimeoutError', 'InvalidStateError',
+           'Future', 'wrap_future', 'isfuture']
 
-import concurrent.futures._base
+import concurrent.futures
 import logging
-import reprlib
 import sys
 import traceback
 
+from . import base_futures
 from . import compat
 from . import events
 
-# States for Future.
-_PENDING = 'PENDING'
-_CANCELLED = 'CANCELLED'
-_FINISHED = 'FINISHED'
 
-Error = concurrent.futures._base.Error
-CancelledError = concurrent.futures.CancelledError
-TimeoutError = concurrent.futures.TimeoutError
+CancelledError = base_futures.CancelledError
+InvalidStateError = base_futures.InvalidStateError
+TimeoutError = base_futures.TimeoutError
+isfuture = base_futures.isfuture
+
+
+_PENDING = base_futures._PENDING
+_CANCELLED = base_futures._CANCELLED
+_FINISHED = base_futures._FINISHED
+
 
 STACK_DEBUG = logging.DEBUG - 1  # heavy-duty debugging
 
 
-class InvalidStateError(Error):
-    """The operation is not allowed in this state."""
-
-
 class _TracebackLogger:
     """Helper to log a traceback upon destruction if not cleared.
 
@@ -110,56 +107,6 @@
             self.loop.call_exception_handler({'message': msg})
 
 
-def isfuture(obj):
-    """Check for a Future.
-
-    This returns True when obj is a Future instance or is advertising
-    itself as duck-type compatible by setting _asyncio_future_blocking.
-    See comment in Future for more details.
-    """
-    return getattr(obj, '_asyncio_future_blocking', None) is not None
-
-
-def _format_callbacks(cb):
-    """helper function for Future.__repr__"""
-    size = len(cb)
-    if not size:
-        cb = ''
-
-    def format_cb(callback):
-        return events._format_callback_source(callback, ())
-
-    if size == 1:
-        cb = format_cb(cb[0])
-    elif size == 2:
-        cb = '{}, {}'.format(format_cb(cb[0]), format_cb(cb[1]))
-    elif size > 2:
-        cb = '{}, <{} more>, {}'.format(format_cb(cb[0]),
-                                        size-2,
-                                        format_cb(cb[-1]))
-    return 'cb=[%s]' % cb
-
-
-def _future_repr_info(future):
-    # (Future) -> str
-    """helper function for Future.__repr__"""
-    info = [future._state.lower()]
-    if future._state == _FINISHED:
-        if future._exception is not None:
-            info.append('exception={!r}'.format(future._exception))
-        else:
-            # use reprlib to limit the length of the output, especially
-            # for very long strings
-            result = reprlib.repr(future._result)
-            info.append('result={}'.format(result))
-    if future._callbacks:
-        info.append(_format_callbacks(future._callbacks))
-    if future._source_traceback:
-        frame = future._source_traceback[-1]
-        info.append('created at %s:%s' % (frame[0], frame[1]))
-    return info
-
-
 class Future:
     """This class is *almost* compatible with concurrent.futures.Future.
 
@@ -212,7 +159,7 @@
         if self._loop.get_debug():
             self._source_traceback = traceback.extract_stack(sys._getframe(1))
 
-    _repr_info = _future_repr_info
+    _repr_info = base_futures._future_repr_info
 
     def __repr__(self):
         return '<%s %s>' % (self.__class__.__name__, ' '.join(self._repr_info()))
@@ -247,10 +194,10 @@
         if self._state != _PENDING:
             return False
         self._state = _CANCELLED
-        self.__schedule_callbacks()
+        self._schedule_callbacks()
         return True
 
-    def __schedule_callbacks(self):
+    def _schedule_callbacks(self):
         """Internal: Ask the event loop to call all callbacks.
 
         The callbacks are scheduled to be called as soon as possible. Also
@@ -352,7 +299,7 @@
             raise InvalidStateError('{}: {!r}'.format(self._state, self))
         self._result = result
         self._state = _FINISHED
-        self.__schedule_callbacks()
+        self._schedule_callbacks()
 
     def set_exception(self, exception):
         """Mark the future done and set an exception.
@@ -369,7 +316,7 @@
                             "and cannot be raised into a Future")
         self._exception = exception
         self._state = _FINISHED
-        self.__schedule_callbacks()
+        self._schedule_callbacks()
         if compat.PY34:
             self._log_traceback = True
         else:
diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py
index 8852aa5..5a43ef2 100644
--- a/Lib/asyncio/tasks.py
+++ b/Lib/asyncio/tasks.py
@@ -9,11 +9,10 @@
 import concurrent.futures
 import functools
 import inspect
-import linecache
-import traceback
 import warnings
 import weakref
 
+from . import base_tasks
 from . import compat
 from . import coroutines
 from . import events
@@ -93,18 +92,7 @@
             futures.Future.__del__(self)
 
     def _repr_info(self):
-        info = super()._repr_info()
-
-        if self._must_cancel:
-            # replace status
-            info[0] = 'cancelling'
-
-        coro = coroutines._format_coroutine(self._coro)
-        info.insert(1, 'coro=<%s>' % coro)
-
-        if self._fut_waiter is not None:
-            info.insert(2, 'wait_for=%r' % self._fut_waiter)
-        return info
+        return base_tasks._task_repr_info(self)
 
     def get_stack(self, *, limit=None):
         """Return the list of stack frames for this task's coroutine.
@@ -127,31 +115,7 @@
         For reasons beyond our control, only one stack frame is
         returned for a suspended coroutine.
         """
-        frames = []
-        try:
-            # 'async def' coroutines
-            f = self._coro.cr_frame
-        except AttributeError:
-            f = self._coro.gi_frame
-        if f is not None:
-            while f is not None:
-                if limit is not None:
-                    if limit <= 0:
-                        break
-                    limit -= 1
-                frames.append(f)
-                f = f.f_back
-            frames.reverse()
-        elif self._exception is not None:
-            tb = self._exception.__traceback__
-            while tb is not None:
-                if limit is not None:
-                    if limit <= 0:
-                        break
-                    limit -= 1
-                frames.append(tb.tb_frame)
-                tb = tb.tb_next
-        return frames
+        return base_tasks._task_get_stack(self, limit)
 
     def print_stack(self, *, limit=None, file=None):
         """Print the stack or traceback for this task's coroutine.
@@ -162,31 +126,7 @@
         to which the output is written; by default output is written
         to sys.stderr.
         """
-        extracted_list = []
-        checked = set()
-        for f in self.get_stack(limit=limit):
-            lineno = f.f_lineno
-            co = f.f_code
-            filename = co.co_filename
-            name = co.co_name
-            if filename not in checked:
-                checked.add(filename)
-                linecache.checkcache(filename)
-            line = linecache.getline(filename, lineno, f.f_globals)
-            extracted_list.append((filename, lineno, name, line))
-        exc = self._exception
-        if not extracted_list:
-            print('No stack for %r' % self, file=file)
-        elif exc is not None:
-            print('Traceback for %r (most recent call last):' % self,
-                  file=file)
-        else:
-            print('Stack for %r (most recent call last):' % self,
-                  file=file)
-        traceback.print_list(extracted_list, file=file)
-        if exc is not None:
-            for line in traceback.format_exception_only(exc.__class__, exc):
-                print(line, file=file, end='')
+        return base_tasks._task_print_stack(self, limit, file)
 
     def cancel(self):
         """Request that this task cancel itself.
@@ -316,6 +256,18 @@
         self = None  # Needed to break cycles when an exception occurs.
 
 
+_PyTask = Task
+
+
+try:
+    import _asyncio
+except ImportError:
+    pass
+else:
+    # _CTask is needed for tests.
+    Task = _CTask = _asyncio.Task
+
+
 # wait() and as_completed() similar to those in PEP 3148.
 
 FIRST_COMPLETED = concurrent.futures.FIRST_COMPLETED
diff --git a/Lib/test/test_asyncio/test_tasks.py b/Lib/test/test_asyncio/test_tasks.py
index 1ceb9b2..d8862fc 100644
--- a/Lib/test/test_asyncio/test_tasks.py
+++ b/Lib/test/test_asyncio/test_tasks.py
@@ -1,5 +1,6 @@
 """Tests for tasks.py."""
 
+import collections
 import contextlib
 import functools
 import io
@@ -14,6 +15,8 @@
 
 import asyncio
 from asyncio import coroutines
+from asyncio import futures
+from asyncio import tasks
 from asyncio import test_utils
 try:
     from test import support
@@ -72,14 +75,25 @@
         pass
 
 
-class TaskTests(test_utils.TestCase):
+class BaseTaskTests:
+
+    Task = None
+    Future = None
+
+    def new_task(self, loop, coro):
+        return self.__class__.Task(coro, loop=loop)
+
+    def new_future(self, loop):
+        return self.__class__.Future(loop=loop)
 
     def setUp(self):
         self.loop = self.new_test_loop()
+        self.loop.set_task_factory(self.new_task)
+        self.loop.create_future = lambda: self.new_future(self.loop)
 
     def test_other_loop_future(self):
         other_loop = asyncio.new_event_loop()
-        fut = asyncio.Future(loop=other_loop)
+        fut = self.new_future(other_loop)
 
         @asyncio.coroutine
         def run(fut):
@@ -107,7 +121,7 @@
         @asyncio.coroutine
         def notmuch():
             return 'ok'
-        t = asyncio.Task(notmuch(), loop=self.loop)
+        t = self.new_task(self.loop, notmuch())
         self.loop.run_until_complete(t)
         self.assertTrue(t.done())
         self.assertEqual(t.result(), 'ok')
@@ -115,7 +129,7 @@
 
         loop = asyncio.new_event_loop()
         self.set_event_loop(loop)
-        t = asyncio.Task(notmuch(), loop=loop)
+        t = self.new_task(loop, notmuch())
         self.assertIs(t._loop, loop)
         loop.run_until_complete(t)
         loop.close()
@@ -138,7 +152,7 @@
         loop.close()
 
     def test_ensure_future_future(self):
-        f_orig = asyncio.Future(loop=self.loop)
+        f_orig = self.new_future(self.loop)
         f_orig.set_result('ko')
 
         f = asyncio.ensure_future(f_orig)
@@ -162,7 +176,7 @@
         @asyncio.coroutine
         def notmuch():
             return 'ok'
-        t_orig = asyncio.Task(notmuch(), loop=self.loop)
+        t_orig = self.new_task(self.loop, notmuch())
         t = asyncio.ensure_future(t_orig)
         self.loop.run_until_complete(t)
         self.assertTrue(t.done())
@@ -203,7 +217,7 @@
             asyncio.ensure_future('ok')
 
     def test_async_warning(self):
-        f = asyncio.Future(loop=self.loop)
+        f = self.new_future(self.loop)
         with self.assertWarnsRegex(DeprecationWarning,
                                    'function is deprecated, use ensure_'):
             self.assertIs(f, asyncio.async(f))
@@ -250,8 +264,8 @@
         # test coroutine function
         self.assertEqual(notmuch.__name__, 'notmuch')
         if PY35:
-            self.assertEqual(notmuch.__qualname__,
-                             'TaskTests.test_task_repr.<locals>.notmuch')
+            self.assertRegex(notmuch.__qualname__,
+                             r'\w+.test_task_repr.<locals>.notmuch')
         self.assertEqual(notmuch.__module__, __name__)
 
         filename, lineno = test_utils.get_function_source(notmuch)
@@ -260,7 +274,7 @@
         # test coroutine object
         gen = notmuch()
         if coroutines._DEBUG or PY35:
-            coro_qualname = 'TaskTests.test_task_repr.<locals>.notmuch'
+            coro_qualname = 'BaseTaskTests.test_task_repr.<locals>.notmuch'
         else:
             coro_qualname = 'notmuch'
         self.assertEqual(gen.__name__, 'notmuch')
@@ -269,7 +283,7 @@
                              coro_qualname)
 
         # test pending Task
-        t = asyncio.Task(gen, loop=self.loop)
+        t = self.new_task(self.loop, gen)
         t.add_done_callback(Dummy())
 
         coro = format_coroutine(coro_qualname, 'running', src,
@@ -291,7 +305,7 @@
                          '<Task cancelled %s>' % coro)
 
         # test finished Task
-        t = asyncio.Task(notmuch(), loop=self.loop)
+        t = self.new_task(self.loop, notmuch())
         self.loop.run_until_complete(t)
         coro = format_coroutine(coro_qualname, 'done', src,
                                 t._source_traceback)
@@ -310,9 +324,9 @@
         # test coroutine function
         self.assertEqual(notmuch.__name__, 'notmuch')
         if PY35:
-            self.assertEqual(notmuch.__qualname__,
-                             'TaskTests.test_task_repr_coro_decorator'
-                             '.<locals>.notmuch')
+            self.assertRegex(notmuch.__qualname__,
+                             r'\w+.test_task_repr_coro_decorator'
+                             r'\.<locals>\.notmuch')
         self.assertEqual(notmuch.__module__, __name__)
 
         # test coroutine object
@@ -322,7 +336,7 @@
             # function, as expected, and have a qualified name (__qualname__
             # attribute).
             coro_name = 'notmuch'
-            coro_qualname = ('TaskTests.test_task_repr_coro_decorator'
+            coro_qualname = ('BaseTaskTests.test_task_repr_coro_decorator'
                              '.<locals>.notmuch')
         else:
             # On Python < 3.5, generators inherit the name of the code, not of
@@ -350,7 +364,7 @@
             self.assertEqual(repr(gen), '<CoroWrapper %s>' % coro)
 
         # test pending Task
-        t = asyncio.Task(gen, loop=self.loop)
+        t = self.new_task(self.loop, gen)
         t.add_done_callback(Dummy())
 
         # format the coroutine object
@@ -373,8 +387,8 @@
         def wait_for(fut):
             return (yield from fut)
 
-        fut = asyncio.Future(loop=self.loop)
-        task = asyncio.Task(wait_for(fut), loop=self.loop)
+        fut = self.new_future(self.loop)
+        task = self.new_task(self.loop, wait_for(fut))
         test_utils.run_briefly(self.loop)
         self.assertRegex(repr(task),
                          '<Task .* wait_for=%s>' % re.escape(repr(fut)))
@@ -400,10 +414,11 @@
             self.addCleanup(task._coro.close)
 
         coro_repr = repr(task._coro)
-        expected = ('<CoroWrapper TaskTests.test_task_repr_partial_corowrapper'
-                    '.<locals>.func(1)() running, ')
-        self.assertTrue(coro_repr.startswith(expected),
-                        coro_repr)
+        expected = (
+            r'<CoroWrapper \w+.test_task_repr_partial_corowrapper'
+            r'\.<locals>\.func\(1\)\(\) running, '
+        )
+        self.assertRegex(coro_repr, expected)
 
     def test_task_basics(self):
         @asyncio.coroutine
@@ -437,7 +452,7 @@
             yield from asyncio.sleep(10.0, loop=loop)
             return 12
 
-        t = asyncio.Task(task(), loop=loop)
+        t = self.new_task(loop, task())
         loop.call_soon(t.cancel)
         with self.assertRaises(asyncio.CancelledError):
             loop.run_until_complete(t)
@@ -452,7 +467,7 @@
             yield
             return 12
 
-        t = asyncio.Task(task(), loop=self.loop)
+        t = self.new_task(self.loop, task())
         test_utils.run_briefly(self.loop)  # start coro
         t.cancel()
         self.assertRaises(
@@ -462,14 +477,14 @@
         self.assertFalse(t.cancel())
 
     def test_cancel_inner_future(self):
-        f = asyncio.Future(loop=self.loop)
+        f = self.new_future(self.loop)
 
         @asyncio.coroutine
         def task():
             yield from f
             return 12
 
-        t = asyncio.Task(task(), loop=self.loop)
+        t = self.new_task(self.loop, task())
         test_utils.run_briefly(self.loop)  # start task
         f.cancel()
         with self.assertRaises(asyncio.CancelledError):
@@ -478,14 +493,14 @@
         self.assertTrue(t.cancelled())
 
     def test_cancel_both_task_and_inner_future(self):
-        f = asyncio.Future(loop=self.loop)
+        f = self.new_future(self.loop)
 
         @asyncio.coroutine
         def task():
             yield from f
             return 12
 
-        t = asyncio.Task(task(), loop=self.loop)
+        t = self.new_task(self.loop, task())
         test_utils.run_briefly(self.loop)
 
         f.cancel()
@@ -499,8 +514,8 @@
         self.assertTrue(t.cancelled())
 
     def test_cancel_task_catching(self):
-        fut1 = asyncio.Future(loop=self.loop)
-        fut2 = asyncio.Future(loop=self.loop)
+        fut1 = self.new_future(self.loop)
+        fut2 = self.new_future(self.loop)
 
         @asyncio.coroutine
         def task():
@@ -510,7 +525,7 @@
             except asyncio.CancelledError:
                 return 42
 
-        t = asyncio.Task(task(), loop=self.loop)
+        t = self.new_task(self.loop, task())
         test_utils.run_briefly(self.loop)
         self.assertIs(t._fut_waiter, fut1)  # White-box test.
         fut1.set_result(None)
@@ -523,9 +538,9 @@
         self.assertFalse(t.cancelled())
 
     def test_cancel_task_ignoring(self):
-        fut1 = asyncio.Future(loop=self.loop)
-        fut2 = asyncio.Future(loop=self.loop)
-        fut3 = asyncio.Future(loop=self.loop)
+        fut1 = self.new_future(self.loop)
+        fut2 = self.new_future(self.loop)
+        fut3 = self.new_future(self.loop)
 
         @asyncio.coroutine
         def task():
@@ -537,7 +552,7 @@
             res = yield from fut3
             return res
 
-        t = asyncio.Task(task(), loop=self.loop)
+        t = self.new_task(self.loop, task())
         test_utils.run_briefly(self.loop)
         self.assertIs(t._fut_waiter, fut1)  # White-box test.
         fut1.set_result(None)
@@ -565,7 +580,7 @@
             yield from asyncio.sleep(100, loop=loop)
             return 12
 
-        t = asyncio.Task(task(), loop=loop)
+        t = self.new_task(loop, task())
         self.assertRaises(
             asyncio.CancelledError, loop.run_until_complete, t)
         self.assertTrue(t.done())
@@ -598,7 +613,7 @@
                 if x == 2:
                     loop.stop()
 
-        t = asyncio.Task(task(), loop=loop)
+        t = self.new_task(loop, task())
         with self.assertRaises(RuntimeError) as cm:
             loop.run_until_complete(t)
         self.assertEqual(str(cm.exception),
@@ -636,7 +651,7 @@
                 foo_running = False
             return 'done'
 
-        fut = asyncio.Task(foo(), loop=loop)
+        fut = self.new_task(loop, foo())
 
         with self.assertRaises(asyncio.TimeoutError):
             loop.run_until_complete(asyncio.wait_for(fut, 0.1, loop=loop))
@@ -676,7 +691,7 @@
 
         asyncio.set_event_loop(loop)
         try:
-            fut = asyncio.Task(foo(), loop=loop)
+            fut = self.new_task(loop, foo())
             with self.assertRaises(asyncio.TimeoutError):
                 loop.run_until_complete(asyncio.wait_for(fut, 0.01))
         finally:
@@ -695,7 +710,7 @@
 
         loop = self.new_test_loop(gen)
 
-        fut = asyncio.Future(loop=loop)
+        fut = self.new_future(loop)
         task = asyncio.wait_for(fut, timeout=0.2, loop=loop)
         loop.call_later(0.1, fut.set_result, "ok")
         res = loop.run_until_complete(task)
@@ -712,8 +727,8 @@
 
         loop = self.new_test_loop(gen)
 
-        a = asyncio.Task(asyncio.sleep(0.1, loop=loop), loop=loop)
-        b = asyncio.Task(asyncio.sleep(0.15, loop=loop), loop=loop)
+        a = self.new_task(loop, asyncio.sleep(0.1, loop=loop))
+        b = self.new_task(loop, asyncio.sleep(0.15, loop=loop))
 
         @asyncio.coroutine
         def foo():
@@ -722,12 +737,12 @@
             self.assertEqual(pending, set())
             return 42
 
-        res = loop.run_until_complete(asyncio.Task(foo(), loop=loop))
+        res = loop.run_until_complete(self.new_task(loop, foo()))
         self.assertEqual(res, 42)
         self.assertAlmostEqual(0.15, loop.time())
 
         # Doing it again should take no time and exercise a different path.
-        res = loop.run_until_complete(asyncio.Task(foo(), loop=loop))
+        res = loop.run_until_complete(self.new_task(loop, foo()))
         self.assertAlmostEqual(0.15, loop.time())
         self.assertEqual(res, 42)
 
@@ -742,8 +757,8 @@
 
         loop = self.new_test_loop(gen)
 
-        a = asyncio.Task(asyncio.sleep(0.01, loop=loop), loop=loop)
-        b = asyncio.Task(asyncio.sleep(0.015, loop=loop), loop=loop)
+        a = self.new_task(loop, asyncio.sleep(0.01, loop=loop))
+        b = self.new_task(loop, asyncio.sleep(0.015, loop=loop))
 
         @asyncio.coroutine
         def foo():
@@ -754,7 +769,7 @@
 
         asyncio.set_event_loop(loop)
         res = loop.run_until_complete(
-            asyncio.Task(foo(), loop=loop))
+            self.new_task(loop, foo()))
 
         self.assertEqual(res, 42)
 
@@ -764,9 +779,9 @@
             return s
         c = coro('test')
 
-        task = asyncio.Task(
-            asyncio.wait([c, c, coro('spam')], loop=self.loop),
-            loop=self.loop)
+        task =self.new_task(
+            self.loop,
+            asyncio.wait([c, c, coro('spam')], loop=self.loop))
 
         done, pending = self.loop.run_until_complete(task)
 
@@ -797,12 +812,12 @@
 
         loop = self.new_test_loop(gen)
 
-        a = asyncio.Task(asyncio.sleep(10.0, loop=loop), loop=loop)
-        b = asyncio.Task(asyncio.sleep(0.1, loop=loop), loop=loop)
-        task = asyncio.Task(
+        a = self.new_task(loop, asyncio.sleep(10.0, loop=loop))
+        b = self.new_task(loop, asyncio.sleep(0.1, loop=loop))
+        task = self.new_task(
+            loop,
             asyncio.wait([b, a], return_when=asyncio.FIRST_COMPLETED,
-                         loop=loop),
-            loop=loop)
+                         loop=loop))
 
         done, pending = loop.run_until_complete(task)
         self.assertEqual({b}, done)
@@ -829,12 +844,12 @@
             yield
             yield
 
-        a = asyncio.Task(coro1(), loop=self.loop)
-        b = asyncio.Task(coro2(), loop=self.loop)
-        task = asyncio.Task(
+        a = self.new_task(self.loop, coro1())
+        b = self.new_task(self.loop, coro2())
+        task = self.new_task(
+            self.loop,
             asyncio.wait([b, a], return_when=asyncio.FIRST_COMPLETED,
-                         loop=self.loop),
-            loop=self.loop)
+                         loop=self.loop))
 
         done, pending = self.loop.run_until_complete(task)
         self.assertEqual({a, b}, done)
@@ -853,17 +868,17 @@
         loop = self.new_test_loop(gen)
 
         # first_exception, task already has exception
-        a = asyncio.Task(asyncio.sleep(10.0, loop=loop), loop=loop)
+        a = self.new_task(loop, asyncio.sleep(10.0, loop=loop))
 
         @asyncio.coroutine
         def exc():
             raise ZeroDivisionError('err')
 
-        b = asyncio.Task(exc(), loop=loop)
-        task = asyncio.Task(
+        b = self.new_task(loop, exc())
+        task = self.new_task(
+            loop,
             asyncio.wait([b, a], return_when=asyncio.FIRST_EXCEPTION,
-                         loop=loop),
-            loop=loop)
+                         loop=loop))
 
         done, pending = loop.run_until_complete(task)
         self.assertEqual({b}, done)
@@ -886,14 +901,14 @@
         loop = self.new_test_loop(gen)
 
         # first_exception, exception during waiting
-        a = asyncio.Task(asyncio.sleep(10.0, loop=loop), loop=loop)
+        a = self.new_task(loop, asyncio.sleep(10.0, loop=loop))
 
         @asyncio.coroutine
         def exc():
             yield from asyncio.sleep(0.01, loop=loop)
             raise ZeroDivisionError('err')
 
-        b = asyncio.Task(exc(), loop=loop)
+        b = self.new_task(loop, exc())
         task = asyncio.wait([b, a], return_when=asyncio.FIRST_EXCEPTION,
                             loop=loop)
 
@@ -917,14 +932,14 @@
 
         loop = self.new_test_loop(gen)
 
-        a = asyncio.Task(asyncio.sleep(0.1, loop=loop), loop=loop)
+        a = self.new_task(loop, asyncio.sleep(0.1, loop=loop))
 
         @asyncio.coroutine
         def sleeper():
             yield from asyncio.sleep(0.15, loop=loop)
             raise ZeroDivisionError('really')
 
-        b = asyncio.Task(sleeper(), loop=loop)
+        b = self.new_task(loop, sleeper())
 
         @asyncio.coroutine
         def foo():
@@ -934,10 +949,10 @@
             errors = set(f for f in done if f.exception() is not None)
             self.assertEqual(len(errors), 1)
 
-        loop.run_until_complete(asyncio.Task(foo(), loop=loop))
+        loop.run_until_complete(self.new_task(loop, foo()))
         self.assertAlmostEqual(0.15, loop.time())
 
-        loop.run_until_complete(asyncio.Task(foo(), loop=loop))
+        loop.run_until_complete(self.new_task(loop, foo()))
         self.assertAlmostEqual(0.15, loop.time())
 
     def test_wait_with_timeout(self):
@@ -953,8 +968,8 @@
 
         loop = self.new_test_loop(gen)
 
-        a = asyncio.Task(asyncio.sleep(0.1, loop=loop), loop=loop)
-        b = asyncio.Task(asyncio.sleep(0.15, loop=loop), loop=loop)
+        a = self.new_task(loop, asyncio.sleep(0.1, loop=loop))
+        b = self.new_task(loop, asyncio.sleep(0.15, loop=loop))
 
         @asyncio.coroutine
         def foo():
@@ -963,7 +978,7 @@
             self.assertEqual(done, set([a]))
             self.assertEqual(pending, set([b]))
 
-        loop.run_until_complete(asyncio.Task(foo(), loop=loop))
+        loop.run_until_complete(self.new_task(loop, foo()))
         self.assertAlmostEqual(0.11, loop.time())
 
         # move forward to close generator
@@ -983,8 +998,8 @@
 
         loop = self.new_test_loop(gen)
 
-        a = asyncio.Task(asyncio.sleep(0.1, loop=loop), loop=loop)
-        b = asyncio.Task(asyncio.sleep(0.15, loop=loop), loop=loop)
+        a = self.new_task(loop, asyncio.sleep(0.1, loop=loop))
+        b = self.new_task(loop, asyncio.sleep(0.15, loop=loop))
 
         done, pending = loop.run_until_complete(
             asyncio.wait([b, a], timeout=0.1, loop=loop))
@@ -1032,14 +1047,14 @@
                 values.append((yield from f))
             return values
 
-        res = loop.run_until_complete(asyncio.Task(foo(), loop=loop))
+        res = loop.run_until_complete(self.new_task(loop, foo()))
         self.assertAlmostEqual(0.15, loop.time())
         self.assertTrue('a' in res[:2])
         self.assertTrue('b' in res[:2])
         self.assertEqual(res[2], 'c')
 
         # Doing it again should take no time and exercise a different path.
-        res = loop.run_until_complete(asyncio.Task(foo(), loop=loop))
+        res = loop.run_until_complete(self.new_task(loop, foo()))
         self.assertAlmostEqual(0.15, loop.time())
 
     def test_as_completed_with_timeout(self):
@@ -1068,7 +1083,7 @@
                     values.append((2, exc))
             return values
 
-        res = loop.run_until_complete(asyncio.Task(foo(), loop=loop))
+        res = loop.run_until_complete(self.new_task(loop, foo()))
         self.assertEqual(len(res), 2, res)
         self.assertEqual(res[0], (1, 'a'))
         self.assertEqual(res[1][0], 2)
@@ -1096,7 +1111,7 @@
                 v = yield from f
                 self.assertEqual(v, 'a')
 
-        loop.run_until_complete(asyncio.Task(foo(), loop=loop))
+        loop.run_until_complete(self.new_task(loop, foo()))
 
     def test_as_completed_reverse_wait(self):
 
@@ -1156,7 +1171,7 @@
                 result.append((yield from f))
             return result
 
-        fut = asyncio.Task(runner(), loop=self.loop)
+        fut = self.new_task(self.loop, runner())
         self.loop.run_until_complete(fut)
         result = fut.result()
         self.assertEqual(set(result), {'ham', 'spam'})
@@ -1179,7 +1194,7 @@
             res = yield from asyncio.sleep(dt/2, arg, loop=loop)
             return res
 
-        t = asyncio.Task(sleeper(0.1, 'yeah'), loop=loop)
+        t = self.new_task(loop, sleeper(0.1, 'yeah'))
         loop.run_until_complete(t)
         self.assertTrue(t.done())
         self.assertEqual(t.result(), 'yeah')
@@ -1194,8 +1209,7 @@
 
         loop = self.new_test_loop(gen)
 
-        t = asyncio.Task(asyncio.sleep(10.0, 'yeah', loop=loop),
-                         loop=loop)
+        t = self.new_task(loop, asyncio.sleep(10.0, 'yeah', loop=loop))
 
         handle = None
         orig_call_later = loop.call_later
@@ -1231,7 +1245,7 @@
 
         @asyncio.coroutine
         def doit():
-            sleeper = asyncio.Task(sleep(5000), loop=loop)
+            sleeper = self.new_task(loop, sleep(5000))
             loop.call_later(0.1, sleeper.cancel)
             try:
                 yield from sleeper
@@ -1245,13 +1259,13 @@
         self.assertAlmostEqual(0.1, loop.time())
 
     def test_task_cancel_waiter_future(self):
-        fut = asyncio.Future(loop=self.loop)
+        fut = self.new_future(self.loop)
 
         @asyncio.coroutine
         def coro():
             yield from fut
 
-        task = asyncio.Task(coro(), loop=self.loop)
+        task = self.new_task(self.loop, coro())
         test_utils.run_briefly(self.loop)
         self.assertIs(task._fut_waiter, fut)
 
@@ -1268,7 +1282,7 @@
             return 'ko'
 
         gen = notmuch()
-        task = asyncio.Task(gen, loop=self.loop)
+        task = self.new_task(self.loop, gen)
         task.set_result('ok')
 
         self.assertRaises(AssertionError, task._step)
@@ -1304,7 +1318,7 @@
             nonlocal result
             result = yield from fut
 
-        t = asyncio.Task(wait_for_future(), loop=self.loop)
+        t = self.new_task(self.loop, wait_for_future())
         test_utils.run_briefly(self.loop)
         self.assertTrue(fut.cb_added)
 
@@ -1320,7 +1334,7 @@
         def notmutch():
             raise BaseException()
 
-        task = asyncio.Task(notmutch(), loop=self.loop)
+        task = self.new_task(self.loop, notmutch())
         self.assertRaises(BaseException, task._step)
 
         self.assertTrue(task.done())
@@ -1348,7 +1362,7 @@
             except asyncio.CancelledError:
                 raise base_exc
 
-        task = asyncio.Task(notmutch(), loop=loop)
+        task = self.new_task(loop, notmutch())
         test_utils.run_briefly(loop)
 
         task.cancel()
@@ -1376,7 +1390,7 @@
         self.assertTrue(asyncio.iscoroutinefunction(fn2))
 
     def test_yield_vs_yield_from(self):
-        fut = asyncio.Future(loop=self.loop)
+        fut = self.new_future(self.loop)
 
         @asyncio.coroutine
         def wait_for_future():
@@ -1420,7 +1434,7 @@
         self.assertEqual(res, 'test')
 
     def test_coroutine_non_gen_function_return_future(self):
-        fut = asyncio.Future(loop=self.loop)
+        fut = self.new_future(self.loop)
 
         @asyncio.coroutine
         def func():
@@ -1430,49 +1444,53 @@
         def coro():
             fut.set_result('test')
 
-        t1 = asyncio.Task(func(), loop=self.loop)
-        t2 = asyncio.Task(coro(), loop=self.loop)
+        t1 = self.new_task(self.loop, func())
+        t2 = self.new_task(self.loop, coro())
         res = self.loop.run_until_complete(t1)
         self.assertEqual(res, 'test')
         self.assertIsNone(t2.result())
 
     def test_current_task(self):
-        self.assertIsNone(asyncio.Task.current_task(loop=self.loop))
+        Task = self.__class__.Task
+
+        self.assertIsNone(Task.current_task(loop=self.loop))
 
         @asyncio.coroutine
         def coro(loop):
-            self.assertTrue(asyncio.Task.current_task(loop=loop) is task)
+            self.assertTrue(Task.current_task(loop=loop) is task)
 
-        task = asyncio.Task(coro(self.loop), loop=self.loop)
+        task = self.new_task(self.loop, coro(self.loop))
         self.loop.run_until_complete(task)
-        self.assertIsNone(asyncio.Task.current_task(loop=self.loop))
+        self.assertIsNone(Task.current_task(loop=self.loop))
 
     def test_current_task_with_interleaving_tasks(self):
-        self.assertIsNone(asyncio.Task.current_task(loop=self.loop))
+        Task = self.__class__.Task
 
-        fut1 = asyncio.Future(loop=self.loop)
-        fut2 = asyncio.Future(loop=self.loop)
+        self.assertIsNone(Task.current_task(loop=self.loop))
+
+        fut1 = self.new_future(self.loop)
+        fut2 = self.new_future(self.loop)
 
         @asyncio.coroutine
         def coro1(loop):
-            self.assertTrue(asyncio.Task.current_task(loop=loop) is task1)
+            self.assertTrue(Task.current_task(loop=loop) is task1)
             yield from fut1
-            self.assertTrue(asyncio.Task.current_task(loop=loop) is task1)
+            self.assertTrue(Task.current_task(loop=loop) is task1)
             fut2.set_result(True)
 
         @asyncio.coroutine
         def coro2(loop):
-            self.assertTrue(asyncio.Task.current_task(loop=loop) is task2)
+            self.assertTrue(Task.current_task(loop=loop) is task2)
             fut1.set_result(True)
             yield from fut2
-            self.assertTrue(asyncio.Task.current_task(loop=loop) is task2)
+            self.assertTrue(Task.current_task(loop=loop) is task2)
 
-        task1 = asyncio.Task(coro1(self.loop), loop=self.loop)
-        task2 = asyncio.Task(coro2(self.loop), loop=self.loop)
+        task1 = self.new_task(self.loop, coro1(self.loop))
+        task2 = self.new_task(self.loop, coro2(self.loop))
 
         self.loop.run_until_complete(asyncio.wait((task1, task2),
                                                   loop=self.loop))
-        self.assertIsNone(asyncio.Task.current_task(loop=self.loop))
+        self.assertIsNone(Task.current_task(loop=self.loop))
 
     # Some thorough tests for cancellation propagation through
     # coroutines, tasks and wait().
@@ -1480,7 +1498,7 @@
     def test_yield_future_passes_cancel(self):
         # Cancelling outer() cancels inner() cancels waiter.
         proof = 0
-        waiter = asyncio.Future(loop=self.loop)
+        waiter = self.new_future(self.loop)
 
         @asyncio.coroutine
         def inner():
@@ -1514,7 +1532,7 @@
         # Cancelling outer() makes wait() return early, leaves inner()
         # running.
         proof = 0
-        waiter = asyncio.Future(loop=self.loop)
+        waiter = self.new_future(self.loop)
 
         @asyncio.coroutine
         def inner():
@@ -1538,14 +1556,14 @@
         self.assertEqual(proof, 1)
 
     def test_shield_result(self):
-        inner = asyncio.Future(loop=self.loop)
+        inner = self.new_future(self.loop)
         outer = asyncio.shield(inner)
         inner.set_result(42)
         res = self.loop.run_until_complete(outer)
         self.assertEqual(res, 42)
 
     def test_shield_exception(self):
-        inner = asyncio.Future(loop=self.loop)
+        inner = self.new_future(self.loop)
         outer = asyncio.shield(inner)
         test_utils.run_briefly(self.loop)
         exc = RuntimeError('expected')
@@ -1554,7 +1572,7 @@
         self.assertIs(outer.exception(), exc)
 
     def test_shield_cancel(self):
-        inner = asyncio.Future(loop=self.loop)
+        inner = self.new_future(self.loop)
         outer = asyncio.shield(inner)
         test_utils.run_briefly(self.loop)
         inner.cancel()
@@ -1562,7 +1580,7 @@
         self.assertTrue(outer.cancelled())
 
     def test_shield_shortcut(self):
-        fut = asyncio.Future(loop=self.loop)
+        fut = self.new_future(self.loop)
         fut.set_result(42)
         res = self.loop.run_until_complete(asyncio.shield(fut))
         self.assertEqual(res, 42)
@@ -1570,7 +1588,7 @@
     def test_shield_effect(self):
         # Cancelling outer() does not affect inner().
         proof = 0
-        waiter = asyncio.Future(loop=self.loop)
+        waiter = self.new_future(self.loop)
 
         @asyncio.coroutine
         def inner():
@@ -1594,8 +1612,8 @@
         self.assertEqual(proof, 1)
 
     def test_shield_gather(self):
-        child1 = asyncio.Future(loop=self.loop)
-        child2 = asyncio.Future(loop=self.loop)
+        child1 = self.new_future(self.loop)
+        child2 = self.new_future(self.loop)
         parent = asyncio.gather(child1, child2, loop=self.loop)
         outer = asyncio.shield(parent, loop=self.loop)
         test_utils.run_briefly(self.loop)
@@ -1608,8 +1626,8 @@
         self.assertEqual(parent.result(), [1, 2])
 
     def test_gather_shield(self):
-        child1 = asyncio.Future(loop=self.loop)
-        child2 = asyncio.Future(loop=self.loop)
+        child1 = self.new_future(self.loop)
+        child2 = self.new_future(self.loop)
         inner1 = asyncio.shield(child1, loop=self.loop)
         inner2 = asyncio.shield(child2, loop=self.loop)
         parent = asyncio.gather(inner1, inner2, loop=self.loop)
@@ -1625,7 +1643,7 @@
         test_utils.run_briefly(self.loop)
 
     def test_as_completed_invalid_args(self):
-        fut = asyncio.Future(loop=self.loop)
+        fut = self.new_future(self.loop)
 
         # as_completed() expects a list of futures, not a future instance
         self.assertRaises(TypeError, self.loop.run_until_complete,
@@ -1636,7 +1654,7 @@
         coro.close()
 
     def test_wait_invalid_args(self):
-        fut = asyncio.Future(loop=self.loop)
+        fut = self.new_future(self.loop)
 
         # wait() expects a list of futures, not a future instance
         self.assertRaises(TypeError, self.loop.run_until_complete,
@@ -1663,7 +1681,7 @@
                 yield from fut
 
             # A completed Future used to run the coroutine.
-            fut = asyncio.Future(loop=self.loop)
+            fut = self.new_future(self.loop)
             fut.set_result(None)
 
             # Call the coroutine.
@@ -1697,15 +1715,15 @@
 
             @asyncio.coroutine
             def t2():
-                f = asyncio.Future(loop=self.loop)
-                asyncio.Task(t3(f), loop=self.loop)
+                f = self.new_future(self.loop)
+                self.new_task(self.loop, t3(f))
                 return (yield from f)
 
             @asyncio.coroutine
             def t3(f):
                 f.set_result((1, 2, 3))
 
-            task = asyncio.Task(t1(), loop=self.loop)
+            task = self.new_task(self.loop, t1())
             val = self.loop.run_until_complete(task)
             self.assertEqual(val, (1, 2, 3))
 
@@ -1768,9 +1786,11 @@
     @unittest.skipUnless(PY34,
                          'need python 3.4 or later')
     def test_log_destroyed_pending_task(self):
+        Task = self.__class__.Task
+
         @asyncio.coroutine
         def kill_me(loop):
-            future = asyncio.Future(loop=loop)
+            future = self.new_future(loop)
             yield from future
             # at this point, the only reference to kill_me() task is
             # the Task._wakeup() method in future._callbacks
@@ -1783,7 +1803,7 @@
         # schedule the task
         coro = kill_me(self.loop)
         task = asyncio.ensure_future(coro, loop=self.loop)
-        self.assertEqual(asyncio.Task.all_tasks(loop=self.loop), {task})
+        self.assertEqual(Task.all_tasks(loop=self.loop), {task})
 
         # execute the task so it waits for future
         self.loop._run_once()
@@ -1798,7 +1818,7 @@
         # no more reference to kill_me() task: the task is destroyed by the GC
         support.gc_collect()
 
-        self.assertEqual(asyncio.Task.all_tasks(loop=self.loop), set())
+        self.assertEqual(Task.all_tasks(loop=self.loop), set())
 
         mock_handler.assert_called_with(self.loop, {
             'message': 'Task was destroyed but it is pending!',
@@ -1863,10 +1883,10 @@
     def test_task_source_traceback(self):
         self.loop.set_debug(True)
 
-        task = asyncio.Task(coroutine_function(), loop=self.loop)
+        task = self.new_task(self.loop, coroutine_function())
         lineno = sys._getframe().f_lineno - 1
         self.assertIsInstance(task._source_traceback, list)
-        self.assertEqual(task._source_traceback[-1][:3],
+        self.assertEqual(task._source_traceback[-2][:3],
                          (__file__,
                           lineno,
                           'test_task_source_traceback'))
@@ -1878,7 +1898,7 @@
 
         @asyncio.coroutine
         def blocking_coroutine():
-            fut = asyncio.Future(loop=loop)
+            fut = self.new_future(loop)
             # Block: fut result is never set
             yield from fut
 
@@ -1905,7 +1925,7 @@
         loop = asyncio.new_event_loop()
         self.addCleanup(loop.close)
 
-        fut = asyncio.Future(loop=loop)
+        fut = self.new_future(loop)
         # The indirection fut->child_coro is needed since otherwise the
         # gathering task is done at the same time as the child future
         def child_coro():
@@ -1929,6 +1949,157 @@
         self.assertFalse(gather_task.cancelled())
         self.assertEqual(gather_task.result(), [42])
 
+    @mock.patch('asyncio.base_events.logger')
+    def test_error_in_call_soon(self, m_log):
+        def call_soon(callback, *args):
+            raise ValueError
+        self.loop.call_soon = call_soon
+
+        @asyncio.coroutine
+        def coro():
+            pass
+
+        self.assertFalse(m_log.error.called)
+
+        with self.assertRaises(ValueError):
+            self.new_task(self.loop, coro())
+
+        self.assertTrue(m_log.error.called)
+        message = m_log.error.call_args[0][0]
+        self.assertIn('Task was destroyed but it is pending', message)
+
+        self.assertEqual(self.Task.all_tasks(self.loop), set())
+
+
+def add_subclass_tests(cls):
+    BaseTask = cls.Task
+    BaseFuture = cls.Future
+
+    if BaseTask is None or BaseFuture is None:
+        return cls
+
+    class CommonFuture:
+        def __init__(self, *args, **kwargs):
+            self.calls = collections.defaultdict(lambda: 0)
+            super().__init__(*args, **kwargs)
+
+        def _schedule_callbacks(self):
+            self.calls['_schedule_callbacks'] += 1
+            return super()._schedule_callbacks()
+
+        def add_done_callback(self, *args):
+            self.calls['add_done_callback'] += 1
+            return super().add_done_callback(*args)
+
+    class Task(CommonFuture, BaseTask):
+        def _step(self, *args):
+            self.calls['_step'] += 1
+            return super()._step(*args)
+
+        def _wakeup(self, *args):
+            self.calls['_wakeup'] += 1
+            return super()._wakeup(*args)
+
+    class Future(CommonFuture, BaseFuture):
+        pass
+
+    def test_subclasses_ctask_cfuture(self):
+        fut = self.Future(loop=self.loop)
+
+        async def func():
+            self.loop.call_soon(lambda: fut.set_result('spam'))
+            return await fut
+
+        task = self.Task(func(), loop=self.loop)
+
+        result = self.loop.run_until_complete(task)
+
+        self.assertEqual(result, 'spam')
+
+        self.assertEqual(
+            dict(task.calls),
+            {'_step': 2, '_wakeup': 1, 'add_done_callback': 1,
+             '_schedule_callbacks': 1})
+
+        self.assertEqual(
+            dict(fut.calls),
+            {'add_done_callback': 1, '_schedule_callbacks': 1})
+
+    # Add patched Task & Future back to the test case
+    cls.Task = Task
+    cls.Future = Future
+
+    # Add an extra unit-test
+    cls.test_subclasses_ctask_cfuture = test_subclasses_ctask_cfuture
+
+    # Disable the "test_task_source_traceback" test
+    # (the test is hardcoded for a particular call stack, which
+    # is slightly different for Task subclasses)
+    cls.test_task_source_traceback = None
+
+    return cls
+
+
+@unittest.skipUnless(hasattr(futures, '_CFuture'),
+                     'requires the C _asyncio module')
+class CTask_CFuture_Tests(BaseTaskTests, test_utils.TestCase):
+    Task = getattr(tasks, '_CTask', None)
+    Future = getattr(futures, '_CFuture', None)
+
+
+@unittest.skipUnless(hasattr(futures, '_CFuture'),
+                     'requires the C _asyncio module')
+@add_subclass_tests
+class CTask_CFuture_SubclassTests(BaseTaskTests, test_utils.TestCase):
+    Task = getattr(tasks, '_CTask', None)
+    Future = getattr(futures, '_CFuture', None)
+
+
+@unittest.skipUnless(hasattr(futures, '_CFuture'),
+                     'requires the C _asyncio module')
+class CTask_PyFuture_Tests(BaseTaskTests, test_utils.TestCase):
+    Task = getattr(tasks, '_CTask', None)
+    Future = futures._PyFuture
+
+
+@unittest.skipUnless(hasattr(futures, '_CFuture'),
+                     'requires the C _asyncio module')
+class PyTask_CFuture_Tests(BaseTaskTests, test_utils.TestCase):
+    Task = tasks._PyTask
+    Future = getattr(futures, '_CFuture', None)
+
+
+class PyTask_PyFuture_Tests(BaseTaskTests, test_utils.TestCase):
+    Task = tasks._PyTask
+    Future = futures._PyFuture
+
+
+@add_subclass_tests
+class PyTask_PyFuture_SubclassTests(BaseTaskTests, test_utils.TestCase):
+    Task = tasks._PyTask
+    Future = futures._PyFuture
+
+
+class GenericTaskTests(test_utils.TestCase):
+
+    def test_future_subclass(self):
+        self.assertTrue(issubclass(asyncio.Task, asyncio.Future))
+
+    def test_asyncio_module_compiled(self):
+        # Because of circular imports it's easy to make _asyncio
+        # module non-importable.  This is a simple test that will
+        # fail on systems where C modules were successfully compiled
+        # (hence the test for _functools), but _asyncio somehow didn't.
+        try:
+            import _functools
+        except ImportError:
+            pass
+        else:
+            try:
+                import _asyncio
+            except ImportError:
+                self.fail('_asyncio module is missing')
+
 
 class GatherTestsBase: