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.
This commit is contained in:
Jason Turner
2010-08-03 01:17:38 +00:00
parent 4358564065
commit f4e4f92dae
4 changed files with 98 additions and 19 deletions

View File

@@ -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<std::pair<Type_Info, std::string> > m_typeinfos;
std::vector<std::pair<Proxy_Function, std::string> > m_funcs;
std::vector<std::string> m_evals;
std::vector<Dynamic_Cast_Conversion> m_conversions;
template<typename T, typename InItr>
void apply(InItr begin, InItr end, T &t) const
@@ -80,6 +88,16 @@ namespace chaiscript
}
}
template<typename T, typename InItr>
void apply_single(InItr begin, InItr end, T &t) const
{
while (begin != end)
{
t.add(*begin);
++begin;
}
}
template<typename T, typename InItr>
void apply_eval(InItr begin, InItr end, T &t) const
{
@@ -89,8 +107,6 @@ namespace chaiscript
++begin;
}
}
};
typedef boost::shared_ptr<Module> 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<std::string, Proxy_Function> function_cache;
};
std::vector<Dynamic_Cast_Conversion> m_conversions;
chaiscript::threading::Thread_Storage<Stack_Holder> m_stack_holder;

View File

@@ -116,6 +116,7 @@ namespace chaiscript
}
};
class Dynamic_Conversions
{
public:
@@ -126,19 +127,38 @@ namespace chaiscript
}
template<typename Base, typename Derived>
void add_conversion()
{
static boost::shared_ptr<Dynamic_Conversion> create()
{
return boost::shared_ptr<Dynamic_Conversion>(new Dynamic_Conversion_Impl<Base, Derived>());
}
template<typename InItr>
void cleanup(InItr begin, const InItr &end)
{
#ifndef CHAISCRIPT_NO_THREADS
boost::unique_lock<boost::shared_mutex> l(m_mutex);
boost::unique_lock<boost::shared_mutex> l(m_mutex);
#endif
if (find(user_type<Base>(), user_type<Derived>()) == m_conversions.end())
while (begin != end)
{
if (begin->unique())
{
m_conversions.push_back(
boost::shared_ptr<Dynamic_Conversion>(new Dynamic_Conversion_Impl<Base, Derived>())
);
m_conversions.erase(begin->get());
}
++begin;
}
}
void add_conversion(const boost::shared_ptr<Dynamic_Conversion> &conversion)
{
#ifndef CHAISCRIPT_NO_THREADS
boost::unique_lock<boost::shared_mutex> 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<Dynamic_Conversion> 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<boost::shared_mutex> l(m_mutex);
#endif
std::vector<boost::shared_ptr<Dynamic_Conversion> >::const_iterator itr =
std::set<Dynamic_Conversion *>::const_iterator itr =
find(base, derived);
if (itr != m_conversions.end())
@@ -170,10 +190,10 @@ namespace chaiscript
private:
Dynamic_Conversions() {}
std::vector<boost::shared_ptr<Dynamic_Conversion> >::const_iterator find(
std::set<Dynamic_Conversion *>::const_iterator find(
const Type_Info &base, const Type_Info &derived)
{
for (std::vector<boost::shared_ptr<Dynamic_Conversion> >::const_iterator itr = m_conversions.begin();
for (std::set<Dynamic_Conversion *>::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<boost::shared_ptr<Dynamic_Conversion> > m_conversions;
std::set<Dynamic_Conversion *> m_conversions;
};
}
typedef boost::shared_ptr<chaiscript::detail::Dynamic_Conversion> Dynamic_Cast_Conversion;
template<typename Base, typename Derived>
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<Base>::value);
BOOST_STATIC_ASSERT(boost::is_polymorphic<Derived>::value);
detail::Dynamic_Conversions::get().add_conversion<Base, Derived>();
return detail::Dynamic_Conversions::create<Base, Derived>();
}
template<typename Base, typename Derived>