1 // future -*- C++ -*- 2 3 // Copyright (C) 2009-2022 Free Software Foundation, Inc. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the 7 // terms of the GNU General Public License as published by the 8 // Free Software Foundation; either version 3, or (at your option) 9 // any later version. 10 11 // This library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 16 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 // <http://www.gnu.org/licenses/>. 24 25 #include <future> 26 #include <bits/functexcept.h> 27 28 #if __has_cpp_attribute(clang::require_constant_initialization) 29 # define __constinit [[clang::require_constant_initialization]] 30 #endif 31 32 namespace 33 { 34 struct future_error_category final : public std::error_category 35 { 36 const char* 37 name() const noexcept final 38 { return "future"; } 39 40 _GLIBCXX_DEFAULT_ABI_TAG 41 std::string 42 message(int __ec) const final 43 { 44 std::string __msg; 45 switch (std::future_errc(__ec)) 46 { 47 case std::future_errc::broken_promise: 48 __msg = "Broken promise"; 49 break; 50 case std::future_errc::future_already_retrieved: 51 __msg = "Future already retrieved"; 52 break; 53 case std::future_errc::promise_already_satisfied: 54 __msg = "Promise already satisfied"; 55 break; 56 case std::future_errc::no_state: 57 __msg = "No associated state"; 58 break; 59 default: 60 __msg = "Unknown error"; 61 break; 62 } 63 return __msg; 64 } 65 }; 66 67 struct constant_init 68 { 69 union { 70 unsigned char unused; 71 future_error_category cat; 72 }; 73 constexpr constant_init() : cat() { } 74 ~constant_init() { /* do nothing, union member is not destroyed */ } 75 }; 76 77 __constinit constant_init future_category_instance{}; 78 } 79 80 namespace std _GLIBCXX_VISIBILITY(default) 81 { 82 _GLIBCXX_BEGIN_NAMESPACE_VERSION 83 84 void 85 __throw_future_error(int __i __attribute__((unused))) 86 { _GLIBCXX_THROW_OR_ABORT(future_error(make_error_code(future_errc(__i)))); } 87 88 const error_category& future_category() noexcept 89 { return future_category_instance.cat; } 90 91 future_error::~future_error() noexcept { } 92 93 const char* 94 future_error::what() const noexcept { return logic_error::what(); } 95 96 #ifdef _GLIBCXX_HAS_GTHREADS 97 __future_base::_Result_base::_Result_base() = default; 98 99 __future_base::_Result_base::~_Result_base() = default; 100 101 void 102 __future_base::_State_baseV2::_Make_ready::_S_run(void* p) 103 { 104 unique_ptr<_Make_ready> mr{static_cast<_Make_ready*>(p)}; 105 if (auto state = mr->_M_shared_state.lock()) 106 { 107 // Use release MO to synchronize with observers of the ready state. 108 state->_M_status._M_store_notify_all(_Status::__ready, 109 memory_order_release); 110 } 111 } 112 113 // defined in src/c++11/condition_variable.cc 114 extern void 115 __at_thread_exit(__at_thread_exit_elt* elt); 116 117 void 118 __future_base::_State_baseV2::_Make_ready::_M_set() 119 { 120 _M_cb = &_Make_ready::_S_run; 121 __at_thread_exit(this); 122 } 123 #endif // _GLIBCXX_HAS_GTHREADS 124 125 _GLIBCXX_END_NAMESPACE_VERSION 126 } // namespace std 127