Skip to content

Commit

Permalink
Renamed augment_id to error_monitor
Browse files Browse the repository at this point in the history
  • Loading branch information
zajo committed Jun 19, 2020
1 parent b61116a commit 8dd2b7f
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 95 deletions.
136 changes: 67 additions & 69 deletions doc/leaf.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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 <<current_error>>, which returns the error ID returned by the most recent call (from this thread) to <<new_error>>. One possible approach to solving the problem is to use the following logic (implemented by the <<augment_id>> type):
To support this tricky use case, LEAF provides the function <<current_error>>, which returns the error ID returned by the most recent call (from this thread) to <<new_error>>. One possible approach to solving the problem is to use the following logic (implemented by the <<error_monitor>> type):

. Before calling the uncooperative API, call <<current_error>> and cache the returned value.
. Call the API, then call `current_error` again:
Expand Down Expand Up @@ -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.

Expand Down Expand Up @@ -1443,13 +1443,13 @@ leaf::result<int> 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
{
Expand All @@ -1460,11 +1460,11 @@ leaf::result<int> call_lua( lua_State * L )
}
----
[.text-right]
<<result>> | <<on_error>> | <<augment_id>>
<<result>> | <<on_error>> | <<error_monitor>>

<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:
Expand Down Expand Up @@ -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 <<tutorial-on_error>> and <<tutorial-classification>>.

The `augment_id` type is used internally by `on_error` to determine the correct <<error_id>> to associate error objects with.
The `error_monitor` type is used internally by `on_error` to determine the correct <<error_id>> to associate error objects with.

====
[source,c++]
Expand All @@ -1780,23 +1780,22 @@ namespace boost { namespace leaf {
template <class... Item>
<<unspecified-type>> 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 <class... E>
error_id get_error( E && ... e ) const noexcept;
error_id assigned_error_id() const noexcept;
};
} }
----
[.text-right]
<<on_error>> | <<augment_id>>
<<on_error>> | <<error_monitor>>
====

[[exception.hpp]]
Expand Down Expand Up @@ -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 <class... E>
error_id get_error( E && ... e ) const noexcept;
};
} }
----

This class helps obtain an <<error_id>> 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<int> 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 <<error_id>>.
<2> Initialize an `augment_id` object.
<3> The call to `compute_value` has failed:
- If <<new_error>> 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 <<tutorial-on_error_in_c_callbacks>>.

'''

[[catch_]]
=== `catch_`

Expand Down Expand Up @@ -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 <<error_id>> 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<int> 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 <<error_id>>.
<2> Initialize an `error_monitor` object.
<3> The call to `compute_value` has failed:
- If <<new_error>> 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 <<tutorial-on_error_in_c_callbacks>>.

'''

[[e_api_function]]
=== `e_api_function`

Expand Down
8 changes: 4 additions & 4 deletions examples/lua_callback_result.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ std::shared_ptr<lua_State> init_lua_state()
// If it fails, we'll communicate that failure to our caller.
leaf::result<int> 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" );
Expand All @@ -86,9 +86,9 @@ leaf::result<int> 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
{
Expand Down
21 changes: 10 additions & 11 deletions include/boost/leaf/all.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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_;
Expand All @@ -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
Expand Down Expand Up @@ -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 <class... E>
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>(e)...);
return leaf_detail::make_error_id(get_id());
}
};

Expand Down Expand Up @@ -2051,7 +2050,7 @@ namespace boost { namespace leaf {

std::tuple<Item...> p_;
bool moved_;
augment_id id_;
error_monitor id_;

public:

Expand Down Expand Up @@ -2194,7 +2193,7 @@ namespace boost { namespace leaf {
inline decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...)) capture_impl(is_result_tag<R, false>, 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>(f)(std::forward<A>(a)...);
Expand All @@ -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)) );
}
}
Expand All @@ -2219,7 +2218,7 @@ namespace boost { namespace leaf {
inline decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...)) capture_impl(is_result_tag<R, true>, 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>(f)(std::forward<A>(a)...) )
Expand All @@ -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)) );
}
}
Expand Down
8 changes: 4 additions & 4 deletions include/boost/leaf/capture.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ namespace boost { namespace leaf {
inline decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...)) capture_impl(is_result_tag<R, false>, 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>(f)(std::forward<A>(a)...);
Expand All @@ -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)) );
}
}
Expand All @@ -124,7 +124,7 @@ namespace boost { namespace leaf {
inline decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...)) capture_impl(is_result_tag<R, true>, 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>(f)(std::forward<A>(a)...) )
Expand All @@ -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)) );
}
}
Expand Down
13 changes: 6 additions & 7 deletions include/boost/leaf/on_error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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_;
Expand All @@ -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
Expand Down Expand Up @@ -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 <class... E>
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>(e)...);
return leaf_detail::make_error_id(get_id());
}
};

Expand Down Expand Up @@ -202,7 +201,7 @@ namespace boost { namespace leaf {

std::tuple<Item...> p_;
bool moved_;
augment_id id_;
error_monitor id_;

public:

Expand Down

0 comments on commit 8dd2b7f

Please sign in to comment.