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 32namespace 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 80namespace 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