mirror of
https://github.com/boostorg/leaf.git
synced 2026-01-19 04:22:08 +00:00
Fix a bug in dynamic_allocator
This commit is contained in:
@@ -134,6 +134,16 @@ namespace leaf_detail
|
||||
return value_;
|
||||
}
|
||||
|
||||
BOOST_LEAF_CONSTEXPR T const * has_value() const noexcept
|
||||
{
|
||||
return key_ ? &value_ : nullptr;
|
||||
}
|
||||
|
||||
BOOST_LEAF_CONSTEXPR T * has_value() noexcept
|
||||
{
|
||||
return key_ ? &value_ : nullptr;
|
||||
}
|
||||
|
||||
BOOST_LEAF_CONSTEXPR T const * has_value(int key) const noexcept
|
||||
{
|
||||
BOOST_LEAF_ASSERT(key);
|
||||
|
||||
@@ -111,6 +111,11 @@ namespace leaf_detail
|
||||
BOOST_LEAF_ASSERT(x.prev_==nullptr);
|
||||
}
|
||||
|
||||
~slot() noexcept
|
||||
{
|
||||
BOOST_LEAF_ASSERT(tls::read_ptr<slot<E>>() != this);
|
||||
}
|
||||
|
||||
void activate() noexcept
|
||||
{
|
||||
prev_ = tls::read_ptr<slot<E>>();
|
||||
@@ -240,7 +245,7 @@ namespace leaf_detail
|
||||
|
||||
public:
|
||||
|
||||
explicit capturing_exception_node( capture_list::node * * & last, std::exception_ptr && ex ) noexcept:
|
||||
capturing_exception_node( capture_list::node * * & last, std::exception_ptr && ex ) noexcept:
|
||||
capturing_node(last),
|
||||
ex_(std::move(ex))
|
||||
{
|
||||
@@ -250,14 +255,12 @@ namespace leaf_detail
|
||||
};
|
||||
#endif
|
||||
|
||||
int err_id_;
|
||||
node * * last_;
|
||||
|
||||
public:
|
||||
|
||||
dynamic_allocator() noexcept:
|
||||
capture_list(nullptr),
|
||||
err_id_(0),
|
||||
last_(&first_)
|
||||
{
|
||||
BOOST_LEAF_ASSERT(first_ == nullptr);
|
||||
@@ -265,7 +268,6 @@ namespace leaf_detail
|
||||
|
||||
dynamic_allocator( dynamic_allocator && other ) noexcept:
|
||||
capture_list(std::move(other)),
|
||||
err_id_(other.err_id_),
|
||||
last_(other.last_ == &other.first_? &first_ : other.last_)
|
||||
{
|
||||
BOOST_LEAF_ASSERT(last_ != nullptr);
|
||||
@@ -274,17 +276,6 @@ namespace leaf_detail
|
||||
other.last_ = &other.first_;
|
||||
}
|
||||
|
||||
void append( dynamic_allocator && other ) noexcept
|
||||
{
|
||||
if( node * other_first = other.first_ )
|
||||
{
|
||||
*last_ = other_first;
|
||||
last_ = other.last_;
|
||||
other.first_ = nullptr;
|
||||
other.last_ = &other.first_;
|
||||
}
|
||||
}
|
||||
|
||||
template <class E>
|
||||
typename std::decay<E>::type & dynamic_load(int err_id, E && e)
|
||||
{
|
||||
@@ -294,7 +285,6 @@ namespace leaf_detail
|
||||
BOOST_LEAF_ASSERT(tls::read_ptr<slot<T>>() == nullptr);
|
||||
capturing_slot_node<T> * csn = new capturing_slot_node<T>(last_, err_id, std::forward<E>(e));
|
||||
csn->activate();
|
||||
err_id_ = err_id;
|
||||
return csn->value(err_id);
|
||||
}
|
||||
|
||||
@@ -308,7 +298,7 @@ namespace leaf_detail
|
||||
}
|
||||
|
||||
template <class LeafResult>
|
||||
LeafResult extract_capture_list() noexcept
|
||||
LeafResult extract_capture_list(int err_id) noexcept
|
||||
{
|
||||
#ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
if( std::exception_ptr ex = std::current_exception() )
|
||||
@@ -317,9 +307,10 @@ namespace leaf_detail
|
||||
leaf_detail::capture_list::node * const f = first_;
|
||||
first_ = nullptr;
|
||||
last_ = &first_;
|
||||
return { err_id_, capture_list(f) };
|
||||
return { err_id, capture_list(f) };
|
||||
}
|
||||
|
||||
using capture_list::unload;
|
||||
using capture_list::print;
|
||||
};
|
||||
|
||||
@@ -337,9 +328,8 @@ namespace leaf_detail
|
||||
template <>
|
||||
inline void slot<dynamic_allocator>::deactivate() const noexcept
|
||||
{
|
||||
if( int const err_id = this->key() )
|
||||
if( dynamic_allocator const * c = this->has_value(err_id) )
|
||||
c->deactivate();
|
||||
if( dynamic_allocator const * c = this->has_value() )
|
||||
c->deactivate();
|
||||
tls::write_ptr<slot<dynamic_allocator>>(prev_);
|
||||
}
|
||||
|
||||
@@ -347,12 +337,8 @@ namespace leaf_detail
|
||||
inline void slot<dynamic_allocator>::unload( int err_id ) noexcept(false)
|
||||
{
|
||||
BOOST_LEAF_ASSERT(err_id);
|
||||
if( dynamic_allocator * da1 = this->has_value(err_id) )
|
||||
if( impl * p = tls::read_ptr<slot<dynamic_allocator>>() )
|
||||
if( dynamic_allocator * da2 = p->has_value(err_id) )
|
||||
da2->append(std::move(*da1));
|
||||
else
|
||||
*p = std::move(*this);
|
||||
if( dynamic_allocator * da1 = this->has_value() )
|
||||
da1->unload(err_id);
|
||||
}
|
||||
|
||||
template <class E>
|
||||
@@ -360,7 +346,7 @@ namespace leaf_detail
|
||||
{
|
||||
if( slot<dynamic_allocator> * sl = tls::read_ptr<slot<dynamic_allocator>>() )
|
||||
{
|
||||
if( dynamic_allocator * c = sl->has_value(err_id) )
|
||||
if( dynamic_allocator * c = sl->has_value() )
|
||||
c->dynamic_load(err_id, std::forward<E>(e));
|
||||
else
|
||||
sl->load(err_id).dynamic_load(err_id, std::forward<E>(e));
|
||||
@@ -435,7 +421,10 @@ namespace leaf_detail
|
||||
if( this->key()!=err_id )
|
||||
return;
|
||||
if( impl * p = tls::read_ptr<slot<E>>() )
|
||||
*p = std::move(*this);
|
||||
{
|
||||
if( !p->has_value(err_id) )
|
||||
*p = std::move(*this);
|
||||
}
|
||||
#if BOOST_LEAF_CFG_CAPTURE
|
||||
else
|
||||
dynamic_load<false>(err_id, std::move(*this).value(err_id));
|
||||
|
||||
@@ -226,6 +226,36 @@ protected:
|
||||
|
||||
namespace leaf_detail
|
||||
{
|
||||
template <class T>
|
||||
struct get_dispatch
|
||||
{
|
||||
static BOOST_LEAF_CONSTEXPR T const * get(T const * x) noexcept
|
||||
{
|
||||
return x;
|
||||
}
|
||||
static BOOST_LEAF_CONSTEXPR T const * get(void const *) noexcept
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, int I = 0, class... Tp>
|
||||
BOOST_LEAF_CONSTEXPR inline typename std::enable_if<I == sizeof...(Tp) - 1, T>::type const *
|
||||
find_in_tuple(std::tuple<Tp...> const & t) noexcept
|
||||
{
|
||||
return get_dispatch<T>::get(&std::get<I>(t));
|
||||
}
|
||||
|
||||
template<class T, int I = 0, class... Tp>
|
||||
BOOST_LEAF_CONSTEXPR inline typename std::enable_if<I < sizeof...(Tp) - 1, T>::type const *
|
||||
find_in_tuple(std::tuple<Tp...> const & t) noexcept
|
||||
{
|
||||
if( T const * x = get_dispatch<T>::get(&std::get<I>(t)) )
|
||||
return x;
|
||||
else
|
||||
return find_in_tuple<T, I+1, Tp...>(t);
|
||||
}
|
||||
|
||||
struct verbose_diagnostic_info_: verbose_diagnostic_info
|
||||
{
|
||||
template <class Tup>
|
||||
@@ -241,7 +271,8 @@ namespace leaf_detail
|
||||
template <class Tup>
|
||||
BOOST_LEAF_CONSTEXPR static verbose_diagnostic_info_ get( Tup const & tup, error_info const & ei ) noexcept
|
||||
{
|
||||
return verbose_diagnostic_info_(ei, tup, handler_argument_traits_defaults<dynamic_allocator>::check(tup, ei));
|
||||
slot<dynamic_allocator> const * da = find_in_tuple<slot<dynamic_allocator>>(tup);
|
||||
return verbose_diagnostic_info_(ei, tup, da ? da->has_value() : nullptr );
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -945,19 +976,22 @@ namespace leaf_detail
|
||||
else
|
||||
{
|
||||
sl.deactivate();
|
||||
return leaf_result(sl.value(error_id(r.error()).value()).template extract_capture_list<leaf_result>());
|
||||
int const err_id = error_id(r.error()).value();
|
||||
return leaf_result(sl.value(err_id).template extract_capture_list<leaf_result>(err_id));
|
||||
}
|
||||
}
|
||||
#ifndef BOOST_LEAF_NO_EXCEPTIONS
|
||||
catch( std::exception & ex )
|
||||
{
|
||||
sl.deactivate();
|
||||
return sl.value(error_info(&ex).error().value()).template extract_capture_list<leaf_result>();
|
||||
int const err_id = error_info(&ex).error().value();
|
||||
return sl.value(err_id).template extract_capture_list<leaf_result>(err_id);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
sl.deactivate();
|
||||
return sl.value(error_info(nullptr).error().value()).template extract_capture_list<leaf_result>();
|
||||
int const err_id = error_info(nullptr).error().value();
|
||||
return sl.value(err_id).template extract_capture_list<leaf_result>(err_id);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1002,12 +1036,14 @@ namespace leaf_detail
|
||||
catch( std::exception & ex )
|
||||
{
|
||||
sl.deactivate();
|
||||
return sl.value(error_info(&ex).error().value()).template extract_capture_list<leaf_result>();
|
||||
int const err_id = error_info(&ex).error().value();
|
||||
return sl.value(err_id).template extract_capture_list<leaf_result>(err_id);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
sl.deactivate();
|
||||
return sl.value(error_info(nullptr).error().value()).template extract_capture_list<leaf_result>();
|
||||
int const err_id = error_info(nullptr).error().value();
|
||||
return sl.value(err_id).template extract_capture_list<leaf_result>(err_id);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -127,6 +127,7 @@ if option_enable_unit_tests
|
||||
'diagnostic_info_test3',
|
||||
'diagnostic_info_test4',
|
||||
'diagnostic_info_test5',
|
||||
'diagnostic_info_test6',
|
||||
'e_errno_test',
|
||||
'e_LastError_test',
|
||||
'error_code_test',
|
||||
|
||||
135
test/diagnostic_info_test6.cpp
Normal file
135
test/diagnostic_info_test6.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
// Copyright 2018-2023 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 <boost/leaf/config.hpp>
|
||||
# include <boost/leaf/handle_errors.hpp>
|
||||
# include <boost/leaf/on_error.hpp>
|
||||
# include <boost/leaf/result.hpp>
|
||||
#endif
|
||||
|
||||
#if BOOST_LEAF_CFG_STD_STRING
|
||||
# include <sstream>
|
||||
# include <iostream>
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "lightweight_test.hpp"
|
||||
|
||||
namespace leaf = boost::leaf;
|
||||
|
||||
template <int> struct info { int value; };
|
||||
|
||||
leaf::result<void> f1()
|
||||
{
|
||||
return leaf::new_error(info<1>{11}, info<2>{21});
|
||||
}
|
||||
|
||||
leaf::result<void> f2()
|
||||
{
|
||||
return leaf::try_handle_some(
|
||||
[]
|
||||
{
|
||||
return f1();
|
||||
},
|
||||
[]
|
||||
{
|
||||
return leaf::new_error(info<1>{12});
|
||||
} );
|
||||
}
|
||||
|
||||
leaf::result<void> f3()
|
||||
{
|
||||
return leaf::try_handle_some(
|
||||
[]
|
||||
{
|
||||
return f1();
|
||||
},
|
||||
[](leaf::verbose_diagnostic_info const &)
|
||||
{
|
||||
return leaf::new_error(info<1>{13});
|
||||
} );
|
||||
}
|
||||
|
||||
leaf::result<void> f4()
|
||||
{
|
||||
return leaf::try_handle_some(
|
||||
[]
|
||||
{
|
||||
return f1();
|
||||
},
|
||||
[](leaf::verbose_diagnostic_info const & e)
|
||||
{
|
||||
return e.error().load(info<1>{14});
|
||||
} );
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
leaf::try_handle_all([]() -> leaf::result<void>
|
||||
{
|
||||
return f2();
|
||||
},
|
||||
[](leaf::verbose_diagnostic_info const & e)
|
||||
{
|
||||
#if BOOST_LEAF_CFG_STD_STRING
|
||||
std::ostringstream st;
|
||||
st << e;
|
||||
std::string s = st.str();
|
||||
std::cout << s << std::endl;
|
||||
if( BOOST_LEAF_CFG_DIAGNOSTICS && BOOST_LEAF_CFG_CAPTURE )
|
||||
{
|
||||
BOOST_TEST_EQ(s.find(": 11"), s.npos);
|
||||
BOOST_TEST_NE(s.find(": 12"), s.npos);
|
||||
BOOST_TEST_EQ(s.find(": 21"), s.npos);
|
||||
}
|
||||
#endif
|
||||
} );
|
||||
|
||||
leaf::try_handle_all([]() -> leaf::result<void>
|
||||
{
|
||||
return f3();
|
||||
},
|
||||
[](leaf::verbose_diagnostic_info const & e)
|
||||
{
|
||||
#if BOOST_LEAF_CFG_STD_STRING
|
||||
std::ostringstream st;
|
||||
st << e;
|
||||
std::string s = st.str();
|
||||
std::cout << s << std::endl;
|
||||
if( BOOST_LEAF_CFG_DIAGNOSTICS && BOOST_LEAF_CFG_CAPTURE )
|
||||
{
|
||||
BOOST_TEST_EQ(s.find(": 11"), s.npos);
|
||||
BOOST_TEST_NE(s.find(": 13"), s.npos);
|
||||
BOOST_TEST_EQ(s.find(": 21"), s.npos);
|
||||
}
|
||||
#endif
|
||||
} );
|
||||
|
||||
leaf::try_handle_all([]() -> leaf::result<void>
|
||||
{
|
||||
return f4();
|
||||
},
|
||||
[](leaf::verbose_diagnostic_info const & e)
|
||||
{
|
||||
#if BOOST_LEAF_CFG_STD_STRING
|
||||
std::ostringstream st;
|
||||
st << e;
|
||||
std::string s = st.str();
|
||||
std::cout << s << std::endl;
|
||||
if( BOOST_LEAF_CFG_DIAGNOSTICS && BOOST_LEAF_CFG_CAPTURE )
|
||||
{
|
||||
BOOST_TEST_EQ(s.find(": 12"), s.npos);
|
||||
BOOST_TEST_NE(s.find(": 14"), s.npos);
|
||||
BOOST_TEST_NE(s.find(": 21"), s.npos);
|
||||
}
|
||||
#endif
|
||||
} );
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
Reference in New Issue
Block a user