1 //  Copyright (c) 2007-2013 Hartmut Kaiser
2 //  Copyright (c) 2011      Bryce Lelbach
3 //
4 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
5 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 
7 /// \file exception.hpp
8 
9 #if !defined(HPX_EXCEPTION_MAR_24_2008_0929AM)
10 #define HPX_EXCEPTION_MAR_24_2008_0929AM
11 
12 #include <hpx/config.hpp>
13 #include <hpx/error.hpp>
14 #include <hpx/error_code.hpp>
15 #include <hpx/exception_fwd.hpp>
16 #include <hpx/exception_info.hpp>
17 #include <hpx/runtime/naming_fwd.hpp>
18 
19 #include <boost/system/error_code.hpp>
20 #include <boost/system/system_error.hpp>
21 
22 #include <cstddef>
23 #include <cstdint>
24 #include <exception>
25 #include <string>
26 
27 #include <hpx/config/warnings_prefix.hpp>
28 
29 ///////////////////////////////////////////////////////////////////////////////
30 namespace hpx
31 {
32     ///////////////////////////////////////////////////////////////////////////
33     /// \brief A hpx::exception is the main exception type used by HPX to
34     ///        report errors.
35     ///
36     /// The hpx::exception type is the main exception type  used by HPX to
37     /// report errors. Any exceptions thrown by functions in the HPX library
38     /// are either of this type or of a type derived from it. This implies that
39     /// it is always safe to use this type only in catch statements guarding
40     /// HPX library calls.
41     class HPX_EXCEPTION_EXPORT exception : public boost::system::system_error
42     {
43     public:
44         /// Construct a hpx::exception from a \a hpx::error.
45         ///
46         /// \param e    The parameter \p e holds the hpx::error code the new
47         ///             exception should encapsulate.
48         explicit exception(error e = success);
49 
50         /// Construct a hpx::exception from a boost#system_error.
51         explicit exception(boost::system::system_error const& e);
52 
53         /// Construct a hpx::exception from a boost#system#error_code (this is
54         /// new for Boost V1.69). This constructor is required to compensate
55         /// for the changes introduced as a resolution to LWG3162
56         /// (https://cplusplus.github.io/LWG/issue3162).
57         explicit exception(boost::system::error_code const& e);
58 
59         /// Construct a hpx::exception from a \a hpx::error and an error message.
60         ///
61         /// \param e      The parameter \p e holds the hpx::error code the new
62         ///               exception should encapsulate.
63         /// \param msg    The parameter \p msg holds the error message the new
64         ///               exception should encapsulate.
65         /// \param mode   The parameter \p mode specifies whether the returned
66         ///               hpx::error_code belongs to the error category
67         ///               \a hpx_category (if mode is \a plain, this is the
68         ///               default) or to the category \a hpx_category_rethrow
69         ///               (if mode is \a rethrow).
70         exception(error e, char const* msg, throwmode mode = plain);
71 
72         /// Construct a hpx::exception from a \a hpx::error and an error message.
73         ///
74         /// \param e      The parameter \p e holds the hpx::error code the new
75         ///               exception should encapsulate.
76         /// \param msg    The parameter \p msg holds the error message the new
77         ///               exception should encapsulate.
78         /// \param mode   The parameter \p mode specifies whether the returned
79         ///               hpx::error_code belongs to the error category
80         ///               \a hpx_category (if mode is \a plain, this is the
81         ///               default) or to the category \a hpx_category_rethrow
82         ///               (if mode is \a rethrow).
83         exception(error e, std::string const& msg, throwmode mode = plain);
84 
85         /// Destruct a hpx::exception
86         ///
87         /// \throws nothing
88         ~exception() throw();
89 
90         /// The function \a get_error() returns the hpx::error code stored
91         /// in the referenced instance of a hpx::exception. It returns
92         /// the hpx::error code this exception instance was constructed
93         /// from.
94         ///
95         /// \throws nothing
96         error get_error() const noexcept;
97 
98         /// The function \a get_error_code() returns a hpx::error_code which
99         /// represents the same error condition as this hpx::exception instance.
100         ///
101         /// \param mode   The parameter \p mode specifies whether the returned
102         ///               hpx::error_code belongs to the error category
103         ///               \a hpx_category (if mode is \a plain, this is the
104         ///               default) or to the category \a hpx_category_rethrow
105         ///               (if mode is \a rethrow).
106         error_code get_error_code(throwmode mode = plain) const noexcept;
107     };
108 
109     ///////////////////////////////////////////////////////////////////////////
110     /// \brief A hpx::thread_interrupted is the exception type used by HPX to
111     ///        interrupt a running HPX thread.
112     ///
113     /// The \a hpx::thread_interrupted type is the exception type used by HPX to
114     /// interrupt a running thread.
115     ///
116     /// A running thread can be interrupted by invoking the interrupt() member
117     /// function of the corresponding hpx::thread object. When the interrupted
118     /// thread next executes one of the specified interruption points (or if it
119     /// is currently blocked whilst executing one) with interruption enabled,
120     /// then a hpx::thread_interrupted exception will be thrown in the interrupted
121     /// thread. If not caught, this will cause the execution of the interrupted
122     /// thread to terminate. As with any other exception, the stack will be
123     /// unwound, and destructors for objects of automatic storage duration will
124     /// be executed.
125     ///
126     /// If a thread wishes to avoid being interrupted, it can create an instance
127     /// of \a hpx::this_thread::disable_interruption. Objects of this class disable
128     /// interruption for the thread that created them on construction, and
129     /// restore the interruption state to whatever it was before on destruction.
130     ///
131     /// \code
132     ///     void f()
133     ///     {
134     ///         // interruption enabled here
135     ///         {
136     ///             hpx::this_thread::disable_interruption di;
137     ///             // interruption disabled
138     ///             {
139     ///                 hpx::this_thread::disable_interruption di2;
140     ///                 // interruption still disabled
141     ///             } // di2 destroyed, interruption state restored
142     ///             // interruption still disabled
143     ///         } // di destroyed, interruption state restored
144     ///         // interruption now enabled
145     ///     }
146     /// \endcode
147     ///
148     /// The effects of an instance of \a hpx::this_thread::disable_interruption can be
149     /// temporarily reversed by constructing an instance of
150     /// \a hpx::this_thread::restore_interruption, passing in the
151     /// \a hpx::this_thread::disable_interruption object in question. This will restore
152     /// the interruption state to what it was when the
153     /// \a hpx::this_thread::disable_interruption
154     /// object was constructed, and then disable interruption again when the
155     /// \a hpx::this_thread::restore_interruption object is destroyed.
156     ///
157     /// \code
158     ///     void g()
159     ///     {
160     ///         // interruption enabled here
161     ///         {
162     ///             hpx::this_thread::disable_interruption di;
163     ///             // interruption disabled
164     ///             {
165     ///                 hpx::this_thread::restore_interruption ri(di);
166     ///                 // interruption now enabled
167     ///             } // ri destroyed, interruption disable again
168     ///         } // di destroyed, interruption state restored
169     ///         // interruption now enabled
170     ///     }
171     /// \endcode
172     ///
173     /// At any point, the interruption state for the current thread can be
174     /// queried by calling \a hpx::this_thread::interruption_enabled().
175     struct HPX_EXCEPTION_EXPORT thread_interrupted : std::exception {};
176 
177     /// \cond NODETAIL
178     namespace detail
179     {
180         struct HPX_EXCEPTION_EXPORT std_exception : std::exception
181         {
182           private:
183             std::string what_;
184 
185           public:
std_exceptionhpx::detail::std_exception186             explicit std_exception(std::string const& w)
187               : what_(w)
188             {}
189 
~std_exceptionhpx::detail::std_exception190             ~std_exception() throw() {}
191 
whathpx::detail::std_exception192             const char* what() const throw()
193             {
194                 return what_.c_str();
195             }
196         };
197 
198         struct HPX_EXCEPTION_EXPORT bad_alloc : std::bad_alloc
199         {
200           private:
201             std::string what_;
202 
203           public:
bad_allochpx::detail::bad_alloc204             explicit bad_alloc(std::string const& w)
205               : what_(w)
206             {}
207 
~bad_allochpx::detail::bad_alloc208             ~bad_alloc() throw() {}
209 
whathpx::detail::bad_alloc210             const char* what() const throw()
211             {
212                 return what_.c_str();
213             }
214         };
215 
216         struct HPX_EXCEPTION_EXPORT bad_exception : std::bad_exception
217         {
218           private:
219             std::string what_;
220 
221           public:
bad_exceptionhpx::detail::bad_exception222             explicit bad_exception(std::string const& w)
223               : what_(w)
224             {}
225 
~bad_exceptionhpx::detail::bad_exception226             ~bad_exception() throw() {}
227 
whathpx::detail::bad_exception228             const char* what() const throw()
229             {
230                 return what_.c_str();
231             }
232         };
233 
234         struct HPX_EXCEPTION_EXPORT bad_cast : std::bad_cast
235         {
236           private:
237             std::string what_;
238 
239           public:
bad_casthpx::detail::bad_cast240             explicit bad_cast(std::string const& w)
241               : what_(w)
242             {}
243 
~bad_casthpx::detail::bad_cast244             ~bad_cast() throw() {}
245 
whathpx::detail::bad_cast246             const char* what() const throw()
247             {
248                 return what_.c_str();
249             }
250         };
251 
252         struct HPX_EXCEPTION_EXPORT bad_typeid : std::bad_typeid
253         {
254           private:
255             std::string what_;
256 
257           public:
bad_typeidhpx::detail::bad_typeid258             explicit bad_typeid(std::string const& w)
259               : what_(w)
260             {}
261 
~bad_typeidhpx::detail::bad_typeid262             ~bad_typeid() throw() {}
263 
whathpx::detail::bad_typeid264             const char* what() const throw()
265             {
266                 return what_.c_str();
267             }
268         };
269 
270         ///////////////////////////////////////////////////////////////////////
271         // Stores the information about the locality id the exception has been
272         // raised on. This information will show up in error messages under the
273         // [locality] tag.
274         HPX_DEFINE_ERROR_INFO(throw_locality, std::uint32_t);
275 
276         // Stores the information about the hostname of the locality the exception
277         // has been raised on. This information will show up in error messages
278         // under the [hostname] tag.
279         HPX_DEFINE_ERROR_INFO(throw_hostname, std::string);
280 
281         // Stores the information about the pid of the OS process the exception
282         // has been raised on. This information will show up in error messages
283         // under the [pid] tag.
284         HPX_DEFINE_ERROR_INFO(throw_pid, std::int64_t);
285 
286         // Stores the information about the shepherd thread the exception has been
287         // raised on. This information will show up in error messages under the
288         // [shepherd] tag.
289         HPX_DEFINE_ERROR_INFO(throw_shepherd, std::size_t);
290 
291         // Stores the information about the HPX thread the exception has been
292         // raised on. This information will show up in error messages under the
293         // [thread_id] tag.
294         HPX_DEFINE_ERROR_INFO(throw_thread_id, std::size_t);
295 
296         // Stores the information about the HPX thread name the exception has been
297         // raised on. This information will show up in error messages under the
298         // [thread_name] tag.
299         HPX_DEFINE_ERROR_INFO(throw_thread_name, std::string);
300 
301         // Stores the information about the function name the exception has been
302         // raised in. This information will show up in error messages under the
303         // [function] tag.
304         HPX_DEFINE_ERROR_INFO(throw_function, std::string);
305 
306         // Stores the information about the source file name the exception has
307         // been raised in. This information will show up in error messages under
308         // the [file] tag.
309         HPX_DEFINE_ERROR_INFO(throw_file, std::string);
310 
311         // Stores the information about the source file line number the exception
312         // has been raised at. This information will show up in error messages
313         // under the [line] tag.
314         HPX_DEFINE_ERROR_INFO(throw_line, long);
315 
316         // Stores the information about the stack backtrace at the point the
317         // exception has been raised at. This information will show up in error
318         // messages under the [stack_trace] tag.
319         HPX_DEFINE_ERROR_INFO(throw_stacktrace, std::string);
320 
321         // Stores the full execution environment of the locality the exception
322         // has been raised in. This information will show up in error messages
323         // under the [env] tag.
324         HPX_DEFINE_ERROR_INFO(throw_env, std::string);
325 
326         // Stores the full HPX configuration information of the locality the
327         // exception has been raised in. This information will show up in error
328         // messages under the [config] tag.
329         HPX_DEFINE_ERROR_INFO(throw_config, std::string);
330 
331         // Stores the current runtime state. This information will show up in
332         // error messages under the [state] tag.
333         HPX_DEFINE_ERROR_INFO(throw_state, std::string);
334 
335         // Stores additional auxiliary information (such as information about
336         // the current parcel). This information will show up in error messages
337         // under the [auxinfo] tag.
338         HPX_DEFINE_ERROR_INFO(throw_auxinfo, std::string);
339 
340         // construct an exception, internal helper
341         template <typename Exception>
342         HPX_EXPORT std::exception_ptr
343             construct_exception(Exception const& e,
344                 std::string const& func, std::string const& file, long line,
345                 std::string const& back_trace = "", std::uint32_t node = 0,
346                 std::string const& hostname = "", std::int64_t pid = -1,
347                 std::size_t shepherd = ~0, std::size_t thread_id = 0,
348                 std::string const& thread_name = "",
349                 std::string const& env = "", std::string const& config = "",
350                 std::string const& state = "", std::string const& auxinfo = "");
351 
352         template <typename Exception>
353         HPX_EXPORT std::exception_ptr
354             construct_lightweight_exception(Exception const& e);
355 
356         // HPX_ASSERT handler
357         HPX_NORETURN HPX_EXPORT
358         void assertion_failed(char const* expr, char const* function,
359             char const* file, long line);
360 
361         // HPX_ASSERT_MSG handler
362         HPX_NORETURN HPX_EXPORT
363         void assertion_failed_msg(char const* msg, char const* expr,
364             char const* function, char const* file, long line);
365 
366         // If backtrace support is enabled, this function returns the current
367         // stack backtrace, otherwise it will return an empty string.
368         HPX_EXPORT std::string backtrace(
369             std::size_t frames = HPX_HAVE_THREAD_BACKTRACE_DEPTH);
370         HPX_EXPORT std::string backtrace_direct(
371             std::size_t frames = HPX_HAVE_THREAD_BACKTRACE_DEPTH);
372 
373         // Portably extract the current execution environment
374         HPX_EXPORT std::string get_execution_environment();
375 
376         // Report an early or late exception and locally abort execution. There
377         // isn't anything more we could do.
378         HPX_NORETURN HPX_EXPORT void report_exception_and_terminate(
379             std::exception_ptr const&);
380         HPX_NORETURN HPX_EXPORT void report_exception_and_terminate(
381             hpx::exception const&);
382 
383         // Report an early or late exception and locally exit execution. There
384         // isn't anything more we could do. The exception will be re-thrown
385         // from hpx::init
386         HPX_EXPORT void report_exception_and_continue(std::exception_ptr const&);
387         HPX_EXPORT void report_exception_and_continue(hpx::exception const&);
388     }
389     /// \endcond
390 
391     ///////////////////////////////////////////////////////////////////////////
392     /// \brief Extract the diagnostic information embedded in the given
393     /// exception and return a string holding a formatted message.
394     ///
395     /// The function \a hpx::diagnostic_information can be used to extract all
396     /// diagnostic information stored in the given exception instance as a
397     /// formatted string. This simplifies debug output as it composes the
398     /// diagnostics into one, easy to use function call. This includes
399     /// the name of the source file and line number, the sequence number of the
400     /// OS-thread and the HPX-thread id, the locality id and the stack backtrace
401     /// of the point where the original exception was thrown.
402     ///
403     /// \param xi   The parameter \p e will be inspected for all diagnostic
404     ///             information elements which have been stored at the point
405     ///             where the exception was thrown. This parameter can be one
406     ///             of the following types: \a hpx::exception_info,
407     ///             \a hpx::error_code, \a std::exception, or
408     ///             \a std::exception_ptr.
409     ///
410     /// \returns    The formatted string holding all of the available
411     ///             diagnostic information stored in the given exception
412     ///             instance.
413     ///
414     /// \throws     std#bad_alloc (if any of the required allocation operations
415     ///             fail)
416     ///
417     /// \see        \a hpx::get_error_locality_id(), \a hpx::get_error_host_name(),
418     ///             \a hpx::get_error_process_id(), \a hpx::get_error_function_name(),
419     ///             \a hpx::get_error_file_name(), \a hpx::get_error_line_number(),
420     ///             \a hpx::get_error_os_thread(), \a hpx::get_error_thread_id(),
421     ///             \a hpx::get_error_thread_description(), \a hpx::get_error(),
422     ///             \a hpx::get_error_backtrace(), \a hpx::get_error_env(),
423     ///             \a hpx::get_error_what(), \a hpx::get_error_config(),
424     ///             \a hpx::get_error_state()
425     ///
426     HPX_EXPORT std::string diagnostic_information(exception_info const& xi);
427 
428     /// \cond NOINTERNAL
429     template <typename E>
diagnostic_information(E const & e)430     std::string diagnostic_information(E const& e)
431     {
432         return invoke_with_exception_info(e, [](exception_info const* xi) {
433             return xi ? diagnostic_information(*xi) : std::string("<unknown>");
434         });
435     }
436     /// \endcond
437 
438     ///////////////////////////////////////////////////////////////////////////
439     // Extract elements of the diagnostic information embedded in the given
440     // exception.
441 
442     /// \brief Return the error message of the thrown exception.
443     ///
444     /// The function \a hpx::get_error_what can be used to extract the
445     /// diagnostic information element representing the error message as stored
446     /// in the given exception instance.
447     ///
448     /// \param xi   The parameter \p e will be inspected for the requested
449     ///             diagnostic information elements which have been stored at
450     ///             the point where the exception was thrown. This parameter
451     ///             can be one of the following types: \a hpx::exception_info,
452     ///             \a hpx::error_code, \a std::exception, or
453     ///             \a std::exception_ptr.
454     ///
455     /// \returns    The error message stored in the exception
456     ///             If the exception instance does not hold
457     ///             this information, the function will return an empty string.
458     ///
459     /// \throws     std#bad_alloc (if one of the required allocations fails)
460     ///
461     /// \see        \a hpx::diagnostic_information(), \a hpx::get_error_host_name(),
462     ///             \a hpx::get_error_process_id(), \a hpx::get_error_function_name(),
463     ///             \a hpx::get_error_file_name(), \a hpx::get_error_line_number(),
464     ///             \a hpx::get_error_os_thread(), \a hpx::get_error_thread_id(),
465     ///             \a hpx::get_error_thread_description(), \a hpx::get_error()
466     ///             \a hpx::get_error_backtrace(), \a hpx::get_error_env(),
467     ///             \a hpx::get_error_config(), \a hpx::get_error_state()
468     ///
469     HPX_EXPORT std::string get_error_what(exception_info const& xi);
470 
471     /// \cond NOINTERNAL
472     template <typename E>
get_error_what(E const & e)473     std::string get_error_what(E const& e)
474     {
475         return invoke_with_exception_info(e, [](exception_info const* xi) {
476             return xi ? get_error_what(*xi) : std::string("<unknown>");
477         });
478     }
479 
get_error_what(hpx::error_code const & e)480     inline std::string get_error_what(hpx::error_code const& e)
481     {
482         // if this is a lightweight error_code, return canned response
483         if (e.category() == hpx::get_lightweight_hpx_category())
484             return e.message();
485 
486         return get_error_what<hpx::error_code>(e);
487     }
488 
get_error_what(std::exception const & e)489     inline std::string get_error_what(std::exception const& e)
490     {
491         return e.what();
492     }
493     /// \endcond
494 
495     /// \brief Return the locality id where the exception was thrown.
496     ///
497     /// The function \a hpx::get_error_locality_id can be used to extract the
498     /// diagnostic information element representing the locality id as stored
499     /// in the given exception instance.
500     ///
501     /// \param xi   The parameter \p e will be inspected for the requested
502     ///             diagnostic information elements which have been stored at
503     ///             the point where the exception was thrown. This parameter
504     ///             can be one of the following types: \a hpx::exception_info,
505     ///             \a hpx::error_code, \a std::exception, or
506     ///             \a std::exception_ptr.
507     ///
508     /// \returns    The locality id of the locality where the exception was
509     ///             thrown. If the exception instance does not hold
510     ///             this information, the function will return
511     ///             \a hpx::naming#invalid_locality_id.
512     ///
513     /// \throws     nothing
514     ///
515     /// \see        \a hpx::diagnostic_information(), \a hpx::get_error_host_name(),
516     ///             \a hpx::get_error_process_id(), \a hpx::get_error_function_name(),
517     ///             \a hpx::get_error_file_name(), \a hpx::get_error_line_number(),
518     ///             \a hpx::get_error_os_thread(), \a hpx::get_error_thread_id(),
519     ///             \a hpx::get_error_thread_description(), \a hpx::get_error(),
520     ///             \a hpx::get_error_backtrace(), \a hpx::get_error_env(),
521     ///             \a hpx::get_error_what(), \a hpx::get_error_config(),
522     ///             \a hpx::get_error_state()
523     ///
524     HPX_EXPORT std::uint32_t get_error_locality_id(hpx::exception_info const& xi);
525 
526     /// \cond NOINTERNAL
527     template <typename E>
get_error_locality_id(E const & e)528     std::uint32_t get_error_locality_id(E const& e)
529     {
530         return invoke_with_exception_info(e, [](exception_info const* xi) {
531             return xi ? get_error_locality_id(*xi) : naming::invalid_locality_id;
532         });
533     }
534     /// \endcond
535 
536     /// \brief Return the locality id where the exception was thrown.
537     ///
538     /// The function \a hpx::get_error can be used to extract the
539     /// diagnostic information element representing the error value code as
540     /// stored in the given exception instance.
541     ///
542     /// \param e    The parameter \p e will be inspected for the requested
543     ///             diagnostic information elements which have been stored at
544     ///             the point where the exception was thrown. This parameter
545     ///             can be one of the following types: \a hpx::exception,
546     ///             \a hpx::error_code, or \a std::exception_ptr.
547     ///
548     /// \returns    The error value code of the locality where the exception was
549     ///             thrown. If the exception instance does not hold
550     ///             this information, the function will return
551     ///             \a hpx::naming#invalid_locality_id.
552     ///
553     /// \throws     nothing
554     ///
555     /// \see        \a hpx::diagnostic_information(), \a hpx::get_error_host_name(),
556     ///             \a hpx::get_error_process_id(), \a hpx::get_error_function_name(),
557     ///             \a hpx::get_error_file_name(), \a hpx::get_error_line_number(),
558     ///             \a hpx::get_error_os_thread(), \a hpx::get_error_thread_id(),
559     ///             \a hpx::get_error_thread_description(),
560     ///             \a hpx::get_error_backtrace(), \a hpx::get_error_env(),
561     ///             \a hpx::get_error_what(), \a hpx::get_error_config(),
562     ///             \a hpx::get_error_state()
563     ///
564     HPX_EXPORT error get_error(hpx::exception const& e);
565 
566     /// \copydoc get_error(hpx::exception const& e)
567     HPX_EXPORT error get_error(hpx::error_code const& e);
568 
569     /// \cond NOINTERNAL
570     HPX_EXPORT error get_error(std::exception_ptr const& e);
571     /// \endcond
572 
573     /// \brief Return the hostname of the locality where the exception was
574     ///        thrown.
575     ///
576     /// The function \a hpx::get_error_host_name can be used to extract the
577     /// diagnostic information element representing the host name as stored in
578     /// the given exception instance.
579     ///
580     /// \param xi   The parameter \p e will be inspected for the requested
581     ///             diagnostic information elements which have been stored at
582     ///             the point where the exception was thrown. This parameter
583     ///             can be one of the following types: \a hpx::exception_info,
584     ///             \a hpx::error_code, \a std::exception, or
585     ///             \a std::exception_ptr.
586     ///
587     /// \returns    The hostname of the locality where the exception was
588     ///             thrown. If the exception instance does not hold
589     ///             this information, the function will return and empty string.
590     ///
591     /// \throws     std#bad_alloc (if one of the required allocations fails)
592     ///
593     /// \see        \a hpx::diagnostic_information()
594     ///             \a hpx::get_error_process_id(), \a hpx::get_error_function_name(),
595     ///             \a hpx::get_error_file_name(), \a hpx::get_error_line_number(),
596     ///             \a hpx::get_error_os_thread(), \a hpx::get_error_thread_id(),
597     ///             \a hpx::get_error_thread_description(), \a hpx::get_error()
598     ///             \a hpx::get_error_backtrace(), \a hpx::get_error_env(),
599     ///             \a hpx::get_error_what(), \a hpx::get_error_config(),
600     ///             \a hpx::get_error_state()
601     ///
602     HPX_EXPORT std::string get_error_host_name(hpx::exception_info const& xi);
603 
604     /// \cond NOINTERNAL
605     template <typename E>
get_error_host_name(E const & e)606     std::string get_error_host_name(E const& e)
607     {
608         return invoke_with_exception_info(e, [](exception_info const* xi) {
609             return xi ? get_error_host_name(*xi) : std::string();
610         });
611     }
612     /// \endcond
613 
614     /// \brief Return the (operating system) process id of the locality where
615     ///        the exception was thrown.
616     ///
617     /// The function \a hpx::get_error_process_id can be used to extract the
618     /// diagnostic information element representing the process id as stored in
619     /// the given exception instance.
620     ///
621     /// \returns    The process id of the OS-process which threw the exception
622     ///             If the exception instance does not hold
623     ///             this information, the function will return 0.
624     ///
625     /// \param xi   The parameter \p e will be inspected for the requested
626     ///             diagnostic information elements which have been stored at
627     ///             the point where the exception was thrown. This parameter
628     ///             can be one of the following types: \a hpx::exception_info,
629     ///             \a hpx::error_code, \a std::exception, or
630     ///             \a std::exception_ptr.
631     ///
632     /// \throws     nothing
633     ///
634     /// \see        \a hpx::diagnostic_information(), \a hpx::get_error_host_name(),
635     ///             \a hpx::get_error_function_name(),
636     ///             \a hpx::get_error_file_name(), \a hpx::get_error_line_number(),
637     ///             \a hpx::get_error_os_thread(), \a hpx::get_error_thread_id(),
638     ///             \a hpx::get_error_thread_description(), \a hpx::get_error(),
639     ///             \a hpx::get_error_backtrace(), \a hpx::get_error_env(),
640     ///             \a hpx::get_error_what(), \a hpx::get_error_config(),
641     ///             \a hpx::get_error_state()
642     ///
643     HPX_EXPORT std::int64_t get_error_process_id(hpx::exception_info const& xi);
644 
645     /// \cond NOINTERNAL
646     template <typename E>
get_error_process_id(E const & e)647     std::int64_t get_error_process_id(E const& e)
648     {
649         return invoke_with_exception_info(e, [](exception_info const* xi) {
650             return xi ? get_error_process_id(*xi) : -1;
651         });
652     }
653     /// \endcond
654 
655     /// \brief Return the environment of the OS-process at the point the
656     ///        exception was thrown.
657     ///
658     /// The function \a hpx::get_error_env can be used to extract the
659     /// diagnostic information element representing the environment of the
660     /// OS-process collected at the point the exception was thrown.
661     ///
662     /// \returns    The environment from the point the exception was
663     ///             thrown. If the exception instance does not hold
664     ///             this information, the function will return an empty string.
665     ///
666     /// \param xi   The parameter \p e will be inspected for the requested
667     ///             diagnostic information elements which have been stored at
668     ///             the point where the exception was thrown. This parameter
669     ///             can be one of the following types: \a hpx::exception_info,
670     ///             \a hpx::error_code, \a std::exception, or
671     ///             \a std::exception_ptr.
672     ///
673     /// \throws     std#bad_alloc (if one of the required allocations fails)
674     ///
675     /// \see        \a hpx::diagnostic_information(), \a hpx::get_error_host_name(),
676     ///             \a hpx::get_error_process_id(), \a hpx::get_error_function_name(),
677     ///             \a hpx::get_error_file_name(), \a hpx::get_error_line_number(),
678     ///             \a hpx::get_error_os_thread(), \a hpx::get_error_thread_id(),
679     ///             \a hpx::get_error_thread_description(), \a hpx::get_error(),
680     ///             \a hpx::get_error_backtrace(),
681     ///             \a hpx::get_error_what(), \a hpx::get_error_config(),
682     ///             \a hpx::get_error_state()
683     ///
684     HPX_EXPORT std::string get_error_env(hpx::exception_info const& xi);
685 
686     /// \cond NOINTERNAL
687     template <typename E>
get_error_env(E const & e)688     std::string get_error_env(E const& e)
689     {
690         return invoke_with_exception_info(e, [](exception_info const* xi) {
691             return xi ? get_error_env(*xi) : std::string("<unknown>");
692         });
693     }
694     /// \endcond
695 
696     /// \brief Return the function name from which the exception was thrown.
697     ///
698     /// The function \a hpx::get_error_function_name can be used to extract the
699     /// diagnostic information element representing the name of the function
700     /// as stored in the given exception instance.
701     ///
702     /// \returns    The name of the function from which the exception was
703     ///             thrown. If the exception instance does not hold
704     ///             this information, the function will return an empty string.
705     ///
706     /// \param xi   The parameter \p e will be inspected for the requested
707     ///             diagnostic information elements which have been stored at
708     ///             the point where the exception was thrown. This parameter
709     ///             can be one of the following types: \a hpx::exception_info,
710     ///             \a hpx::error_code, \a std::exception, or
711     ///             \a std::exception_ptr.
712     ///
713     /// \throws     std#bad_alloc (if one of the required allocations fails)
714     ///
715     /// \see        \a hpx::diagnostic_information(), \a hpx::get_error_host_name(),
716     ///             \a hpx::get_error_process_id()
717     ///             \a hpx::get_error_file_name(), \a hpx::get_error_line_number(),
718     ///             \a hpx::get_error_os_thread(), \a hpx::get_error_thread_id(),
719     ///             \a hpx::get_error_thread_description(), \a hpx::get_error(),
720     ///             \a hpx::get_error_backtrace(), \a hpx::get_error_env(),
721     ///             \a hpx::get_error_what(), \a hpx::get_error_config(),
722     ///             \a hpx::get_error_state()
723     ///
724     HPX_EXPORT std::string get_error_function_name(hpx::exception_info const& xi);
725 
726     /// \cond NOINTERNAL
727     template <typename E>
get_error_function_name(E const & e)728     std::string get_error_function_name(E const& e)
729     {
730         return invoke_with_exception_info(e, [](exception_info const* xi) {
731             return xi ? get_error_function_name(*xi) : std::string();
732         });
733     }
734     /// \endcond
735 
736     /// \brief Return the stack backtrace from the point the exception was thrown.
737     ///
738     /// The function \a hpx::get_error_backtrace can be used to extract the
739     /// diagnostic information element representing the stack backtrace
740     /// collected at the point the exception was thrown.
741     ///
742     /// \returns    The stack back trace from the point the exception was
743     ///             thrown. If the exception instance does not hold
744     ///             this information, the function will return an empty string.
745     ///
746     /// \param xi   The parameter \p e will be inspected for the requested
747     ///             diagnostic information elements which have been stored at
748     ///             the point where the exception was thrown. This parameter
749     ///             can be one of the following types: \a hpx::exception_info,
750     ///             \a hpx::error_code, \a std::exception, or
751     ///             \a std::exception_ptr.
752     ///
753     /// \throws     std#bad_alloc (if one of the required allocations fails)
754     ///
755     /// \see        \a hpx::diagnostic_information(), \a hpx::get_error_host_name(),
756     ///             \a hpx::get_error_process_id(), \a hpx::get_error_function_name(),
757     ///             \a hpx::get_error_file_name(), \a hpx::get_error_line_number(),
758     ///             \a hpx::get_error_os_thread(), \a hpx::get_error_thread_id(),
759     ///             \a hpx::get_error_thread_description(), \a hpx::get_error(),
760     ///             \a hpx::get_error_env(),
761     ///             \a hpx::get_error_what(), \a hpx::get_error_config(),
762     ///             \a hpx::get_error_state()
763     ///
764     HPX_EXPORT std::string get_error_backtrace(hpx::exception_info const& xi);
765 
766     /// \cond NOINTERNAL
767     template <typename E>
get_error_backtrace(E const & e)768     std::string get_error_backtrace(E const& e)
769     {
770         return invoke_with_exception_info(e, [](exception_info const* xi) {
771             return xi ? get_error_backtrace(*xi) : std::string();
772         });
773     }
774     /// \endcond
775 
776     /// \brief Return the (source code) file name of the function from which
777     ///        the exception was thrown.
778     ///
779     /// The function \a hpx::get_error_file_name can be used to extract the
780     /// diagnostic information element representing the name of the source file
781     /// as stored in the given exception instance.
782     ///
783     /// \returns    The name of the source file of the function from which the
784     ///             exception was thrown. If the exception instance does
785     ///             not hold this information, the function will return an empty
786     ///             string.
787     ///
788     /// \param xi   The parameter \p e will be inspected for the requested
789     ///             diagnostic information elements which have been stored at
790     ///             the point where the exception was thrown. This parameter
791     ///             can be one of the following types: \a hpx::exception_info,
792     ///             \a hpx::error_code, \a std::exception, or
793     ///             \a std::exception_ptr.
794     ///
795     /// \throws     std#bad_alloc (if one of the required allocations fails)
796     ///
797     /// \see        \a hpx::diagnostic_information(), \a hpx::get_error_host_name(),
798     ///             \a hpx::get_error_process_id(), \a hpx::get_error_function_name(),
799     ///             \a hpx::get_error_line_number(),
800     ///             \a hpx::get_error_os_thread(), \a hpx::get_error_thread_id(),
801     ///             \a hpx::get_error_thread_description(), \a hpx::get_error(),
802     ///             \a hpx::get_error_backtrace(), \a hpx::get_error_env(),
803     ///             \a hpx::get_error_what(), \a hpx::get_error_config(),
804     ///             \a hpx::get_error_state()
805     ///
806     HPX_EXPORT std::string get_error_file_name(hpx::exception_info const& xi);
807 
808     /// \cond NOINTERNAL
809     template <typename E>
get_error_file_name(E const & e)810     std::string get_error_file_name(E const& e)
811     {
812         return invoke_with_exception_info(e, [](exception_info const* xi) {
813             return xi ? get_error_file_name(*xi) : std::string("<unknown>");
814         });
815     }
816     /// \endcond
817 
818     /// \brief Return the line number in the (source code) file of the function
819     ///        from which the exception was thrown.
820     ///
821     /// The function \a hpx::get_error_line_number can be used to extract the
822     /// diagnostic information element representing the line number
823     /// as stored in the given exception instance.
824     ///
825     /// \returns    The line number of the place where the exception was
826     ///             thrown. If the exception instance does not hold
827     ///             this information, the function will return -1.
828     ///
829     /// \param xi   The parameter \p e will be inspected for the requested
830     ///             diagnostic information elements which have been stored at
831     ///             the point where the exception was thrown. This parameter
832     ///             can be one of the following types: \a hpx::exception_info,
833     ///             \a hpx::error_code, \a std::exception, or
834     ///             \a std::exception_ptr.
835     ///
836     /// \throws     nothing
837     ///
838     /// \see        \a hpx::diagnostic_information(), \a hpx::get_error_host_name(),
839     ///             \a hpx::get_error_process_id(), \a hpx::get_error_function_name(),
840     ///             \a hpx::get_error_file_name()
841     ///             \a hpx::get_error_os_thread(), \a hpx::get_error_thread_id(),
842     ///             \a hpx::get_error_thread_description(), \a hpx::get_error(),
843     ///             \a hpx::get_error_backtrace(), \a hpx::get_error_env(),
844     ///             \a hpx::get_error_what(), \a hpx::get_error_config(),
845     ///             \a hpx::get_error_state()
846     ///
847     HPX_EXPORT long get_error_line_number(hpx::exception_info const& xi);
848 
849     /// \cond NOINTERNAL
850     template <typename E>
get_error_line_number(E const & e)851     long get_error_line_number(E const& e)
852     {
853         return invoke_with_exception_info(e, [](exception_info const* xi) {
854             return xi ? get_error_line_number(*xi) : -1;
855         });
856     }
857     /// \endcond
858 
859     /// \brief Return the sequence number of the OS-thread used to execute
860     ///        HPX-threads from which the exception was thrown.
861     ///
862     /// The function \a hpx::get_error_os_thread can be used to extract the
863     /// diagnostic information element representing the sequence number  of the
864     /// OS-thread as stored in the given exception instance.
865     ///
866     /// \returns    The sequence number of the OS-thread used to execute the
867     ///             HPX-thread from which the exception was
868     ///             thrown. If the exception instance does not hold
869     ///             this information, the function will return std::size(-1).
870     ///
871     /// \param xi   The parameter \p e will be inspected for the requested
872     ///             diagnostic information elements which have been stored at
873     ///             the point where the exception was thrown. This parameter
874     ///             can be one of the following types: \a hpx::exception_info,
875     ///             \a hpx::error_code, \a std::exception, or
876     ///             \a std::exception_ptr.
877     ///
878     /// \throws     nothing
879     ///
880     /// \see        \a hpx::diagnostic_information(), \a hpx::get_error_host_name(),
881     ///             \a hpx::get_error_process_id(), \a hpx::get_error_function_name(),
882     ///             \a hpx::get_error_file_name(), \a hpx::get_error_line_number(),
883     ///             \a hpx::get_error_thread_id(),
884     ///             \a hpx::get_error_thread_description(), \a hpx::get_error(),
885     ///             \a hpx::get_error_backtrace(), \a hpx::get_error_env(),
886     ///             \a hpx::get_error_what(), \a hpx::get_error_config(),
887     ///             \a hpx::get_error_state()
888     ///
889     HPX_EXPORT std::size_t get_error_os_thread(hpx::exception_info const& xi);
890 
891     /// \cond NOINTERNAL
892     template <typename E>
get_error_os_thread(E const & e)893     std::size_t get_error_os_thread(E const& e)
894     {
895         return invoke_with_exception_info(e, [](exception_info const* xi) {
896             return xi ? get_error_os_thread(*xi) : std::size_t(-1);
897         });
898     }
899     /// \endcond
900 
901     /// \brief Return the unique thread id of the HPX-thread from which the
902     ///        exception was thrown.
903     ///
904     /// The function \a hpx::get_error_thread_id can be used to extract the
905     /// diagnostic information element representing the HPX-thread id
906     /// as stored in the given exception instance.
907     ///
908     /// \returns    The unique thread id of the HPX-thread from which the
909     ///             exception was thrown. If the exception instance
910     ///             does not hold this information, the function will return
911     ///             std::size_t(0).
912     ///
913     /// \param xi   The parameter \p e will be inspected for the requested
914     ///             diagnostic information elements which have been stored at
915     ///             the point where the exception was thrown. This parameter
916     ///             can be one of the following types: \a hpx::exception_info,
917     ///             \a hpx::error_code, \a std::exception, or
918     ///             \a std::exception_ptr.
919     ///
920     /// \throws     nothing
921     ///
922     /// \see        \a hpx::diagnostic_information(), \a hpx::get_error_host_name(),
923     ///             \a hpx::get_error_process_id(), \a hpx::get_error_function_name(),
924     ///             \a hpx::get_error_file_name(), \a hpx::get_error_line_number(),
925     ///             \a hpx::get_error_os_thread()
926     ///             \a hpx::get_error_thread_description(), \a hpx::get_error(),
927     ///             \a hpx::get_error_backtrace(), \a hpx::get_error_env(),
928     ///             \a hpx::get_error_what(), \a hpx::get_error_config(),
929     ///             \a hpx::get_error_state()
930     ///
931     HPX_EXPORT std::size_t get_error_thread_id(hpx::exception_info const& xi);
932 
933     /// \cond NOINTERNAL
934     template <typename E>
get_error_thread_id(E const & e)935     std::size_t get_error_thread_id(E const& e)
936     {
937         return invoke_with_exception_info(e, [](exception_info const* xi) {
938             return xi ? get_error_thread_id(*xi) : std::size_t(-1);
939         });
940     }
941     /// \endcond
942 
943     /// \brief Return any additionally available thread description of the
944     ///        HPX-thread from which the exception was thrown.
945     ///
946     /// The function \a hpx::get_error_thread_description can be used to extract the
947     /// diagnostic information element representing the additional thread
948     /// description as stored in the given exception instance.
949     ///
950     /// \returns    Any additionally available thread description of the
951     ///             HPX-thread from which the exception was
952     ///             thrown. If the exception instance does not hold
953     ///             this information, the function will return an empty string.
954     ///
955     /// \param xi   The parameter \p e will be inspected for the requested
956     ///             diagnostic information elements which have been stored at
957     ///             the point where the exception was thrown. This parameter
958     ///             can be one of the following types: \a hpx::exception_info,
959     ///             \a hpx::error_code, \a std::exception, or
960     ///             \a std::exception_ptr.
961     ///
962     /// \throws     std#bad_alloc (if one of the required allocations fails)
963     ///
964     /// \see        \a hpx::diagnostic_information(), \a hpx::get_error_host_name(),
965     ///             \a hpx::get_error_process_id(), \a hpx::get_error_function_name(),
966     ///             \a hpx::get_error_file_name(), \a hpx::get_error_line_number(),
967     ///             \a hpx::get_error_os_thread(), \a hpx::get_error_thread_id(),
968     ///             \a hpx::get_error_backtrace(), \a hpx::get_error_env(),
969     ///             \a hpx::get_error(), \a hpx::get_error_state(),
970     ///             \a hpx::get_error_what(), \a hpx::get_error_config()
971     ///
972     HPX_EXPORT std::string get_error_thread_description(hpx::exception_info const& xi);
973 
974     /// \cond NOINTERNAL
975     template <typename E>
get_error_thread_description(E const & e)976     std::string get_error_thread_description(E const& e)
977     {
978         return invoke_with_exception_info(e, [](exception_info const* xi) {
979             return xi ? get_error_thread_description(*xi) : std::string();
980         });
981     }
982     /// \endcond
983 
984     /// \brief Return the HPX configuration information point from which the
985     ///        exception was thrown.
986     ///
987     /// The function \a hpx::get_error_config can be used to extract the
988     /// HPX configuration information element representing the full HPX
989     /// configuration information as stored in the given exception instance.
990     ///
991     /// \returns    Any additionally available HPX configuration information
992     ///             the point from which the exception was
993     ///             thrown. If the exception instance does not hold
994     ///             this information, the function will return an empty string.
995     ///
996     /// \param xi   The parameter \p e will be inspected for the requested
997     ///             diagnostic information elements which have been stored at
998     ///             the point where the exception was thrown. This parameter
999     ///             can be one of the following types: \a hpx::exception_info,
1000     ///             \a hpx::error_code, \a std::exception, or
1001     ///             \a std::exception_ptr.
1002     ///
1003     /// \throws     std#bad_alloc (if one of the required allocations fails)
1004     ///
1005     /// \see        \a hpx::diagnostic_information(), \a hpx::get_error_host_name(),
1006     ///             \a hpx::get_error_process_id(), \a hpx::get_error_function_name(),
1007     ///             \a hpx::get_error_file_name(), \a hpx::get_error_line_number(),
1008     ///             \a hpx::get_error_os_thread(), \a hpx::get_error_thread_id(),
1009     ///             \a hpx::get_error_backtrace(), \a hpx::get_error_env(),
1010     ///             \a hpx::get_error(), \a hpx::get_error_state()
1011     ///             \a hpx::get_error_what(), \a hpx::get_error_thread_description()
1012     ///
1013     HPX_EXPORT std::string get_error_config(hpx::exception_info const& xi);
1014 
1015     /// \cond NOINTERNAL
1016     template <typename E>
get_error_config(E const & e)1017     std::string get_error_config(E const& e)
1018     {
1019         return invoke_with_exception_info(e, [](exception_info const* xi) {
1020             return xi ? get_error_config(*xi) : std::string();
1021         });
1022     }
1023     /// \endcond
1024 
1025     /// \brief Return the HPX runtime state information at which the exception
1026     ///        was thrown.
1027     ///
1028     /// The function \a hpx::get_error_state can be used to extract the
1029     /// HPX runtime state information element representing the state the
1030     /// runtime system is currently in as stored in the given exception
1031     /// instance.
1032     ///
1033     /// \returns    The point runtime state at the point at which the exception
1034     ///             was thrown. If the exception instance does not hold
1035     ///             this information, the function will return an empty string.
1036     ///
1037     /// \param xi   The parameter \p e will be inspected for the requested
1038     ///             diagnostic information elements which have been stored at
1039     ///             the point where the exception was thrown. This parameter
1040     ///             can be one of the following types: \a hpx::exception_info,
1041     ///             \a hpx::error_code, \a std::exception, or
1042     ///             \a std::exception_ptr.
1043     ///
1044     /// \throws     std#bad_alloc (if one of the required allocations fails)
1045     ///
1046     /// \see        \a hpx::diagnostic_information(), \a hpx::get_error_host_name(),
1047     ///             \a hpx::get_error_process_id(), \a hpx::get_error_function_name(),
1048     ///             \a hpx::get_error_file_name(), \a hpx::get_error_line_number(),
1049     ///             \a hpx::get_error_os_thread(), \a hpx::get_error_thread_id(),
1050     ///             \a hpx::get_error_backtrace(), \a hpx::get_error_env(),
1051     ///             \a hpx::get_error(),
1052     ///             \a hpx::get_error_what(), \a hpx::get_error_thread_description()
1053     ///
1054     HPX_EXPORT std::string get_error_state(hpx::exception_info const& xi);
1055 
1056     /// \cond NOINTERNAL
1057     template <typename E>
get_error_state(E const & e)1058     std::string get_error_state(E const& e)
1059     {
1060         return invoke_with_exception_info(e, [](exception_info const* xi) {
1061             return xi ? get_error_state(*xi) : std::string();
1062         });
1063     }
1064     /// \endcond
1065 
1066     ///////////////////////////////////////////////////////////////////////////
1067     // \cond NOINTERNAL
1068     // forwarder for HPX_ASSERT handler
1069     HPX_NORETURN HPX_EXPORT
1070     void assertion_failed(char const* expr, char const* function,
1071         char const* file, long line);
1072 
1073     // forwarder for HPX_ASSERT_MSG handler
1074     HPX_NORETURN HPX_EXPORT
1075     void assertion_failed_msg(char const* msg, char const* expr,
1076         char const* function, char const* file, long line);
1077 
1078     // For testing purposes we sometime expect to see exceptions, allow those
1079     // to go through without attaching a debugger.
1080     //
1081     // This should be used carefully as it disables the possible attaching of
1082     // a debugger for all exceptions, not only the expected ones.
1083     HPX_EXPORT bool expect_exception(bool flag = true);
1084     /// \endcond
1085 }
1086 
1087 #include <hpx/throw_exception.hpp>
1088 
1089 #include <hpx/config/warnings_suffix.hpp>
1090 
1091 #endif
1092