Improve the implementation of the std::category conversion

This commit is contained in:
Peter Dimov
2021-06-12 04:29:13 +03:00
parent a650f5d676
commit 04bfb05b19
4 changed files with 51 additions and 79 deletions

View File

@ -13,20 +13,10 @@
// BOOST_SYSTEM_HAS_SYSTEM_ERROR
#if !defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR)
#if !defined(BOOST_NO_CXX11_HDR_SYSTEM_ERROR) && !defined(BOOST_NO_CXX11_HDR_ATOMIC)
# define BOOST_SYSTEM_HAS_SYSTEM_ERROR
#endif
#if BOOST_WORKAROUND(BOOST_GCC, < 40600)
// g++ 4.4's <map> is not good enough
# undef BOOST_SYSTEM_HAS_SYSTEM_ERROR
#endif
#if defined(BOOST_NO_CXX11_HDR_MUTEX)
// Required for thread-safe map manipulation
# undef BOOST_SYSTEM_HAS_SYSTEM_ERROR
#endif
// BOOST_SYSTEM_NOEXCEPT
// Retained for backward compatibility

View File

@ -19,6 +19,7 @@
#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
# include <system_error>
# include <atomic>
#endif
namespace boost
@ -38,11 +39,7 @@ namespace detail
BOOST_SYSTEM_CONSTEXPR bool failed_impl( int ev, error_category const & cat );
#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
std::error_category const & to_std_category( error_category const & cat );
#endif
class std_category;
} // namespace detail
@ -58,10 +55,6 @@ private:
friend std::size_t hash_value( error_code const & ec );
friend BOOST_SYSTEM_CONSTEXPR bool detail::failed_impl( int ev, error_category const & cat );
#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
friend std::error_category const & detail::to_std_category( error_category const & cat );
#endif
#if !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS)
public:
@ -80,6 +73,16 @@ private:
boost::ulong_long_type id_;
#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
mutable std::atomic< boost::system::detail::std_category* > ps_;
#else
boost::system::detail::std_category* ps_;
#endif
protected:
#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) && !defined(BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS)
@ -97,11 +100,11 @@ protected:
#endif
BOOST_SYSTEM_CONSTEXPR error_category() BOOST_NOEXCEPT: id_( 0 )
BOOST_SYSTEM_CONSTEXPR error_category() BOOST_NOEXCEPT: id_( 0 ), ps_()
{
}
explicit BOOST_SYSTEM_CONSTEXPR error_category( boost::ulong_long_type id ) BOOST_NOEXCEPT: id_( id )
explicit BOOST_SYSTEM_CONSTEXPR error_category( boost::ulong_long_type id ) BOOST_NOEXCEPT: id_( id ), ps_()
{
}

View File

@ -96,11 +96,40 @@ inline char const * error_category::message( int ev, char * buffer, std::size_t
#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
#include <boost/system/detail/to_std_category.hpp>
#include <boost/system/detail/std_category.hpp>
inline boost::system::error_category::operator std::error_category const & () const
{
return boost::system::detail::to_std_category( *this );
if( id_ == boost::system::detail::system_category_id )
{
static const boost::system::detail::std_category system_instance( this, 0x1F4D7 );
return system_instance;
}
if( id_ == boost::system::detail::generic_category_id )
{
static const boost::system::detail::std_category generic_instance( this, 0x1F4D3 );
return generic_instance;
}
boost::system::detail::std_category* p = ps_.load( std::memory_order_acquire );
if( p != 0 )
{
return *p;
}
boost::system::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 ) )
{
return *q;
}
else
{
delete q;
return *p;
}
}
#endif // #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)

View File

@ -1,9 +1,9 @@
#ifndef BOOST_SYSTEM_DETAIL_TO_STD_CATEGORY_HPP_INCLUDED
#define BOOST_SYSTEM_DETAIL_TO_STD_CATEGORY_HPP_INCLUDED
#ifndef BOOST_SYSTEM_DETAIL_STD_CATEGORY_HPP_INCLUDED
#define BOOST_SYSTEM_DETAIL_STD_CATEGORY_HPP_INCLUDED
// Support for interoperability between Boost.System and <system_error>
//
// Copyright 2018 Peter Dimov
// 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)
@ -15,9 +15,6 @@
#include <boost/system/detail/error_code.hpp>
#include <boost/system/detail/generic_category.hpp>
#include <system_error>
#include <map>
#include <memory>
#include <mutex>
//
@ -73,54 +70,6 @@ public:
bool equivalent( const std::error_code & code, int condition ) const BOOST_NOEXCEPT BOOST_OVERRIDE;
};
#if !defined(__SUNPRO_CC) // trailing __global is not supported
inline std::error_category const & to_std_category( boost::system::error_category const & cat ) BOOST_SYMBOL_VISIBLE;
#endif
struct cat_ptr_less
{
bool operator()( boost::system::error_category const * p1, boost::system::error_category const * p2 ) const BOOST_NOEXCEPT
{
return *p1 < *p2;
}
};
inline std::error_category const & to_std_category( boost::system::error_category const & cat )
{
if( cat.id_ == boost::system::detail::system_category_id )
{
static const std_category system_instance( &cat, 0x1F4D7 );
return system_instance;
}
else if( cat.id_ == boost::system::detail::generic_category_id )
{
static const std_category generic_instance( &cat, 0x1F4D3 );
return generic_instance;
}
else
{
typedef std::map< boost::system::error_category const *, std::unique_ptr<std_category>, cat_ptr_less > map_type;
static map_type map_;
static std::mutex map_mx_;
std::lock_guard<std::mutex> guard( map_mx_ );
map_type::iterator i = map_.find( &cat );
if( i == map_.end() )
{
std::unique_ptr<std_category> p( new std_category( &cat, 0 ) );
std::pair<map_type::iterator, bool> r = map_.insert( map_type::value_type( &cat, std::move( p ) ) );
i = r.first;
}
return *i->second;
}
}
inline bool std_category::equivalent( int code, const std::error_condition & condition ) const BOOST_NOEXCEPT
{
if( condition.category() == *this )
@ -170,6 +119,7 @@ inline bool std_category::equivalent( const std::error_code & code, int conditio
boost::system::error_code bc( code.value(), *pc2->pc_ );
return pc_->equivalent( bc, condition );
}
#endif
else if( *pc_ == boost::system::generic_category() )
@ -188,4 +138,4 @@ inline bool std_category::equivalent( const std::error_code & code, int conditio
} // namespace boost
#endif // #ifndef BOOST_SYSTEM_DETAIL_TO_STD_CATEGORY_HPP_INCLUDED
#endif // #ifndef BOOST_SYSTEM_DETAIL_STD_CATEGORY_HPP_INCLUDED