From 8dd2b7f4e86cd30eec7d1ffd2a33e2e722d8fe07 Mon Sep 17 00:00:00 2001 From: Emil Dotchevski Date: Fri, 19 Jun 2020 13:03:00 -0700 Subject: [PATCH] Renamed augment_id to error_monitor --- doc/leaf.adoc | 136 +++++++++++++++---------------- examples/lua_callback_result.cpp | 8 +- include/boost/leaf/all.hpp | 21 +++-- include/boost/leaf/capture.hpp | 8 +- include/boost/leaf/on_error.hpp | 13 ++- 5 files changed, 91 insertions(+), 95 deletions(-) diff --git a/doc/leaf.adoc b/doc/leaf.adoc index 13543acb..9534edab 100644 --- a/doc/leaf.adoc +++ b/doc/leaf.adoc @@ -501,7 +501,7 @@ For example, the error may need to be communicated through uncooperative 3rd-par Further, it is sometimes necessary to communicate errors through an interface that does not even use `std::error_code`. An example of this is when an external lower-level library throws an exception, which is unlikely to be able to carry an `error_id`. -To support this tricky use case, LEAF provides the function <>, which returns the error ID returned by the most recent call (from this thread) to <>. One possible approach to solving the problem is to use the following logic (implemented by the <> type): +To support this tricky use case, LEAF provides the function <>, which returns the error ID returned by the most recent call (from this thread) to <>. One possible approach to solving the problem is to use the following logic (implemented by the <> type): . Before calling the uncooperative API, call <> and cache the returned value. . Call the API, then call `current_error` again: @@ -1360,7 +1360,7 @@ NOTE: The complete program illustrating this technique is available https://gith ''' [[tutorial-on_error_in_c_callbacks]] -=== Using `augment_id` to Report Arbitrary Errors from C-callbacks +=== Using `error_monitor` to Report Arbitrary Errors from C-callbacks Communicating information pertaining to a failure detected in a C callback is tricky, because C callbacks are limited to a specific static signature, which may not use {CPP} types. @@ -1443,13 +1443,13 @@ leaf::result call_lua( lua_State * L ) { lua_getfield(L, LUA_GLOBALSINDEX, "call_do_work"); - augment_id augment; + error_monitor cur_err; if( int err=lua_pcall(L, 0, 1, 0) ) <1> { auto load = leaf::on_error(e_lua_error_message{lua_tostring(L,1)}); <2> lua_pop(L,1); - return augment.get_error(e_lua_pcall_error{err}); <3> + return cur_err.assigned_error_id().load(e_lua_pcall_error{err}); <3> } else { @@ -1460,11 +1460,11 @@ leaf::result call_lua( lua_State * L ) } ---- [.text-right] -<> | <> | <> +<> | <> | <> <1> Ask the Lua interpreter to call the global Lua function `call_do_work`. <2> `on_error` works as usual. -<3> `get_error` will return the `error_id` generated in our Lua callback. This is the same `error_id` the `on_error` uses as well. +<3> `load` will return the `error_id` generated in our Lua callback. This is the same `error_id` the `on_error` uses as well. <4> Success! Just return the `int` answer. Finally, here is the `main` function which exercises `call_lua`, each time handling any failure: @@ -1769,7 +1769,7 @@ namespace boost { namespace leaf { This header defines the `on_error` function, which is used for automatic inclusion of error objects with any error exiting the scope in which it is invoked. See <> and <>. -The `augment_id` type is used internally by `on_error` to determine the correct <> to associate error objects with. +The `error_monitor` type is used internally by `on_error` to determine the correct <> to associate error objects with. ==== [source,c++] @@ -1780,23 +1780,22 @@ namespace boost { namespace leaf { template <> on_error( Item && ... e ) noexcept; - class augment_id + class error_monitor { public: - augment_id() noexcept; + error_monitor() noexcept; - error_id check_error() const noexcept; + error_id check() const noexcept; - template - error_id get_error( E && ... e ) const noexcept; + error_id assigned_error_id() const noexcept; }; } } ---- [.text-right] -<> | <> +<> | <> ==== [[exception.hpp]] @@ -2799,62 +2798,6 @@ TIP: The contents of each Reference section are organized alphabetically. ''' -[[augment_id]] -=== `augment_id` - -[source,c++] ----- -namespace boost { namespace leaf { - - class augment_id - { - public: - - augment_id() noexcept; - - error_id check_error() const noexcept; - - template - error_id get_error( E && ... e ) const noexcept; - }; - -} } ----- - -This class helps obtain an <> to associate error objects with, when augmenting failures communicated using LEAF through uncooperative APIs that do not use LEAF to report errors (and therefore do not return an `error_id` on error). - -The common usage of this class is as follows: - -[source,c++] ----- -error_code compute_value( int * out_value ) noexcept; <1> - -leaf::error augmenter() noexcept -{ - leaf::augment_id augment; <2> - - int val; - auto ec = compute_value(&val); - - if( failure(ec) ) - return augment.get_error(e1, e2, ...); <3> - else - return val; <4> -} ----- -<1> Uncooperative third-party API that does not use LEAF, but results in calling a user callback that does use LEAF. In case our callback reports a failure, we'll augment it with error objects available in the calling scope, even though `compute_value` can not communicate an <>. -<2> Initialize an `augment_id` object. -<3> The call to `compute_value` has failed: -- If <> was invoked (by the calling thread) after the `augment` object was initialized, `get_error` returns the last `error_id` returned by `new_error`. This would be the case if the failure originates in our callback (invoked internally by `compute_value`). -- Else, `get_error` invokes `new_error` and returns that `error_id`. -<4> The call was successful, return the computed value. - -The `check_error` function works similarly, but instead of invoking `new_error` it returns a defaul-initialized `error_id`. - -TIP: See <>. - -''' - [[catch_]] === `catch_` @@ -3428,6 +3371,61 @@ Effects: :: ''' +[[error_monitor]] +=== `error_monitor` + +[source,c++] +---- +namespace boost { namespace leaf { + + class error_monitor + { + public: + + error_monitor() noexcept; + + error_id check() const noexcept; + + error_id assigned_error_id( E && ... e ) const noexcept; + }; + +} } +---- + +This class helps obtain an <> to associate error objects with, when augmenting failures communicated using LEAF through uncooperative APIs that do not use LEAF to report errors (and therefore do not return an `error_id` on error). + +The common usage of this class is as follows: + +[source,c++] +---- +error_code compute_value( int * out_value ) noexcept; <1> + +leaf::error augmenter() noexcept +{ + leaf::error_monitor cur_err; <2> + + int val; + auto ec = compute_value(&val); + + if( failure(ec) ) + return cur_err.assigned_error_id().load(e1, e2, ...); <3> + else + return val; <4> +} +---- +<1> Uncooperative third-party API that does not use LEAF, but results in calling a user callback that does use LEAF. In case our callback reports a failure, we'll augment it with error objects available in the calling scope, even though `compute_value` can not communicate an <>. +<2> Initialize an `error_monitor` object. +<3> The call to `compute_value` has failed: +- If <> was invoked (by the calling thread) after the `augment` object was initialized, `assigned_error_id` returns the last `error_id` returned by `new_error`. This would be the case if the failure originates in our callback (invoked internally by `compute_value`). +- Else, `assigned_error_id` invokes `new_error` and returns that `error_id`. +<4> The call was successful, return the computed value. + +The `check` function works similarly, but instead of invoking `new_error` it returns a defaul-initialized `error_id`. + +TIP: See <>. + +''' + [[e_api_function]] === `e_api_function` diff --git a/examples/lua_callback_result.cpp b/examples/lua_callback_result.cpp index cf21aec7..ac8b71a0 100644 --- a/examples/lua_callback_result.cpp +++ b/examples/lua_callback_result.cpp @@ -76,7 +76,7 @@ std::shared_ptr init_lua_state() // If it fails, we'll communicate that failure to our caller. leaf::result call_lua( lua_State * L ) { - leaf::augment_id augment; + leaf::error_monitor cur_err; // Ask the Lua interpreter to call the global Lua function call_do_work. lua_getfield( L, LUA_GLOBALSINDEX, "call_do_work" ); @@ -86,9 +86,9 @@ leaf::result call_lua( lua_State * L ) lua_pop(L,1); // We got a Lua error which may be the error we're reporting from do_work, or some other error. - // If it is another error, augment.get_error() will return a new leaf::error_id, otherwise - // we'll be working with the original value returned by leaf::new_error in do_work. - return augment.get_error(e_lua_pcall_error{err}); + // If it is another error, cur_err.assigned_error_id() will return a new leaf::error_id, + // otherwise we'll be working with the original value returned by leaf::new_error in do_work. + return cur_err.assigned_error_id().load(e_lua_pcall_error{err}); } else { diff --git a/include/boost/leaf/all.hpp b/include/boost/leaf/all.hpp index 0ad850fc..3ee53f38 100644 --- a/include/boost/leaf/all.hpp +++ b/include/boost/leaf/all.hpp @@ -1867,7 +1867,7 @@ namespace boost { namespace leaf { namespace boost { namespace leaf { - class augment_id + class error_monitor { #if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS int const uncaught_exceptions_; @@ -1876,7 +1876,7 @@ namespace boost { namespace leaf { public: - augment_id() noexcept: + error_monitor() noexcept: #if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS uncaught_exceptions_(std::uncaught_exceptions()), #endif @@ -1912,15 +1912,14 @@ namespace boost { namespace leaf { return leaf_detail::new_id(); } - error_id check_error() const noexcept + error_id check() const noexcept { return leaf_detail::make_error_id(check_id()); } - template - error_id get_error( E && ... e ) const noexcept + error_id assigned_error_id() const noexcept { - return leaf_detail::make_error_id(get_id()).load(std::forward(e)...); + return leaf_detail::make_error_id(get_id()); } }; @@ -2051,7 +2050,7 @@ namespace boost { namespace leaf { std::tuple p_; bool moved_; - augment_id id_; + error_monitor id_; public: @@ -2194,7 +2193,7 @@ namespace boost { namespace leaf { inline decltype(std::declval()(std::forward(std::declval())...)) capture_impl(is_result_tag, context_ptr && ctx, F && f, A... a) { auto active_context = activate_context(*ctx); - augment_id aug; + error_monitor cur_err; try { return std::forward(f)(std::forward(a)...); @@ -2210,7 +2209,7 @@ namespace boost { namespace leaf { } catch(...) { - ctx->captured_id_ = aug.get_error(); + ctx->captured_id_ = cur_err.assigned_error_id(); throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) ); } } @@ -2219,7 +2218,7 @@ namespace boost { namespace leaf { inline decltype(std::declval()(std::forward(std::declval())...)) capture_impl(is_result_tag, context_ptr && ctx, F && f, A... a) { auto active_context = activate_context(*ctx); - augment_id aug; + error_monitor cur_err; try { if( auto && r = std::forward(f)(std::forward(a)...) ) @@ -2241,7 +2240,7 @@ namespace boost { namespace leaf { } catch(...) { - ctx->captured_id_ = aug.get_error(); + ctx->captured_id_ = cur_err.assigned_error_id(); throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) ); } } diff --git a/include/boost/leaf/capture.hpp b/include/boost/leaf/capture.hpp index 2ef81c96..066ff741 100644 --- a/include/boost/leaf/capture.hpp +++ b/include/boost/leaf/capture.hpp @@ -99,7 +99,7 @@ namespace boost { namespace leaf { inline decltype(std::declval()(std::forward(std::declval())...)) capture_impl(is_result_tag, context_ptr && ctx, F && f, A... a) { auto active_context = activate_context(*ctx); - augment_id aug; + error_monitor cur_err; try { return std::forward(f)(std::forward(a)...); @@ -115,7 +115,7 @@ namespace boost { namespace leaf { } catch(...) { - ctx->captured_id_ = aug.get_error(); + ctx->captured_id_ = cur_err.assigned_error_id(); throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) ); } } @@ -124,7 +124,7 @@ namespace boost { namespace leaf { inline decltype(std::declval()(std::forward(std::declval())...)) capture_impl(is_result_tag, context_ptr && ctx, F && f, A... a) { auto active_context = activate_context(*ctx); - augment_id aug; + error_monitor cur_err; try { if( auto && r = std::forward(f)(std::forward(a)...) ) @@ -146,7 +146,7 @@ namespace boost { namespace leaf { } catch(...) { - ctx->captured_id_ = aug.get_error(); + ctx->captured_id_ = cur_err.assigned_error_id(); throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) ); } } diff --git a/include/boost/leaf/on_error.hpp b/include/boost/leaf/on_error.hpp index e5015cd0..cb18ba93 100644 --- a/include/boost/leaf/on_error.hpp +++ b/include/boost/leaf/on_error.hpp @@ -18,7 +18,7 @@ namespace boost { namespace leaf { - class augment_id + class error_monitor { #if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS int const uncaught_exceptions_; @@ -27,7 +27,7 @@ namespace boost { namespace leaf { public: - augment_id() noexcept: + error_monitor() noexcept: #if !defined(BOOST_LEAF_NO_EXCEPTIONS) && BOOST_LEAF_STD_UNCAUGHT_EXCEPTIONS uncaught_exceptions_(std::uncaught_exceptions()), #endif @@ -63,15 +63,14 @@ namespace boost { namespace leaf { return leaf_detail::new_id(); } - error_id check_error() const noexcept + error_id check() const noexcept { return leaf_detail::make_error_id(check_id()); } - template - error_id get_error( E && ... e ) const noexcept + error_id assigned_error_id() const noexcept { - return leaf_detail::make_error_id(get_id()).load(std::forward(e)...); + return leaf_detail::make_error_id(get_id()); } }; @@ -202,7 +201,7 @@ namespace boost { namespace leaf { std::tuple p_; bool moved_; - augment_id id_; + error_monitor id_; public: