]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - libstdc++-v3/include/std/future
Update copyright years in libstdc++-v3/
[thirdparty/gcc.git] / libstdc++-v3 / include / std / future
index dd1a86b4d7b498efedd7f0c289a5f7396611a386..ca3dacd5588cefd1209646fec3a4e1c82a49aad7 100644 (file)
@@ -1,6 +1,6 @@
 // <future> -*- C++ -*-
 
-// Copyright (C) 2009-2012 Free Software Foundation, Inc.
+// Copyright (C) 2009-2014 Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
 // software; you can redistribute it and/or modify it under the
@@ -46,6 +46,7 @@
 #include <bits/shared_ptr.h>
 #include <bits/uses_allocator.h>
 #include <bits/alloc_traits.h>
+#include <ext/aligned_buffer.h>
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
@@ -170,19 +171,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     future<typename result_of<_Fn(_Args...)>::type>
     async(launch __policy, _Fn&& __fn, _Args&&... __args);
 
-  template<typename _FnCheck, typename _Fn, typename... _Args>
-    struct __async_sfinae_helper
-    {
-      typedef future<typename result_of<_Fn(_Args...)>::type> type;
-    };
-
-  template<typename _Fn, typename... _Args>
-    struct __async_sfinae_helper<launch, _Fn, _Args...>
-    { };
-
   template<typename _Fn, typename... _Args>
-    typename
-    __async_sfinae_helper<typename decay<_Fn>::type, _Fn, _Args...>::type
+    future<typename result_of<_Fn(_Args...)>::type>
     async(_Fn&& __fn, _Args&&... __args);
 
 #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) \
@@ -217,14 +207,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       struct _Result : _Result_base
       {
       private:
-       typedef alignment_of<_Res>                              __a_of;
-       typedef aligned_storage<sizeof(_Res), __a_of::value>    __align_storage;
-       typedef typename __align_storage::type                  __align_type;
-
-       __align_type            _M_storage;
-       bool                    _M_initialized;
+       __gnu_cxx::__aligned_buffer<_Res>       _M_storage;
+       bool                                    _M_initialized;
 
       public:
+       typedef _Res result_type;
+
        _Result() noexcept : _M_initialized() { }
        
        ~_Result()
@@ -235,26 +223,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
        // Return lvalue, future will add const or rvalue-reference
        _Res&
-       _M_value() noexcept { return *static_cast<_Res*>(_M_addr()); }
+       _M_value() noexcept { return *_M_storage._M_ptr(); }
 
        void
        _M_set(const _Res& __res)
        {
-         ::new (_M_addr()) _Res(__res);
+         ::new (_M_storage._M_addr()) _Res(__res);
          _M_initialized = true;
        }
 
        void
        _M_set(_Res&& __res)
        {
-         ::new (_M_addr()) _Res(std::move(__res));
+         ::new (_M_storage._M_addr()) _Res(std::move(__res));
          _M_initialized = true;
        }
 
       private:
        void _M_destroy() { delete this; }
-
-       void* _M_addr() noexcept { return static_cast<void*>(&_M_storage); }
     };
 
     /// A unique_ptr based on the instantiating type.
@@ -292,21 +278,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
         typename __traits::allocator_type __a2(__a);
         __result_type* __p = __traits::allocate(__a2, 1);
         __try
-       {
-         __traits::construct(__a2, __p, __a);
-        }
+         {
+           __traits::construct(__a2, __p, __a);
+         }
         __catch(...)
-        {
-         __traits::deallocate(__a2, __p, 1);
-          __throw_exception_again;
-        }
+         {
+           __traits::deallocate(__a2, __p, 1);
+           __throw_exception_again;
+         }
         return _Ptr<__result_type>(__p);
       }
 
+    template<typename _Res, typename _Tp>
+      static _Ptr<_Result<_Res>>
+      _S_allocate_result(const std::allocator<_Tp>& __a)
+      {
+       return _Ptr<_Result<_Res>>(new _Result<_Res>);
+      }
 
     /// Base class for state between a promise and one or more
     /// associated futures.
-    class _State_base
+    class _State_baseV2
     {
       typedef _Ptr<_Result_base> _Ptr_type;
 
@@ -317,15 +309,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       once_flag                        _M_once;
 
     public:
-      _State_base() noexcept : _M_result(), _M_retrieved(ATOMIC_FLAG_INIT) { }
-      _State_base(const _State_base&) = delete;
-      _State_base& operator=(const _State_base&) = delete;
-      virtual ~_State_base();
+      _State_baseV2() noexcept : _M_result(), _M_retrieved(ATOMIC_FLAG_INIT)
+       { }
+      _State_baseV2(const _State_baseV2&) = delete;
+      _State_baseV2& operator=(const _State_baseV2&) = delete;
+      virtual ~_State_baseV2() = default;
 
       _Result_base&
       wait()
       {
-       _M_run_deferred();
+       _M_complete_async();
        unique_lock<mutex> __lock(_M_mutex);
        _M_cond.wait(__lock, [&] { return _M_ready(); });
        return *_M_result;
@@ -336,8 +329,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
         wait_for(const chrono::duration<_Rep, _Period>& __rel)
         {
          unique_lock<mutex> __lock(_M_mutex);
-         if (_M_cond.wait_for(__lock, __rel, [&] { return _M_ready(); }))
+         if (_M_ready())
            return future_status::ready;
+         if (_M_has_deferred())
+           return future_status::deferred;
+         if (_M_cond.wait_for(__lock, __rel, [&] { return _M_ready(); }))
+           {
+             // _GLIBCXX_RESOLVE_LIB_DEFECTS
+             // 2100.  timed waiting functions must also join
+             _M_complete_async();
+             return future_status::ready;
+           }
          return future_status::timeout;
        }
 
@@ -346,8 +348,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
         wait_until(const chrono::time_point<_Clock, _Duration>& __abs)
         {
          unique_lock<mutex> __lock(_M_mutex);
-         if (_M_cond.wait_until(__lock, __abs, [&] { return _M_ready(); }))
+         if (_M_ready())
            return future_status::ready;
+         if (_M_has_deferred())
+           return future_status::deferred;
+         if (_M_cond.wait_until(__lock, __abs, [&] { return _M_ready(); }))
+           {
+             // _GLIBCXX_RESOLVE_LIB_DEFECTS
+             // 2100.  timed waiting functions must also join
+             _M_complete_async();
+             return future_status::ready;
+           }
          return future_status::timeout;
        }
 
@@ -357,7 +368,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
         bool __set = __ignore_failure;
         // all calls to this function are serialized,
         // side-effects of invoking __res only happen once
-        call_once(_M_once, &_State_base::_M_do_set, this, ref(__res),
+        call_once(_M_once, &_State_baseV2::_M_do_set, this, ref(__res),
             ref(__set));
         if (!__set)
           __throw_future_error(int(future_errc::promise_already_satisfied));
@@ -369,7 +380,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        if (static_cast<bool>(__res))
          {
            error_code __ec(make_error_code(future_errc::broken_promise));
-           __res->_M_error = copy_exception(future_error(__ec));
+           __res->_M_error = make_exception_ptr(future_error(__ec));
            {
              lock_guard<mutex> __lock(_M_mutex);
              _M_result.swap(__res);
@@ -401,7 +412,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
           typename promise<_Res>::_Ptr_type operator()()
           {
-            _State_base::_S_check(_M_promise->_M_future);
+            _State_baseV2::_S_check(_M_promise->_M_future);
             _M_promise->_M_storage->_M_set(_M_arg);
             return std::move(_M_promise->_M_storage);
           }
@@ -415,7 +426,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
         {
           typename promise<_Res>::_Ptr_type operator()()
           {
-            _State_base::_S_check(_M_promise->_M_future);
+            _State_baseV2::_S_check(_M_promise->_M_future);
             _M_promise->_M_storage->_M_set(std::move(_M_arg));
             return std::move(_M_promise->_M_storage);
           }
@@ -431,7 +442,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
         {
           typename promise<_Res>::_Ptr_type operator()()
           {
-            _State_base::_S_check(_M_promise->_M_future);
+            _State_baseV2::_S_check(_M_promise->_M_future);
             _M_promise->_M_storage->_M_error = _M_ex;
             return std::move(_M_promise->_M_storage);
           }
@@ -458,7 +469,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __setter(promise<void>* __prom);
 
       template<typename _Tp>
-        static bool
+        static void
         _S_check(const shared_ptr<_Tp>& __p)
         {
           if (!static_cast<bool>(__p))
@@ -480,19 +491,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       bool _M_ready() const noexcept { return static_cast<bool>(_M_result); }
 
-      // Misnamed: waits for completion of async function.
-      virtual void _M_run_deferred() { }
+      // Wait for completion of async function.
+      virtual void _M_complete_async() { }
+
+      // Return true if state contains a deferred function.
+      virtual bool _M_has_deferred() const { return false; }
     };
 
+#ifdef _GLIBCXX_ASYNC_ABI_COMPAT
+    class _State_base;
+    class _Async_state_common;
+#else
+    using _State_base = _State_baseV2;
+    class _Async_state_commonV2;
+#endif
+
     template<typename _BoundFn, typename = typename _BoundFn::result_type>
       class _Deferred_state;
 
-    class _Async_state_common;
-
     template<typename _BoundFn, typename = typename _BoundFn::result_type>
       class _Async_state_impl;
 
     template<typename _Signature>
+      class _Task_state_base;
+
+    template<typename _Fn, typename _Alloc, typename _Signature>
       class _Task_state;
 
     template<typename _BoundFn>
@@ -503,24 +526,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       static std::shared_ptr<_State_base>
       _S_make_async_state(_BoundFn&& __fn);
 
-    template<typename _Res_ptr, typename _Res>
+    template<typename _Res_ptr,
+            typename _Res = typename _Res_ptr::element_type::result_type>
       struct _Task_setter;
 
     template<typename _Res_ptr, typename _BoundFn>
-      class _Task_setter_helper
-      {
-       typedef typename remove_reference<_BoundFn>::type::result_type __res;
-      public:
-       typedef _Task_setter<_Res_ptr, __res> __type;
-      };
-
-    template<typename _Res_ptr, typename _BoundFn>
-      static typename _Task_setter_helper<_Res_ptr, _BoundFn>::__type
+      static _Task_setter<_Res_ptr>
       _S_task_setter(_Res_ptr& __ptr, _BoundFn&& __call)
       {
-       typedef _Task_setter_helper<_Res_ptr, _BoundFn> __helper_type;
-       typedef typename __helper_type::__type _Setter;
-       return _Setter{ __ptr, std::ref(__call) };
+       return _Task_setter<_Res_ptr>{ __ptr, std::ref(__call) };
       }
   };
 
@@ -528,6 +542,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Res>
     struct __future_base::_Result<_Res&> : __future_base::_Result_base
     {
+      typedef _Res& result_type;
+
       _Result() noexcept : _M_value_ptr() { }
 
       void _M_set(_Res& __res) noexcept { _M_value_ptr = &__res; }
@@ -544,10 +560,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<>
     struct __future_base::_Result<void> : __future_base::_Result_base
     {
+      typedef void result_type;
+
     private:
       void _M_destroy() { delete this; }
     };
 
+#ifndef _GLIBCXX_ASYNC_ABI_COMPAT
 
   /// Common implementation for future and shared_future.
   template<typename _Res>
@@ -594,7 +613,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     protected:
       /// Wait for the state to be ready and rethrow any stored exception
       __result_type
-      _M_get_result()
+      _M_get_result() const
       {
         _State_base::_S_check(_M_state);
         _Result_base& __res = _M_state->wait();
@@ -805,12 +824,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       /// Retrieving the value
       const _Res&
-      get()
-      {
-       typename _Base_type::__result_type __r = this->_M_get_result();
-       _Res& __rs(__r._M_value());
-       return __rs;
-      }
+      get() const { return this->_M_get_result()._M_value(); }
     };
 
   /// Partial specialization for shared_future<R&>
@@ -849,7 +863,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       /// Retrieving the value
       _Res&
-      get() { return this->_M_get_result()._M_get(); }
+      get() const { return this->_M_get_result()._M_get(); }
     };
 
   /// Explicit specialization for shared_future<void>
@@ -888,7 +902,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       // Retrieving the value
       void
-      get() { this->_M_get_result(); }
+      get() const { this->_M_get_result(); }
     };
 
   // Now we can define the protected __basic_future constructors.
@@ -1132,6 +1146,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
          _M_storage(__future_base::_S_allocate_result<void>(__a))
         { }
 
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 2095.  missing constructors needed for uses-allocator construction
       template<typename _Allocator>
         promise(allocator_arg_t, const _Allocator&, promise&& __rhs)
         : _M_future(std::move(__rhs._M_future)),
@@ -1211,7 +1227,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     {
       _Ptr_type operator()()
       {
-        __try
+       __try
          {
            _M_result->_M_set(_M_fn());
          }
@@ -1219,7 +1235,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
          {
            _M_result->_M_error = current_exception();
          }
-        return std::move(_M_result);
+       return std::move(_M_result);
       }
       _Ptr_type&                _M_result;
       std::function<_Res()>     _M_fn;
@@ -1230,7 +1246,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     {
       _Ptr_type operator()()
       {
-        __try
+       __try
          {
            _M_fn();
          }
@@ -1245,49 +1261,85 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     };
 
   template<typename _Res, typename... _Args>
-    struct __future_base::_Task_state<_Res(_Args...)> final
+    struct __future_base::_Task_state_base<_Res(_Args...)>
     : __future_base::_State_base
     {
       typedef _Res _Res_type;
 
-      _Task_state(std::function<_Res(_Args...)> __task)
-      : _M_result(new _Result<_Res>()), _M_task(std::move(__task))
-      { }
+      template<typename _Alloc>
+       _Task_state_base(const _Alloc& __a)
+       : _M_result(_S_allocate_result<_Res>(__a))
+       { }
 
-      template<typename _Func, typename _Alloc>
-        _Task_state(_Func&& __task, const _Alloc& __a)
-        : _M_result(_S_allocate_result<_Res>(__a)),
-         _M_task(allocator_arg, __a, std::move(__task))
-        { }
+      virtual void
+      _M_run(_Args... __args) = 0;
 
-      void
+      virtual shared_ptr<_Task_state_base>
+      _M_reset() = 0;
+
+      typedef __future_base::_Ptr<_Result<_Res>> _Ptr_type;
+      _Ptr_type _M_result;
+    };
+
+  template<typename _Fn, typename _Alloc, typename _Res, typename... _Args>
+    struct __future_base::_Task_state<_Fn, _Alloc, _Res(_Args...)> final
+    : __future_base::_Task_state_base<_Res(_Args...)>
+    {
+      _Task_state(_Fn&& __fn, const _Alloc& __a)
+      : _Task_state_base<_Res(_Args...)>(__a), _M_impl(std::move(__fn), __a)
+      { }
+
+    private:
+      virtual void
       _M_run(_Args... __args)
       {
-        // bound arguments decay so wrap lvalue references
-       auto __boundfn = std::__bind_simple(std::ref(_M_task),
+       // bound arguments decay so wrap lvalue references
+       auto __boundfn = std::__bind_simple(std::ref(_M_impl._M_fn),
            _S_maybe_wrap_ref(std::forward<_Args>(__args))...);
-        auto __setter = _S_task_setter(_M_result, std::move(__boundfn));
-        _M_set_result(std::move(__setter));
+       auto __setter = _S_task_setter(this->_M_result, std::move(__boundfn));
+       this->_M_set_result(std::move(__setter));
       }
 
-      typedef __future_base::_Ptr<_Result<_Res>> _Ptr_type;
-      _Ptr_type _M_result;
-      std::function<_Res(_Args...)> _M_task;
+      virtual shared_ptr<_Task_state_base<_Res(_Args...)>>
+      _M_reset();
 
       template<typename _Tp>
-        static reference_wrapper<_Tp>
-        _S_maybe_wrap_ref(_Tp& __t)
-        { return std::ref(__t); }
+       static reference_wrapper<_Tp>
+       _S_maybe_wrap_ref(_Tp& __t)
+       { return std::ref(__t); }
 
       template<typename _Tp>
-        static typename enable_if<!is_lvalue_reference<_Tp>::value,
-                        _Tp>::type&&
-        _S_maybe_wrap_ref(_Tp&& __t)
-        { return std::forward<_Tp>(__t); }
+       static
+       typename enable_if<!is_lvalue_reference<_Tp>::value, _Tp>::type&&
+       _S_maybe_wrap_ref(_Tp&& __t)
+       { return std::forward<_Tp>(__t); }
+
+      struct _Impl : _Alloc
+      {
+       _Impl(_Fn&& __fn, const _Alloc& __a)
+         : _Alloc(__a), _M_fn(std::move(__fn)) { }
+       _Fn _M_fn;
+      } _M_impl;
     };
 
+    template<typename _Signature, typename _Fn, typename _Alloc>
+      static shared_ptr<__future_base::_Task_state_base<_Signature>>
+      __create_task_state(_Fn&& __fn, const _Alloc& __a)
+      {
+       typedef __future_base::_Task_state<_Fn, _Alloc, _Signature> _State;
+       return std::allocate_shared<_State>(__a, std::move(__fn), __a);
+      }
+
+  template<typename _Fn, typename _Alloc, typename _Res, typename... _Args>
+    shared_ptr<__future_base::_Task_state_base<_Res(_Args...)>>
+    __future_base::_Task_state<_Fn, _Alloc, _Res(_Args...)>::_M_reset()
+    {
+      return __create_task_state<_Res(_Args...)>(std::move(_M_impl._M_fn),
+                                                static_cast<_Alloc&>(_M_impl));
+    }
+
   template<typename _Task, typename _Fn, bool
-           = is_same<_Task, typename decay<_Fn>::type>::value>
+          = is_same<_Task, typename decay<_Fn>::type>::value>
     struct __constrain_pkgdtask
     { typedef void __type; };
 
@@ -1299,37 +1351,40 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Res, typename... _ArgTypes>
     class packaged_task<_Res(_ArgTypes...)>
     {
-      typedef __future_base::_Task_state<_Res(_ArgTypes...)>  _State_type;
+      typedef __future_base::_Task_state_base<_Res(_ArgTypes...)> _State_type;
       shared_ptr<_State_type>                   _M_state;
 
     public:
       // Construction and destruction
       packaged_task() noexcept { }
 
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 2095.  missing constructors needed for uses-allocator construction
       template<typename _Allocator>
-        explicit
-        packaged_task(allocator_arg_t, const _Allocator& __a) noexcept
-        { }
+       packaged_task(allocator_arg_t, const _Allocator& __a) noexcept
+       { }
 
       template<typename _Fn, typename = typename
-               __constrain_pkgdtask<packaged_task, _Fn>::__type>
-        explicit
-        packaged_task(_Fn&& __fn)
-        : _M_state(std::make_shared<_State_type>(std::forward<_Fn>(__fn)))
-        { }
-
-      template<typename _Fn, typename _Allocator, typename = typename
-               __constrain_pkgdtask<packaged_task, _Fn>::__type>
-        explicit
-        packaged_task(allocator_arg_t, const _Allocator& __a, _Fn&& __fn)
-        : _M_state(std::allocate_shared<_State_type>(__a,
-                                                     std::forward<_Fn>(__fn)))
-        { }
+              __constrain_pkgdtask<packaged_task, _Fn>::__type>
+       explicit
+       packaged_task(_Fn&& __fn)
+       : packaged_task(allocator_arg, std::allocator<int>(), std::move(__fn))
+       { }
+
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 2097.  packaged_task constructors should be constrained
+      template<typename _Fn, typename _Alloc, typename = typename
+              __constrain_pkgdtask<packaged_task, _Fn>::__type>
+       explicit
+       packaged_task(allocator_arg_t, const _Alloc& __a, _Fn&& __fn)
+       : _M_state(__create_task_state<_Res(_ArgTypes...)>(
+                   std::forward<_Fn>(__fn), __a))
+       { }
 
       ~packaged_task()
       {
         if (static_cast<bool>(_M_state) && !_M_state.unique())
-          _M_state->_M_break_promise(std::move(_M_state->_M_result));
+         _M_state->_M_break_promise(std::move(_M_state->_M_result));
       }
 
       // No copy
@@ -1337,24 +1392,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       packaged_task& operator=(const packaged_task&) = delete;
 
       template<typename _Allocator>
-        explicit
-        packaged_task(allocator_arg_t, const _Allocator&,
-                      const packaged_task&) = delete;
+       packaged_task(allocator_arg_t, const _Allocator&,
+                     const packaged_task&) = delete;
 
       // Move support
       packaged_task(packaged_task&& __other) noexcept
       { this->swap(__other); }
 
       template<typename _Allocator>
-        explicit
-        packaged_task(allocator_arg_t, const _Allocator&,
-                      packaged_task&& __other) noexcept
-        { this->swap(__other); }
+       packaged_task(allocator_arg_t, const _Allocator&,
+                     packaged_task&& __other) noexcept
+       { this->swap(__other); }
 
       packaged_task& operator=(packaged_task&& __other) noexcept
       {
-        packaged_task(std::move(__other)).swap(*this);
-        return *this;
+       packaged_task(std::move(__other)).swap(*this);
+       return *this;
       }
 
       void
@@ -1374,15 +1427,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       void
       operator()(_ArgTypes... __args)
       {
-        __future_base::_State_base::_S_check(_M_state);
-        _M_state->_M_run(std::forward<_ArgTypes>(__args)...);
+       __future_base::_State_base::_S_check(_M_state);
+       _M_state->_M_run(std::forward<_ArgTypes>(__args)...);
       }
 
       void
       reset()
       {
-        __future_base::_State_base::_S_check(_M_state);
-        packaged_task(std::move(_M_state->_M_task)).swap(*this);
+       __future_base::_State_base::_S_check(_M_state);
+       packaged_task __tmp;
+       __tmp._M_state = _M_state;
+       _M_state = _M_state->_M_reset();
       }
     };
 
@@ -1413,26 +1468,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       _Ptr_type _M_result;
       _BoundFn _M_fn;
 
+      // Run the deferred function.
       virtual void
-      _M_run_deferred()
+      _M_complete_async()
       {
         // safe to call multiple times so ignore failure
         _M_set_result(_S_task_setter(_M_result, _M_fn), true);
       }
+
+      virtual bool
+      _M_has_deferred() const { return static_cast<bool>(_M_result); }
     };
 
-  class __future_base::_Async_state_common : public __future_base::_State_base
+  class __future_base::_Async_state_commonV2
+    : public __future_base::_State_base
   {
   protected:
-#ifdef _GLIBCXX_ASYNC_ABI_COMPAT
-    ~_Async_state_common();
-#else
-    ~_Async_state_common() = default;
-#endif
+    ~_Async_state_commonV2() = default;
 
-    // Allow non-timed waiting functions to block until the thread completes,
-    // as if joined.
-    virtual void _M_run_deferred() { _M_join(); }
+    // Make waiting functions block until the thread completes, as if joined.
+    virtual void _M_complete_async() { _M_join(); }
 
     void _M_join() { std::call_once(_M_once, &thread::join, ref(_M_thread)); }
 
@@ -1442,7 +1497,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template<typename _BoundFn, typename _Res>
     class __future_base::_Async_state_impl final
-    : public __future_base::_Async_state_common
+    : public __future_base::_Async_state_commonV2
     {
     public:
       explicit
@@ -1503,14 +1558,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   /// async, potential overload
   template<typename _Fn, typename... _Args>
-    inline typename
-    __async_sfinae_helper<typename decay<_Fn>::type, _Fn, _Args...>::type
+    inline future<typename result_of<_Fn(_Args...)>::type>
     async(_Fn&& __fn, _Args&&... __args)
     {
       return async(launch::async|launch::deferred, std::forward<_Fn>(__fn),
                   std::forward<_Args>(__args)...);
     }
 
+#endif // _GLIBCXX_ASYNC_ABI_COMPAT
 #endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1
        // && ATOMIC_INT_LOCK_FREE