diff --git a/include/chaiscript/dispatchkit/boxed_cast.hpp b/include/chaiscript/dispatchkit/boxed_cast.hpp index f2074d9..1fc5755 100644 --- a/include/chaiscript/dispatchkit/boxed_cast.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast.hpp @@ -86,7 +86,7 @@ namespace chaiscript #pragma warning(disable : 4127) #endif - if ( /*std::is_polymorphic::type>::value && */ t_conversions) + if (t_conversions && t_conversions->convertable_type()) { try { // std::cout << "trying an up conversion " << typeid(Type).name() << std::endl; diff --git a/include/chaiscript/dispatchkit/type_conversions.hpp b/include/chaiscript/dispatchkit/type_conversions.hpp index 3d6da1b..574f80c 100644 --- a/include/chaiscript/dispatchkit/type_conversions.hpp +++ b/include/chaiscript/dispatchkit/type_conversions.hpp @@ -7,6 +7,7 @@ #ifndef CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_ #define CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_ +#include #include #include #include @@ -203,22 +204,53 @@ namespace chaiscript class Type_Conversions { public: + struct Less_Than + { + bool operator()(const std::type_info *t_lhs, const std::type_info *t_rhs) const + { + return *t_lhs != *t_rhs && t_lhs->before(*t_rhs); + } + }; + Type_Conversions() + : m_num_types(0), + m_thread_cache(this) { } Type_Conversions(const Type_Conversions &t_other) - : m_conversions(t_other.get_conversions()) + : m_conversions(t_other.get_conversions()), m_num_types(m_conversions.size()), + m_thread_cache(this) { } + const std::set &thread_cache() const + { + auto &cache = *m_thread_cache; + if (cache.size() != m_num_types) + { + chaiscript::detail::threading::shared_lock l(m_mutex); + cache = m_convertableTypes; + } + + return cache; + } + void add_conversion(const std::shared_ptr &conversion) { chaiscript::detail::threading::unique_lock l(m_mutex); /// \todo error if a conversion already exists m_conversions.insert(conversion); + m_convertableTypes.insert({conversion->to().bare_type_info(), conversion->from().bare_type_info()}); + m_num_types = m_convertableTypes.size(); } + template + bool convertable_type() const + { + return thread_cache().count(user_type().bare_type_info()) != 0; + } + template bool converts() const { @@ -227,7 +259,14 @@ namespace chaiscript bool converts(const Type_Info &to, const Type_Info &from) const { - return has_conversion(to, from) || has_conversion(from, to); + const auto &types = thread_cache(); + if (types.count(to.bare_type_info()) != 0 && types.count(to.bare_type_info()) != 0) + { + return has_conversion(to, from) || has_conversion(from, to); + } else { + return false; + } + } template @@ -294,8 +333,12 @@ namespace chaiscript return m_conversions; } + mutable chaiscript::detail::threading::shared_mutex m_mutex; std::set> m_conversions; + std::set m_convertableTypes; + std::atomic_size_t m_num_types; + chaiscript::detail::threading::Thread_Storage> m_thread_cache; }; typedef std::shared_ptr Type_Conversion; diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index 3e129e4..2cf6455 100644 --- a/include/chaiscript/dispatchkit/type_info.hpp +++ b/include/chaiscript/dispatchkit/type_info.hpp @@ -111,6 +111,11 @@ namespace chaiscript } } + CHAISCRIPT_CONSTEXPR const std::type_info *bare_type_info() const + { + return m_bare_type_info; + } + private: const std::type_info *m_type_info; const std::type_info *m_bare_type_info;