Compare commits

...

5 Commits

9 changed files with 279 additions and 74 deletions

View File

@ -148,10 +148,6 @@ jobs:
cxxstd: "14"
addrmd: 32,64
os: windows-2019
- toolset: msvc-14.1
cxxstd: "14,17,latest"
addrmd: 32,64
os: windows-2016
- toolset: msvc-14.2
cxxstd: "14,17,20,latest"
addrmd: 32,64

View File

@ -97,7 +97,7 @@ inline char const * error_category::message( int ev, char * buffer, std::size_t
#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
#include <boost/system/detail/std_category.hpp>
#include <boost/system/detail/std_category_impl.hpp>
namespace boost
{
@ -143,6 +143,19 @@ inline error_category::operator std::error_category const & () const
return *p;
}
// One `std_category` object is allocated for every
// user-defined `error_category` that is converted to
// `std::error_category`.
//
// This one-time allocation will show up on leak checkers.
// That's unavoidable. There is no way to deallocate the
// `std_category` object because first, `error_category`
// is a literal type (so it can't have a destructor) and
// second, `error_category` needs to be usable during program
// shutdown.
//
// https://github.com/boostorg/system/issues/78
detail::std_category* q = new detail::std_category( this, 0 );
if( ps_.compare_exchange_strong( p, q, std::memory_order_release, std::memory_order_acquire ) )

View File

@ -21,6 +21,11 @@
#include <boost/system/detail/append_int.hpp>
#include <boost/system/detail/snprintf.hpp>
#include <boost/system/detail/config.hpp>
#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
# include <boost/system/detail/std_category.hpp>
#endif
#include <boost/assert/source_location.hpp>
#include <boost/cstdint.hpp>
#include <boost/config.hpp>
@ -158,9 +163,21 @@ public:
#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
error_code( std::error_code const& ec ) BOOST_NOEXCEPT:
lc_flags_( 1 )
d1_(), lc_flags_( 0 )
{
::new( d2_ ) std::error_code( ec );
#ifndef BOOST_NO_RTTI
if( detail::std_category const* pc2 = dynamic_cast< detail::std_category const* >( &ec.category() ) )
{
*this = boost::system::error_code( ec.value(), pc2->original_category() );
}
else
#endif
{
::new( d2_ ) std::error_code( ec );
lc_flags_ = 1;
}
}
#endif

View File

@ -11,9 +11,6 @@
// See library home page at http://www.boost.org/libs/system
#include <boost/system/detail/error_category.hpp>
#include <boost/system/detail/error_condition.hpp>
#include <boost/system/detail/error_code.hpp>
#include <boost/system/detail/generic_category.hpp>
#include <system_error>
//
@ -33,6 +30,13 @@ private:
boost::system::error_category const * pc_;
public:
boost::system::error_category const & original_category() const BOOST_NOEXCEPT
{
return *pc_;
}
public:
explicit std_category( boost::system::error_category const * pc, unsigned id ): pc_( pc )
@ -66,72 +70,10 @@ public:
return pc_->default_error_condition( ev );
}
bool equivalent( int code, const std::error_condition & condition ) const BOOST_NOEXCEPT BOOST_OVERRIDE;
bool equivalent( const std::error_code & code, int condition ) const BOOST_NOEXCEPT BOOST_OVERRIDE;
inline bool equivalent( int code, const std::error_condition & condition ) const BOOST_NOEXCEPT BOOST_OVERRIDE;
inline bool equivalent( const std::error_code & code, int condition ) const BOOST_NOEXCEPT BOOST_OVERRIDE;
};
inline bool std_category::equivalent( int code, const std::error_condition & condition ) const BOOST_NOEXCEPT
{
if( condition.category() == *this )
{
boost::system::error_condition bn( condition.value(), *pc_ );
return pc_->equivalent( code, bn );
}
else if( condition.category() == std::generic_category() || condition.category() == boost::system::generic_category() )
{
boost::system::error_condition bn( condition.value(), boost::system::generic_category() );
return pc_->equivalent( code, bn );
}
#ifndef BOOST_NO_RTTI
else if( std_category const* pc2 = dynamic_cast< std_category const* >( &condition.category() ) )
{
boost::system::error_condition bn( condition.value(), *pc2->pc_ );
return pc_->equivalent( code, bn );
}
#endif
else
{
return default_error_condition( code ) == condition;
}
}
inline bool std_category::equivalent( const std::error_code & code, int condition ) const BOOST_NOEXCEPT
{
if( code.category() == *this )
{
boost::system::error_code bc( code.value(), *pc_ );
return pc_->equivalent( bc, condition );
}
else if( code.category() == std::generic_category() || code.category() == boost::system::generic_category() )
{
boost::system::error_code bc( code.value(), boost::system::generic_category() );
return pc_->equivalent( bc, condition );
}
#ifndef BOOST_NO_RTTI
else if( std_category const* pc2 = dynamic_cast< std_category const* >( &code.category() ) )
{
boost::system::error_code bc( code.value(), *pc2->pc_ );
return pc_->equivalent( bc, condition );
}
#endif
else if( *pc_ == boost::system::generic_category() )
{
return std::generic_category().equivalent( code, condition );
}
else
{
return false;
}
}
} // namespace detail
} // namespace system

View File

@ -0,0 +1,97 @@
#ifndef BOOST_SYSTEM_DETAIL_STD_CATEGORY_IMPL_HPP_INCLUDED
#define BOOST_SYSTEM_DETAIL_STD_CATEGORY_IMPL_HPP_INCLUDED
// Support for interoperability between Boost.System and <system_error>
//
// Copyright 2018, 2021 Peter Dimov
//
// 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)
//
// See library home page at http://www.boost.org/libs/system
#include <boost/system/detail/std_category.hpp>
#include <boost/system/detail/error_condition.hpp>
#include <boost/system/detail/error_code.hpp>
#include <boost/system/detail/generic_category.hpp>
//
namespace boost
{
namespace system
{
namespace detail
{
inline bool std_category::equivalent( int code, const std::error_condition & condition ) const BOOST_NOEXCEPT
{
if( condition.category() == *this )
{
boost::system::error_condition bn( condition.value(), *pc_ );
return pc_->equivalent( code, bn );
}
else if( condition.category() == std::generic_category() || condition.category() == boost::system::generic_category() )
{
boost::system::error_condition bn( condition.value(), boost::system::generic_category() );
return pc_->equivalent( code, bn );
}
#ifndef BOOST_NO_RTTI
else if( std_category const* pc2 = dynamic_cast< std_category const* >( &condition.category() ) )
{
boost::system::error_condition bn( condition.value(), *pc2->pc_ );
return pc_->equivalent( code, bn );
}
#endif
else
{
return default_error_condition( code ) == condition;
}
}
inline bool std_category::equivalent( const std::error_code & code, int condition ) const BOOST_NOEXCEPT
{
if( code.category() == *this )
{
boost::system::error_code bc( code.value(), *pc_ );
return pc_->equivalent( bc, condition );
}
else if( code.category() == std::generic_category() || code.category() == boost::system::generic_category() )
{
boost::system::error_code bc( code.value(), boost::system::generic_category() );
return pc_->equivalent( bc, condition );
}
#ifndef BOOST_NO_RTTI
else if( std_category const* pc2 = dynamic_cast< std_category const* >( &code.category() ) )
{
boost::system::error_code bc( code.value(), *pc2->pc_ );
return pc_->equivalent( bc, condition );
}
#endif
else if( *pc_ == boost::system::generic_category() )
{
return std::generic_category().equivalent( code, condition );
}
else
{
return false;
}
}
} // namespace detail
} // namespace system
} // namespace boost
#endif // #ifndef BOOST_SYSTEM_DETAIL_STD_CATEGORY_IMPL_HPP_INCLUDED

View File

@ -118,6 +118,9 @@ boost_test(TYPE run SOURCES std_interop_test12.cpp)
boost_test(TYPE run SOURCES errc_test4.cpp)
boost_test(TYPE run SOURCES std_interop_test13.cpp)
boost_test(TYPE run SOURCES std_interop_test14.cpp)
# result
set(BOOST_TEST_COMPILE_FEATURES cxx_std_11)

View File

@ -142,6 +142,9 @@ run std_interop_test12.cpp ;
run errc_test4.cpp ;
run std_interop_test13.cpp ;
run std_interop_test14.cpp ;
# result
import ../../config/checks/config : requires ;

View File

@ -0,0 +1,77 @@
// Copyright 2021, 2022 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/system/error_code.hpp>
#include <boost/system/error_category.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/config/pragma_message.hpp>
#include <boost/config.hpp>
#include <cerrno>
#if !defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
BOOST_PRAGMA_MESSAGE( "BOOST_SYSTEM_HAS_SYSTEM_ERROR not defined, test will be skipped" )
int main() {}
#else
#include <system_error>
class my_category_impl: public std::error_category
{
public:
char const* name() const BOOST_NOEXCEPT
{
return "mycat";
}
std::string message( int /*ev*/ ) const
{
return "Unknown error";
}
};
std::error_category const& my_category()
{
static my_category_impl mycat;
return mycat;
}
int main()
{
{
std::error_code e1( 5, boost::system::system_category() );
boost::system::error_code e2( e1 );
std::error_code e3( e2 );
BOOST_TEST_EQ( e1, e3 );
BOOST_TEST_EQ( e1.value(), e3.value() );
BOOST_TEST_EQ( &e1.category(), &e3.category() );
}
{
std::error_code e1( 5, boost::system::generic_category() );
boost::system::error_code e2( e1 );
std::error_code e3( e2 );
BOOST_TEST_EQ( e1, e3 );
BOOST_TEST_EQ( e1.value(), e3.value() );
BOOST_TEST_EQ( &e1.category(), &e3.category() );
}
{
std::error_code e1( 5, my_category() );
boost::system::error_code e2( e1 );
std::error_code e3( e2 );
BOOST_TEST_EQ( e1, e3 );
BOOST_TEST_EQ( e1.value(), e3.value() );
BOOST_TEST_EQ( &e1.category(), &e3.category() );
}
return boost::report_errors();
}
#endif

View File

@ -0,0 +1,57 @@
// Copyright 2021, 2022 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/system/error_code.hpp>
#include <boost/system/error_category.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/config/pragma_message.hpp>
#include <boost/config.hpp>
#include <cerrno>
#if !defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
BOOST_PRAGMA_MESSAGE( "BOOST_SYSTEM_HAS_SYSTEM_ERROR not defined, test will be skipped" )
int main() {}
#else
#include <system_error>
class my_category_impl: public boost::system::error_category
{
public:
char const* name() const BOOST_NOEXCEPT
{
return "mycat";
}
std::string message( int /*ev*/ ) const
{
return "Unknown error";
}
};
boost::system::error_category const& my_category()
{
static my_category_impl mycat;
return mycat;
}
int main()
{
{
boost::system::error_code e1( 5, my_category() );
std::error_code e2( e1 );
boost::system::error_code e3( e2 );
BOOST_TEST_EQ( e1, e3 );
BOOST_TEST_EQ( e1.value(), e3.value() );
BOOST_TEST_EQ( &e1.category(), &e3.category() );
}
return boost::report_errors();
}
#endif