error_category.hpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. #ifndef BOOST_SYSTEM_DETAIL_ERROR_CATEGORY_HPP_INCLUDED
  2. #define BOOST_SYSTEM_DETAIL_ERROR_CATEGORY_HPP_INCLUDED
  3. // Copyright Beman Dawes 2006, 2007
  4. // Copyright Christoper Kohlhoff 2007
  5. // Copyright Peter Dimov 2017, 2018
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. // See library home page at http://www.boost.org/libs/system
  11. #include <boost/system/detail/config.hpp>
  12. #include <boost/cstdint.hpp>
  13. #include <boost/config.hpp>
  14. #include <boost/config/workaround.hpp>
  15. #include <string>
  16. #include <functional>
  17. #include <cstddef>
  18. #include <system_error>
  19. #include <atomic>
  20. namespace boost
  21. {
  22. namespace system
  23. {
  24. class error_category;
  25. class error_code;
  26. class error_condition;
  27. std::size_t hash_value( error_code const & ec );
  28. namespace detail
  29. {
  30. BOOST_SYSTEM_CONSTEXPR bool failed_impl( int ev, error_category const & cat );
  31. class std_category;
  32. } // namespace detail
  33. #if ( defined( BOOST_GCC ) && BOOST_GCC >= 40600 ) || defined( BOOST_CLANG )
  34. #pragma GCC diagnostic push
  35. #pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
  36. #endif
  37. #if defined(BOOST_MSVC) && BOOST_MSVC < 1900
  38. #pragma warning(push)
  39. #pragma warning(disable: 4351) // new behavior: elements of array will be default initialized
  40. #endif
  41. class BOOST_SYMBOL_VISIBLE error_category
  42. {
  43. private:
  44. friend std::size_t hash_value( error_code const & ec );
  45. friend BOOST_SYSTEM_CONSTEXPR bool detail::failed_impl( int ev, error_category const & cat );
  46. friend class error_code;
  47. friend class error_condition;
  48. public:
  49. error_category( error_category const & ) = delete;
  50. error_category& operator=( error_category const & ) = delete;
  51. private:
  52. boost::ulong_long_type id_;
  53. static std::size_t const stdcat_size_ = 4 * sizeof( void const* );
  54. union
  55. {
  56. mutable unsigned char stdcat_[ stdcat_size_ ];
  57. void const* stdcat_align_;
  58. };
  59. mutable std::atomic< unsigned > sc_init_;
  60. protected:
  61. ~error_category() = default;
  62. constexpr error_category() noexcept: id_( 0 ), stdcat_(), sc_init_()
  63. {
  64. }
  65. explicit constexpr error_category( boost::ulong_long_type id ) noexcept: id_( id ), stdcat_(), sc_init_()
  66. {
  67. }
  68. public:
  69. virtual const char * name() const noexcept = 0;
  70. virtual error_condition default_error_condition( int ev ) const noexcept;
  71. virtual bool equivalent( int code, const error_condition & condition ) const noexcept;
  72. virtual bool equivalent( const error_code & code, int condition ) const noexcept;
  73. virtual std::string message( int ev ) const = 0;
  74. virtual char const * message( int ev, char * buffer, std::size_t len ) const noexcept;
  75. virtual bool failed( int ev ) const noexcept
  76. {
  77. return ev != 0;
  78. }
  79. friend BOOST_SYSTEM_CONSTEXPR bool operator==( error_category const & lhs, error_category const & rhs ) noexcept
  80. {
  81. return rhs.id_ == 0? &lhs == &rhs: lhs.id_ == rhs.id_;
  82. }
  83. friend BOOST_SYSTEM_CONSTEXPR bool operator!=( error_category const & lhs, error_category const & rhs ) noexcept
  84. {
  85. return !( lhs == rhs );
  86. }
  87. friend BOOST_SYSTEM_CONSTEXPR bool operator<( error_category const & lhs, error_category const & rhs ) noexcept
  88. {
  89. if( lhs.id_ < rhs.id_ )
  90. {
  91. return true;
  92. }
  93. if( lhs.id_ > rhs.id_ )
  94. {
  95. return false;
  96. }
  97. if( rhs.id_ != 0 )
  98. {
  99. return false; // equal
  100. }
  101. return std::less<error_category const *>()( &lhs, &rhs );
  102. }
  103. void init_stdcat() const;
  104. # if defined(__SUNPRO_CC) // trailing __global is not supported
  105. operator std::error_category const & () const;
  106. # else
  107. operator std::error_category const & () const BOOST_SYMBOL_VISIBLE;
  108. # endif
  109. };
  110. #if defined(BOOST_MSVC) && BOOST_MSVC < 1900
  111. #pragma warning(pop)
  112. #endif
  113. #if ( defined( BOOST_GCC ) && BOOST_GCC >= 40600 ) || defined( BOOST_CLANG )
  114. #pragma GCC diagnostic pop
  115. #endif
  116. namespace detail
  117. {
  118. static const boost::ulong_long_type generic_category_id = ( boost::ulong_long_type( 0xB2AB117A ) << 32 ) + 0x257EDFD0;
  119. static const boost::ulong_long_type system_category_id = generic_category_id + 1;
  120. static const boost::ulong_long_type interop_category_id = generic_category_id + 2;
  121. BOOST_SYSTEM_CONSTEXPR inline bool failed_impl( int ev, error_category const & cat )
  122. {
  123. if( cat.id_ == system_category_id || cat.id_ == generic_category_id )
  124. {
  125. return ev != 0;
  126. }
  127. else
  128. {
  129. return cat.failed( ev );
  130. }
  131. }
  132. } // namespace detail
  133. } // namespace system
  134. } // namespace boost
  135. #endif // #ifndef BOOST_SYSTEM_DETAIL_ERROR_CATEGORY_HPP_INCLUDED