]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - libstdc++-v3/include/std/future
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / include / std / future
index 93889cd49d222244cc1fb5e6ba8de47148d160d2..59aa981261b2e2aa27e5212ebd5953dcadb9aa44 100644 (file)
@@ -1,6 +1,6 @@
 // <future> -*- C++ -*-
 
-// Copyright (C) 2009-2015 Free Software Foundation, Inc.
+// Copyright (C) 2009-2020 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
@@ -35,7 +35,6 @@
 # include <bits/c++0x_warning.h>
 #else
 
-#include <functional>
 #include <mutex>
 #include <thread>
 #include <condition_variable>
 #include <atomic>
 #include <bits/atomic_futex.h>
 #include <bits/functexcept.h>
+#include <bits/invoke.h>
 #include <bits/unique_ptr.h>
 #include <bits/shared_ptr.h>
+#include <bits/std_function.h>
 #include <bits/uses_allocator.h>
 #include <bits/allocated_ptr.h>
 #include <ext/aligned_buffer.h>
@@ -94,11 +95,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    */
   class future_error : public logic_error
   {
-    error_code                         _M_code;
-
   public:
-    explicit future_error(error_code __ec)
-    : logic_error("std::future_error: " + __ec.message()), _M_code(__ec)
+    explicit
+    future_error(future_errc __errc)
+    : future_error(std::make_error_code(__errc))
     { }
 
     virtual ~future_error() noexcept;
@@ -108,6 +108,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
     const error_code&
     code() const noexcept { return _M_code; }
+
+  private:
+    explicit
+    future_error(error_code __ec)
+    : logic_error("std::future_error: " + __ec.message()), _M_code(__ec)
+    { }
+
+    friend void __throw_future_error(int);
+
+    error_code                         _M_code;
   };
 
   // Forward declarations.
@@ -171,8 +181,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // _GLIBCXX_RESOLVE_LIB_DEFECTS
   // 2021. Further incorrect usages of result_of
   template<typename _Fn, typename... _Args>
-    using __async_result_of = typename result_of<
-      typename decay<_Fn>::type(typename decay<_Args>::type...)>::type;
+    using __async_result_of = typename __invoke_result<
+      typename decay<_Fn>::type, typename decay<_Args>::type...>::type;
 
   template<typename _Fn, typename... _Args>
     future<__async_result_of<_Fn, _Args...>>
@@ -182,8 +192,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     future<__async_result_of<_Fn, _Args...>>
     async(_Fn&& __fn, _Args&&... __args);
 
-#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) \
-  && (ATOMIC_INT_LOCK_FREE > 1)
+#if defined(_GLIBCXX_HAS_GTHREADS)
 
   /// Base class and enclosing scope.
   struct __future_base
@@ -225,7 +234,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        typedef _Res result_type;
 
        _Result() noexcept : _M_initialized() { }
-       
+
        ~_Result()
        {
          if (_M_initialized)
@@ -263,7 +272,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
         explicit
        _Result_alloc(const _Alloc& __a) : _Result<_Res>(), _Alloc(__a)
        { }
-       
+
       private:
        void _M_destroy()
        {
@@ -425,8 +434,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       {
        if (static_cast<bool>(__res))
          {
-           error_code __ec(make_error_code(future_errc::broken_promise));
-           __res->_M_error = make_exception_ptr(future_error(__ec));
+           __res->_M_error =
+             make_exception_ptr(future_error(future_errc::broken_promise));
            // This function is only called when the last asynchronous result
            // provider is abandoning this shared state, so noone can be
            // trying to make the shared state ready at the same time, and
@@ -462,7 +471,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
          // Used by std::promise to copy construct the result.
           typename promise<_Res>::_Ptr_type operator()() const
           {
-            _State_baseV2::_S_check(_M_promise->_M_future);
             _M_promise->_M_storage->_M_set(*_M_arg);
             return std::move(_M_promise->_M_storage);
           }
@@ -477,7 +485,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
          // Used by std::promise to move construct the result.
           typename promise<_Res>::_Ptr_type operator()() const
           {
-            _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);
           }
@@ -485,6 +492,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
           _Res*             _M_arg;
         };
 
+      // set void
+      template<typename _Res>
+       struct _Setter<_Res, void>
+       {
+         static_assert(is_void<_Res>::value, "Only used for promise<void>");
+
+         typename promise<_Res>::_Ptr_type operator()() const
+         { return std::move(_M_promise->_M_storage); }
+
+         promise<_Res>*    _M_promise;
+       };
+
       struct __exception_ptr_tag { };
 
       // set exceptions
@@ -494,7 +513,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
          // Used by std::promise to store an exception as the result.
           typename promise<_Res>::_Ptr_type operator()() const
           {
-            _State_baseV2::_S_check(_M_promise->_M_future);
             _M_promise->_M_storage->_M_error = *_M_ex;
             return std::move(_M_promise->_M_storage);
           }
@@ -507,16 +525,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
         static _Setter<_Res, _Arg&&>
         __setter(promise<_Res>* __prom, _Arg&& __arg)
         {
-          return _Setter<_Res, _Arg&&>{ __prom, &__arg };
+         _S_check(__prom->_M_future);
+          return _Setter<_Res, _Arg&&>{ __prom, std::__addressof(__arg) };
         }
 
       template<typename _Res>
         static _Setter<_Res, __exception_ptr_tag>
         __setter(exception_ptr& __ex, promise<_Res>* __prom)
         {
+         _S_check(__prom->_M_future);
           return _Setter<_Res, __exception_ptr_tag>{ __prom, &__ex };
         }
 
+      template<typename _Res>
+       static _Setter<_Res, void>
+       __setter(promise<_Res>* __prom)
+       {
+         _S_check(__prom->_M_future);
+         return _Setter<_Res, void>{ __prom };
+       }
+
       template<typename _Tp>
         static void
         _S_check(const shared_ptr<_Tp>& __p)
@@ -560,10 +588,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     class _Async_state_commonV2;
 #endif
 
-    template<typename _BoundFn, typename = typename _BoundFn::result_type>
+    template<typename _BoundFn,
+            typename _Res = decltype(std::declval<_BoundFn&>()())>
       class _Deferred_state;
 
-    template<typename _BoundFn, typename = typename _BoundFn::result_type>
+    template<typename _BoundFn,
+            typename _Res = decltype(std::declval<_BoundFn&>()())>
       class _Async_state_impl;
 
     template<typename _Signature>
@@ -766,7 +796,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
         return std::move(this->_M_get_result()._M_value());
       }
 
-      shared_future<_Res> share();
+      shared_future<_Res> share() noexcept;
     };
 
   /// Partial specialization for future<R&>
@@ -809,7 +839,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
         return this->_M_get_result()._M_get();
       }
 
-      shared_future<_Res&> share();
+      shared_future<_Res&> share() noexcept;
     };
 
   /// Explicit specialization for future<void>
@@ -852,7 +882,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
         this->_M_get_result();
       }
 
-      shared_future<void> share();
+      shared_future<void> share() noexcept;
     };
 
 
@@ -866,7 +896,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       constexpr shared_future() noexcept : _Base_type() { }
 
       /// Copy constructor
-      shared_future(const shared_future& __sf) : _Base_type(__sf) { }
+      shared_future(const shared_future& __sf) noexcept : _Base_type(__sf) { }
 
       /// Construct from a future rvalue
       shared_future(future<_Res>&& __uf) noexcept
@@ -878,7 +908,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       : _Base_type(std::move(__sf))
       { }
 
-      shared_future& operator=(const shared_future& __sf)
+      shared_future& operator=(const shared_future& __sf) noexcept
       {
         shared_future(__sf)._M_swap(*this);
         return *this;
@@ -992,18 +1022,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     : _M_state(std::move(__uf._M_state))
     { }
 
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // 2556. Wide contract for future::share()
   template<typename _Res>
     inline shared_future<_Res>
-    future<_Res>::share()
+    future<_Res>::share() noexcept
     { return shared_future<_Res>(std::move(*this)); }
 
   template<typename _Res>
     inline shared_future<_Res&>
-    future<_Res&>::share()
+    future<_Res&>::share() noexcept
     { return shared_future<_Res&>(std::move(*this)); }
 
   inline shared_future<void>
-  future<void>::share()
+  future<void>::share() noexcept
   { return shared_future<void>(std::move(*this)); }
 
   /// Primary template for promise
@@ -1014,6 +1046,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef __future_base::_Result<_Res>     _Res_type;
       typedef __future_base::_Ptr<_Res_type>   _Ptr_type;
       template<typename, typename> friend class _State::_Setter;
+      friend _State;
 
       shared_ptr<_State>                        _M_future;
       _Ptr_type                                 _M_storage;
@@ -1124,6 +1157,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef __future_base::_Result<_Res&>    _Res_type;
       typedef __future_base::_Ptr<_Res_type>   _Ptr_type;
       template<typename, typename> friend class _State::_Setter;
+      friend _State;
 
       shared_ptr<_State>                        _M_future;
       _Ptr_type                                 _M_storage;
@@ -1213,6 +1247,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef __future_base::_Result<void>     _Res_type;
       typedef __future_base::_Ptr<_Res_type>   _Ptr_type;
       template<typename, typename> friend class _State::_Setter;
+      friend _State;
 
       shared_ptr<_State>                        _M_future;
       _Ptr_type                                 _M_storage;
@@ -1273,14 +1308,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       { return future<void>(_M_future); }
 
       // Setting the result
-      void set_value();
+      void
+      set_value()
+      { _M_future->_M_set_result(_State::__setter(this)); }
 
       void
       set_exception(exception_ptr __p)
       { _M_future->_M_set_result(_State::__setter(__p, this)); }
 
       void
-      set_value_at_thread_exit();
+      set_value_at_thread_exit()
+      { _M_future->_M_set_delayed_result(_State::__setter(this), _M_future); }
 
       void
       set_exception_at_thread_exit(exception_ptr __p)
@@ -1290,30 +1328,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       }
     };
 
-  // set void
-  template<>
-    struct __future_base::_State_base::_Setter<void, void>
-    {
-      promise<void>::_Ptr_type operator()() const
-      {
-        _State_base::_S_check(_M_promise->_M_future);
-        return std::move(_M_promise->_M_storage);
-      }
-
-      promise<void>*    _M_promise;
-    };
-
-  inline void
-  promise<void>::set_value()
-  { _M_future->_M_set_result(_State::_Setter<void, void>{ this }); }
-
-  inline void
-  promise<void>::set_value_at_thread_exit()
-  {
-    _M_future->_M_set_delayed_result(_State::_Setter<void, void>{this},
-                                    _M_future);
-  }
-
   template<typename _Ptr_type, typename _Fn, typename _Res>
     struct __future_base::_Task_setter
     {
@@ -1403,18 +1417,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       virtual void
       _M_run(_Args&&... __args)
       {
-       // 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 __boundfn = [&] () -> _Res {
+           return std::__invoke_r<_Res>(_M_impl._M_fn,
+                                        std::forward<_Args>(__args)...);
+       };
        this->_M_set_result(_S_task_setter(this->_M_result, __boundfn));
       }
 
       virtual void
       _M_run_delayed(_Args&&... __args, weak_ptr<_State_base> __self)
       {
-       // 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 __boundfn = [&] () -> _Res {
+           return std::__invoke_r<_Res>(_M_impl._M_fn,
+                                        std::forward<_Args>(__args)...);
+       };
        this->_M_set_delayed_result(_S_task_setter(this->_M_result, __boundfn),
                                    std::move(__self));
       }
@@ -1422,17 +1438,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       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); }
-
-      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); }
-
       struct _Impl : _Alloc
       {
        template<typename _Fn2>
@@ -1442,9 +1447,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       } _M_impl;
     };
 
-  template<typename _Signature, typename _Fn, typename _Alloc>
+  template<typename _Signature, typename _Fn,
+          typename _Alloc = std::allocator<int>>
     static shared_ptr<__future_base::_Task_state_base<_Signature>>
-    __create_task_state(_Fn&& __fn, const _Alloc& __a)
+    __create_task_state(_Fn&& __fn, const _Alloc& __a = _Alloc())
     {
       typedef typename decay<_Fn>::type _Fn2;
       typedef __future_base::_Task_state<_Fn2, _Alloc, _Signature> _State;
@@ -1459,15 +1465,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                                                 static_cast<_Alloc&>(_M_impl));
     }
 
-  template<typename _Task, typename _Fn, bool
-          = is_same<_Task, typename decay<_Fn>::type>::value>
-    struct __constrain_pkgdtask
-    { typedef void __type; };
-
-  template<typename _Task, typename _Fn>
-    struct __constrain_pkgdtask<_Task, _Fn, true>
-    { };
-
   /// packaged_task
   template<typename _Res, typename... _ArgTypes>
     class packaged_task<_Res(_ArgTypes...)>
@@ -1475,34 +1472,50 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef __future_base::_Task_state_base<_Res(_ArgTypes...)> _State_type;
       shared_ptr<_State_type>                   _M_state;
 
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 3039. Unnecessary decay in thread and packaged_task
+      template<typename _Fn, typename _Fn2 = __remove_cvref_t<_Fn>>
+       using __not_same
+         = typename enable_if<!is_same<packaged_task, _Fn2>::value>::type;
+
     public:
       // Construction and destruction
       packaged_task() noexcept { }
 
-      // _GLIBCXX_RESOLVE_LIB_DEFECTS
-      // 2095.  missing constructors needed for uses-allocator construction
-      template<typename _Allocator>
-       packaged_task(allocator_arg_t, const _Allocator& __a) noexcept
-       { }
-
-      template<typename _Fn, typename = typename
-              __constrain_pkgdtask<packaged_task, _Fn>::__type>
+      template<typename _Fn, typename = __not_same<_Fn>>
        explicit
        packaged_task(_Fn&& __fn)
-       : packaged_task(allocator_arg, std::allocator<int>(),
-                       std::forward<_Fn>(__fn))
+       : _M_state(
+           __create_task_state<_Res(_ArgTypes...)>(std::forward<_Fn>(__fn)))
        { }
 
+#if __cplusplus < 201703L
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
-      // 2097.  packaged_task constructors should be constrained
+      // 2097. packaged_task constructors should be constrained
       // 2407. [this constructor should not be] explicit
-      template<typename _Fn, typename _Alloc, typename = typename
-              __constrain_pkgdtask<packaged_task, _Fn>::__type>
+      // 2921. packaged_task and type-erased allocators
+      template<typename _Fn, typename _Alloc, typename = __not_same<_Fn>>
        packaged_task(allocator_arg_t, const _Alloc& __a, _Fn&& __fn)
        : _M_state(__create_task_state<_Res(_ArgTypes...)>(
-                   std::forward<_Fn>(__fn), __a))
+                  std::forward<_Fn>(__fn), __a))
        { }
 
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 2095.  missing constructors needed for uses-allocator construction
+      template<typename _Allocator>
+       packaged_task(allocator_arg_t, const _Allocator& __a) noexcept
+       { }
+
+      template<typename _Allocator>
+       packaged_task(allocator_arg_t, const _Allocator&,
+                     const packaged_task&) = delete;
+
+      template<typename _Allocator>
+       packaged_task(allocator_arg_t, const _Allocator&,
+                     packaged_task&& __other) noexcept
+       { this->swap(__other); }
+#endif
+
       ~packaged_task()
       {
         if (static_cast<bool>(_M_state) && !_M_state.unique())
@@ -1513,19 +1526,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       packaged_task(const packaged_task&) = delete;
       packaged_task& operator=(const packaged_task&) = delete;
 
-      template<typename _Allocator>
-       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>
-       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);
@@ -1577,10 +1581,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
         packaged_task<_Res(_ArgTypes...)>& __y) noexcept
     { __x.swap(__y); }
 
+#if __cplusplus < 201703L
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // 2976. Dangling uses_allocator specialization for packaged_task
   template<typename _Res, typename _Alloc>
     struct uses_allocator<packaged_task<_Res>, _Alloc>
     : public true_type { };
-
+#endif
 
   // Shared state created by std::async().
   // Holds a deferred function and storage for its result.
@@ -1631,17 +1638,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     //
     // [futures.async]:
     //
-    //  a call to a waiting function on an asynchronous return object that
+    // - a call to a waiting function on an asynchronous return object that
     // shares the shared state created by this async call shall block until
     // the associated thread has completed, as if joined, or else time out.
     //
-    //  the associated thread completion synchronizes with the return from
+    // - the associated thread completion synchronizes with the return from
     // the first function that successfully detects the ready status of the
     // shared state or with the return from the last function that releases
     // the shared state, whichever happens first.
     virtual void _M_complete_async() { _M_join(); }
 
-    void _M_join() { std::call_once(_M_once, &thread::join, ref(_M_thread)); }
+    void _M_join() { std::call_once(_M_once, &thread::join, &_M_thread); }
 
     thread _M_thread;
     once_flag _M_once;
@@ -1705,7 +1712,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   /// async
   template<typename _Fn, typename... _Args>
-    future<__async_result_of<_Fn, _Args...>>
+    _GLIBCXX_NODISCARD future<__async_result_of<_Fn, _Args...>>
     async(launch __policy, _Fn&& __fn, _Args&&... __args)
     {
       std::shared_ptr<__future_base::_State_base> __state;
@@ -1713,8 +1720,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        {
          __try
            {
-             __state = __future_base::_S_make_async_state(std::__bind_simple(
-                 std::forward<_Fn>(__fn), std::forward<_Args>(__args)...));
+             __state = __future_base::_S_make_async_state(
+                 std::thread::__make_invoker(std::forward<_Fn>(__fn),
+                                             std::forward<_Args>(__args)...)
+                 );
            }
 #if __cpp_exceptions
          catch(const system_error& __e)
@@ -1727,15 +1736,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        }
       if (!__state)
        {
-         __state = __future_base::_S_make_deferred_state(std::__bind_simple(
-              std::forward<_Fn>(__fn), std::forward<_Args>(__args)...));
+         __state = __future_base::_S_make_deferred_state(
+             std::thread::__make_invoker(std::forward<_Fn>(__fn),
+                                         std::forward<_Args>(__args)...));
        }
       return future<__async_result_of<_Fn, _Args...>>(__state);
     }
 
   /// async, potential overload
   template<typename _Fn, typename... _Args>
-    inline future<__async_result_of<_Fn, _Args...>>
+    _GLIBCXX_NODISCARD inline future<__async_result_of<_Fn, _Args...>>
     async(_Fn&& __fn, _Args&&... __args)
     {
       return std::async(launch::async|launch::deferred,
@@ -1744,8 +1754,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
 #endif // _GLIBCXX_ASYNC_ABI_COMPAT
-#endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1
-       // && ATOMIC_INT_LOCK_FREE
+#endif // _GLIBCXX_HAS_GTHREADS
 
   // @} group futures
 _GLIBCXX_END_NAMESPACE_VERSION