From f4e4f92dae96a3c92b2075d8c9081e83e76da8b2 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 3 Aug 2010 01:17:38 +0000 Subject: [PATCH] Move type registration into module code, and fix problems with unloading of modules and type conversions registered inside of a module. We have to allow the same type registration more than once now, just in case several different modules register the same conversion. --- CMakeLists.txt | 7 +-- .../chaiscript/dispatchkit/dispatchkit.hpp | 31 +++++++++++- .../dispatchkit/dynamic_cast_conversion.hpp | 50 +++++++++++++------ src/test_module.cpp | 29 +++++++++++ 4 files changed, 98 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f88aa4..9c23f4a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,9 +76,6 @@ add_executable(chai src/main.cpp) #add_executable(dispatchkit_test contrib/test/dispatchkit_test.cpp) target_link_libraries(chai ${DYNAMIC_LOADER} ${Boost_LIBRARIES} ${READLINE_LIB}) -add_library(test_module MODULE src/test_module.cpp) -target_link_libraries(test_module ${Boost_LIBRARIES}) - add_library(stl_extra MODULE src/stl_extra.cpp) target_link_libraries(stl_extra ${Boost_LIBRARIES}) @@ -105,6 +102,10 @@ IF(BUILD_TESTING) target_link_libraries(dynamic_object_test ${DYNAMIC_LOADER} ${Boost_LIBRARIES} ${READLINE_LIB}) add_test(NAME Dynamic_Object_Test COMMAND dynamic_object_test) + add_library(test_module MODULE src/test_module.cpp) + target_link_libraries(test_module ${Boost_LIBRARIES}) + + install(TARGETS test_module RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript) ENDIF(BUILD_TESTING) install(TARGETS chai stl_extra test_module RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript ) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 9c2e5d0..e617430 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -37,6 +37,12 @@ namespace chaiscript return *this; } + Module &add(const Dynamic_Cast_Conversion &d) + { + m_conversions.push_back(d); + return *this; + } + Module &add(const Proxy_Function &f, const std::string &name) { m_funcs.push_back(std::make_pair(f, name)); @@ -63,12 +69,14 @@ namespace chaiscript apply(m_typeinfos.begin(), m_typeinfos.end(), t_engine); apply(m_funcs.begin(), m_funcs.end(), t_engine); apply_eval(m_evals.begin(), m_evals.end(), t_eval); + apply_single(m_conversions.begin(), m_conversions.end(), t_engine); } private: std::vector > m_typeinfos; std::vector > m_funcs; std::vector m_evals; + std::vector m_conversions; template void apply(InItr begin, InItr end, T &t) const @@ -80,6 +88,16 @@ namespace chaiscript } } + template + void apply_single(InItr begin, InItr end, T &t) const + { + while (begin != end) + { + t.add(*begin); + ++begin; + } + } + template void apply_eval(InItr begin, InItr end, T &t) const { @@ -89,8 +107,6 @@ namespace chaiscript ++begin; } } - - }; typedef boost::shared_ptr ModulePtr; @@ -213,9 +229,19 @@ namespace chaiscript ~Dispatch_Engine() { + detail::Dynamic_Conversions::get().cleanup(m_conversions.begin(), m_conversions.end()); Boxed_Value::clear_cache(); } + /** + * Add a new conversion for upcasting to a base class + */ + void add(const Dynamic_Cast_Conversion &d) + { + m_conversions.push_back(d); + return detail::Dynamic_Conversions::get().add_conversion(d); + } + /** * Add a new named Proxy_Function to the system */ @@ -755,6 +781,7 @@ namespace chaiscript std::multimap function_cache; }; + std::vector m_conversions; chaiscript::threading::Thread_Storage m_stack_holder; diff --git a/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp b/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp index 12ad4bc..0488147 100644 --- a/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp +++ b/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp @@ -116,6 +116,7 @@ namespace chaiscript } }; + class Dynamic_Conversions { public: @@ -126,19 +127,38 @@ namespace chaiscript } template - void add_conversion() - { + static boost::shared_ptr create() + { + return boost::shared_ptr(new Dynamic_Conversion_Impl()); + + } + + template + void cleanup(InItr begin, const InItr &end) + { #ifndef CHAISCRIPT_NO_THREADS - boost::unique_lock l(m_mutex); + boost::unique_lock l(m_mutex); #endif - if (find(user_type(), user_type()) == m_conversions.end()) + while (begin != end) + { + if (begin->unique()) { - m_conversions.push_back( - boost::shared_ptr(new Dynamic_Conversion_Impl()) - ); + m_conversions.erase(begin->get()); } + + ++begin; } + } + + void add_conversion(const boost::shared_ptr &conversion) + { +#ifndef CHAISCRIPT_NO_THREADS + boost::unique_lock l(m_mutex); +#endif + + m_conversions.insert(conversion.get()); + } bool has_conversion(const Type_Info &base, const Type_Info &derived) { @@ -150,13 +170,13 @@ namespace chaiscript } - boost::shared_ptr get_conversion(const Type_Info &base, const Type_Info &derived) + Dynamic_Conversion *get_conversion(const Type_Info &base, const Type_Info &derived) { #ifndef CHAISCRIPT_NO_THREADS boost::shared_lock l(m_mutex); #endif - std::vector >::const_iterator itr = + std::set::const_iterator itr = find(base, derived); if (itr != m_conversions.end()) @@ -170,10 +190,10 @@ namespace chaiscript private: Dynamic_Conversions() {} - std::vector >::const_iterator find( + std::set::const_iterator find( const Type_Info &base, const Type_Info &derived) { - for (std::vector >::const_iterator itr = m_conversions.begin(); + for (std::set::const_iterator itr = m_conversions.begin(); itr != m_conversions.end(); ++itr) { @@ -188,12 +208,14 @@ namespace chaiscript #ifndef CHAISCRIPT_NO_THREADS boost::shared_mutex m_mutex; #endif - std::vector > m_conversions; + std::set m_conversions; }; } + typedef boost::shared_ptr Dynamic_Cast_Conversion; + template - void register_base_class() + Dynamic_Cast_Conversion base_class() { //Can only be used with related polymorphic types //may be expanded some day to support conversions other than child -> parent @@ -201,7 +223,7 @@ namespace chaiscript BOOST_STATIC_ASSERT(boost::is_polymorphic::value); BOOST_STATIC_ASSERT(boost::is_polymorphic::value); - detail::Dynamic_Conversions::get().add_conversion(); + return detail::Dynamic_Conversions::create(); } template diff --git a/src/test_module.cpp b/src/test_module.cpp index 8acc9c6..91d30bd 100644 --- a/src/test_module.cpp +++ b/src/test_module.cpp @@ -2,6 +2,21 @@ #include #include +class TestBaseType +{ + public: + virtual ~TestBaseType() {} + virtual int func() { return 0; } + +}; + +class TestDerivedType : public TestBaseType +{ + public: + virtual ~TestDerivedType() {} + virtual int func() { return 1; } +}; + std::string hello_world() { return "Hello World"; @@ -12,5 +27,19 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo chaiscript::ModulePtr m(new chaiscript::Module()); m->add(chaiscript::fun(hello_world), "hello_world"); + + m->add(chaiscript::user_type(), "TestBaseType"); + m->add(chaiscript::user_type(), "TestDerivedType"); + + m->add(chaiscript::constructor(), "TestBaseType"); + m->add(chaiscript::constructor(), "TestBaseType"); + + m->add(chaiscript::constructor(), "TestDerivedType"); + m->add(chaiscript::constructor(), "TestDerivedType"); + + m->add(chaiscript::base_class()); + + m->add(chaiscript::fun(&TestBaseType::func), "func"); + return m; }