mirror of
https://github.com/boostorg/leaf.git
synced 2026-01-19 04:22:08 +00:00
Context activation/deactivation/propagation refactored.
This commit is contained in:
106
.travis.yml
106
.travis.yml
@@ -1,5 +1,5 @@
|
||||
# Copyright 2016-2018 Peter Dimov
|
||||
# Copyright 2018-2019 Emil Dotchevski
|
||||
# Copyright 2016 Peter Dimov
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -52,7 +52,7 @@ matrix:
|
||||
|
||||
include:
|
||||
|
||||
- os: linux
|
||||
- os: linux
|
||||
env: DOC=1
|
||||
script:
|
||||
- |-
|
||||
@@ -137,6 +137,10 @@ matrix:
|
||||
compiler: clang++
|
||||
env: TOOLSET=clang COMPILER=clang++ CXXSTD=11,14,1z
|
||||
|
||||
- os: osx
|
||||
compiler: clang++
|
||||
env: UBSAN=1 TOOLSET=clang COMPILER=clang++ CXXSTD=11,14,1z UBSAN_OPTIONS=print_stacktrace=1
|
||||
|
||||
- os: linux
|
||||
compiler: g++-4.9
|
||||
env: TOOLSET=gcc COMPILER=g++-4.9 CXXSTD=11
|
||||
@@ -169,7 +173,7 @@ matrix:
|
||||
|
||||
- os: linux
|
||||
compiler: g++-7
|
||||
env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=11,14,1z
|
||||
env: TOOLSET=gcc COMPILER=g++-7 CXXSTD=11,14,17
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
@@ -187,6 +191,26 @@ matrix:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-9
|
||||
env: TOOLSET=gcc COMPILER=g++-9 CXXSTD=11,14,17,2a
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-9
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-9
|
||||
env: UBSAN=1 TOOLSET=gcc COMPILER=g++-9 CXXSTD=11,14,17,2a UBSAN_OPTIONS=print_stacktrace=1 LINKFLAGS=-fuse-ld=gold
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-9
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: /usr/bin/clang++
|
||||
env: TOOLSET=clang COMPILER=/usr/bin/clang++ CXXSTD=11
|
||||
@@ -203,6 +227,10 @@ matrix:
|
||||
packages:
|
||||
- clang-3.4
|
||||
|
||||
- os: linux
|
||||
compiler: clang++
|
||||
env: TOOLSET=clang COMPILER=clang++ CXXSTD=11
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.5
|
||||
env: TOOLSET=clang COMPILER=clang++-3.5 CXXSTD=11,14,1z
|
||||
@@ -213,7 +241,6 @@ matrix:
|
||||
- libstdc++-4.9-dev
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.5
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.6
|
||||
@@ -222,9 +249,9 @@ matrix:
|
||||
apt:
|
||||
packages:
|
||||
- clang-3.6
|
||||
- libstdc++-4.9-dev
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.6
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.7
|
||||
@@ -247,7 +274,6 @@ matrix:
|
||||
- libstdc++-4.9-dev
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.8
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.9
|
||||
@@ -259,7 +285,6 @@ matrix:
|
||||
- libstdc++-4.9-dev
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.9
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-4.0
|
||||
@@ -294,6 +319,52 @@ matrix:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-6.0
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-7
|
||||
env: TOOLSET=clang COMPILER=clang++-7 CXXSTD=11,14,17,2a
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-7
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-7
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-8
|
||||
env: TOOLSET=clang COMPILER=clang++-8 CXXSTD=11,14,17,2a
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-8
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-8
|
||||
|
||||
- os: linux
|
||||
dist: xenial
|
||||
compiler: clang++-9
|
||||
env: TOOLSET=clang COMPILER=clang++-9 CXXSTD=11,14,17,2a
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-9
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main'
|
||||
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-8
|
||||
env: UBSAN=1 TOOLSET=clang COMPILER=clang++-8 CXXSTD=11,14,17,2a UBSAN_OPTIONS=print_stacktrace=1
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-8
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-8
|
||||
|
||||
install:
|
||||
- gem install asciidoctor
|
||||
- gem install coderay
|
||||
@@ -316,23 +387,10 @@ install:
|
||||
script:
|
||||
- |-
|
||||
echo "using $TOOLSET : : $COMPILER ;" > ~/user-config.jam
|
||||
- ../../b2 test toolset=$TOOLSET cxxstd=$CXXSTD variant=debug
|
||||
- ../../b2 test toolset=$TOOLSET cxxstd=$CXXSTD variant=release
|
||||
- ../../b2 test toolset=$TOOLSET cxxstd=$CXXSTD variant=debug-diagnostics0
|
||||
- ../../b2 test toolset=$TOOLSET cxxstd=$CXXSTD variant=release-diagnostics0
|
||||
- ../../b2 exception-handling=off rtti=off test toolset=$TOOLSET cxxstd=$CXXSTD variant=debug
|
||||
- ../../b2 exception-handling=off rtti=off test toolset=$TOOLSET cxxstd=$CXXSTD variant=release
|
||||
- ../../b2 exception-handling=off rtti=off test toolset=$TOOLSET cxxstd=$CXXSTD variant=debug-diagnostics0
|
||||
- ../../b2 exception-handling=off rtti=off test toolset=$TOOLSET cxxstd=$CXXSTD variant=release-diagnostics0
|
||||
- ../../b2 threading=single test toolset=$TOOLSET cxxstd=$CXXSTD variant=debug
|
||||
- ../../b2 threading=single test toolset=$TOOLSET cxxstd=$CXXSTD variant=release
|
||||
- ../../b2 threading=single test toolset=$TOOLSET cxxstd=$CXXSTD variant=debug-diagnostics0
|
||||
- ../../b2 threading=single test toolset=$TOOLSET cxxstd=$CXXSTD variant=release-diagnostics0
|
||||
- ../../b2 threading=single exception-handling=off rtti=off test toolset=$TOOLSET cxxstd=$CXXSTD variant=debug
|
||||
- ../../b2 threading=single exception-handling=off rtti=off test toolset=$TOOLSET cxxstd=$CXXSTD variant=release
|
||||
- ../../b2 threading=single exception-handling=off rtti=off test toolset=$TOOLSET cxxstd=$CXXSTD variant=debug-diagnostics0
|
||||
- ../../b2 threading=single exception-handling=off rtti=off test toolset=$TOOLSET cxxstd=$CXXSTD variant=release-diagnostics0
|
||||
# - cd bld/debug && meson test
|
||||
- ../../b2 test toolset=$TOOLSET cxxstd=$CXXSTD variant=debug,release,debug-diagnostics0,release-diagnostics0 ${UBSAN:+cxxflags=-fsanitize=undefined cxxflags=-fno-sanitize-recover=undefined linkflags=-fsanitize=undefined debug-symbols=on} ${LINKFLAGS:+linkflags=$LINKFLAGS}
|
||||
- ../../b2 exception-handling=off rtti=off test toolset=$TOOLSET cxxstd=$CXXSTD variant=debug,release,debug-diagnostics0,release-diagnostics0 ${UBSAN:+cxxflags=-fsanitize=undefined cxxflags=-fno-sanitize-recover=undefined linkflags=-fsanitize=undefined debug-symbols=on} ${LINKFLAGS:+linkflags=$LINKFLAGS}
|
||||
- ../../b2 threading=single test toolset=$TOOLSET cxxstd=$CXXSTD variant=debug,release,debug-diagnostics0,release-diagnostics0 ${UBSAN:+cxxflags=-fsanitize=undefined cxxflags=-fno-sanitize-recover=undefined linkflags=-fsanitize=undefined debug-symbols=on} ${LINKFLAGS:+linkflags=$LINKFLAGS}
|
||||
- ../../b2 threading=single exception-handling=off rtti=off test toolset=$TOOLSET cxxstd=$CXXSTD variant=debug,release,debug-diagnostics0,release-diagnostics0 ${UBSAN:+cxxflags=-fsanitize=undefined cxxflags=-fno-sanitize-recover=undefined linkflags=-fsanitize=undefined debug-symbols=on} ${LINKFLAGS:+linkflags=$LINKFLAGS}
|
||||
|
||||
notifications:
|
||||
email:
|
||||
|
||||
27
.vscode/tasks.json
vendored
27
.vscode/tasks.json
vendored
@@ -167,6 +167,33 @@
|
||||
"command": "${workspaceRoot}/.vscode/msvc.bat && cd ${workspaceRoot}/bld/debug && meson test context_deduction_test"
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "ctx_handle_all_test",
|
||||
"type": "shell",
|
||||
"command": "cd ${workspaceRoot}/bld/debug && meson test ctx_handle_all_test",
|
||||
"problemMatcher": { "base": "$gcc", "fileLocation": ["relative","${workspaceRoot}/bld/debug"] },
|
||||
"windows": {
|
||||
"command": "${workspaceRoot}/.vscode/msvc.bat && cd ${workspaceRoot}/bld/debug && meson test ctx_handle_all_test"
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "ctx_handle_exception_test",
|
||||
"type": "shell",
|
||||
"command": "cd ${workspaceRoot}/bld/debug && meson test ctx_handle_exception_test",
|
||||
"problemMatcher": { "base": "$gcc", "fileLocation": ["relative","${workspaceRoot}/bld/debug"] },
|
||||
"windows": {
|
||||
"command": "${workspaceRoot}/.vscode/msvc.bat && cd ${workspaceRoot}/bld/debug && meson test ctx_handle_exception_test"
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "ctx_handle_some_test",
|
||||
"type": "shell",
|
||||
"command": "cd ${workspaceRoot}/bld/debug && meson test ctx_handle_some_test",
|
||||
"problemMatcher": { "base": "$gcc", "fileLocation": ["relative","${workspaceRoot}/bld/debug"] },
|
||||
"windows": {
|
||||
"command": "${workspaceRoot}/.vscode/msvc.bat && cd ${workspaceRoot}/bld/debug && meson test ctx_handle_some_test"
|
||||
}
|
||||
},
|
||||
{
|
||||
"label": "ctx_remote_handle_all_test",
|
||||
"type": "shell",
|
||||
|
||||
145
doc/leaf.adoc
145
doc/leaf.adoc
@@ -1634,21 +1634,16 @@ namespace boost { namespace leaf {
|
||||
public:
|
||||
|
||||
virtual void activate() noexcept = 0;
|
||||
virtual void deactivate( bool propagate_errors ) noexcept = 0;
|
||||
virtual void deactivate() noexcept = 0;
|
||||
virtual bool is_active() const noexcept = 0;
|
||||
|
||||
virtual void propagate() noexcept = 0;
|
||||
|
||||
virtual void print( std::ostream & ) const = 0;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////
|
||||
|
||||
enum class on_deactivation
|
||||
{
|
||||
propagate,
|
||||
propagate_if_uncaught_exception,
|
||||
capture_do_not_propagate
|
||||
};
|
||||
|
||||
template <class Ctx>
|
||||
class context_activator
|
||||
{
|
||||
@@ -1657,17 +1652,15 @@ namespace boost { namespace leaf {
|
||||
|
||||
public:
|
||||
|
||||
context_activator( Ctx & ctx, on_deactivation on_deactivate ) noexcept;
|
||||
explicit context_activator( Ctx & ctx ) noexcept;
|
||||
context_activator( context_activator && ) noexcept;
|
||||
~context_activator() noexcept;
|
||||
|
||||
void set_on_deactivate( on_deactivation on_deactivate ) noexcept;
|
||||
};
|
||||
|
||||
} }
|
||||
|
||||
template <class Ctx>
|
||||
context_activator<Ctx> activate_context( Ctx & ctx, on_deactivation on_deactivate ) noexcept;
|
||||
context_activator<Ctx> activate_context( Ctx & ctx ) noexcept;
|
||||
|
||||
#define LEAF_NEW_ERROR(...) ....
|
||||
#define LEAF_AUTO(v,r) ....
|
||||
@@ -1936,9 +1929,11 @@ namespace boost { namespace leaf {
|
||||
~context() noexcept;
|
||||
|
||||
void activate() noexcept;
|
||||
void deactivate( bool propagate_errors ) noexcept;
|
||||
void deactivate() noexcept;
|
||||
bool is_active() const noexcept;
|
||||
|
||||
void propagate () noexcept;
|
||||
|
||||
void print( std::ostream & os ) const;
|
||||
|
||||
// Note: <boost/leaf/context.hpp> leaves the rest of the member functions undefined.
|
||||
@@ -1949,29 +1944,29 @@ namespace boost { namespace leaf {
|
||||
|
||||
template <class R, class... H>
|
||||
typename std::decay<decltype(std::declval<R>().value())>::type
|
||||
handle_all( R &, H && ... ) const;
|
||||
handle_all( R &, H && ... );
|
||||
|
||||
template <class R, class RemoteH>
|
||||
typename std::decay<decltype(std::declval<R>().value())>::type
|
||||
remote_handle_all( R &, RemoteH && ) const;
|
||||
remote_handle_all( R &, RemoteH && );
|
||||
|
||||
template <class R, class... H>
|
||||
R handle_some( R &&, H && ... ) const;
|
||||
R handle_some( R &&, H && ... );
|
||||
|
||||
template <class R, class RemoteH>
|
||||
R remote_handle_some( R &&, RemoteH && ) const;
|
||||
R remote_handle_some( R &&, RemoteH && );
|
||||
|
||||
template <class R, class... H>
|
||||
R handle_current_exception( H && ... ) const;
|
||||
R handle_current_exception( H && ... );
|
||||
|
||||
template <class R, class RemoteH>
|
||||
R remote_handle_current_exception( RemoteH && ) const;
|
||||
R remote_handle_current_exception( RemoteH && );
|
||||
|
||||
template <class R, class... H>
|
||||
R handle_exception( std::exception_ptr const &, H && ... ) const;
|
||||
R handle_exception( std::exception_ptr const &, H && ... );
|
||||
|
||||
template <class R, class RemoteH>
|
||||
R remote_handle_exception( std::exception_ptr const &, RemoteH && ) const;
|
||||
R remote_handle_exception( std::exception_ptr const &, RemoteH && );
|
||||
|
||||
};
|
||||
|
||||
@@ -2216,9 +2211,9 @@ TIP: See also <<tutorial-accumulate>> from the Tutorial.
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
template <class Ctx>
|
||||
context_activator<Ctx> activate_context( Ctx & ctx, on_deactivation on_deactivate ) noexcept
|
||||
context_activator<Ctx> activate_context( Ctx & ctx ) noexcept
|
||||
{
|
||||
return context_activator<Ctx>(ctx, on_deactivate);
|
||||
return context_activator<Ctx>(ctx);
|
||||
}
|
||||
|
||||
} }
|
||||
@@ -3043,39 +3038,41 @@ namespace boost { namespace leaf {
|
||||
|
||||
context() noexcept;
|
||||
context( context && x ) noexcept;
|
||||
~context() noexcept final override;
|
||||
~context() noexcept;
|
||||
|
||||
void activate() noexcept final override;
|
||||
void deactivate( bool propagate_errors ) noexcept final override;
|
||||
virtual bool is_active() const noexcept = 0;
|
||||
void activate() noexcept;
|
||||
void deactivate() noexcept;
|
||||
bool is_active() const noexcept = 0;
|
||||
|
||||
void print( std::ostream & os ) const final override;
|
||||
void propagate() noexcept = 0;
|
||||
|
||||
void print( std::ostream & os ) const;
|
||||
|
||||
template <class R, class... H>
|
||||
typename std::decay<decltype(std::declval<R>().value())>::type
|
||||
handle_all( R &, H && ... ) const;
|
||||
handle_all( R &, H && ... );
|
||||
|
||||
template <class R, class RemoteH>
|
||||
typename std::decay<decltype(std::declval<R>().value())>::type
|
||||
remote_handle_all( R &, RemoteH && ) const;
|
||||
remote_handle_all( R &, RemoteH && );
|
||||
|
||||
template <class R, class... H>
|
||||
R handle_some( R &&, H && ... ) const;
|
||||
R handle_some( R &&, H && ... );
|
||||
|
||||
template <class R, class RemoteH>
|
||||
R remote_handle_some( R &&, RemoteH && ) const;
|
||||
R remote_handle_some( R &&, RemoteH && );
|
||||
|
||||
template <class R, class... H>
|
||||
R handle_current_exception( H && ... ) const;
|
||||
R handle_current_exception( H && ... );
|
||||
|
||||
template <class R, class RemoteH>
|
||||
R remote_handle_current_exception( RemoteH && ) const;
|
||||
R remote_handle_current_exception( RemoteH && );
|
||||
|
||||
template <class R, class... H>
|
||||
R handle_exception( std::exception_ptr const &, H && ... ) const;
|
||||
R handle_exception( std::exception_ptr const &, H && ... );
|
||||
|
||||
template <class R, class RemoteH>
|
||||
R remote_handle_exception( std::exception_ptr const &, RemoteH && ) const;
|
||||
R remote_handle_exception( std::exception_ptr const &, RemoteH && );
|
||||
};
|
||||
|
||||
template <class RemoteH>
|
||||
@@ -3096,7 +3093,7 @@ To be able to load up error objects in a `context` object, it must be activated.
|
||||
|
||||
To handle an error, call one of the error handling member functions, which match E-objects currently stored in `*this` to the user-supplied handler functions. See <<context::handle_some>> for a description of the handler matching procedure (this works regardless of whether or not the `context` is currently `active`).
|
||||
|
||||
When a `context` is deactivated, it detaches from the calling thread, restoring the thread-local pointers to their pre-`activate` values. Typically, at this point the stored E-objects, if any, are either moved to corresponding storage in other `context` objects active in the calling thread (if available) -- or discarded, depending on the `propagate_errors` argument passed to <<context::activate>>.
|
||||
When a `context` is deactivated, it detaches from the calling thread, restoring the thread-local pointers to their pre-`activate` values. Typically, at this point the stored E-objects, if any, are either discarded (by default) or moved to corresponding storage in other `context` objects active in the calling thread (if available), by calling <<context::propagate>>.
|
||||
|
||||
TIP: `context` objects can be moved, as long as they aren't active. Moving an active `context` results in undefined behavior.
|
||||
|
||||
@@ -3162,7 +3159,7 @@ When an E-object is <<tutorial-loading,loaded>>, it is moved in the last activat
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
template <class... E>
|
||||
void context<E...>::deactivate( bool propagate_errors ) noexcept final override;
|
||||
void context<E...>::deactivate() noexcept;
|
||||
|
||||
} }
|
||||
----
|
||||
@@ -3177,11 +3174,6 @@ Ensures: :: * `!<<context::is_active,is_active>>()`.
|
||||
|
||||
When a context is deactivated, the thread-local pointers that currently point to each individual E-object storage in it are restored to their original value prior to calling <<context::activate>>.
|
||||
|
||||
What happens to the E-objects currently stored in `*this` depends on `propagate_errors`:
|
||||
|
||||
* If `propagate_errors` is `false`, any stored E-objects are discarded.
|
||||
* If `propagate_errors` is `true`, each stored E-object is moved to the storage pointed by the restored corresponding thread-local pointer. If that pointer is `0`, the stored E-object is discarded.
|
||||
|
||||
'''
|
||||
|
||||
[[context::is_active]]
|
||||
@@ -3202,6 +3194,29 @@ Returns: :: `true` if the `*this` is active in any thread, `false` otherwise.
|
||||
|
||||
'''
|
||||
|
||||
[[context::propagate]]
|
||||
==== `propagate`
|
||||
|
||||
.#include <boost/leaf/context.hpp>
|
||||
[source,c++]
|
||||
----
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
template <class... E>
|
||||
void context<E...>::propagate() noexcept;
|
||||
|
||||
} }
|
||||
----
|
||||
|
||||
Preconditions: ::
|
||||
`<<context::is_active,is_active>>()` or `*this` must be the last deactivated `context` object in the calling thread. That is, it is valid to call `propagate` while `is_active()` is true, or immediately after calling `<<context::deactivate,deactivate>>()`.
|
||||
|
||||
Effects: ::
|
||||
|
||||
Each stored E-object is moved to the storage (within other active `context` objects) pointed by the corresponding thread-local pointer, set when a `context` is activated -- or discarded, if the corresponding thread-local pointer is null.
|
||||
|
||||
'''
|
||||
|
||||
[[context::handle_all]]
|
||||
==== `handle_all`
|
||||
|
||||
@@ -3213,7 +3228,7 @@ namespace boost { namespace leaf {
|
||||
template <class... E>
|
||||
template <class R, class... H>
|
||||
typename std::decay<decltype(std::declval<R>().value())>::type
|
||||
context<E...>::handle_all( R && r, H && ... h ) const;
|
||||
context<E...>::handle_all( R && r, H && ... h );
|
||||
|
||||
} }
|
||||
----
|
||||
@@ -3251,7 +3266,7 @@ namespace boost { namespace leaf {
|
||||
|
||||
template <class... E>
|
||||
template <class R, class... H>
|
||||
R context<E...>::handle_current_exception( H && ... h ) const;
|
||||
R context<E...>::handle_current_exception( H && ... h );
|
||||
|
||||
} }
|
||||
----
|
||||
@@ -3287,7 +3302,7 @@ namespace boost { namespace leaf {
|
||||
|
||||
template <class... E>
|
||||
template <class R, class... H>
|
||||
R context<E...>::handle_exception( std::exception_ptr const & ep, H && ... h ) const
|
||||
R context<E...>::handle_exception( std::exception_ptr const & ep, H && ... h )
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -3317,7 +3332,7 @@ namespace boost { namespace leaf {
|
||||
|
||||
template <class... E>
|
||||
template <class R, class... H>
|
||||
R context<E...>::handle_some( R && r, H && ... h ) const;
|
||||
R context<E...>::handle_some( R && r, H && ... h );
|
||||
|
||||
} }
|
||||
----
|
||||
@@ -3613,7 +3628,7 @@ else
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
template <class... E>
|
||||
void context<E...>::print( std::ostream & os ) const final override;
|
||||
void context<E...>::print( std::ostream & os ) const;
|
||||
|
||||
} }
|
||||
----
|
||||
@@ -3633,7 +3648,7 @@ namespace boost { namespace leaf {
|
||||
template <class... E>
|
||||
template <class R, class RemoteH>
|
||||
typename std::decay<decltype(std::declval<R>().value())>::type
|
||||
context<E...>::remote_handle_all( R & r, RemoteH && h ) const;
|
||||
context<E...>::remote_handle_all( R & r, RemoteH && h );
|
||||
|
||||
} }
|
||||
----
|
||||
@@ -3699,7 +3714,7 @@ namespace boost { namespace leaf {
|
||||
|
||||
template <class... E>
|
||||
template <class R, class RemoteH>
|
||||
R context<E...>::remote_handle_current_exception( RemoteH && h ) const;
|
||||
R context<E...>::remote_handle_current_exception( RemoteH && h );
|
||||
|
||||
} }
|
||||
----
|
||||
@@ -3760,7 +3775,7 @@ namespace boost { namespace leaf {
|
||||
|
||||
template <class... E>
|
||||
template <class R, class RemoteH>
|
||||
R context<E...>::remote_handle_exception( std::exception_ptr const & ep, RemoteH && h ) const;
|
||||
R context<E...>::remote_handle_exception( std::exception_ptr const & ep, RemoteH && h );
|
||||
|
||||
} }
|
||||
----
|
||||
@@ -3794,7 +3809,7 @@ namespace boost { namespace leaf {
|
||||
|
||||
template <class... E>
|
||||
template <class R, class RemoteH>
|
||||
R context<E...>::remote_handle_some( R && r, RemoteH && h ) const;
|
||||
R context<E...>::remote_handle_some( R && r, RemoteH && h );
|
||||
|
||||
} }
|
||||
----
|
||||
@@ -3857,13 +3872,6 @@ TIP: Because LEAF does not invoke the user-defined `handle_error` function direc
|
||||
----
|
||||
namespace boost { namespace leaf {
|
||||
|
||||
enum class on_deactivation
|
||||
{
|
||||
propagate,
|
||||
propagate_if_uncaught_exception,
|
||||
capture_do_not_propagate
|
||||
};
|
||||
|
||||
template <class Ctx>
|
||||
class context_activator
|
||||
{
|
||||
@@ -3872,11 +3880,9 @@ namespace boost { namespace leaf {
|
||||
|
||||
public:
|
||||
|
||||
context_activator( Ctx & ctx, on_deactivation on_deactivate ) noexcept;
|
||||
explicit context_activator( Ctx & ctx ) noexcept;
|
||||
context_activator( context_activator && ) noexcept;
|
||||
~context_activator() noexcept;
|
||||
|
||||
void set_on_deactivate( on_deactivation on_deactivate ) noexcept;
|
||||
};
|
||||
|
||||
} }
|
||||
@@ -3884,11 +3890,12 @@ namespace boost { namespace leaf {
|
||||
|
||||
`context_activator` is a simple class that activates and deactivates a <<context>> using RAII:
|
||||
|
||||
* The constructor stores a reference to `ctx` and calls <<context::activate>>.
|
||||
* The destructor behavior depends on the `on_deactivation` state:
|
||||
** `on_deactivation::propagate` instructs `~context_activator` to call <<context::deactivate>> with `true`;
|
||||
** `on_deactivation::propagate_if_uncaught_exception` instructs `~context_activator` to call `deactivate` with the value returned from `std::uncaught_exception()`;
|
||||
** `on_deactivation::capture_do_not_propagate` instructs `~context_activator` to call `deactivate` with `false`.
|
||||
If `<<context::is_active,ctx.is_active>>`() is `true` at the time the `context_activator` is initialized, the constructor and the destructor have no effects. Otherwise:
|
||||
|
||||
* The constructor stores a reference to `ctx` and calls `<<context::activate,ctx.activate>>`().
|
||||
* The destructor:
|
||||
** If `ctx.is_active()` is false, has no effects (that is, it is valid to call <<context::deactivate>> manually, before the `context_activator` object expires);
|
||||
** Otherwise, calls `<<context::deactivate,ctx.deactivate>>`() and, if there are new uncaught exceptions since the constructor was called, the destructor calls `<<context::propagate,ctx.propagate>>`().
|
||||
|
||||
For automatic deduction of `Ctx`, use <<activate_context>>.
|
||||
|
||||
@@ -4412,9 +4419,11 @@ namespace boost { namespace leaf {
|
||||
public:
|
||||
|
||||
virtual void activate() noexcept = 0;
|
||||
virtual void deactivate( bool propagate_errors ) noexcept = 0;
|
||||
virtual void deactivate() noexcept = 0;
|
||||
virtual bool is_active() const noexcept = 0;
|
||||
|
||||
virtual void propagate() noexcept = 0;
|
||||
|
||||
virtual void print( std::ostream & ) const = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ auto async_demo_rpc(AsyncStream &stream, ErrorContext &error_context, Completion
|
||||
void operator()(error_code ec, std::size_t /*bytes_transferred*/ = 0) {
|
||||
leaf::result<bool> result_continue_execution;
|
||||
{
|
||||
auto active_context = activate_context(m_error_context, leaf::on_deactivation::do_not_propagate);
|
||||
auto active_context = activate_context(m_error_context);
|
||||
auto load = leaf::preload(e_last_operation{m_data.response ? "async_demo_rpc::continuation-write"
|
||||
: "async_demo_rpc::continuation-read"});
|
||||
if (ec == http::error::end_of_stream) {
|
||||
@@ -539,7 +539,7 @@ int main(int argc, char **argv) {
|
||||
async_demo_rpc(socket, error_context, [&](leaf::result<void> result) {
|
||||
// Note: In case we wanted to add some additional information to the error associated with the result
|
||||
// we would need to activate the error-context
|
||||
auto active_context = activate_context(error_context, leaf::on_deactivation::do_not_propagate);
|
||||
auto active_context = activate_context(error_context);
|
||||
if (result) {
|
||||
std::cout << "Server: Client work completed successfully" << std::endl;
|
||||
rv = 0;
|
||||
|
||||
@@ -119,10 +119,10 @@
|
||||
|
||||
#if __cplusplus > 201402L
|
||||
# define LEAF_CONSTEXPR constexpr
|
||||
# define LEAF_UNCAUGHT_EXCEPTIONS std::uncaught_exceptions
|
||||
# define LEAF_STD_UNCAUGHT_EXCEPTIONS 1
|
||||
#else
|
||||
# define LEAF_CONSTEXPR
|
||||
# define LEAF_UNCAUGHT_EXCEPTIONS std::uncaught_exception
|
||||
# define LEAF_STD_UNCAUGHT_EXCEPTIONS 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1129,20 +1129,22 @@ namespace boost { namespace leaf {
|
||||
assert(x.top_==0);
|
||||
}
|
||||
|
||||
~slot() noexcept
|
||||
{
|
||||
assert(top_==0);
|
||||
}
|
||||
|
||||
LEAF_CONSTEXPR void activate() noexcept
|
||||
{
|
||||
assert(top_==0);
|
||||
assert(top_==0 || *top_!=this);
|
||||
top_ = &tl_slot_ptr<E>();
|
||||
prev_ = *top_;
|
||||
*top_ = this;
|
||||
}
|
||||
|
||||
LEAF_CONSTEXPR void deactivate( bool propagate_errors ) noexcept;
|
||||
|
||||
LEAF_CONSTEXPR void deactivate() noexcept
|
||||
{
|
||||
assert(top_!=0 && *top_==this);
|
||||
*top_ = prev_;
|
||||
}
|
||||
|
||||
LEAF_CONSTEXPR void propagate() noexcept;
|
||||
|
||||
using impl::put;
|
||||
using impl::has_value;
|
||||
@@ -1182,28 +1184,25 @@ namespace boost { namespace leaf {
|
||||
#endif
|
||||
|
||||
template <class E>
|
||||
LEAF_CONSTEXPR inline void slot<E>::deactivate( bool propagate_errors ) noexcept
|
||||
LEAF_CONSTEXPR inline void slot<E>::propagate() noexcept
|
||||
{
|
||||
assert(top_!=0);
|
||||
if( propagate_errors )
|
||||
if( prev_ )
|
||||
{
|
||||
impl & this_ = *this;
|
||||
impl & that_ = *prev_;
|
||||
that_ = std::move(this_);
|
||||
}
|
||||
assert(top_!=0 && (*top_==prev_ || *top_==this));
|
||||
if( prev_ )
|
||||
{
|
||||
impl & this_ = *this;
|
||||
impl & that_ = *prev_;
|
||||
that_ = std::move(this_);
|
||||
}
|
||||
#if LEAF_DIAGNOSTICS
|
||||
else
|
||||
{
|
||||
int c = tl_unexpected_enabled_counter();
|
||||
assert(c>=0);
|
||||
if( c )
|
||||
if( int err_id = impl::key() )
|
||||
load_unexpected(err_id, std::move(*this).value(err_id));
|
||||
}
|
||||
else
|
||||
{
|
||||
int c = tl_unexpected_enabled_counter();
|
||||
assert(c>=0);
|
||||
if( c )
|
||||
if( int err_id = impl::key() )
|
||||
load_unexpected(err_id, std::move(*this).value(err_id));
|
||||
}
|
||||
#endif
|
||||
*top_ = prev_;
|
||||
top_ = 0;
|
||||
}
|
||||
|
||||
template <class E>
|
||||
@@ -1494,7 +1493,8 @@ namespace boost { namespace leaf {
|
||||
public:
|
||||
virtual error_id propagate_captured_errors() noexcept = 0;
|
||||
virtual void activate() noexcept = 0;
|
||||
virtual void deactivate( bool propagate_errors ) noexcept = 0;
|
||||
virtual void deactivate() noexcept = 0;
|
||||
virtual void propagate() noexcept = 0;
|
||||
virtual bool is_active() const noexcept = 0;
|
||||
virtual void print( std::ostream & ) const = 0;
|
||||
error_id captured_id_;
|
||||
@@ -1504,77 +1504,61 @@ namespace boost { namespace leaf {
|
||||
|
||||
////////////////////////////////////////////
|
||||
|
||||
enum class on_deactivation
|
||||
{
|
||||
propagate,
|
||||
do_not_propagate,
|
||||
propagate_if_uncaught_exception
|
||||
};
|
||||
|
||||
template <class Ctx>
|
||||
class context_activator
|
||||
{
|
||||
context_activator( context_activator const & ) = delete;
|
||||
context_activator & operator=( context_activator const & ) = delete;
|
||||
|
||||
#if !defined(LEAF_NO_EXCEPTIONS) && LEAF_STD_UNCAUGHT_EXCEPTIONS
|
||||
int const uncaught_exceptions_;
|
||||
#endif
|
||||
Ctx * ctx_;
|
||||
bool const ctx_was_active_;
|
||||
on_deactivation on_deactivate_;
|
||||
|
||||
public:
|
||||
|
||||
LEAF_CONSTEXPR LEAF_ALWAYS_INLINE context_activator(Ctx & ctx, on_deactivation on_deactivate) noexcept:
|
||||
ctx_(&ctx),
|
||||
ctx_was_active_(ctx.is_active()),
|
||||
on_deactivate_(on_deactivate)
|
||||
explicit LEAF_CONSTEXPR LEAF_ALWAYS_INLINE context_activator(Ctx & ctx) noexcept:
|
||||
#if !defined(LEAF_NO_EXCEPTIONS) && LEAF_STD_UNCAUGHT_EXCEPTIONS
|
||||
uncaught_exceptions_(std::uncaught_exceptions()),
|
||||
#endif
|
||||
ctx_(ctx.is_active() ? 0 : &ctx)
|
||||
{
|
||||
if( !ctx_was_active_ )
|
||||
ctx.activate();
|
||||
if( ctx_ )
|
||||
ctx_->activate();
|
||||
}
|
||||
|
||||
LEAF_CONSTEXPR LEAF_ALWAYS_INLINE context_activator( context_activator && x ) noexcept:
|
||||
ctx_(x.ctx_),
|
||||
ctx_was_active_(x.ctx_was_active_),
|
||||
on_deactivate_(x.on_deactivate_)
|
||||
#if !defined(LEAF_NO_EXCEPTIONS) && LEAF_STD_UNCAUGHT_EXCEPTIONS
|
||||
uncaught_exceptions_(x.uncaught_exceptions_),
|
||||
#endif
|
||||
ctx_(x.ctx_)
|
||||
{
|
||||
x.ctx_ = 0;
|
||||
}
|
||||
|
||||
LEAF_ALWAYS_INLINE ~context_activator() noexcept
|
||||
{
|
||||
if( ctx_ )
|
||||
{
|
||||
assert(
|
||||
on_deactivate_ == on_deactivation::propagate ||
|
||||
on_deactivate_ == on_deactivation::do_not_propagate ||
|
||||
on_deactivate_ == on_deactivation::propagate_if_uncaught_exception);
|
||||
if( !ctx_was_active_ )
|
||||
if( on_deactivate_ == on_deactivation::propagate_if_uncaught_exception )
|
||||
{
|
||||
#ifdef LEAF_NO_EXCEPTIONS
|
||||
ctx_->deactivate(false);
|
||||
#else
|
||||
bool has_exception = LEAF_UNCAUGHT_EXCEPTIONS();
|
||||
ctx_->deactivate(has_exception);
|
||||
if( !has_exception )
|
||||
(void) leaf_detail::new_id();
|
||||
if( !ctx_ )
|
||||
return;
|
||||
if( ctx_->is_active() )
|
||||
ctx_->deactivate();
|
||||
#ifndef LEAF_NO_EXCEPTIONS
|
||||
# if LEAF_STD_UNCAUGHT_EXCEPTIONS
|
||||
if( std::uncaught_exceptions() > uncaught_exceptions_ )
|
||||
# else
|
||||
if( std::uncaught_exception() )
|
||||
# endif
|
||||
ctx_->propagate();
|
||||
else
|
||||
(void) leaf_detail::new_id();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
ctx_->deactivate(on_deactivate_ == on_deactivation::propagate);
|
||||
}
|
||||
}
|
||||
|
||||
LEAF_CONSTEXPR LEAF_ALWAYS_INLINE void set_on_deactivate( on_deactivation on_deactivate ) noexcept
|
||||
{
|
||||
on_deactivate_ = on_deactivate;
|
||||
}
|
||||
};
|
||||
|
||||
template <class Ctx>
|
||||
LEAF_CONSTEXPR LEAF_ALWAYS_INLINE context_activator<Ctx> activate_context( Ctx & ctx, on_deactivation on_deactivate ) noexcept
|
||||
LEAF_CONSTEXPR LEAF_ALWAYS_INLINE context_activator<Ctx> activate_context(Ctx & ctx) noexcept
|
||||
{
|
||||
return context_activator<Ctx>(ctx, on_deactivate);
|
||||
return context_activator<Ctx>(ctx);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////
|
||||
@@ -1660,7 +1644,7 @@ namespace boost { namespace leaf {
|
||||
{
|
||||
public:
|
||||
|
||||
virtual error_id get_error_id() const = 0;
|
||||
virtual error_id get_error_id() const noexcept = 0;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -1674,7 +1658,7 @@ namespace boost { namespace leaf {
|
||||
public exception_base,
|
||||
public error_id
|
||||
{
|
||||
error_id get_error_id() const final override
|
||||
error_id get_error_id() const noexcept final override
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
@@ -1754,7 +1738,11 @@ namespace boost { namespace leaf {
|
||||
else
|
||||
{
|
||||
#ifndef LEAF_NO_EXCEPTIONS
|
||||
if( LEAF_UNCAUGHT_EXCEPTIONS() )
|
||||
# if LEAF_STD_UNCAUGHT_EXCEPTIONS
|
||||
if( std::uncaught_exceptions() )
|
||||
# else
|
||||
if( std::uncaught_exception() )
|
||||
# endif
|
||||
return leaf_detail::new_id();
|
||||
#endif
|
||||
return 0;
|
||||
@@ -2068,7 +2056,7 @@ namespace boost { namespace leaf {
|
||||
[[noreturn]] void unload_and_rethrow_original_exception() const
|
||||
{
|
||||
assert(ctx_->captured_id_);
|
||||
auto active_context = activate_context(*ctx_, on_deactivation::propagate);
|
||||
auto active_context = activate_context(*ctx_);
|
||||
id_factory<>::current_id = ctx_->captured_id_.value();
|
||||
std::rethrow_exception(ex_);
|
||||
}
|
||||
@@ -2082,7 +2070,7 @@ namespace boost { namespace leaf {
|
||||
template <class R, class F, class... A>
|
||||
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, on_deactivation::do_not_propagate);
|
||||
auto active_context = activate_context(*ctx);
|
||||
augment_id aug;
|
||||
try
|
||||
{
|
||||
@@ -2107,7 +2095,7 @@ namespace boost { namespace leaf {
|
||||
template <class R, class F, class... A>
|
||||
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, on_deactivation::do_not_propagate);
|
||||
auto active_context = activate_context(*ctx);
|
||||
augment_id aug;
|
||||
try
|
||||
{
|
||||
@@ -2172,14 +2160,14 @@ namespace boost { namespace leaf {
|
||||
template <class R, class F, class... A>
|
||||
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) noexcept
|
||||
{
|
||||
auto active_context = activate_context(*ctx, on_deactivation::do_not_propagate);
|
||||
auto active_context = activate_context(*ctx);
|
||||
return std::forward<F>(f)(std::forward<A>(a)...);
|
||||
}
|
||||
|
||||
template <class R, class F, class... A>
|
||||
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) noexcept
|
||||
{
|
||||
auto active_context = activate_context(*ctx, on_deactivation::do_not_propagate);
|
||||
auto active_context = activate_context(*ctx);
|
||||
if( auto r = std::forward<F>(f)(std::forward<A>(a)...) )
|
||||
return r;
|
||||
else
|
||||
@@ -2398,18 +2386,25 @@ namespace boost { namespace leaf {
|
||||
std::get<I-1>(tup).activate();
|
||||
}
|
||||
|
||||
LEAF_CONSTEXPR static void deactivate( Tuple & tup, bool propagate_errors ) noexcept
|
||||
LEAF_CONSTEXPR static void deactivate( Tuple & tup ) noexcept
|
||||
{
|
||||
std::get<I-1>(tup).deactivate(propagate_errors);
|
||||
tuple_for_each<I-1,Tuple>::deactivate(tup, propagate_errors);
|
||||
std::get<I-1>(tup).deactivate();
|
||||
tuple_for_each<I-1,Tuple>::deactivate(tup);
|
||||
}
|
||||
|
||||
LEAF_CONSTEXPR static void propagate( Tuple & tup, int err_id ) noexcept
|
||||
LEAF_CONSTEXPR static void propagate( Tuple & tup ) noexcept
|
||||
{
|
||||
auto & sl = std::get<I-1>(tup);
|
||||
sl.propagate();
|
||||
tuple_for_each<I-1,Tuple>::propagate(tup);
|
||||
}
|
||||
|
||||
LEAF_CONSTEXPR static void propagate_captured( Tuple & tup, int err_id ) noexcept
|
||||
{
|
||||
auto & sl = std::get<I-1>(tup);
|
||||
if( sl.has_value(err_id) )
|
||||
leaf_detail::load_slot(err_id, std::move(sl).value(err_id));
|
||||
tuple_for_each<I-1,Tuple>::propagate(tup, err_id);
|
||||
tuple_for_each<I-1,Tuple>::propagate_captured(tup, err_id);
|
||||
}
|
||||
|
||||
static void print( std::ostream & os, void const * tup, int key_to_print )
|
||||
@@ -2424,8 +2419,9 @@ namespace boost { namespace leaf {
|
||||
struct tuple_for_each<0, Tuple>
|
||||
{
|
||||
LEAF_CONSTEXPR static void activate( Tuple & ) noexcept { }
|
||||
LEAF_CONSTEXPR static void deactivate( Tuple &, bool ) noexcept { }
|
||||
LEAF_CONSTEXPR static void propagate( Tuple & tup, int ) noexcept { }
|
||||
LEAF_CONSTEXPR static void deactivate( Tuple & ) noexcept { }
|
||||
LEAF_CONSTEXPR static void propagate( Tuple & tup ) noexcept { }
|
||||
LEAF_CONSTEXPR static void propagate_captured( Tuple & tup, int ) noexcept { }
|
||||
static void print( std::ostream &, void const *, int ) { }
|
||||
};
|
||||
}
|
||||
@@ -2606,7 +2602,7 @@ namespace boost { namespace leaf {
|
||||
is_active_ = true;
|
||||
}
|
||||
|
||||
LEAF_CONSTEXPR void deactivate( bool propagate_errors ) noexcept
|
||||
LEAF_CONSTEXPR void deactivate() noexcept
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
assert(is_active());
|
||||
@@ -2619,7 +2615,12 @@ namespace boost { namespace leaf {
|
||||
if( unexpected_requested<Tup>::value )
|
||||
--tl_unexpected_enabled_counter();
|
||||
#endif
|
||||
tuple_for_each<std::tuple_size<Tup>::value,Tup>::deactivate(tup_, propagate_errors);
|
||||
tuple_for_each<std::tuple_size<Tup>::value,Tup>::deactivate(tup_);
|
||||
}
|
||||
|
||||
LEAF_CONSTEXPR void propagate() noexcept
|
||||
{
|
||||
tuple_for_each<std::tuple_size<Tup>::value,Tup>::propagate(tup_);
|
||||
}
|
||||
|
||||
LEAF_CONSTEXPR bool is_active() const noexcept
|
||||
@@ -2632,57 +2633,69 @@ namespace boost { namespace leaf {
|
||||
leaf_detail::tuple_for_each<std::tuple_size<Tup>::value,Tup>::print(os, &tup_, 0);
|
||||
}
|
||||
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR typename std::decay<decltype(std::declval<R>().value())>::type handle_all_( R &, H && ... );
|
||||
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR typename std::decay<decltype(std::declval<R>().value())>::type remote_handle_all_( R &, RemoteH && );
|
||||
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR R handle_some_( R &&, H && ... );
|
||||
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR R remote_handle_some_( R &&, RemoteH && );
|
||||
|
||||
template <class TryBlock, class... H>
|
||||
decltype(std::declval<TryBlock>()()) try_catch_( TryBlock &&, H && ... );
|
||||
|
||||
template <class TryBlock, class RemoteH>
|
||||
decltype(std::declval<TryBlock>()()) remote_try_catch_( TryBlock &&, RemoteH && );
|
||||
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR R handle_current_exception_( H && ... );
|
||||
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR R remote_handle_current_exception_( RemoteH && );
|
||||
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR R handle_exception_( std::exception_ptr const &, H && ... );
|
||||
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR R remote_handle_exception_( std::exception_ptr const &, RemoteH && );
|
||||
|
||||
protected:
|
||||
|
||||
LEAF_CONSTEXPR error_id propagate_captured_errors( error_id err_id ) noexcept
|
||||
{
|
||||
tuple_for_each<std::tuple_size<Tup>::value,Tup>::propagate(tup_, err_id.value());
|
||||
tuple_for_each<std::tuple_size<Tup>::value,Tup>::propagate_captured(tup_, err_id.value());
|
||||
return err_id;
|
||||
}
|
||||
|
||||
template <class TryBlock, class... H>
|
||||
LEAF_CONSTEXPR typename std::decay<decltype(std::declval<TryBlock>()().value())>::type try_handle_all_( TryBlock &&, H && ... ) const;
|
||||
|
||||
template <class TryBlock, class RemoteH>
|
||||
LEAF_CONSTEXPR typename std::decay<decltype(std::declval<TryBlock>()().value())>::type remote_try_handle_all_( TryBlock &&, RemoteH && ) const;
|
||||
|
||||
template <class TryBlock, class... H, class Ctx>
|
||||
LEAF_CONSTEXPR typename std::decay<decltype(std::declval<TryBlock>()())>::type try_handle_some_( context_activator<Ctx> &, TryBlock &&, H && ... ) const;
|
||||
|
||||
template <class TryBlock, class RemoteH, class Ctx>
|
||||
LEAF_CONSTEXPR typename std::decay<decltype(std::declval<TryBlock>()())>::type remote_try_handle_some_( context_activator<Ctx> &, TryBlock &&, RemoteH && ) const;
|
||||
|
||||
public:
|
||||
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR typename std::decay<decltype(std::declval<R>().value())>::type handle_all( R &, H && ... ) const;
|
||||
LEAF_CONSTEXPR typename std::decay<decltype(std::declval<R>().value())>::type handle_all( R &, H && ... );
|
||||
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR typename std::decay<decltype(std::declval<R>().value())>::type remote_handle_all( R &, RemoteH && ) const;
|
||||
LEAF_CONSTEXPR typename std::decay<decltype(std::declval<R>().value())>::type remote_handle_all( R &, RemoteH && );
|
||||
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR R handle_some( R &&, H && ... ) const;
|
||||
LEAF_CONSTEXPR R handle_some( R &&, H && ... );
|
||||
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR R remote_handle_some( R &&, RemoteH && ) const;
|
||||
|
||||
template <class TryBlock, class... H>
|
||||
decltype(std::declval<TryBlock>()()) try_catch_( TryBlock &&, H && ... ) const;
|
||||
|
||||
template <class TryBlock, class RemoteH>
|
||||
decltype(std::declval<TryBlock>()()) remote_try_catch_( TryBlock &&, RemoteH && ) const;
|
||||
LEAF_CONSTEXPR R remote_handle_some( R &&, RemoteH && );
|
||||
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR R handle_current_exception( H && ... ) const;
|
||||
LEAF_CONSTEXPR R handle_current_exception( H && ... );
|
||||
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR R remote_handle_current_exception( RemoteH && ) const;
|
||||
LEAF_CONSTEXPR R remote_handle_current_exception( RemoteH && );
|
||||
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR R handle_exception( std::exception_ptr const &, H && ... ) const;
|
||||
LEAF_CONSTEXPR R handle_exception( std::exception_ptr const &, H && ... );
|
||||
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR R remote_handle_exception( std::exception_ptr const &, RemoteH && ) const;
|
||||
LEAF_CONSTEXPR R remote_handle_exception( std::exception_ptr const &, RemoteH && );
|
||||
};
|
||||
|
||||
template <class... E>
|
||||
@@ -2813,7 +2826,8 @@ namespace boost { namespace leaf {
|
||||
{
|
||||
error_id propagate_captured_errors() noexcept final override { return Ctx::propagate_captured_errors(captured_id_); }
|
||||
void activate() noexcept final override { Ctx::activate(); }
|
||||
void deactivate( bool propagate_errors ) noexcept final override { Ctx::deactivate(propagate_errors); }
|
||||
void deactivate() noexcept final override { Ctx::deactivate(); }
|
||||
void propagate() noexcept final override { Ctx::propagate(); }
|
||||
bool is_active() const noexcept final override { return Ctx::is_active(); }
|
||||
void print( std::ostream & os ) const final override { return Ctx::print(os); }
|
||||
};
|
||||
@@ -3574,102 +3588,80 @@ namespace boost { namespace leaf {
|
||||
{
|
||||
template <class... E>
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR inline typename std::decay<decltype(std::declval<R>().value())>::type context_base<E...>::handle_all( R & r, H && ... h ) const
|
||||
LEAF_CONSTEXPR inline typename std::decay<decltype(std::declval<R>().value())>::type context_base<E...>::handle_all_( R & r, H && ... h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
using Ret = typename std::decay<decltype(std::declval<R>().value())>::type;
|
||||
static_assert(is_result_type<R>::value, "The R type used with a handle_all function must be registered with leaf::is_result_type");
|
||||
return handle_error_<Ret>(tup(), error_info(r.error()), std::forward<H>(h)...);
|
||||
assert(is_active());
|
||||
error_info const ei(r.error());
|
||||
deactivate();
|
||||
return handle_error_<Ret>(tup(), ei, std::forward<H>(h)...);
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR inline typename std::decay<decltype(std::declval<R>().value())>::type context_base<E...>::remote_handle_all( R & r, RemoteH && h ) const
|
||||
LEAF_CONSTEXPR inline typename std::decay<decltype(std::declval<R>().value())>::type context_base<E...>::remote_handle_all_( R & r, RemoteH && h )
|
||||
{
|
||||
static_assert(is_result_type<R>::value, "The R type used with a handle_all function must be registered with leaf::is_result_type");
|
||||
return std::forward<RemoteH>(h)(error_info(r.error(), this)).get();
|
||||
assert(is_active());
|
||||
error_info const ei(r.error(), this);
|
||||
deactivate();
|
||||
return std::forward<RemoteH>(h)(ei).get();
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::handle_some( R && r, H && ... h ) const
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::handle_some_( R && r, H && ... h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<R>::value, "The R type used with a handle_some function must be registered with leaf::is_result_type");
|
||||
return handle_error_<R>(tup(), error_info(r.error()), std::forward<H>(h)...,
|
||||
assert(is_active());
|
||||
error_info const ei(r.error());
|
||||
deactivate();
|
||||
return handle_error_<R>(tup(), ei, std::forward<H>(h)...,
|
||||
[&r]()->R { return std::move(r); });
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::remote_handle_some( R && r, RemoteH && h ) const
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::remote_handle_some_( R && r, RemoteH && h )
|
||||
{
|
||||
static_assert(is_result_type<R>::value, "The R type used with a handle_some function must be registered with leaf::is_result_type");
|
||||
return std::forward<RemoteH>(h)(error_info(r.error(), this)).get();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////
|
||||
|
||||
template <class... E>
|
||||
template <class TryBlock, class... H>
|
||||
LEAF_CONSTEXPR inline typename std::decay<decltype(std::declval<TryBlock>()().value())>::type context_base<E...>::try_handle_all_( TryBlock && try_block, H && ... h ) const
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a try_handle_all function must be registered with leaf::is_result_type");
|
||||
assert(this->is_active());
|
||||
if( auto r = std::forward<TryBlock>(try_block)() )
|
||||
return r.value();
|
||||
else
|
||||
return handle_all(r, std::forward<H>(h)...);
|
||||
assert(is_active());
|
||||
error_info const ei(r.error(), this);
|
||||
deactivate();
|
||||
return std::forward<RemoteH>(h)(ei).get();
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class TryBlock, class RemoteH>
|
||||
LEAF_CONSTEXPR inline typename std::decay<decltype(std::declval<TryBlock>()().value())>::type context_base<E...>::remote_try_handle_all_( TryBlock && try_block, RemoteH && h ) const
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR inline typename std::decay<decltype(std::declval<R>().value())>::type context_base<E...>::handle_all( R & r, H && ... h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a remote_try_handle_all function must be registered with leaf::is_result_type");
|
||||
assert(this->is_active());
|
||||
if( auto r = std::forward<TryBlock>(try_block)() )
|
||||
return r.value();
|
||||
else
|
||||
return remote_handle_all(r, std::forward<RemoteH>(h));
|
||||
auto active_context = activate_context(*this);
|
||||
return handle_all_(r, std::forward<H>(h)...);
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class TryBlock, class... H, class Ctx>
|
||||
LEAF_CONSTEXPR inline typename std::decay<decltype(std::declval<TryBlock>()())>::type context_base<E...>::try_handle_some_( context_activator<Ctx> & active_context, TryBlock && try_block, H && ... h ) const
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR inline typename std::decay<decltype(std::declval<R>().value())>::type context_base<E...>::remote_handle_all( R & r, RemoteH && h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a try_handle_some function must be registered with leaf::is_result_type");
|
||||
assert(this->is_active());
|
||||
if( auto r = std::forward<TryBlock>(try_block)() )
|
||||
return r;
|
||||
else
|
||||
{
|
||||
auto rr = handle_some(std::move(r), std::forward<H>(h)...);
|
||||
if( !rr )
|
||||
active_context.set_on_deactivate(on_deactivation::propagate);
|
||||
return rr;
|
||||
}
|
||||
auto active_context = activate_context(*this);
|
||||
return remote_handle_all_(r, std::forward<RemoteH>(h));
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class TryBlock, class RemoteH, class Ctx>
|
||||
LEAF_CONSTEXPR inline typename std::decay<decltype(std::declval<TryBlock>()())>::type context_base<E...>::remote_try_handle_some_( context_activator<Ctx> & active_context, TryBlock && try_block, RemoteH && h ) const
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::handle_some( R && r, H && ... h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a remote_try_handle_some function must be registered with leaf::is_result_type");
|
||||
assert(this->is_active());
|
||||
if( auto r = std::forward<TryBlock>(try_block)() )
|
||||
return r;
|
||||
else
|
||||
{
|
||||
auto rr = remote_handle_some(std::move(r), std::forward<RemoteH>(h));
|
||||
if( !rr )
|
||||
active_context.set_on_deactivate(on_deactivation::propagate);
|
||||
return rr;
|
||||
}
|
||||
auto active_context = activate_context(*this);
|
||||
return handle_some_(std::forward<R>(r), std::forward<H>(h)...);
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::remote_handle_some( R && r, RemoteH && h )
|
||||
{
|
||||
auto active_context = activate_context(*this);
|
||||
return remote_handle_some_(std::forward<R>(r), std::forward<RemoteH>(h));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3780,32 +3772,62 @@ namespace boost { namespace leaf {
|
||||
template <class TryBlock, class... H>
|
||||
LEAF_CONSTEXPR LEAF_ALWAYS_INLINE typename std::decay<decltype(std::declval<TryBlock>()().value())>::type nocatch_context<E...>::try_handle_all( TryBlock && try_block, H && ... h )
|
||||
{
|
||||
auto active_context = activate_context(*this, on_deactivation::do_not_propagate);
|
||||
return this->try_handle_all_( std::forward<TryBlock>(try_block), std::forward<H>(h)... );
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a try_handle_all function must be registered with leaf::is_result_type");
|
||||
auto active_context = activate_context(*this);
|
||||
if( auto r = std::forward<TryBlock>(try_block)() )
|
||||
return r.value();
|
||||
else
|
||||
return this->handle_all_(r, std::forward<H>(h)...);
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class TryBlock, class RemoteH>
|
||||
LEAF_CONSTEXPR LEAF_ALWAYS_INLINE typename std::decay<decltype(std::declval<TryBlock>()().value())>::type nocatch_context<E...>::remote_try_handle_all( TryBlock && try_block, RemoteH && h )
|
||||
{
|
||||
auto active_context = activate_context(*this, on_deactivation::do_not_propagate);
|
||||
return this->remote_try_handle_all_( std::forward<TryBlock>(try_block), std::forward<RemoteH>(h) );
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a remote_try_handle_all function must be registered with leaf::is_result_type");
|
||||
auto active_context = activate_context(*this);
|
||||
if( auto r = std::forward<TryBlock>(try_block)() )
|
||||
return r.value();
|
||||
else
|
||||
return this->remote_handle_all_(r, std::forward<RemoteH>(h));
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class TryBlock, class... H>
|
||||
LEAF_CONSTEXPR LEAF_ALWAYS_INLINE typename std::decay<decltype(std::declval<TryBlock>()())>::type nocatch_context<E...>::try_handle_some( TryBlock && try_block, H && ... h )
|
||||
{
|
||||
auto active_context = activate_context(*this, on_deactivation::propagate_if_uncaught_exception);
|
||||
return this->try_handle_some_( active_context, std::forward<TryBlock>(try_block), std::forward<H>(h)... );
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a try_handle_some function must be registered with leaf::is_result_type");
|
||||
auto active_context = activate_context(*this);
|
||||
if( auto r = std::forward<TryBlock>(try_block)() )
|
||||
return r;
|
||||
else
|
||||
{
|
||||
auto rr = this->handle_some_(std::move(r), std::forward<H>(h)...);
|
||||
if( !rr )
|
||||
this->propagate();
|
||||
return rr;
|
||||
}
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class TryBlock, class RemoteH>
|
||||
LEAF_CONSTEXPR LEAF_ALWAYS_INLINE typename std::decay<decltype(std::declval<TryBlock>()())>::type nocatch_context<E...>::remote_try_handle_some( TryBlock && try_block, RemoteH && h )
|
||||
{
|
||||
auto active_context = activate_context(*this, on_deactivation::propagate_if_uncaught_exception);
|
||||
return this->remote_try_handle_some_( active_context, std::forward<TryBlock>(try_block), std::forward<RemoteH>(h) );
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a remote_try_handle_some function must be registered with leaf::is_result_type");
|
||||
auto active_context = activate_context(*this);
|
||||
if( auto r = std::forward<TryBlock>(try_block)() )
|
||||
return r;
|
||||
else
|
||||
{
|
||||
auto rr = remote_handle_some_(std::move(r), std::forward<RemoteH>(h));
|
||||
if( !rr )
|
||||
this->propagate();
|
||||
return rr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4059,49 +4081,23 @@ namespace boost { namespace leaf {
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
template <class TryBlock, class... H>
|
||||
LEAF_CONSTEXPR inline decltype(std::declval<TryBlock>()()) try_catch( TryBlock && try_block, H && ... h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
context_type_from_handlers<H...> ctx;
|
||||
auto active_context = activate_context(ctx, on_deactivation::propagate_if_uncaught_exception);
|
||||
return ctx.try_catch_(
|
||||
[&]
|
||||
{
|
||||
return std::forward<TryBlock>(try_block)();
|
||||
},
|
||||
std::forward<H>(h)...);
|
||||
}
|
||||
|
||||
template <class TryBlock, class RemoteH>
|
||||
LEAF_CONSTEXPR inline decltype(std::declval<TryBlock>()()) remote_try_catch( TryBlock && try_block, RemoteH && h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
context_type_from_remote_handler<RemoteH> ctx;
|
||||
auto active_context = activate_context(ctx, on_deactivation::propagate_if_uncaught_exception);
|
||||
return ctx.remote_try_catch_(
|
||||
[&]
|
||||
{
|
||||
return std::forward<TryBlock>(try_block)();
|
||||
},
|
||||
std::forward<RemoteH>(h));
|
||||
}
|
||||
|
||||
namespace leaf_detail
|
||||
{
|
||||
template <class... E>
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::handle_current_exception( H && ... h ) const
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::handle_current_exception_( H && ... h )
|
||||
{
|
||||
assert(is_active());
|
||||
return this->try_catch_(
|
||||
[]{ throw; },
|
||||
[]() -> R { throw; },
|
||||
std::forward<H>(h)...);
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::remote_handle_current_exception( RemoteH && h ) const
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::remote_handle_current_exception_( RemoteH && h )
|
||||
{
|
||||
assert(is_active());
|
||||
return this->remote_try_catch_(
|
||||
[]() -> R { throw; },
|
||||
std::forward<RemoteH>(h));
|
||||
@@ -4109,22 +4105,56 @@ namespace boost { namespace leaf {
|
||||
|
||||
template <class... E>
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::handle_exception( std::exception_ptr const & ep, H && ... h ) const
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::handle_exception_( std::exception_ptr const & ep, H && ... h )
|
||||
{
|
||||
assert(is_active());
|
||||
return this->try_catch_(
|
||||
[&]{ std::rethrow_exception(ep); },
|
||||
[&]() -> R { std::rethrow_exception(ep); },
|
||||
std::forward<H>(h)...);
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::remote_handle_exception( std::exception_ptr const & ep, RemoteH && h ) const
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::remote_handle_exception_( std::exception_ptr const & ep, RemoteH && h )
|
||||
{
|
||||
assert(is_active());
|
||||
return this->remote_try_catch_(
|
||||
[&]() -> R { std::rethrow_exception(ep); },
|
||||
std::forward<RemoteH>(h));
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::handle_current_exception( H && ... h )
|
||||
{
|
||||
auto active_context = activate_context(*this);
|
||||
return handle_current_exception_<R>(std::forward<H>(h)...);
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::remote_handle_current_exception( RemoteH && h )
|
||||
{
|
||||
auto active_context = activate_context(*this);
|
||||
return remote_handle_current_exception_<R>(std::forward<RemoteH>(h));
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::handle_exception( std::exception_ptr const & ep, H && ... h )
|
||||
{
|
||||
auto active_context = activate_context(*this);
|
||||
return handle_exception_<R>(ep, std::forward<H>(h)...);
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::remote_handle_exception( std::exception_ptr const & ep, RemoteH && h )
|
||||
{
|
||||
auto active_context = activate_context(*this);
|
||||
return remote_handle_exception_<R>(ep, std::forward<RemoteH>(h));
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
template <class... E>
|
||||
@@ -4133,7 +4163,7 @@ namespace boost { namespace leaf {
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a try_handle_all function must be registered with leaf::is_result_type");
|
||||
auto active_context = activate_context(*this, on_deactivation::propagate_if_uncaught_exception);
|
||||
auto active_context = activate_context(*this);
|
||||
if( auto r = this->try_catch_(
|
||||
[&]
|
||||
{
|
||||
@@ -4151,7 +4181,7 @@ namespace boost { namespace leaf {
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a try_handle_all function must be registered with leaf::is_result_type");
|
||||
auto active_context = activate_context(*this, on_deactivation::propagate_if_uncaught_exception);
|
||||
auto active_context = activate_context(*this);
|
||||
if( auto r = this->remote_try_catch_(
|
||||
[&]
|
||||
{
|
||||
@@ -4169,7 +4199,7 @@ namespace boost { namespace leaf {
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a try_handle_some function must be registered with leaf::is_result_type");
|
||||
auto active_context = activate_context(*this, on_deactivation::propagate_if_uncaught_exception);
|
||||
auto active_context = activate_context(*this);
|
||||
if( auto r = this->try_catch_(
|
||||
[&]
|
||||
{
|
||||
@@ -4181,7 +4211,7 @@ namespace boost { namespace leaf {
|
||||
{
|
||||
auto rr = this->handle_some(std::move(r), std::forward<H>(h)...);
|
||||
if( !rr )
|
||||
active_context.set_on_deactivate(on_deactivation::propagate);
|
||||
this->propagate();
|
||||
return rr;
|
||||
}
|
||||
}
|
||||
@@ -4190,7 +4220,9 @@ namespace boost { namespace leaf {
|
||||
template <class TryBlock, class RemoteH>
|
||||
LEAF_CONSTEXPR inline typename std::decay<decltype(std::declval<TryBlock>()())>::type catch_context<E...>::remote_try_handle_some( TryBlock && try_block, RemoteH && h )
|
||||
{
|
||||
auto active_context = activate_context(*this, on_deactivation::propagate_if_uncaught_exception);
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a remote_try_handle_some function must be registered with leaf::is_result_type");
|
||||
auto active_context = activate_context(*this);
|
||||
if( auto r = this->remote_try_catch_(
|
||||
[&]
|
||||
{
|
||||
@@ -4202,7 +4234,7 @@ namespace boost { namespace leaf {
|
||||
{
|
||||
auto rr = this->remote_handle_some(std::move(r), std::forward<RemoteH>(h));
|
||||
if( !rr )
|
||||
active_context.set_on_deactivate(on_deactivation::propagate);
|
||||
this->propagate();
|
||||
return rr;
|
||||
}
|
||||
}
|
||||
@@ -4228,9 +4260,10 @@ namespace boost { namespace leaf {
|
||||
|
||||
template <class... E>
|
||||
template <class TryBlock, class... H>
|
||||
inline decltype(std::declval<TryBlock>()()) context_base<E...>::try_catch_( TryBlock && try_block, H && ... h ) const
|
||||
inline decltype(std::declval<TryBlock>()()) context_base<E...>::try_catch_( TryBlock && try_block, H && ... h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
assert(is_active());
|
||||
using R = decltype(std::declval<TryBlock>()());
|
||||
try
|
||||
{
|
||||
@@ -4244,22 +4277,26 @@ namespace boost { namespace leaf {
|
||||
}
|
||||
catch( std::exception const & ex )
|
||||
{
|
||||
deactivate();
|
||||
return leaf_detail::handle_error_<R>(this->tup(), error_info(exception_info_(&ex)), std::forward<H>(h)...,
|
||||
[]() -> R { throw; } );
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
deactivate();
|
||||
return leaf_detail::handle_error_<R>(this->tup(), error_info(exception_info_(0)), std::forward<H>(h)...,
|
||||
[]() -> R { throw; } );
|
||||
}
|
||||
}
|
||||
catch( std::exception const & ex )
|
||||
{
|
||||
deactivate();
|
||||
return leaf_detail::handle_error_<R>(this->tup(), error_info(exception_info_(&ex)), std::forward<H>(h)...,
|
||||
[]() -> R { throw; } );
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
deactivate();
|
||||
return leaf_detail::handle_error_<R>(this->tup(), error_info(exception_info_(0)), std::forward<H>(h)...,
|
||||
[]() -> R { throw; } );
|
||||
}
|
||||
@@ -4267,9 +4304,10 @@ namespace boost { namespace leaf {
|
||||
|
||||
template <class... E>
|
||||
template <class TryBlock, class RemoteH>
|
||||
inline decltype(std::declval<TryBlock>()()) context_base<E...>::remote_try_catch_( TryBlock && try_block, RemoteH && h ) const
|
||||
inline decltype(std::declval<TryBlock>()()) context_base<E...>::remote_try_catch_( TryBlock && try_block, RemoteH && h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
assert(is_active());
|
||||
try
|
||||
{
|
||||
return std::forward<TryBlock>(try_block)();
|
||||
@@ -4282,19 +4320,23 @@ namespace boost { namespace leaf {
|
||||
}
|
||||
catch( std::exception const & ex )
|
||||
{
|
||||
deactivate();
|
||||
return std::forward<RemoteH>(h)(error_info(exception_info_(&ex), this)).get();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
deactivate();
|
||||
return std::forward<RemoteH>(h)(error_info(exception_info_(0), this)).get();
|
||||
}
|
||||
}
|
||||
catch( std::exception const & ex )
|
||||
{
|
||||
deactivate();
|
||||
return std::forward<RemoteH>(h)(error_info(exception_info_(&ex), this)).get();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
deactivate();
|
||||
return std::forward<RemoteH>(h)(error_info(exception_info_(0), this)).get();
|
||||
}
|
||||
}
|
||||
@@ -4376,6 +4418,36 @@ namespace boost { namespace leaf {
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
template <class TryBlock, class... H>
|
||||
LEAF_CONSTEXPR inline decltype(std::declval<TryBlock>()()) try_catch( TryBlock && try_block, H && ... h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
context_type_from_handlers<H...> ctx;
|
||||
auto active_context = activate_context(ctx);
|
||||
return ctx.try_catch_(
|
||||
[&]
|
||||
{
|
||||
return std::forward<TryBlock>(try_block)();
|
||||
},
|
||||
std::forward<H>(h)...);
|
||||
}
|
||||
|
||||
template <class TryBlock, class RemoteH>
|
||||
LEAF_CONSTEXPR inline decltype(std::declval<TryBlock>()()) remote_try_catch( TryBlock && try_block, RemoteH && h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
context_type_from_remote_handler<RemoteH> ctx;
|
||||
auto active_context = activate_context(ctx);
|
||||
return ctx.remote_try_catch_(
|
||||
[&]
|
||||
{
|
||||
return std::forward<TryBlock>(try_block)();
|
||||
},
|
||||
std::forward<RemoteH>(h));
|
||||
}
|
||||
|
||||
} }
|
||||
|
||||
#endif
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace boost { namespace leaf {
|
||||
[[noreturn]] void unload_and_rethrow_original_exception() const
|
||||
{
|
||||
assert(ctx_->captured_id_);
|
||||
auto active_context = activate_context(*ctx_, on_deactivation::propagate);
|
||||
auto active_context = activate_context(*ctx_);
|
||||
id_factory<>::current_id = ctx_->captured_id_.value();
|
||||
std::rethrow_exception(ex_);
|
||||
}
|
||||
@@ -50,7 +50,7 @@ namespace boost { namespace leaf {
|
||||
template <class R, class F, class... A>
|
||||
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, on_deactivation::do_not_propagate);
|
||||
auto active_context = activate_context(*ctx);
|
||||
augment_id aug;
|
||||
try
|
||||
{
|
||||
@@ -75,7 +75,7 @@ namespace boost { namespace leaf {
|
||||
template <class R, class F, class... A>
|
||||
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, on_deactivation::do_not_propagate);
|
||||
auto active_context = activate_context(*ctx);
|
||||
augment_id aug;
|
||||
try
|
||||
{
|
||||
@@ -140,14 +140,14 @@ namespace boost { namespace leaf {
|
||||
template <class R, class F, class... A>
|
||||
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) noexcept
|
||||
{
|
||||
auto active_context = activate_context(*ctx, on_deactivation::do_not_propagate);
|
||||
auto active_context = activate_context(*ctx);
|
||||
return std::forward<F>(f)(std::forward<A>(a)...);
|
||||
}
|
||||
|
||||
template <class R, class F, class... A>
|
||||
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) noexcept
|
||||
{
|
||||
auto active_context = activate_context(*ctx, on_deactivation::do_not_propagate);
|
||||
auto active_context = activate_context(*ctx);
|
||||
if( auto r = std::forward<F>(f)(std::forward<A>(a)...) )
|
||||
return r;
|
||||
else
|
||||
|
||||
@@ -109,10 +109,10 @@
|
||||
|
||||
#if __cplusplus > 201402L
|
||||
# define LEAF_CONSTEXPR constexpr
|
||||
# define LEAF_UNCAUGHT_EXCEPTIONS std::uncaught_exceptions
|
||||
# define LEAF_STD_UNCAUGHT_EXCEPTIONS 1
|
||||
#else
|
||||
# define LEAF_CONSTEXPR
|
||||
# define LEAF_UNCAUGHT_EXCEPTIONS std::uncaught_exception
|
||||
# define LEAF_STD_UNCAUGHT_EXCEPTIONS 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -21,18 +21,25 @@ namespace boost { namespace leaf {
|
||||
std::get<I-1>(tup).activate();
|
||||
}
|
||||
|
||||
LEAF_CONSTEXPR static void deactivate( Tuple & tup, bool propagate_errors ) noexcept
|
||||
LEAF_CONSTEXPR static void deactivate( Tuple & tup ) noexcept
|
||||
{
|
||||
std::get<I-1>(tup).deactivate(propagate_errors);
|
||||
tuple_for_each<I-1,Tuple>::deactivate(tup, propagate_errors);
|
||||
std::get<I-1>(tup).deactivate();
|
||||
tuple_for_each<I-1,Tuple>::deactivate(tup);
|
||||
}
|
||||
|
||||
LEAF_CONSTEXPR static void propagate( Tuple & tup, int err_id ) noexcept
|
||||
LEAF_CONSTEXPR static void propagate( Tuple & tup ) noexcept
|
||||
{
|
||||
auto & sl = std::get<I-1>(tup);
|
||||
sl.propagate();
|
||||
tuple_for_each<I-1,Tuple>::propagate(tup);
|
||||
}
|
||||
|
||||
LEAF_CONSTEXPR static void propagate_captured( Tuple & tup, int err_id ) noexcept
|
||||
{
|
||||
auto & sl = std::get<I-1>(tup);
|
||||
if( sl.has_value(err_id) )
|
||||
leaf_detail::load_slot(err_id, std::move(sl).value(err_id));
|
||||
tuple_for_each<I-1,Tuple>::propagate(tup, err_id);
|
||||
tuple_for_each<I-1,Tuple>::propagate_captured(tup, err_id);
|
||||
}
|
||||
|
||||
static void print( std::ostream & os, void const * tup, int key_to_print )
|
||||
@@ -47,8 +54,9 @@ namespace boost { namespace leaf {
|
||||
struct tuple_for_each<0, Tuple>
|
||||
{
|
||||
LEAF_CONSTEXPR static void activate( Tuple & ) noexcept { }
|
||||
LEAF_CONSTEXPR static void deactivate( Tuple &, bool ) noexcept { }
|
||||
LEAF_CONSTEXPR static void propagate( Tuple & tup, int ) noexcept { }
|
||||
LEAF_CONSTEXPR static void deactivate( Tuple & ) noexcept { }
|
||||
LEAF_CONSTEXPR static void propagate( Tuple & tup ) noexcept { }
|
||||
LEAF_CONSTEXPR static void propagate_captured( Tuple & tup, int ) noexcept { }
|
||||
static void print( std::ostream &, void const *, int ) { }
|
||||
};
|
||||
}
|
||||
@@ -229,7 +237,7 @@ namespace boost { namespace leaf {
|
||||
is_active_ = true;
|
||||
}
|
||||
|
||||
LEAF_CONSTEXPR void deactivate( bool propagate_errors ) noexcept
|
||||
LEAF_CONSTEXPR void deactivate() noexcept
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
assert(is_active());
|
||||
@@ -242,7 +250,12 @@ namespace boost { namespace leaf {
|
||||
if( unexpected_requested<Tup>::value )
|
||||
--tl_unexpected_enabled_counter();
|
||||
#endif
|
||||
tuple_for_each<std::tuple_size<Tup>::value,Tup>::deactivate(tup_, propagate_errors);
|
||||
tuple_for_each<std::tuple_size<Tup>::value,Tup>::deactivate(tup_);
|
||||
}
|
||||
|
||||
LEAF_CONSTEXPR void propagate() noexcept
|
||||
{
|
||||
tuple_for_each<std::tuple_size<Tup>::value,Tup>::propagate(tup_);
|
||||
}
|
||||
|
||||
LEAF_CONSTEXPR bool is_active() const noexcept
|
||||
@@ -255,57 +268,69 @@ namespace boost { namespace leaf {
|
||||
leaf_detail::tuple_for_each<std::tuple_size<Tup>::value,Tup>::print(os, &tup_, 0);
|
||||
}
|
||||
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR typename std::decay<decltype(std::declval<R>().value())>::type handle_all_( R &, H && ... );
|
||||
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR typename std::decay<decltype(std::declval<R>().value())>::type remote_handle_all_( R &, RemoteH && );
|
||||
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR R handle_some_( R &&, H && ... );
|
||||
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR R remote_handle_some_( R &&, RemoteH && );
|
||||
|
||||
template <class TryBlock, class... H>
|
||||
decltype(std::declval<TryBlock>()()) try_catch_( TryBlock &&, H && ... );
|
||||
|
||||
template <class TryBlock, class RemoteH>
|
||||
decltype(std::declval<TryBlock>()()) remote_try_catch_( TryBlock &&, RemoteH && );
|
||||
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR R handle_current_exception_( H && ... );
|
||||
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR R remote_handle_current_exception_( RemoteH && );
|
||||
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR R handle_exception_( std::exception_ptr const &, H && ... );
|
||||
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR R remote_handle_exception_( std::exception_ptr const &, RemoteH && );
|
||||
|
||||
protected:
|
||||
|
||||
LEAF_CONSTEXPR error_id propagate_captured_errors( error_id err_id ) noexcept
|
||||
{
|
||||
tuple_for_each<std::tuple_size<Tup>::value,Tup>::propagate(tup_, err_id.value());
|
||||
tuple_for_each<std::tuple_size<Tup>::value,Tup>::propagate_captured(tup_, err_id.value());
|
||||
return err_id;
|
||||
}
|
||||
|
||||
template <class TryBlock, class... H>
|
||||
LEAF_CONSTEXPR typename std::decay<decltype(std::declval<TryBlock>()().value())>::type try_handle_all_( TryBlock &&, H && ... ) const;
|
||||
|
||||
template <class TryBlock, class RemoteH>
|
||||
LEAF_CONSTEXPR typename std::decay<decltype(std::declval<TryBlock>()().value())>::type remote_try_handle_all_( TryBlock &&, RemoteH && ) const;
|
||||
|
||||
template <class TryBlock, class... H, class Ctx>
|
||||
LEAF_CONSTEXPR typename std::decay<decltype(std::declval<TryBlock>()())>::type try_handle_some_( context_activator<Ctx> &, TryBlock &&, H && ... ) const;
|
||||
|
||||
template <class TryBlock, class RemoteH, class Ctx>
|
||||
LEAF_CONSTEXPR typename std::decay<decltype(std::declval<TryBlock>()())>::type remote_try_handle_some_( context_activator<Ctx> &, TryBlock &&, RemoteH && ) const;
|
||||
|
||||
public:
|
||||
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR typename std::decay<decltype(std::declval<R>().value())>::type handle_all( R &, H && ... ) const;
|
||||
LEAF_CONSTEXPR typename std::decay<decltype(std::declval<R>().value())>::type handle_all( R &, H && ... );
|
||||
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR typename std::decay<decltype(std::declval<R>().value())>::type remote_handle_all( R &, RemoteH && ) const;
|
||||
LEAF_CONSTEXPR typename std::decay<decltype(std::declval<R>().value())>::type remote_handle_all( R &, RemoteH && );
|
||||
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR R handle_some( R &&, H && ... ) const;
|
||||
LEAF_CONSTEXPR R handle_some( R &&, H && ... );
|
||||
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR R remote_handle_some( R &&, RemoteH && ) const;
|
||||
|
||||
template <class TryBlock, class... H>
|
||||
decltype(std::declval<TryBlock>()()) try_catch_( TryBlock &&, H && ... ) const;
|
||||
|
||||
template <class TryBlock, class RemoteH>
|
||||
decltype(std::declval<TryBlock>()()) remote_try_catch_( TryBlock &&, RemoteH && ) const;
|
||||
LEAF_CONSTEXPR R remote_handle_some( R &&, RemoteH && );
|
||||
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR R handle_current_exception( H && ... ) const;
|
||||
LEAF_CONSTEXPR R handle_current_exception( H && ... );
|
||||
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR R remote_handle_current_exception( RemoteH && ) const;
|
||||
LEAF_CONSTEXPR R remote_handle_current_exception( RemoteH && );
|
||||
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR R handle_exception( std::exception_ptr const &, H && ... ) const;
|
||||
LEAF_CONSTEXPR R handle_exception( std::exception_ptr const &, H && ... );
|
||||
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR R remote_handle_exception( std::exception_ptr const &, RemoteH && ) const;
|
||||
LEAF_CONSTEXPR R remote_handle_exception( std::exception_ptr const &, RemoteH && );
|
||||
};
|
||||
|
||||
template <class... E>
|
||||
@@ -436,7 +461,8 @@ namespace boost { namespace leaf {
|
||||
{
|
||||
error_id propagate_captured_errors() noexcept final override { return Ctx::propagate_captured_errors(captured_id_); }
|
||||
void activate() noexcept final override { Ctx::activate(); }
|
||||
void deactivate( bool propagate_errors ) noexcept final override { Ctx::deactivate(propagate_errors); }
|
||||
void deactivate() noexcept final override { Ctx::deactivate(); }
|
||||
void propagate() noexcept final override { Ctx::propagate(); }
|
||||
bool is_active() const noexcept final override { return Ctx::is_active(); }
|
||||
void print( std::ostream & os ) const final override { return Ctx::print(os); }
|
||||
};
|
||||
|
||||
@@ -708,102 +708,80 @@ namespace boost { namespace leaf {
|
||||
{
|
||||
template <class... E>
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR inline typename std::decay<decltype(std::declval<R>().value())>::type context_base<E...>::handle_all( R & r, H && ... h ) const
|
||||
LEAF_CONSTEXPR inline typename std::decay<decltype(std::declval<R>().value())>::type context_base<E...>::handle_all_( R & r, H && ... h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
using Ret = typename std::decay<decltype(std::declval<R>().value())>::type;
|
||||
static_assert(is_result_type<R>::value, "The R type used with a handle_all function must be registered with leaf::is_result_type");
|
||||
return handle_error_<Ret>(tup(), error_info(r.error()), std::forward<H>(h)...);
|
||||
assert(is_active());
|
||||
error_info const ei(r.error());
|
||||
deactivate();
|
||||
return handle_error_<Ret>(tup(), ei, std::forward<H>(h)...);
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR inline typename std::decay<decltype(std::declval<R>().value())>::type context_base<E...>::remote_handle_all( R & r, RemoteH && h ) const
|
||||
LEAF_CONSTEXPR inline typename std::decay<decltype(std::declval<R>().value())>::type context_base<E...>::remote_handle_all_( R & r, RemoteH && h )
|
||||
{
|
||||
static_assert(is_result_type<R>::value, "The R type used with a handle_all function must be registered with leaf::is_result_type");
|
||||
return std::forward<RemoteH>(h)(error_info(r.error(), this)).get();
|
||||
assert(is_active());
|
||||
error_info const ei(r.error(), this);
|
||||
deactivate();
|
||||
return std::forward<RemoteH>(h)(ei).get();
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::handle_some( R && r, H && ... h ) const
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::handle_some_( R && r, H && ... h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<R>::value, "The R type used with a handle_some function must be registered with leaf::is_result_type");
|
||||
return handle_error_<R>(tup(), error_info(r.error()), std::forward<H>(h)...,
|
||||
assert(is_active());
|
||||
error_info const ei(r.error());
|
||||
deactivate();
|
||||
return handle_error_<R>(tup(), ei, std::forward<H>(h)...,
|
||||
[&r]()->R { return std::move(r); });
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::remote_handle_some( R && r, RemoteH && h ) const
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::remote_handle_some_( R && r, RemoteH && h )
|
||||
{
|
||||
static_assert(is_result_type<R>::value, "The R type used with a handle_some function must be registered with leaf::is_result_type");
|
||||
return std::forward<RemoteH>(h)(error_info(r.error(), this)).get();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////
|
||||
|
||||
template <class... E>
|
||||
template <class TryBlock, class... H>
|
||||
LEAF_CONSTEXPR inline typename std::decay<decltype(std::declval<TryBlock>()().value())>::type context_base<E...>::try_handle_all_( TryBlock && try_block, H && ... h ) const
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a try_handle_all function must be registered with leaf::is_result_type");
|
||||
assert(this->is_active());
|
||||
if( auto r = std::forward<TryBlock>(try_block)() )
|
||||
return r.value();
|
||||
else
|
||||
return handle_all(r, std::forward<H>(h)...);
|
||||
assert(is_active());
|
||||
error_info const ei(r.error(), this);
|
||||
deactivate();
|
||||
return std::forward<RemoteH>(h)(ei).get();
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class TryBlock, class RemoteH>
|
||||
LEAF_CONSTEXPR inline typename std::decay<decltype(std::declval<TryBlock>()().value())>::type context_base<E...>::remote_try_handle_all_( TryBlock && try_block, RemoteH && h ) const
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR inline typename std::decay<decltype(std::declval<R>().value())>::type context_base<E...>::handle_all( R & r, H && ... h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a remote_try_handle_all function must be registered with leaf::is_result_type");
|
||||
assert(this->is_active());
|
||||
if( auto r = std::forward<TryBlock>(try_block)() )
|
||||
return r.value();
|
||||
else
|
||||
return remote_handle_all(r, std::forward<RemoteH>(h));
|
||||
auto active_context = activate_context(*this);
|
||||
return handle_all_(r, std::forward<H>(h)...);
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class TryBlock, class... H, class Ctx>
|
||||
LEAF_CONSTEXPR inline typename std::decay<decltype(std::declval<TryBlock>()())>::type context_base<E...>::try_handle_some_( context_activator<Ctx> & active_context, TryBlock && try_block, H && ... h ) const
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR inline typename std::decay<decltype(std::declval<R>().value())>::type context_base<E...>::remote_handle_all( R & r, RemoteH && h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a try_handle_some function must be registered with leaf::is_result_type");
|
||||
assert(this->is_active());
|
||||
if( auto r = std::forward<TryBlock>(try_block)() )
|
||||
return r;
|
||||
else
|
||||
{
|
||||
auto rr = handle_some(std::move(r), std::forward<H>(h)...);
|
||||
if( !rr )
|
||||
active_context.set_on_deactivate(on_deactivation::propagate);
|
||||
return rr;
|
||||
}
|
||||
auto active_context = activate_context(*this);
|
||||
return remote_handle_all_(r, std::forward<RemoteH>(h));
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class TryBlock, class RemoteH, class Ctx>
|
||||
LEAF_CONSTEXPR inline typename std::decay<decltype(std::declval<TryBlock>()())>::type context_base<E...>::remote_try_handle_some_( context_activator<Ctx> & active_context, TryBlock && try_block, RemoteH && h ) const
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::handle_some( R && r, H && ... h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a remote_try_handle_some function must be registered with leaf::is_result_type");
|
||||
assert(this->is_active());
|
||||
if( auto r = std::forward<TryBlock>(try_block)() )
|
||||
return r;
|
||||
else
|
||||
{
|
||||
auto rr = remote_handle_some(std::move(r), std::forward<RemoteH>(h));
|
||||
if( !rr )
|
||||
active_context.set_on_deactivate(on_deactivation::propagate);
|
||||
return rr;
|
||||
}
|
||||
auto active_context = activate_context(*this);
|
||||
return handle_some_(std::forward<R>(r), std::forward<H>(h)...);
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::remote_handle_some( R && r, RemoteH && h )
|
||||
{
|
||||
auto active_context = activate_context(*this);
|
||||
return remote_handle_some_(std::forward<R>(r), std::forward<RemoteH>(h));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -243,20 +243,22 @@ namespace boost { namespace leaf {
|
||||
assert(x.top_==0);
|
||||
}
|
||||
|
||||
~slot() noexcept
|
||||
{
|
||||
assert(top_==0);
|
||||
}
|
||||
|
||||
LEAF_CONSTEXPR void activate() noexcept
|
||||
{
|
||||
assert(top_==0);
|
||||
assert(top_==0 || *top_!=this);
|
||||
top_ = &tl_slot_ptr<E>();
|
||||
prev_ = *top_;
|
||||
*top_ = this;
|
||||
}
|
||||
|
||||
LEAF_CONSTEXPR void deactivate( bool propagate_errors ) noexcept;
|
||||
|
||||
LEAF_CONSTEXPR void deactivate() noexcept
|
||||
{
|
||||
assert(top_!=0 && *top_==this);
|
||||
*top_ = prev_;
|
||||
}
|
||||
|
||||
LEAF_CONSTEXPR void propagate() noexcept;
|
||||
|
||||
using impl::put;
|
||||
using impl::has_value;
|
||||
@@ -296,28 +298,25 @@ namespace boost { namespace leaf {
|
||||
#endif
|
||||
|
||||
template <class E>
|
||||
LEAF_CONSTEXPR inline void slot<E>::deactivate( bool propagate_errors ) noexcept
|
||||
LEAF_CONSTEXPR inline void slot<E>::propagate() noexcept
|
||||
{
|
||||
assert(top_!=0);
|
||||
if( propagate_errors )
|
||||
if( prev_ )
|
||||
{
|
||||
impl & this_ = *this;
|
||||
impl & that_ = *prev_;
|
||||
that_ = std::move(this_);
|
||||
}
|
||||
assert(top_!=0 && (*top_==prev_ || *top_==this));
|
||||
if( prev_ )
|
||||
{
|
||||
impl & this_ = *this;
|
||||
impl & that_ = *prev_;
|
||||
that_ = std::move(this_);
|
||||
}
|
||||
#if LEAF_DIAGNOSTICS
|
||||
else
|
||||
{
|
||||
int c = tl_unexpected_enabled_counter();
|
||||
assert(c>=0);
|
||||
if( c )
|
||||
if( int err_id = impl::key() )
|
||||
load_unexpected(err_id, std::move(*this).value(err_id));
|
||||
}
|
||||
else
|
||||
{
|
||||
int c = tl_unexpected_enabled_counter();
|
||||
assert(c>=0);
|
||||
if( c )
|
||||
if( int err_id = impl::key() )
|
||||
load_unexpected(err_id, std::move(*this).value(err_id));
|
||||
}
|
||||
#endif
|
||||
*top_ = prev_;
|
||||
top_ = 0;
|
||||
}
|
||||
|
||||
template <class E>
|
||||
@@ -608,7 +607,8 @@ namespace boost { namespace leaf {
|
||||
public:
|
||||
virtual error_id propagate_captured_errors() noexcept = 0;
|
||||
virtual void activate() noexcept = 0;
|
||||
virtual void deactivate( bool propagate_errors ) noexcept = 0;
|
||||
virtual void deactivate() noexcept = 0;
|
||||
virtual void propagate() noexcept = 0;
|
||||
virtual bool is_active() const noexcept = 0;
|
||||
virtual void print( std::ostream & ) const = 0;
|
||||
error_id captured_id_;
|
||||
@@ -618,77 +618,61 @@ namespace boost { namespace leaf {
|
||||
|
||||
////////////////////////////////////////////
|
||||
|
||||
enum class on_deactivation
|
||||
{
|
||||
propagate,
|
||||
do_not_propagate,
|
||||
propagate_if_uncaught_exception
|
||||
};
|
||||
|
||||
template <class Ctx>
|
||||
class context_activator
|
||||
{
|
||||
context_activator( context_activator const & ) = delete;
|
||||
context_activator & operator=( context_activator const & ) = delete;
|
||||
|
||||
#if !defined(LEAF_NO_EXCEPTIONS) && LEAF_STD_UNCAUGHT_EXCEPTIONS
|
||||
int const uncaught_exceptions_;
|
||||
#endif
|
||||
Ctx * ctx_;
|
||||
bool const ctx_was_active_;
|
||||
on_deactivation on_deactivate_;
|
||||
|
||||
public:
|
||||
|
||||
LEAF_CONSTEXPR LEAF_ALWAYS_INLINE context_activator(Ctx & ctx, on_deactivation on_deactivate) noexcept:
|
||||
ctx_(&ctx),
|
||||
ctx_was_active_(ctx.is_active()),
|
||||
on_deactivate_(on_deactivate)
|
||||
explicit LEAF_CONSTEXPR LEAF_ALWAYS_INLINE context_activator(Ctx & ctx) noexcept:
|
||||
#if !defined(LEAF_NO_EXCEPTIONS) && LEAF_STD_UNCAUGHT_EXCEPTIONS
|
||||
uncaught_exceptions_(std::uncaught_exceptions()),
|
||||
#endif
|
||||
ctx_(ctx.is_active() ? 0 : &ctx)
|
||||
{
|
||||
if( !ctx_was_active_ )
|
||||
ctx.activate();
|
||||
if( ctx_ )
|
||||
ctx_->activate();
|
||||
}
|
||||
|
||||
LEAF_CONSTEXPR LEAF_ALWAYS_INLINE context_activator( context_activator && x ) noexcept:
|
||||
ctx_(x.ctx_),
|
||||
ctx_was_active_(x.ctx_was_active_),
|
||||
on_deactivate_(x.on_deactivate_)
|
||||
#if !defined(LEAF_NO_EXCEPTIONS) && LEAF_STD_UNCAUGHT_EXCEPTIONS
|
||||
uncaught_exceptions_(x.uncaught_exceptions_),
|
||||
#endif
|
||||
ctx_(x.ctx_)
|
||||
{
|
||||
x.ctx_ = 0;
|
||||
}
|
||||
|
||||
LEAF_ALWAYS_INLINE ~context_activator() noexcept
|
||||
{
|
||||
if( ctx_ )
|
||||
{
|
||||
assert(
|
||||
on_deactivate_ == on_deactivation::propagate ||
|
||||
on_deactivate_ == on_deactivation::do_not_propagate ||
|
||||
on_deactivate_ == on_deactivation::propagate_if_uncaught_exception);
|
||||
if( !ctx_was_active_ )
|
||||
if( on_deactivate_ == on_deactivation::propagate_if_uncaught_exception )
|
||||
{
|
||||
#ifdef LEAF_NO_EXCEPTIONS
|
||||
ctx_->deactivate(false);
|
||||
#else
|
||||
bool has_exception = LEAF_UNCAUGHT_EXCEPTIONS();
|
||||
ctx_->deactivate(has_exception);
|
||||
if( !has_exception )
|
||||
(void) leaf_detail::new_id();
|
||||
if( !ctx_ )
|
||||
return;
|
||||
if( ctx_->is_active() )
|
||||
ctx_->deactivate();
|
||||
#ifndef LEAF_NO_EXCEPTIONS
|
||||
# if LEAF_STD_UNCAUGHT_EXCEPTIONS
|
||||
if( std::uncaught_exceptions() > uncaught_exceptions_ )
|
||||
# else
|
||||
if( std::uncaught_exception() )
|
||||
# endif
|
||||
ctx_->propagate();
|
||||
else
|
||||
(void) leaf_detail::new_id();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
ctx_->deactivate(on_deactivate_ == on_deactivation::propagate);
|
||||
}
|
||||
}
|
||||
|
||||
LEAF_CONSTEXPR LEAF_ALWAYS_INLINE void set_on_deactivate( on_deactivation on_deactivate ) noexcept
|
||||
{
|
||||
on_deactivate_ = on_deactivate;
|
||||
}
|
||||
};
|
||||
|
||||
template <class Ctx>
|
||||
LEAF_CONSTEXPR LEAF_ALWAYS_INLINE context_activator<Ctx> activate_context( Ctx & ctx, on_deactivation on_deactivate ) noexcept
|
||||
LEAF_CONSTEXPR LEAF_ALWAYS_INLINE context_activator<Ctx> activate_context(Ctx & ctx) noexcept
|
||||
{
|
||||
return context_activator<Ctx>(ctx, on_deactivate);
|
||||
return context_activator<Ctx>(ctx);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace boost { namespace leaf {
|
||||
{
|
||||
public:
|
||||
|
||||
virtual error_id get_error_id() const = 0;
|
||||
virtual error_id get_error_id() const noexcept = 0;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace boost { namespace leaf {
|
||||
public exception_base,
|
||||
public error_id
|
||||
{
|
||||
error_id get_error_id() const final override
|
||||
error_id get_error_id() const noexcept final override
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -16,32 +16,62 @@ namespace boost { namespace leaf {
|
||||
template <class TryBlock, class... H>
|
||||
LEAF_CONSTEXPR LEAF_ALWAYS_INLINE typename std::decay<decltype(std::declval<TryBlock>()().value())>::type nocatch_context<E...>::try_handle_all( TryBlock && try_block, H && ... h )
|
||||
{
|
||||
auto active_context = activate_context(*this, on_deactivation::do_not_propagate);
|
||||
return this->try_handle_all_( std::forward<TryBlock>(try_block), std::forward<H>(h)... );
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a try_handle_all function must be registered with leaf::is_result_type");
|
||||
auto active_context = activate_context(*this);
|
||||
if( auto r = std::forward<TryBlock>(try_block)() )
|
||||
return r.value();
|
||||
else
|
||||
return this->handle_all_(r, std::forward<H>(h)...);
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class TryBlock, class RemoteH>
|
||||
LEAF_CONSTEXPR LEAF_ALWAYS_INLINE typename std::decay<decltype(std::declval<TryBlock>()().value())>::type nocatch_context<E...>::remote_try_handle_all( TryBlock && try_block, RemoteH && h )
|
||||
{
|
||||
auto active_context = activate_context(*this, on_deactivation::do_not_propagate);
|
||||
return this->remote_try_handle_all_( std::forward<TryBlock>(try_block), std::forward<RemoteH>(h) );
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a remote_try_handle_all function must be registered with leaf::is_result_type");
|
||||
auto active_context = activate_context(*this);
|
||||
if( auto r = std::forward<TryBlock>(try_block)() )
|
||||
return r.value();
|
||||
else
|
||||
return this->remote_handle_all_(r, std::forward<RemoteH>(h));
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class TryBlock, class... H>
|
||||
LEAF_CONSTEXPR LEAF_ALWAYS_INLINE typename std::decay<decltype(std::declval<TryBlock>()())>::type nocatch_context<E...>::try_handle_some( TryBlock && try_block, H && ... h )
|
||||
{
|
||||
auto active_context = activate_context(*this, on_deactivation::propagate_if_uncaught_exception);
|
||||
return this->try_handle_some_( active_context, std::forward<TryBlock>(try_block), std::forward<H>(h)... );
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a try_handle_some function must be registered with leaf::is_result_type");
|
||||
auto active_context = activate_context(*this);
|
||||
if( auto r = std::forward<TryBlock>(try_block)() )
|
||||
return r;
|
||||
else
|
||||
{
|
||||
auto rr = this->handle_some_(std::move(r), std::forward<H>(h)...);
|
||||
if( !rr )
|
||||
this->propagate();
|
||||
return rr;
|
||||
}
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class TryBlock, class RemoteH>
|
||||
LEAF_CONSTEXPR LEAF_ALWAYS_INLINE typename std::decay<decltype(std::declval<TryBlock>()())>::type nocatch_context<E...>::remote_try_handle_some( TryBlock && try_block, RemoteH && h )
|
||||
{
|
||||
auto active_context = activate_context(*this, on_deactivation::propagate_if_uncaught_exception);
|
||||
return this->remote_try_handle_some_( active_context, std::forward<TryBlock>(try_block), std::forward<RemoteH>(h) );
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a remote_try_handle_some function must be registered with leaf::is_result_type");
|
||||
auto active_context = activate_context(*this);
|
||||
if( auto r = std::forward<TryBlock>(try_block)() )
|
||||
return r;
|
||||
else
|
||||
{
|
||||
auto rr = remote_handle_some_(std::move(r), std::forward<RemoteH>(h));
|
||||
if( !rr )
|
||||
this->propagate();
|
||||
return rr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -119,49 +119,23 @@ namespace boost { namespace leaf {
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
template <class TryBlock, class... H>
|
||||
LEAF_CONSTEXPR inline decltype(std::declval<TryBlock>()()) try_catch( TryBlock && try_block, H && ... h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
context_type_from_handlers<H...> ctx;
|
||||
auto active_context = activate_context(ctx, on_deactivation::propagate_if_uncaught_exception);
|
||||
return ctx.try_catch_(
|
||||
[&]
|
||||
{
|
||||
return std::forward<TryBlock>(try_block)();
|
||||
},
|
||||
std::forward<H>(h)...);
|
||||
}
|
||||
|
||||
template <class TryBlock, class RemoteH>
|
||||
LEAF_CONSTEXPR inline decltype(std::declval<TryBlock>()()) remote_try_catch( TryBlock && try_block, RemoteH && h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
context_type_from_remote_handler<RemoteH> ctx;
|
||||
auto active_context = activate_context(ctx, on_deactivation::propagate_if_uncaught_exception);
|
||||
return ctx.remote_try_catch_(
|
||||
[&]
|
||||
{
|
||||
return std::forward<TryBlock>(try_block)();
|
||||
},
|
||||
std::forward<RemoteH>(h));
|
||||
}
|
||||
|
||||
namespace leaf_detail
|
||||
{
|
||||
template <class... E>
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::handle_current_exception( H && ... h ) const
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::handle_current_exception_( H && ... h )
|
||||
{
|
||||
assert(is_active());
|
||||
return this->try_catch_(
|
||||
[]{ throw; },
|
||||
[]() -> R { throw; },
|
||||
std::forward<H>(h)...);
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::remote_handle_current_exception( RemoteH && h ) const
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::remote_handle_current_exception_( RemoteH && h )
|
||||
{
|
||||
assert(is_active());
|
||||
return this->remote_try_catch_(
|
||||
[]() -> R { throw; },
|
||||
std::forward<RemoteH>(h));
|
||||
@@ -169,22 +143,56 @@ namespace boost { namespace leaf {
|
||||
|
||||
template <class... E>
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::handle_exception( std::exception_ptr const & ep, H && ... h ) const
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::handle_exception_( std::exception_ptr const & ep, H && ... h )
|
||||
{
|
||||
assert(is_active());
|
||||
return this->try_catch_(
|
||||
[&]{ std::rethrow_exception(ep); },
|
||||
[&]() -> R { std::rethrow_exception(ep); },
|
||||
std::forward<H>(h)...);
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::remote_handle_exception( std::exception_ptr const & ep, RemoteH && h ) const
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::remote_handle_exception_( std::exception_ptr const & ep, RemoteH && h )
|
||||
{
|
||||
assert(is_active());
|
||||
return this->remote_try_catch_(
|
||||
[&]() -> R { std::rethrow_exception(ep); },
|
||||
std::forward<RemoteH>(h));
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::handle_current_exception( H && ... h )
|
||||
{
|
||||
auto active_context = activate_context(*this);
|
||||
return handle_current_exception_<R>(std::forward<H>(h)...);
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::remote_handle_current_exception( RemoteH && h )
|
||||
{
|
||||
auto active_context = activate_context(*this);
|
||||
return remote_handle_current_exception_<R>(std::forward<RemoteH>(h));
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class R, class... H>
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::handle_exception( std::exception_ptr const & ep, H && ... h )
|
||||
{
|
||||
auto active_context = activate_context(*this);
|
||||
return handle_exception_<R>(ep, std::forward<H>(h)...);
|
||||
}
|
||||
|
||||
template <class... E>
|
||||
template <class R, class RemoteH>
|
||||
LEAF_CONSTEXPR inline R context_base<E...>::remote_handle_exception( std::exception_ptr const & ep, RemoteH && h )
|
||||
{
|
||||
auto active_context = activate_context(*this);
|
||||
return remote_handle_exception_<R>(ep, std::forward<RemoteH>(h));
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
template <class... E>
|
||||
@@ -193,7 +201,7 @@ namespace boost { namespace leaf {
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a try_handle_all function must be registered with leaf::is_result_type");
|
||||
auto active_context = activate_context(*this, on_deactivation::propagate_if_uncaught_exception);
|
||||
auto active_context = activate_context(*this);
|
||||
if( auto r = this->try_catch_(
|
||||
[&]
|
||||
{
|
||||
@@ -211,7 +219,7 @@ namespace boost { namespace leaf {
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a try_handle_all function must be registered with leaf::is_result_type");
|
||||
auto active_context = activate_context(*this, on_deactivation::propagate_if_uncaught_exception);
|
||||
auto active_context = activate_context(*this);
|
||||
if( auto r = this->remote_try_catch_(
|
||||
[&]
|
||||
{
|
||||
@@ -229,7 +237,7 @@ namespace boost { namespace leaf {
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a try_handle_some function must be registered with leaf::is_result_type");
|
||||
auto active_context = activate_context(*this, on_deactivation::propagate_if_uncaught_exception);
|
||||
auto active_context = activate_context(*this);
|
||||
if( auto r = this->try_catch_(
|
||||
[&]
|
||||
{
|
||||
@@ -241,7 +249,7 @@ namespace boost { namespace leaf {
|
||||
{
|
||||
auto rr = this->handle_some(std::move(r), std::forward<H>(h)...);
|
||||
if( !rr )
|
||||
active_context.set_on_deactivate(on_deactivation::propagate);
|
||||
this->propagate();
|
||||
return rr;
|
||||
}
|
||||
}
|
||||
@@ -250,7 +258,9 @@ namespace boost { namespace leaf {
|
||||
template <class TryBlock, class RemoteH>
|
||||
LEAF_CONSTEXPR inline typename std::decay<decltype(std::declval<TryBlock>()())>::type catch_context<E...>::remote_try_handle_some( TryBlock && try_block, RemoteH && h )
|
||||
{
|
||||
auto active_context = activate_context(*this, on_deactivation::propagate_if_uncaught_exception);
|
||||
using namespace leaf_detail;
|
||||
static_assert(is_result_type<decltype(std::declval<TryBlock>()())>::value, "The return type of the try_block passed to a remote_try_handle_some function must be registered with leaf::is_result_type");
|
||||
auto active_context = activate_context(*this);
|
||||
if( auto r = this->remote_try_catch_(
|
||||
[&]
|
||||
{
|
||||
@@ -262,7 +272,7 @@ namespace boost { namespace leaf {
|
||||
{
|
||||
auto rr = this->remote_handle_some(std::move(r), std::forward<RemoteH>(h));
|
||||
if( !rr )
|
||||
active_context.set_on_deactivate(on_deactivation::propagate);
|
||||
this->propagate();
|
||||
return rr;
|
||||
}
|
||||
}
|
||||
@@ -288,9 +298,10 @@ namespace boost { namespace leaf {
|
||||
|
||||
template <class... E>
|
||||
template <class TryBlock, class... H>
|
||||
inline decltype(std::declval<TryBlock>()()) context_base<E...>::try_catch_( TryBlock && try_block, H && ... h ) const
|
||||
inline decltype(std::declval<TryBlock>()()) context_base<E...>::try_catch_( TryBlock && try_block, H && ... h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
assert(is_active());
|
||||
using R = decltype(std::declval<TryBlock>()());
|
||||
try
|
||||
{
|
||||
@@ -304,22 +315,26 @@ namespace boost { namespace leaf {
|
||||
}
|
||||
catch( std::exception const & ex )
|
||||
{
|
||||
deactivate();
|
||||
return leaf_detail::handle_error_<R>(this->tup(), error_info(exception_info_(&ex)), std::forward<H>(h)...,
|
||||
[]() -> R { throw; } );
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
deactivate();
|
||||
return leaf_detail::handle_error_<R>(this->tup(), error_info(exception_info_(0)), std::forward<H>(h)...,
|
||||
[]() -> R { throw; } );
|
||||
}
|
||||
}
|
||||
catch( std::exception const & ex )
|
||||
{
|
||||
deactivate();
|
||||
return leaf_detail::handle_error_<R>(this->tup(), error_info(exception_info_(&ex)), std::forward<H>(h)...,
|
||||
[]() -> R { throw; } );
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
deactivate();
|
||||
return leaf_detail::handle_error_<R>(this->tup(), error_info(exception_info_(0)), std::forward<H>(h)...,
|
||||
[]() -> R { throw; } );
|
||||
}
|
||||
@@ -327,9 +342,10 @@ namespace boost { namespace leaf {
|
||||
|
||||
template <class... E>
|
||||
template <class TryBlock, class RemoteH>
|
||||
inline decltype(std::declval<TryBlock>()()) context_base<E...>::remote_try_catch_( TryBlock && try_block, RemoteH && h ) const
|
||||
inline decltype(std::declval<TryBlock>()()) context_base<E...>::remote_try_catch_( TryBlock && try_block, RemoteH && h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
assert(is_active());
|
||||
try
|
||||
{
|
||||
return std::forward<TryBlock>(try_block)();
|
||||
@@ -342,19 +358,23 @@ namespace boost { namespace leaf {
|
||||
}
|
||||
catch( std::exception const & ex )
|
||||
{
|
||||
deactivate();
|
||||
return std::forward<RemoteH>(h)(error_info(exception_info_(&ex), this)).get();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
deactivate();
|
||||
return std::forward<RemoteH>(h)(error_info(exception_info_(0), this)).get();
|
||||
}
|
||||
}
|
||||
catch( std::exception const & ex )
|
||||
{
|
||||
deactivate();
|
||||
return std::forward<RemoteH>(h)(error_info(exception_info_(&ex), this)).get();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
deactivate();
|
||||
return std::forward<RemoteH>(h)(error_info(exception_info_(0), this)).get();
|
||||
}
|
||||
}
|
||||
@@ -436,6 +456,36 @@ namespace boost { namespace leaf {
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
template <class TryBlock, class... H>
|
||||
LEAF_CONSTEXPR inline decltype(std::declval<TryBlock>()()) try_catch( TryBlock && try_block, H && ... h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
context_type_from_handlers<H...> ctx;
|
||||
auto active_context = activate_context(ctx);
|
||||
return ctx.try_catch_(
|
||||
[&]
|
||||
{
|
||||
return std::forward<TryBlock>(try_block)();
|
||||
},
|
||||
std::forward<H>(h)...);
|
||||
}
|
||||
|
||||
template <class TryBlock, class RemoteH>
|
||||
LEAF_CONSTEXPR inline decltype(std::declval<TryBlock>()()) remote_try_catch( TryBlock && try_block, RemoteH && h )
|
||||
{
|
||||
using namespace leaf_detail;
|
||||
context_type_from_remote_handler<RemoteH> ctx;
|
||||
auto active_context = activate_context(ctx);
|
||||
return ctx.remote_try_catch_(
|
||||
[&]
|
||||
{
|
||||
return std::forward<TryBlock>(try_block)();
|
||||
},
|
||||
std::forward<RemoteH>(h));
|
||||
}
|
||||
|
||||
} }
|
||||
|
||||
#endif
|
||||
|
||||
@@ -29,7 +29,11 @@ namespace boost { namespace leaf {
|
||||
else
|
||||
{
|
||||
#ifndef LEAF_NO_EXCEPTIONS
|
||||
if( LEAF_UNCAUGHT_EXCEPTIONS() )
|
||||
# if LEAF_STD_UNCAUGHT_EXCEPTIONS
|
||||
if( std::uncaught_exceptions() )
|
||||
# else
|
||||
if( std::uncaught_exception() )
|
||||
# endif
|
||||
return leaf_detail::new_id();
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
@@ -78,6 +78,9 @@ tests = [
|
||||
'context_activator_test',
|
||||
'context_deduction_test',
|
||||
'capture_result_unload_test',
|
||||
'ctx_handle_all_test',
|
||||
'ctx_handle_exception_test',
|
||||
'ctx_handle_some_test',
|
||||
'ctx_remote_handle_all_test',
|
||||
'ctx_remote_handle_exception_test',
|
||||
'ctx_remote_handle_some_test',
|
||||
@@ -127,8 +130,9 @@ tests = [
|
||||
'_hpp_result_test',
|
||||
'_hpp_all_test',
|
||||
]
|
||||
ubsan_args = [ '-fsanitize=undefined', '-fno-sanitize-recover=undefined' ]
|
||||
foreach t : tests
|
||||
test(t, executable(t, 'test/'+t+'.cpp', dependencies: [leaf,thread_dep]+mp11 ) )
|
||||
test(t, executable(t, 'test/'+t+'.cpp', dependencies: [leaf,thread_dep]+mp11, cpp_args: ubsan_args, link_args: ubsan_args) )
|
||||
endforeach
|
||||
|
||||
if exceptions
|
||||
|
||||
@@ -45,6 +45,9 @@ run capture_exception_unload_test.cpp ;
|
||||
run capture_result_async_test.cpp ;
|
||||
run capture_result_state_test.cpp ;
|
||||
run capture_result_unload_test.cpp ;
|
||||
run ctx_handle_all_test.cpp ;
|
||||
run ctx_handle_exception_test.cpp ;
|
||||
run ctx_handle_some_test.cpp ;
|
||||
run ctx_remote_handle_all_test.cpp ;
|
||||
run ctx_remote_handle_exception_test.cpp ;
|
||||
run ctx_remote_handle_some_test.cpp ;
|
||||
|
||||
@@ -55,6 +55,11 @@ int main()
|
||||
return leaf::remote_handle_exception( err,
|
||||
[]( info<1>, info<3> )
|
||||
{
|
||||
return 1;
|
||||
},
|
||||
[]
|
||||
{
|
||||
return 2;
|
||||
} );
|
||||
};
|
||||
BOOST_TEST_EQ(count, 0);
|
||||
@@ -74,8 +79,8 @@ int main()
|
||||
ep = std::current_exception();
|
||||
}
|
||||
BOOST_TEST_EQ(count, 2);
|
||||
leaf::remote_try_catch(
|
||||
[&]
|
||||
int r = leaf::remote_try_catch(
|
||||
[&]() -> int
|
||||
{
|
||||
std::rethrow_exception(ep);
|
||||
},
|
||||
@@ -83,6 +88,7 @@ int main()
|
||||
{
|
||||
return error_handler(err);
|
||||
} );
|
||||
BOOST_TEST_EQ(r, 1);
|
||||
ep = std::exception_ptr();
|
||||
BOOST_TEST_EQ(count, 0);
|
||||
return boost::report_errors();
|
||||
|
||||
@@ -19,7 +19,7 @@ struct info
|
||||
template <class Ctx>
|
||||
leaf::result<int> f( Ctx & ctx )
|
||||
{
|
||||
auto active_context = activate_context(ctx, leaf::on_deactivation::do_not_propagate);
|
||||
auto active_context = activate_context(ctx);
|
||||
return leaf::new_error( info<1>{1} );
|
||||
}
|
||||
|
||||
@@ -43,8 +43,10 @@ int main()
|
||||
[&]
|
||||
{
|
||||
auto ctx = leaf::make_context(&handle_error);
|
||||
auto active_context = activate_context(ctx, leaf::on_deactivation::propagate);
|
||||
return f(ctx);
|
||||
auto active_context = activate_context(ctx);
|
||||
auto r = f(ctx);
|
||||
ctx.propagate();
|
||||
return r;
|
||||
},
|
||||
[&]( leaf::error_info const & error )
|
||||
{
|
||||
|
||||
51
test/ctx_handle_all_test.cpp
Normal file
51
test/ctx_handle_all_test.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) 2018-2019 Emil Dotchevski and Reverge Studios, Inc.
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/leaf/context.hpp>
|
||||
#include <boost/leaf/handle_error.hpp>
|
||||
#include <boost/leaf/result.hpp>
|
||||
#include "lightweight_test.hpp"
|
||||
#include <iostream>
|
||||
|
||||
namespace leaf = boost::leaf;
|
||||
|
||||
template <int>
|
||||
struct info
|
||||
{
|
||||
int value;
|
||||
};
|
||||
|
||||
template <class Ctx>
|
||||
leaf::result<int> f( Ctx & ctx )
|
||||
{
|
||||
auto active_context = activate_context(ctx);
|
||||
return leaf::new_error( info<1>{1} );
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
leaf::context<info<1>, leaf::verbose_diagnostic_info const &> ctx;
|
||||
|
||||
{
|
||||
leaf::result<int> r1 = f(ctx);
|
||||
BOOST_TEST(!r1);
|
||||
|
||||
int r2 = ctx.handle_all(
|
||||
r1,
|
||||
[]( info<1> x )
|
||||
{
|
||||
BOOST_TEST(x.value==1);
|
||||
return 1;
|
||||
},
|
||||
[]( leaf::verbose_diagnostic_info const & info )
|
||||
{
|
||||
std::cout << info;
|
||||
return 2;
|
||||
} );
|
||||
BOOST_TEST_EQ(r2, 1);
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
143
test/ctx_handle_exception_test.cpp
Normal file
143
test/ctx_handle_exception_test.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
// Copyright (c) 2018-2019 Emil Dotchevski and Reverge Studios, Inc.
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/leaf/config.hpp>
|
||||
#ifdef LEAF_NO_EXCEPTIONS
|
||||
|
||||
#include <iostream>
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << "Unit test not applicable." << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <boost/leaf/context.hpp>
|
||||
#include <boost/leaf/handle_exception.hpp>
|
||||
#include "lightweight_test.hpp"
|
||||
|
||||
namespace leaf = boost::leaf;
|
||||
|
||||
template <int>
|
||||
struct info
|
||||
{
|
||||
int value;
|
||||
};
|
||||
|
||||
template <class Ctx>
|
||||
void f( Ctx & ctx )
|
||||
{
|
||||
auto active_context = activate_context(ctx);
|
||||
throw leaf::exception(std::exception(), info<1>{1});
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
using Ctx = leaf::context<leaf::catch_<std::exception>, info<1>>;
|
||||
|
||||
{
|
||||
Ctx ctx;
|
||||
try
|
||||
{
|
||||
f(ctx);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
int r = ctx.handle_current_exception<int>(
|
||||
[]( leaf::catch_<std::exception>, info<1> x )
|
||||
{
|
||||
BOOST_TEST(x.value==1);
|
||||
return 1;
|
||||
},
|
||||
[]
|
||||
{
|
||||
return 2;
|
||||
} );
|
||||
BOOST_TEST_EQ(r, 1);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
Ctx ctx;
|
||||
try
|
||||
{
|
||||
f(ctx);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
int r = ctx.handle_exception<int>(
|
||||
std::current_exception(),
|
||||
[]( leaf::catch_<std::exception>, info<1> x )
|
||||
{
|
||||
BOOST_TEST(x.value==1);
|
||||
return 1;
|
||||
},
|
||||
[]
|
||||
{
|
||||
return 2;
|
||||
} );
|
||||
BOOST_TEST_EQ(r, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
using Ctx = leaf::context<leaf::catch_<std::exception>, info<1>>;
|
||||
|
||||
{
|
||||
Ctx ctx;
|
||||
try
|
||||
{
|
||||
f(ctx);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
int r = 0;
|
||||
ctx.handle_current_exception<void>(
|
||||
[&]( leaf::catch_<std::exception>, info<1> x )
|
||||
{
|
||||
BOOST_TEST(x.value==1);
|
||||
r = 1;
|
||||
},
|
||||
[&]
|
||||
{
|
||||
r = 2;
|
||||
} );
|
||||
BOOST_TEST_EQ(r, 1);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
Ctx ctx;
|
||||
try
|
||||
{
|
||||
f(ctx);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
int r = 0;
|
||||
ctx.handle_exception<void>(
|
||||
std::current_exception(),
|
||||
[&]( leaf::catch_<std::exception>, info<1> x )
|
||||
{
|
||||
BOOST_TEST(x.value==1);
|
||||
r = 1;
|
||||
},
|
||||
[&]
|
||||
{
|
||||
r = 2;
|
||||
} );
|
||||
BOOST_TEST_EQ(r, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
#endif
|
||||
49
test/ctx_handle_some_test.cpp
Normal file
49
test/ctx_handle_some_test.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright (c) 2018-2019 Emil Dotchevski and Reverge Studios, Inc.
|
||||
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/leaf/context.hpp>
|
||||
#include <boost/leaf/handle_error.hpp>
|
||||
#include <boost/leaf/result.hpp>
|
||||
#include "lightweight_test.hpp"
|
||||
|
||||
namespace leaf = boost::leaf;
|
||||
|
||||
template <int>
|
||||
struct info
|
||||
{
|
||||
int value;
|
||||
};
|
||||
|
||||
template <class Ctx>
|
||||
leaf::result<int> f( Ctx & ctx )
|
||||
{
|
||||
auto active_context = activate_context(ctx);
|
||||
return leaf::new_error( info<1>{1} );
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
leaf::context<info<1>> ctx;
|
||||
|
||||
{
|
||||
leaf::result<int> r1 = f(ctx);
|
||||
BOOST_TEST(!r1);
|
||||
|
||||
leaf::result<int> r2 = ctx.handle_some(
|
||||
std::move(r1),
|
||||
[]( info<1> x ) -> leaf::result<int>
|
||||
{
|
||||
BOOST_TEST(x.value==1);
|
||||
return 1;
|
||||
},
|
||||
[]
|
||||
{
|
||||
return 2;
|
||||
} );
|
||||
BOOST_TEST_EQ(r2.value(), 1);
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -20,7 +20,7 @@ struct info
|
||||
template <class Ctx>
|
||||
leaf::result<int> f( Ctx & ctx )
|
||||
{
|
||||
auto active_context = activate_context(ctx, leaf::on_deactivation::do_not_propagate);
|
||||
auto active_context = activate_context(ctx);
|
||||
return leaf::new_error( info<1>{1} );
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ struct info
|
||||
template <class Ctx>
|
||||
void f( Ctx & ctx )
|
||||
{
|
||||
auto active_context = activate_context(ctx, leaf::on_deactivation::do_not_propagate);
|
||||
auto active_context = activate_context(ctx);
|
||||
throw leaf::exception(std::exception(), info<1>{1});
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ struct info
|
||||
template <class Ctx>
|
||||
leaf::result<int> f( Ctx & ctx )
|
||||
{
|
||||
auto active_context = activate_context(ctx, leaf::on_deactivation::do_not_propagate);
|
||||
auto active_context = activate_context(ctx);
|
||||
return leaf::new_error( info<1>{1} );
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
namespace leaf = boost::leaf;
|
||||
|
||||
struct test_info { int value;};
|
||||
|
||||
enum class error_code
|
||||
{
|
||||
error1=1,
|
||||
@@ -170,5 +172,38 @@ int main()
|
||||
}
|
||||
#endif
|
||||
|
||||
///////////////////////////
|
||||
|
||||
{
|
||||
int r = leaf::try_handle_all(
|
||||
[]() -> leaf::result<int>
|
||||
{
|
||||
return leaf::new_error( test_info{42} );
|
||||
},
|
||||
[]( test_info const & x )
|
||||
{
|
||||
BOOST_TEST_EQ(x.value, 42);
|
||||
int r = leaf::try_handle_all(
|
||||
[]() -> leaf::result<int>
|
||||
{
|
||||
return leaf::new_error( test_info{43} );
|
||||
},
|
||||
[]()
|
||||
{
|
||||
return -1;
|
||||
} );
|
||||
BOOST_TEST_EQ(r, -1);
|
||||
BOOST_TEST_EQ(x.value, 42);
|
||||
return 0;
|
||||
},
|
||||
[]()
|
||||
{
|
||||
return -1;
|
||||
} );
|
||||
BOOST_TEST_EQ(r, 0);
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ int main()
|
||||
|
||||
{ // error move -> move
|
||||
context_type ctx;
|
||||
auto active_context = activate_context(ctx, leaf::on_deactivation::do_not_propagate);
|
||||
auto active_context = activate_context(ctx);
|
||||
leaf::result<val> r1 = leaf::new_error( e_err { } );
|
||||
BOOST_TEST(!r1);
|
||||
BOOST_TEST_EQ(err::count, 1);
|
||||
@@ -261,7 +261,7 @@ int main()
|
||||
BOOST_TEST_EQ(val::count, 0);
|
||||
{ // error copy -> move
|
||||
context_type ctx;
|
||||
auto active_context = activate_context(ctx, leaf::on_deactivation::propagate);
|
||||
auto active_context = activate_context(ctx);
|
||||
leaf::error_id err = leaf::new_error( e_err{ } );
|
||||
leaf::result<val> r1 = err;
|
||||
BOOST_TEST(!r1);
|
||||
@@ -278,7 +278,7 @@ int main()
|
||||
|
||||
{ // error move -> assign move
|
||||
context_type ctx;
|
||||
auto active_context = activate_context(ctx, leaf::on_deactivation::propagate);
|
||||
auto active_context = activate_context(ctx);
|
||||
leaf::result<val> r1 = leaf::new_error( e_err { } );
|
||||
BOOST_TEST(!r1);
|
||||
BOOST_TEST_EQ(err::count, 1);
|
||||
@@ -299,7 +299,7 @@ int main()
|
||||
BOOST_TEST_EQ(val::count, 0);
|
||||
{ // error copy -> assign move
|
||||
context_type ctx;
|
||||
auto active_context = activate_context(ctx, leaf::on_deactivation::propagate);
|
||||
auto active_context = activate_context(ctx);
|
||||
leaf::error_id err = leaf::new_error( e_err{ } );
|
||||
leaf::result<val> r1 = err;
|
||||
BOOST_TEST(!r1);
|
||||
@@ -411,7 +411,7 @@ int main()
|
||||
|
||||
{ // void error move -> move
|
||||
context_type ctx;
|
||||
auto active_context = activate_context(ctx, leaf::on_deactivation::do_not_propagate);
|
||||
auto active_context = activate_context(ctx);
|
||||
leaf::result<void> r1 = leaf::new_error( e_err { } );
|
||||
BOOST_TEST(!r1);
|
||||
BOOST_TEST_EQ(err::count, 1);
|
||||
@@ -424,7 +424,7 @@ int main()
|
||||
BOOST_TEST_EQ(err::count, 0);
|
||||
{ // void error copy -> move
|
||||
context_type ctx;
|
||||
auto active_context = activate_context(ctx, leaf::on_deactivation::propagate);
|
||||
auto active_context = activate_context(ctx);
|
||||
leaf::error_id err = leaf::new_error( e_err{ } );
|
||||
leaf::result<void> r1 = err;
|
||||
BOOST_TEST(!r1);
|
||||
@@ -439,7 +439,7 @@ int main()
|
||||
|
||||
{ // void error move -> assign move
|
||||
context_type ctx;
|
||||
auto active_context = activate_context(ctx, leaf::on_deactivation::propagate);
|
||||
auto active_context = activate_context(ctx);
|
||||
leaf::result<void> r1 = leaf::new_error( e_err { } );
|
||||
BOOST_TEST(!r1);
|
||||
BOOST_TEST_EQ(err::count, 1);
|
||||
@@ -454,7 +454,7 @@ int main()
|
||||
BOOST_TEST_EQ(err::count, 0);
|
||||
{ // void error copy -> assign move
|
||||
context_type ctx;
|
||||
auto active_context = activate_context(ctx, leaf::on_deactivation::propagate);
|
||||
auto active_context = activate_context(ctx);
|
||||
leaf::error_id err = leaf::new_error( e_err{ } );
|
||||
leaf::result<void> r1 = err;
|
||||
BOOST_TEST(!r1);
|
||||
|
||||
Reference in New Issue
Block a user