From 04bfb05b19c0f74edec7130454b46a7477a45600 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sat, 12 Jun 2021 04:29:13 +0300 Subject: [PATCH] Improve the implementation of the std::category conversion --- include/boost/system/detail/config.hpp | 12 +--- .../boost/system/detail/error_category.hpp | 25 ++++---- .../system/detail/error_category_impl.hpp | 33 +++++++++- .../{to_std_category.hpp => std_category.hpp} | 60 ++----------------- 4 files changed, 51 insertions(+), 79 deletions(-) rename include/boost/system/detail/{to_std_category.hpp => std_category.hpp} (68%) diff --git a/include/boost/system/detail/config.hpp b/include/boost/system/detail/config.hpp index 1417237..f6c7062 100644 --- a/include/boost/system/detail/config.hpp +++ b/include/boost/system/detail/config.hpp @@ -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 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 diff --git a/include/boost/system/detail/error_category.hpp b/include/boost/system/detail/error_category.hpp index 5aa0c38..b44dd4d 100644 --- a/include/boost/system/detail/error_category.hpp +++ b/include/boost/system/detail/error_category.hpp @@ -19,6 +19,7 @@ #if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR) # include +# include #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_() { } diff --git a/include/boost/system/detail/error_category_impl.hpp b/include/boost/system/detail/error_category_impl.hpp index 35cba4b..9ab0e49 100644 --- a/include/boost/system/detail/error_category_impl.hpp +++ b/include/boost/system/detail/error_category_impl.hpp @@ -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 +#include 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) diff --git a/include/boost/system/detail/to_std_category.hpp b/include/boost/system/detail/std_category.hpp similarity index 68% rename from include/boost/system/detail/to_std_category.hpp rename to include/boost/system/detail/std_category.hpp index 3151f5c..e8f70e1 100644 --- a/include/boost/system/detail/to_std_category.hpp +++ b/include/boost/system/detail/std_category.hpp @@ -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 // -// 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 #include #include -#include -#include -#include // @@ -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, cat_ptr_less > map_type; - - static map_type map_; - static std::mutex map_mx_; - - std::lock_guard guard( map_mx_ ); - - map_type::iterator i = map_.find( &cat ); - - if( i == map_.end() ) - { - std::unique_ptr p( new std_category( &cat, 0 ) ); - - std::pair 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