Speeding up the startup initialization by using proper type maps for GSI.

This commit is contained in:
Matthias Koefferlein 2017-09-03 11:52:06 +02:00
parent 9d5f54d51a
commit 6c26b2a251
3 changed files with 105 additions and 32 deletions

View File

@ -1018,13 +1018,7 @@ const ClassBase *cls_decl ()
// piece of code at the same time and they interfere when storing the results.
static const ClassBase *cd = 0;
if (! cd) {
for (ClassBase::class_iterator c = ClassBase::begin_classes (); c != ClassBase::end_classes (); ++c) {
if (c->declaration () == &*c && c->is_of_type (typeid (X))) {
// assert: duplicate declaration objects for that class
tl_assert (cd == 0);
cd = &*c;
}
}
cd = class_by_typeinfo_no_assert (typeid (X));
if (!cd) {
cd = fallback_cls_decl (typeid (X));
}

View File

@ -489,46 +489,109 @@ ClassBase::add_method (MethodBase *method, bool /*base_class*/)
m_methods.add_method (method);
}
// TODO: thread-safe? Unlikely that multiple threads access this member -
// we do a initial scan and after this no more write access here.
static std::map<std::string, const ClassBase *> s_name_to_class;
const ClassBase *class_by_name_no_assert (const std::string &name)
{
if (s_name_to_class.empty ()) {
for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_classes (); c != gsi::ClassBase::end_classes (); ++c) {
if (c->declaration () != c.operator-> ()) {
continue;
}
if (!s_name_to_class.insert (std::make_pair (c->name (), c.operator-> ())).second) {
// Duplicate registration of this class
tl::error << "Duplicate registration of class " << c->name ();
tl_assert (false);
}
}
}
std::map<std::string, const ClassBase *>::const_iterator c = s_name_to_class.find (name);
if (c != s_name_to_class.end ()) {
return c->second;
} else {
return 0;
}
}
const ClassBase *class_by_name (const std::string &name)
{
for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_classes (); c != gsi::ClassBase::end_classes (); ++c) {
if (c->declaration () == &*c && c->name () == name) {
return &*c;
}
}
// No class with that name
tl_assert (false);
const ClassBase *cd = class_by_name_no_assert (name);
tl_assert (cd != 0);
return cd;
}
bool has_class (const std::string &name)
{
for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_classes (); c != gsi::ClassBase::end_classes (); ++c) {
if (c->declaration () == &*c && c->name () == name) {
return true;
}
return class_by_name (name) != 0;
}
namespace
{
struct type_info_compare
{
bool operator() (const std::type_info *a, const std::type_info *b) const
{
return a->before (*b);
}
};
}
// TODO: thread-safe? Unlikely that multiple threads access this member -
// we do a initial scan and after this no more write access here.
static std::map<const std::type_info *, const ClassBase *, type_info_compare> s_ti_to_class;
const ClassBase *class_by_typeinfo_no_assert (const std::type_info &ti)
{
if (s_ti_to_class.empty ()) {
for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_classes (); c != gsi::ClassBase::end_classes (); ++c) {
if (c->declaration () != c.operator-> ()) {
continue;
}
const std::type_info *ti = c->adapted_type_info ();
if (! ti) {
ti = &c->type ();
}
if (ti && c->is_of_type (*ti) && !s_ti_to_class.insert (std::make_pair (ti, c.operator-> ())).second) {
// Duplicate registration of this class
tl::error << "Duplicate registration of class " << c->name () << " (type " << ti->name () << ")";
tl_assert (false);
}
}
}
std::map<const std::type_info *, const ClassBase *, type_info_compare>::const_iterator c = s_ti_to_class.find (&ti);
if (c != s_ti_to_class.end ()) {
return c->second;
} else {
return 0;
}
return false;
}
const ClassBase *class_by_typeinfo (const std::type_info &ti)
{
for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_classes (); c != gsi::ClassBase::end_classes (); ++c) {
if (c->declaration () == &*c && c->is_of_type (ti)) {
return &*c;
}
}
// No class with that type
tl_assert (false);
const ClassBase *cd = class_by_typeinfo_no_assert (ti);
tl_assert (cd != 0);
return cd;
}
bool has_class (const std::type_info &ti)
{
for (gsi::ClassBase::class_iterator c = gsi::ClassBase::begin_classes (); c != gsi::ClassBase::end_classes (); ++c) {
if (c->declaration () == &*c && c->is_of_type (ti)) {
return true;
}
}
return false;
return class_by_typeinfo_no_assert (ti) != 0;
}
}

View File

@ -584,6 +584,14 @@ private:
*/
GSI_PUBLIC const ClassBase *class_by_name (const std::string &name);
/**
* @brief Accessor to a declaration through name
*
* This version won't assert when there is no such class and
* return 0 instead.
*/
GSI_PUBLIC const ClassBase *class_by_name_no_assert (const std::string &name);
/**
* @brief Returns true if there is a class with the given name
*/
@ -594,6 +602,14 @@ GSI_PUBLIC bool has_class (const std::string &name);
*/
GSI_PUBLIC const ClassBase *class_by_typeinfo (const std::type_info &ti);
/**
* @brief Find a class declaration through the type info
*
* This version won't assert when there is no such class and
* return 0 instead.
*/
GSI_PUBLIC const ClassBase *class_by_typeinfo_no_assert (const std::type_info &ti);
/**
* @brief Returns true if there is a class with the given type info
*/