|
1 | | -// Copyright (c) 2007-2025 Hartmut Kaiser |
| 1 | +// Copyright (c) 2007-2023 Hartmut Kaiser |
2 | 2 | // |
3 | 3 | // SPDX-License-Identifier: BSL-1.0 |
4 | 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying |
5 | 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
6 | 6 |
|
| 7 | +/// \file exception_list.hpp |
| 8 | + |
| 9 | +#pragma once |
| 10 | + |
7 | 11 | #include <hpx/config.hpp> |
8 | 12 | #include <hpx/errors/exception.hpp> |
9 | | -#include <hpx/errors/exception_list.hpp> |
10 | 13 | #include <hpx/modules/thread_support.hpp> |
11 | 14 |
|
| 15 | +#include <cstddef> |
12 | 16 | #include <exception> |
| 17 | +#include <list> |
13 | 18 | #include <mutex> |
14 | | -#include <set> |
15 | 19 | #include <string> |
16 | 20 | #include <system_error> |
17 | | -#include <utility> |
18 | 21 |
|
19 | | -namespace hpx { |
20 | | - namespace detail { |
21 | | - std::string indent_message(std::string const& msg_) |
22 | | - { |
23 | | - std::string result; |
24 | | - std::string const& msg(msg_); |
25 | | - std::string::size_type pos = msg.find_first_of('\n'); |
26 | | - std::string::size_type first_non_ws = msg.find_first_not_of(" \n"); |
27 | | - std::string::size_type pos1 = 0; |
28 | | - |
29 | | - while (std::string::npos != pos) |
30 | | - { |
31 | | - if (pos > first_non_ws) |
32 | | - { // skip leading newline |
33 | | - result += msg.substr(pos1, pos - pos1 + 1); |
34 | | - pos = msg.find_first_of('\n', pos1 = pos + 1); |
35 | | - if (std::string::npos != pos) |
36 | | - { |
37 | | - result += " "; |
38 | | - } |
39 | | - } |
40 | | - else |
41 | | - { |
42 | | - pos = msg.find_first_of('\n', pos1 = pos + 1); |
43 | | - } |
44 | | - } |
45 | | - |
46 | | - result += msg.substr(pos1); |
47 | | - return result; |
48 | | - } |
49 | | - } // namespace detail |
| 22 | +#include <hpx/config/warnings_prefix.hpp> |
50 | 23 |
|
51 | | - error_code throws; // "throw on error" special error_code; |
52 | | - // |
53 | | - // Note that it doesn't matter if this isn't |
54 | | - // initialized before use since the only use is |
55 | | - // to take its address for comparison purposes. |
| 24 | +/////////////////////////////////////////////////////////////////////////////// |
| 25 | +namespace hpx { |
56 | 26 |
|
57 | | - exception_list::exception_list() |
58 | | - : hpx::exception(hpx::error::success) |
59 | | - , mtx_() |
| 27 | + /// The class exception_list is a container of exception_ptr objects |
| 28 | + /// parallel algorithms may use to communicate uncaught exceptions |
| 29 | + /// encountered during parallel execution to the caller of the algorithm |
| 30 | + /// |
| 31 | + /// The type exception_list::const_iterator fulfills the requirements of |
| 32 | + /// a forward iterator. |
| 33 | + /// |
| 34 | + HPX_CXX_EXPORT class HPX_CORE_EXPORT exception_list : public hpx::exception |
60 | 35 | { |
61 | | - } |
| 36 | + private: |
| 37 | + /// \cond NOINTERNAL |
62 | 38 |
|
63 | | - exception_list::exception_list(std::exception_ptr const& e) |
64 | | - : hpx::exception(hpx::get_error(e), hpx::get_error_what(e)) |
65 | | - , mtx_() |
66 | | - { |
67 | | - add_no_lock(e); |
68 | | - } |
69 | | - |
70 | | - exception_list::exception_list(exception_list_type&& l) |
71 | | - : hpx::exception( |
72 | | - !l.empty() ? hpx::get_error(l.front()) : hpx::error::success) |
73 | | - , exceptions_(HPX_MOVE(l)) |
74 | | - , mtx_() |
75 | | - { |
76 | | - } |
| 39 | + // TODO: Does this need to be hpx::spinlock? |
| 40 | + // typedef hpx::spinlock mutex_type; |
| 41 | + // TODO: Add correct initialization of hpx::util::detail spinlock. |
| 42 | + using mutex_type = hpx::util::detail::spinlock; |
77 | 43 |
|
78 | | - exception_list::exception_list(exception_list const& l) |
79 | | - : hpx::exception(static_cast<hpx::exception const&>(l)) |
80 | | - , exceptions_(l.exceptions_) |
81 | | - , mtx_() |
82 | | - { |
83 | | - } |
| 44 | + using exception_list_type = std::list<std::exception_ptr>; |
| 45 | + exception_list_type exceptions_; |
| 46 | + mutable mutex_type mtx_; |
84 | 47 |
|
85 | | - exception_list::exception_list(exception_list&& l) noexcept |
86 | | - : hpx::exception(HPX_MOVE(static_cast<hpx::exception&>(l))) |
87 | | - , exceptions_(HPX_MOVE(l.exceptions_)) |
88 | | - , mtx_() |
89 | | - { |
90 | | - } |
| 48 | + void add_no_lock(std::exception_ptr const& e); |
| 49 | + /// \endcond |
91 | 50 |
|
92 | | - exception_list& exception_list::operator=(exception_list const& l) |
93 | | - { |
94 | | - if (this != &l) |
95 | | - { |
96 | | - *static_cast<hpx::exception*>(this) = |
97 | | - static_cast<hpx::exception const&>(l); |
98 | | - exceptions_ = l.exceptions_; |
99 | | - } |
100 | | - return *this; |
101 | | - } |
| 51 | + public: |
| 52 | + /// bidirectional iterator |
| 53 | + using iterator = exception_list_type::const_iterator; |
102 | 54 |
|
103 | | - exception_list& exception_list::operator=(exception_list&& l) noexcept |
104 | | - { |
105 | | - if (this != &l) |
106 | | - { |
107 | | - static_cast<hpx::exception&>(*this) = |
108 | | - HPX_MOVE(static_cast<hpx::exception&>(l)); |
109 | | - exceptions_ = HPX_MOVE(l.exceptions_); |
110 | | - } |
111 | | - return *this; |
112 | | - } |
| 55 | + /// \cond NOINTERNAL |
| 56 | + // \throws nothing |
| 57 | + ~exception_list() noexcept override = default; |
113 | 58 |
|
114 | | - /////////////////////////////////////////////////////////////////////////// |
115 | | - std::error_code exception_list::get_error_code() const |
116 | | - { |
117 | | - std::lock_guard<mutex_type> l(mtx_); |
118 | | - if (exceptions_.empty()) |
119 | | - return hpx::error::no_success; |
120 | | - return hpx::get_error(exceptions_.front()); |
121 | | - } |
| 59 | + exception_list(); |
| 60 | + explicit exception_list(std::exception_ptr const& e); |
| 61 | + explicit exception_list(exception_list_type&& l); |
122 | 62 |
|
123 | | - std::string exception_list::get_message() const |
124 | | - { |
125 | | - std::lock_guard<mutex_type> l(mtx_); |
126 | | - if (exceptions_.empty()) |
127 | | - return ""; |
| 63 | + exception_list(exception_list const& l); |
| 64 | + exception_list(exception_list&& l) noexcept; |
128 | 65 |
|
129 | | - if (1 == exceptions_.size()) |
130 | | - return hpx::get_error_what(exceptions_.front()); |
| 66 | + exception_list& operator=(exception_list const& l); |
| 67 | + exception_list& operator=(exception_list&& l) noexcept; |
131 | 68 |
|
132 | | - std::string result("\n"); |
| 69 | + /// |
| 70 | + void add(std::exception_ptr const& e); |
| 71 | + /// \endcond |
133 | 72 |
|
134 | | - exception_list_type::const_iterator end = exceptions_.end(); |
135 | | - exception_list_type::const_iterator it = exceptions_.begin(); |
136 | | - for (/**/; it != end; ++it) |
| 73 | + /// The number of exception_ptr objects contained within the |
| 74 | + /// exception_list. |
| 75 | + /// |
| 76 | + /// \note Complexity: Constant time. |
| 77 | + [[nodiscard]] std::size_t size() const noexcept |
137 | 78 | { |
138 | | - result += " "; |
139 | | - result += detail::indent_message(hpx::get_error_what(*it)); |
140 | | - if (result.find_last_of('\n') < result.size() - 1) |
141 | | - result += "\n"; |
| 79 | + std::lock_guard<mutex_type> l(mtx_); |
| 80 | + return exceptions_.size(); |
142 | 81 | } |
143 | | - return result; |
144 | | - } |
145 | 82 |
|
146 | | - void exception_list::add(std::exception_ptr const& e) |
147 | | - { |
148 | | - std::unique_lock<mutex_type> l(mtx_); |
149 | | - if (exceptions_.empty()) |
| 83 | + /// An iterator referring to the first exception_ptr object contained |
| 84 | + /// within the exception_list. |
| 85 | + [[nodiscard]] exception_list_type::const_iterator begin() const noexcept |
150 | 86 | { |
151 | | - hpx::exception ex; |
152 | | - { |
153 | | - unlock_guard<std::unique_lock<mutex_type>> ul(l); |
154 | | - ex = hpx::exception(hpx::get_error(e), hpx::get_error_what(e)); |
155 | | - } |
156 | | - |
157 | | - // set the error code for our base class |
158 | | - static_cast<hpx::exception&>(*this) = ex; |
| 87 | + std::lock_guard<mutex_type> l(mtx_); |
| 88 | + return exceptions_.begin(); |
159 | 89 | } |
160 | | - exceptions_.push_back(e); |
161 | | - } |
162 | 90 |
|
163 | | - void exception_list::add_no_lock(std::exception_ptr const& e) |
164 | | - { |
165 | | - exceptions_.push_back(e); |
166 | | - } |
| 91 | + /// An iterator which is the past-the-end value for the exception_list. |
| 92 | + [[nodiscard]] exception_list_type::const_iterator end() const noexcept |
| 93 | + { |
| 94 | + std::lock_guard<mutex_type> l(mtx_); |
| 95 | + return exceptions_.end(); |
| 96 | + } |
| 97 | + |
| 98 | + /// \cond NOINTERNAL |
| 99 | + [[nodiscard]] std::error_code get_error_code() const; |
| 100 | + |
| 101 | + [[nodiscard]] std::string get_message() const; |
| 102 | + /// \endcond |
| 103 | + }; |
167 | 104 | } // namespace hpx |
| 105 | + |
| 106 | +#include <hpx/config/warnings_suffix.hpp> |
0 commit comments