diff --git a/include/boost/system/detail/std_interoperability.hpp b/include/boost/system/detail/std_interoperability.hpp index 05fceb9..f52e99e 100644 --- a/include/boost/system/detail/std_interoperability.hpp +++ b/include/boost/system/detail/std_interoperability.hpp @@ -30,8 +30,20 @@ private: public: - explicit std_category( boost::system::error_category const * pc ): pc_( pc ) + explicit std_category( boost::system::error_category const * pc, unsigned id ): pc_( pc ) { + if( id != 0 ) + { +#if defined(_MSC_VER) && defined(_CPPLIB_VER) && _MSC_VER >= 1900 && _MSC_VER < 2000 + + // Poking into the protected _Addr member of std::error_category + // is not a particularly good programming practice, but what can + // you do + + _Addr = id; + +#endif + } } virtual const char * name() const BOOST_NOEXCEPT @@ -55,24 +67,45 @@ public: inline std::error_category const & to_std_category( boost::system::error_category const & cat ) BOOST_SYMBOL_VISIBLE; +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 ) { - typedef std::map< boost::system::error_category const *, std::unique_ptr > map_type; - - static map_type map_; - - map_type::iterator i = map_.find( &cat ); - - if( i == map_.end() ) + if( cat == boost::system::system_category() ) { - std::unique_ptr p( new std_category( &cat ) ); - - std::pair r = map_.insert( map_type::value_type( &cat, std::move( p ) ) ); - - i = r.first; + static const std_category system_instance( &cat, 0x1F4D7 ); + return system_instance; } + else if( cat == boost::system::generic_category() ) + { + 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; - return *i->second; + static map_type map_; + + 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 diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 92ab1fd..b428ca0 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -68,4 +68,4 @@ lib std_single_instance_lib2 : std_single_instance_2.cpp : shared: system-run std_single_instance_test.cpp std_single_instance_1.cpp std_single_instance_2.cpp ; run std_single_instance_test.cpp std_single_instance_lib1 std_single_instance_lib2 : : : static : std_single_instance_lib_static ; -run std_single_instance_test.cpp std_single_instance_lib1 std_single_instance_lib2 : : : shared : std_single_instance_lib_shared ; +run std_single_instance_test.cpp std_single_instance_lib1 std_single_instance_lib2 : : : shared STD_SINGLE_INSTANCE_SHARED : std_single_instance_lib_shared ; diff --git a/test/std_single_instance_1.cpp b/test/std_single_instance_1.cpp index 3a73e7e..6986146 100644 --- a/test/std_single_instance_1.cpp +++ b/test/std_single_instance_1.cpp @@ -31,4 +31,10 @@ EXPORT std::error_code get_generic_code() } // namespace lib1 +#else + +EXPORT void lib1_f() +{ +} + #endif diff --git a/test/std_single_instance_2.cpp b/test/std_single_instance_2.cpp index bcedd5f..960b3ca 100644 --- a/test/std_single_instance_2.cpp +++ b/test/std_single_instance_2.cpp @@ -31,4 +31,10 @@ EXPORT std::error_code get_generic_code() } // namespace lib2 +#else + +EXPORT void lib2_f() +{ +} + #endif diff --git a/test/std_single_instance_test.cpp b/test/std_single_instance_test.cpp index 19da8da..c5fe710 100644 --- a/test/std_single_instance_test.cpp +++ b/test/std_single_instance_test.cpp @@ -4,11 +4,31 @@ #include #include +#include #if !defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR) BOOST_PRAGMA_MESSAGE( "BOOST_SYSTEM_HAS_SYSTEM_ERROR not defined, test will be skipped" ) +int main() {} +#elif defined(STD_SINGLE_INSTANCE_SHARED) && defined(__CYGWIN__) + +BOOST_PRAGMA_MESSAGE( "Skipping Windows/DLL test, __CYGWIN__" ) +int main() {} + +#elif defined(STD_SINGLE_INSTANCE_SHARED) && defined(_WIN32) && !defined(_MSC_VER) + +BOOST_PRAGMA_MESSAGE( "Skipping Windows/DLL test, no _MSC_VER" ) +int main() {} + +#elif defined(STD_SINGLE_INSTANCE_SHARED) && defined(_WIN32) && !defined(_CPPLIB_VER) + +BOOST_PRAGMA_MESSAGE( "Skipping Windows/DLL test, no _CPPLIB_VER" ) +int main() {} + +#elif defined(STD_SINGLE_INSTANCE_SHARED) && defined(_WIN32) && (_MSC_VER < 1900 || _MSC_VER >= 2000) + +BOOST_PRAGMA_MESSAGE( "Skipping Windows/DLL test, _MSC_VER is " BOOST_STRINGIZE(_MSC_VER) ) int main() {} #else