From bd58aa238cd389e23a456f0d7ad1422834818496 Mon Sep 17 00:00:00 2001 From: Emil Dotchevski Date: Wed, 11 Feb 2026 18:29:21 -0500 Subject: [PATCH] Refactored on_error behavior in the presence of a dynamic allocator --- include/boost/leaf/error.hpp | 64 +------ include/boost/leaf/on_error.hpp | 44 ++--- meson.build | 3 - test/Jamfile.v2 | 3 - test/on_error_alloc_fail_test.cpp | 239 ------------------------ test/on_error_dynamic_reserve_test2.cpp | 58 ------ test/on_error_dynamic_reserve_test3.cpp | 74 -------- test/on_error_preload_basic_test.cpp | 15 -- 8 files changed, 20 insertions(+), 480 deletions(-) delete mode 100644 test/on_error_alloc_fail_test.cpp delete mode 100644 test/on_error_dynamic_reserve_test2.cpp delete mode 100644 test/on_error_dynamic_reserve_test3.cpp diff --git a/include/boost/leaf/error.hpp b/include/boost/leaf/error.hpp index e0348f3..77304bf 100644 --- a/include/boost/leaf/error.hpp +++ b/include/boost/leaf/error.hpp @@ -224,8 +224,6 @@ namespace detail namespace detail { - class preloaded_base; - template struct capturing_slot_node_allocator; @@ -238,8 +236,6 @@ namespace detail template friend struct capturing_slot_node_allocator; - preloaded_base * preloaded_list_; - class capturing_node: public capture_list::node { @@ -326,7 +322,6 @@ namespace detail dynamic_allocator() noexcept: capture_list(nullptr), - preloaded_list_(nullptr), last_(&first_) { BOOST_LEAF_ASSERT(first_ == nullptr); @@ -334,34 +329,14 @@ namespace detail dynamic_allocator( dynamic_allocator && other ) noexcept: capture_list(std::move(other)), - preloaded_list_(nullptr), last_(other.last_ == &other.first_? &first_ : other.last_) { BOOST_LEAF_ASSERT(last_ != nullptr); BOOST_LEAF_ASSERT(*last_ == nullptr); BOOST_LEAF_ASSERT(other.first_ == nullptr); - BOOST_LEAF_ASSERT(other.preloaded_list_ == nullptr); other.last_ = &other.first_; } - preloaded_base * preloaded_list() const noexcept - { - return preloaded_list_; - } - - preloaded_base * link_preloaded_item(preloaded_base * pb) noexcept - { - BOOST_LEAF_ASSERT(pb != nullptr); - preloaded_base * next = preloaded_list_; - preloaded_list_ = pb; - return next; - } - - void unlink_preloaded_item(preloaded_base * next) noexcept - { - preloaded_list_ = next; - } - template slot * alloc() { @@ -606,38 +581,6 @@ namespace detail namespace detail { -#if BOOST_LEAF_CFG_CAPTURE - class preloaded_base - { - protected: - - preloaded_base() noexcept: - next_( - []( preloaded_base * this_ ) -> preloaded_base * - { - if( dynamic_allocator * da = get_dynamic_allocator() ) - return da->link_preloaded_item(this_); - return nullptr; - }(this)) - { - } - - ~preloaded_base() noexcept - { - if( dynamic_allocator * da = get_dynamic_allocator() ) - da->unlink_preloaded_item(next_); - else - BOOST_LEAF_ASSERT(next_ == nullptr); - } - - public: - - preloaded_base * const next_; - - virtual void reserve( dynamic_allocator & ) const = 0; - }; -#endif // #if BOOST_LEAF_CFG_CAPTURE - inline int current_id() noexcept { unsigned id = tls::read_current_error_id(); @@ -652,13 +595,8 @@ namespace detail return int(id); } - inline int start_new_error() noexcept(!BOOST_LEAF_CFG_CAPTURE) + inline int start_new_error() noexcept { -#if BOOST_LEAF_CFG_CAPTURE - if( dynamic_allocator * da = get_dynamic_allocator() ) - for( preloaded_base const * e = da->preloaded_list(); e; e = e->next_ ) - e->reserve(*da); -#endif return new_id(); } diff --git a/include/boost/leaf/on_error.hpp b/include/boost/leaf/on_error.hpp index 4831226..ff1ff22 100644 --- a/include/boost/leaf/on_error.hpp +++ b/include/boost/leaf/on_error.hpp @@ -40,19 +40,7 @@ public: # else if( std::uncaught_exception() ) # endif -# if BOOST_LEAF_CFG_CAPTURE - try - { - return detail::start_new_error(); - } - catch(...) - { - BOOST_LEAF_ASSERT(detail::current_id() == err_id_); - return detail::new_id(); - } -# else - return detail::start_new_error(); -# endif + return detail::new_id(); #endif return 0; } @@ -260,9 +248,6 @@ namespace detail template class preloaded -#if BOOST_LEAF_CFG_CAPTURE - : preloaded_base -#endif { preloaded( preloaded const & ) = delete; preloaded & operator=( preloaded const & ) = delete; @@ -273,13 +258,6 @@ namespace detail bool moved_ = false; #endif -#if BOOST_LEAF_CFG_CAPTURE - void reserve( dynamic_allocator & da ) const override - { - tuple_for_each_preload::reserve(p_,da); - } -#endif - public: BOOST_LEAF_CONSTEXPR explicit preloaded( Item && ... i ): @@ -302,8 +280,24 @@ namespace detail if( moved_ ) return; #endif - if( auto id = id_.check_id() ) - tuple_for_each_preload::trigger(p_,id); + if( int const err_id = id_.check_id() ) + { +#if BOOST_LEAF_CFG_CAPTURE + if( dynamic_allocator * da = get_dynamic_allocator() ) +# ifndef BOOST_LEAF_NO_EXCEPTIONS + try + { +# endif + tuple_for_each_preload::reserve(p_, *da); +# ifndef BOOST_LEAF_NO_EXCEPTIONS + } + catch(...) + { + } +# endif +#endif + tuple_for_each_preload::trigger(p_, err_id); + } } }; diff --git a/meson.build b/meson.build index 7e28a17..541b73c 100644 --- a/meson.build +++ b/meson.build @@ -153,7 +153,6 @@ if option_enable_unit_tests 'on_error_accumulate_nested_new_error_result_test', 'on_error_accumulate_nested_success_exception_test', 'on_error_accumulate_nested_success_result_test', - 'on_error_alloc_fail_test', 'on_error_defer_basic_test', 'on_error_defer_nested_error_exception_test', 'on_error_defer_nested_error_result_test', @@ -162,8 +161,6 @@ if option_enable_unit_tests 'on_error_defer_nested_success_exception_test', 'on_error_defer_nested_success_result_test', 'on_error_dynamic_reserve_test1', - 'on_error_dynamic_reserve_test2', - 'on_error_dynamic_reserve_test3', 'on_error_preload_basic_test', 'on_error_preload_exception_test', 'on_error_preload_nested_error_exception_test', diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 108d4b8..a1468a4 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -98,7 +98,6 @@ run on_error_accumulate_nested_new_error_exception_test.cpp ; run on_error_accumulate_nested_new_error_result_test.cpp ; run on_error_accumulate_nested_success_exception_test.cpp ; run on_error_accumulate_nested_success_result_test.cpp ; -run on_error_alloc_fail_test.cpp ; run on_error_defer_basic_test.cpp ; run on_error_defer_nested_error_exception_test.cpp ; run on_error_defer_nested_error_result_test.cpp ; @@ -107,8 +106,6 @@ run on_error_defer_nested_new_error_result_test.cpp ; run on_error_defer_nested_success_exception_test.cpp ; run on_error_defer_nested_success_result_test.cpp ; run on_error_dynamic_reserve_test1.cpp ; -run on_error_dynamic_reserve_test2.cpp ; -run on_error_dynamic_reserve_test3.cpp ; run on_error_preload_basic_test.cpp ; run on_error_preload_exception_test.cpp ; run on_error_preload_nested_error_exception_test.cpp ; diff --git a/test/on_error_alloc_fail_test.cpp b/test/on_error_alloc_fail_test.cpp deleted file mode 100644 index 6444b7f..0000000 --- a/test/on_error_alloc_fail_test.cpp +++ /dev/null @@ -1,239 +0,0 @@ -// Copyright 2018-2025 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) - -#ifdef BOOST_LEAF_TEST_SINGLE_HEADER -# include "leaf.hpp" -#else -# include -# include -# include -# include -# include -# include -#endif - -#if !BOOST_LEAF_CFG_CAPTURE || defined(BOOST_LEAF_NO_EXCEPTIONS) - -int main() -{ - return 0; -} - -#else - -#include -#include -#include - -namespace leaf = boost::leaf; - -struct alloc_fail_info -{ - int value; -}; - -namespace boost { namespace leaf { namespace detail { - -template <> -struct capturing_slot_node_allocator -{ - template - static dynamic_allocator::capturing_slot_node * new_( A && ... ) - { - throw std::bad_alloc(); - } - - static void delete_( dynamic_allocator::capturing_slot_node * p ) noexcept - { - delete p; - } -}; - -} } } // namespace boost::leaf::detail - -#include "lightweight_test.hpp" - -template -struct other_info -{ - int value; -}; - -leaf::result f() -{ - auto load = leaf::on_error( other_info<1>{1}, alloc_fail_info{42}, other_info<2>{2} ); - return leaf::new_error(); -} - -int main() -{ - { - auto captured = leaf::try_capture_all( - []() -> leaf::result - { - return f(); - } ); - - int r = leaf::try_handle_all( - [&]() -> leaf::result - { - (void) captured.value(); - return 0; - }, - []( std::bad_alloc const &, other_info<1> const & oi1, other_info<2> const * oi2, alloc_fail_info const * afi ) - { - BOOST_TEST_EQ(oi1.value, 1); - BOOST_TEST_EQ(oi2, nullptr); - BOOST_TEST_EQ(afi, nullptr); - return 1; - }, - [] - { - return 2; - } ); - BOOST_TEST_EQ(r, 1); - } - -#if BOOST_LEAF_CFG_DIAGNOSTICS && BOOST_LEAF_CFG_STD_STRING - { - int r = leaf::try_handle_all( - []() -> leaf::result - { - BOOST_LEAF_CHECK(f()); - return 0; - }, - []( std::bad_alloc const &, leaf::diagnostic_details const & dd ) - { - std::ostringstream s; - s << dd; - std::string str = s.str(); - BOOST_TEST(str.find("other_info<1>") != std::string::npos); - BOOST_TEST(str.find("other_info<2>") == std::string::npos); - BOOST_TEST(str.find("alloc_fail_info") == std::string::npos); - return 1; - }, - [] - { - return 2; - } ); - BOOST_TEST_EQ(r, 1); - } -#endif - -//////////////////////////////////////// - - { - auto captured = leaf::try_capture_all( - []() -> leaf::result - { - auto load = leaf::on_error( other_info<1>{1}, alloc_fail_info{42}, other_info<2>{2} ); - throw std::runtime_error("test"); - } ); - - int r = leaf::try_handle_all( - [&]() -> leaf::result - { - (void) captured.value(); - return 0; - }, - []( other_info<1> const & oi1, other_info<2> const * oi2, alloc_fail_info const * afi ) - { - BOOST_TEST_EQ(oi1.value, 1); - BOOST_TEST_EQ(oi2, nullptr); - BOOST_TEST_EQ(afi, nullptr); - return 1; - }, - [] - { - return 2; - } ); - BOOST_TEST_EQ(r, 1); - } - -#if BOOST_LEAF_CFG_DIAGNOSTICS && BOOST_LEAF_CFG_STD_STRING - { - int r = leaf::try_catch( - []() -> int - { - auto load = leaf::on_error( other_info<1>{1}, alloc_fail_info{42}, other_info<2>{2} ); - throw std::runtime_error("test"); - }, - []( leaf::diagnostic_details const & dd ) - { - std::ostringstream s; - s << dd; - std::string str = s.str(); - BOOST_TEST(str.find("other_info<1>") != std::string::npos); - BOOST_TEST(str.find("other_info<2>") == std::string::npos); - BOOST_TEST(str.find("alloc_fail_info") == std::string::npos); - return 1; - }, - [] - { - return 2; - } ); - BOOST_TEST_EQ(r, 1); - } -#endif - -//////////////////////////////////////// - - { - auto captured = leaf::try_capture_all( - []() -> leaf::result - { - auto load = leaf::on_error( other_info<1>{1}, alloc_fail_info{42}, other_info<2>{2} ); - leaf::throw_exception(std::runtime_error("test")); - } ); - - int r = leaf::try_handle_all( - [&]() -> leaf::result - { - (void) captured.value(); - return 0; - }, - []( std::bad_alloc const &, other_info<1> const & oi1, other_info<2> const * oi2, alloc_fail_info const * afi ) - { - BOOST_TEST_EQ(oi1.value, 1); - BOOST_TEST_EQ(oi2, nullptr); - BOOST_TEST_EQ(afi, nullptr); - return 1; - }, - [] - { - return 2; - } ); - BOOST_TEST_EQ(r, 1); - } - -#if BOOST_LEAF_CFG_DIAGNOSTICS && BOOST_LEAF_CFG_STD_STRING - { - int r = leaf::try_catch( - []() -> int - { - auto load = leaf::on_error( other_info<1>{1}, alloc_fail_info{42}, other_info<2>{2} ); - leaf::throw_exception(std::runtime_error("test")); - }, - []( std::bad_alloc const &, leaf::diagnostic_details const & dd ) - { - std::ostringstream s; - s << dd; - std::string str = s.str(); - BOOST_TEST(str.find("other_info<1>") != std::string::npos); - BOOST_TEST(str.find("other_info<2>") == std::string::npos); - BOOST_TEST(str.find("alloc_fail_info") == std::string::npos); - return 1; - }, - [] - { - return 2; - } ); - BOOST_TEST_EQ(r, 1); - } -#endif - - return boost::report_errors(); -} - -#endif diff --git a/test/on_error_dynamic_reserve_test2.cpp b/test/on_error_dynamic_reserve_test2.cpp deleted file mode 100644 index cb7f787..0000000 --- a/test/on_error_dynamic_reserve_test2.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2018-2025 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) - -#ifdef BOOST_LEAF_TEST_SINGLE_HEADER -# include "leaf.hpp" -#else -# include -# include -# include -# include -# include -#endif - -#include "lightweight_test.hpp" - -namespace leaf = boost::leaf; - -template -struct info -{ - int value; -}; - -leaf::result f() -{ - BOOST_TEST_EQ(leaf::tls::read_ptr>>(), nullptr); - BOOST_TEST_NE(leaf::tls::read_ptr>>(), nullptr); - auto load = leaf::on_error( info<42>{42} ); - BOOST_TEST_EQ(leaf::tls::read_ptr>>(), nullptr); - auto e = leaf::new_error(info<43>{}); - BOOST_TEST( - (BOOST_LEAF_CFG_CAPTURE == 0) - == - (leaf::tls::read_ptr>>() == nullptr)); - return e; -} - -int main() -{ - int r = leaf::try_handle_all( - []() -> leaf::result - { - BOOST_LEAF_CHECK(f()); - return 0; - }, - []( info<43> const & ) - { - return 1; - }, - []( leaf::diagnostic_details const & ) - { - return 2; - } ); - BOOST_TEST_EQ(r, 1); - - return boost::report_errors(); -} diff --git a/test/on_error_dynamic_reserve_test3.cpp b/test/on_error_dynamic_reserve_test3.cpp deleted file mode 100644 index 472cad4..0000000 --- a/test/on_error_dynamic_reserve_test3.cpp +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2018-2025 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 - -#if !BOOST_LEAF_CFG_CAPTURE - -#include - -int main() -{ - std::cout << "Unit test not applicable." << std::endl; - return 0; -} - -#else - -#ifdef BOOST_LEAF_TEST_SINGLE_HEADER -# include "leaf.hpp" -#else -# include -# include -# include -# include -#endif - -#include "lightweight_test.hpp" - -namespace leaf = boost::leaf; - -template -struct info -{ - int value; -}; - -leaf::result f() -{ - BOOST_TEST_EQ(leaf::tls::read_ptr>>(), nullptr); - BOOST_TEST_NE(leaf::tls::read_ptr>>(), nullptr); - auto load = leaf::on_error( info<42>{42} ); - BOOST_TEST_EQ(leaf::tls::read_ptr>>(), nullptr); - auto e = leaf::new_error(info<43>{}); - BOOST_TEST_NE(leaf::tls::read_ptr>>(), nullptr); - return e; -} - -int main() -{ - int r = leaf::try_handle_all( - []() -> leaf::result - { - return leaf::try_capture_all( - []() -> leaf::result - { - BOOST_LEAF_CHECK(f()); - return 0; - } ); - }, - []( info<43> const & ) - { - return 1; - }, - [] - { - return 2; - } ); - BOOST_TEST_EQ(r, 1); - - return boost::report_errors(); -} - -#endif diff --git a/test/on_error_preload_basic_test.cpp b/test/on_error_preload_basic_test.cpp index 86964e4..50ae871 100644 --- a/test/on_error_preload_basic_test.cpp +++ b/test/on_error_preload_basic_test.cpp @@ -71,21 +71,6 @@ int main() return leaf::new_error(); }); -#if BOOST_LEAF_CFG_CAPTURE - (void) leaf::try_capture_all( - []() -> leaf::result - { - leaf::detail::dynamic_allocator * da = leaf::detail::get_dynamic_allocator(); - BOOST_TEST_NE(da, nullptr); - BOOST_TEST_EQ(da->preloaded_list(), nullptr); - { - auto load = leaf::on_error( info<42>{42} ); - BOOST_TEST_NE(da->preloaded_list(), nullptr); - } - BOOST_TEST_EQ(da->preloaded_list(), nullptr); - return { }; - } ); -#endif return boost::report_errors(); }