You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdevelop/languages/cpp/simpletypecachebinder.h

348 lines
12 KiB

/***************************************************************************
copyright : (C) 2006 by David Nolden
email : david.nolden.kdevelop@art-master.de
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef __SIMPLETYPECACHEBINDER_H__
#define __SIMPLETYPECACHEBINDER_H__
#include "simpletypenamespace.h"
///In case the hashing-stuff brings some regressions, it can be removed again using this switch.
#include <ext/hash_map>
#include <map>
//#define TEST_REMAP
template <class Base>
class SimpleTypeCacheBinder : public Base {
public:
SimpleTypeCacheBinder( SimpleTypeCacheBinder<Base>* b ) : Base( b ), m_locateCache( b->m_locateCache ), m_memberCache( b->m_memberCache ), m_basesCache( b->m_basesCache ), secondaryActive( b->secondaryActive ), m_classListCache( b->m_classListCache ), primaryActive( b->primaryActive ), m_haveBasesCache( b->m_haveBasesCache ) {}
SimpleTypeCacheBinder() : Base(), m_haveBasesCache( false ), secondaryActive( true ), primaryActive( true ) {}
template <class InitType>
SimpleTypeCacheBinder( InitType t ) : Base ( t ), m_haveBasesCache( false ) , secondaryActive( true ), primaryActive( true ) {}
template <class InitType1, class InitType2>
SimpleTypeCacheBinder( InitType1 t, InitType2 t2 ) : Base ( t, t2 ), m_haveBasesCache( false ), secondaryActive( true ), primaryActive( true ) {}
using typename Base::LocateMode;
struct LocateDesc {
TypeDesc mname;
//TQString fullName;
SimpleTypeImpl::LocateMode mmode;
int mdir;
SimpleTypeImpl::MemberInfo::MemberType mtypeMask;
size_t m_hashKey;
LocateDesc() {}
LocateDesc( const TypeDesc& name, SimpleTypeImpl::LocateMode mode, int dir, SimpleTypeImpl::MemberInfo::MemberType typeMask ) : mname( name ), mmode( mode ) , mdir( dir ) , mtypeMask( typeMask ), m_hashKey( name.hashKey() + 11*int(mode) + 13*dir + 17*int(typeMask) ) {
//fullName = mname.fullNameChain();//fullTypeStructure();
}
///@todo this should use hashing too
int compare( const LocateDesc& rhs ) const {
if ( m_hashKey != rhs.m_hashKey ) {
if ( m_hashKey < rhs.m_hashKey )
return -1;
else
return 1;
}
if ( mname.hashKey2() != rhs.mname.hashKey2() ) {
if ( mname.hashKey2() < rhs.mname.hashKey2() )
return -1;
else
return 1;
}
if ( mmode != rhs.mmode ) {
if ( mmode < rhs.mmode )
return -1;
else
return 1;
}
if ( mdir != rhs.mdir ) {
if ( mdir < rhs.mdir )
return -1;
else
return 1;
}
if ( mtypeMask != rhs.mtypeMask ) {
if ( mtypeMask < rhs.mtypeMask )
return -1;
else
return 1;
}
return 0;
}
bool operator < ( const LocateDesc& rhs ) const {
return compare( rhs ) == -1;
}
bool operator == ( const LocateDesc& rhs ) const {
//return compare( rhs ) == 0;
if( m_hashKey == rhs.m_hashKey && mname.hashKey2() == rhs.mname.hashKey2() )
return mname.name() == rhs.mname.name();
else
return false;
}
bool operator > ( const LocateDesc& rhs ) const {
return compare( rhs ) == 1;
}
inline size_t hashKey() const {
return m_hashKey;
}
struct hash {
inline size_t operator () ( const LocateDesc& m ) const {
return m.hashKey();
}
};
};
struct MemberFindDesc {
TypeDesc m_desc;
TQString fullName;
SimpleTypeImpl::MemberInfo::MemberType findType;
size_t m_hashKey; //in time check why it is necessary to cache this key
size_t m_hashKey2;
MemberFindDesc() : m_hashKey( 0 ) {}
MemberFindDesc( TypeDesc d, SimpleTypeImpl::MemberInfo::MemberType ft ) : m_desc( d ), findType( ft ), m_hashKey( d.hashKey() + findType ), m_hashKey2( d.hashKey2() + findType ) {
//m_desc.makePrivate();
}
int compare( const MemberFindDesc& rhs ) const {
if ( fullName.isEmpty() ) const_cast<MemberFindDesc*>(this)->fullName = m_desc.fullNameChain();
if ( rhs.fullName.isEmpty() ) const_cast<MemberFindDesc*>(&rhs)->fullName = rhs.m_desc.fullNameChain();
const TQString& a = fullName; //m_desc.fullNameChain();
const TQString& b = rhs.fullName; //m_desc.fullNameChain();
if ( a != b ) {
if ( a < b )
return -1;
else
return 1;
}
if ( findType != rhs.findType ) {
if ( findType < rhs.findType )
return -1;
else
return 1;
}
return 0;
}
bool operator < ( const MemberFindDesc& rhs ) const {
return compare( rhs ) == -1;
}
//#endif
inline size_t hashKey() const {
return m_hashKey;
}
bool operator == ( const MemberFindDesc& rhs ) const {
bool ret = m_hashKey2 == rhs.m_hashKey2 && findType == rhs.findType;
if( ret )
return m_desc.name() == rhs.m_desc.name(); //Just for a little more security
return ret;
}
/*
bool operator > ( const MemberFindDesc& rhs ) const {
return compare( rhs ) == 1;
}*/
struct hash {
inline size_t operator () ( const MemberFindDesc& m ) const {
return m.hashKey();
}
};
};
typedef __gnu_cxx::hash_map<LocateDesc, LocateResult, typename LocateDesc::hash > LocateMap;
typedef __gnu_cxx::hash_map<MemberFindDesc, SimpleTypeImpl::MemberInfo, typename MemberFindDesc::hash > MemberMap;
typedef __gnu_cxx::hash_map<MemberFindDesc, TQValueList<TypePointer>, typename MemberFindDesc::hash > ClassListMap;
virtual SimpleTypeImpl::MemberInfo findMember( TypeDesc name, SimpleTypeImpl::MemberInfo::MemberType type ) {
if ( !primaryActive )
return Base::findMember( name, type );
MemberFindDesc key( name, type );
typename MemberMap::iterator it = m_memberCache.find( key );
if ( it != m_memberCache.end() ) {
ifVerbose( dbg() << "\"" << Base::str() << "\" took member-info for \"" << name.fullNameChain() << "\" from the cache: " << (*it).second.name << endl );
return (*it).second;
} else {
SimpleTypeImpl::MemberInfo mem;
m_memberCache.insert( std::make_pair( key, mem ) ); //This is done to prevent expensive endless recursion
mem = Base::findMember( name, type );
std::pair< typename MemberMap::iterator, bool > r = m_memberCache.insert( std::make_pair( key, mem ) );
if ( !r.second ) {
(*r.first).second = mem;
}
#ifdef TEST_REMAP
typename MemberMap::iterator it = m_memberCache.find( key );
if ( it == m_memberCache.end() ) dbgMajor() << "\"" << Base::str() << "\"remap failed with \"" << name.fullNameChain() << "\"" << endl;
#endif
return mem;
}
}
virtual TQValueList<TypePointer> getMemberClasses( const TypeDesc& name ) {
if ( !primaryActive )
return Base::getMemberClasses( name );
MemberFindDesc key( name, Base::MemberInfo::NestedType );
typename ClassListMap::iterator it = m_classListCache.find( key );
if ( it != m_classListCache.end() ) {
/*ifVerbose( dbg() << "\"" << Base::str() << "\" took member-info for \"" << name.fullNameChain() << "\" from the cache: " << (*it).second. << endl );*/
return (*it).second;
} else {
TQValueList<TypePointer> mem;
m_classListCache.insert( std::make_pair( key, mem ) );
mem = Base::getMemberClasses( name );
std::pair<typename ClassListMap::iterator, bool> r = m_classListCache.insert( std::make_pair( key, mem ) );
if ( !r.second )
(*r.first).second = mem;
#ifdef TEST_REMAP
typename ClassListMap::iterator it = m_classListCache.find( key );
if ( it == m_classListCache.end() ) dbgMajor() << "\"" << Base::str() << "\"remap failed with \"" << name.fullNameChain() << "\"" << endl;
#endif
return mem;
}
}
virtual LocateResult locateType( TypeDesc name , SimpleTypeImpl::LocateMode mode, int dir, SimpleTypeImpl::MemberInfo::MemberType typeMask ) {
if ( !secondaryActive )
return Base::locateType( name, mode, dir, typeMask );
LocateDesc desc( name, mode, dir, typeMask );
typename LocateMap::iterator it = m_locateCache.find( desc );
if ( it != m_locateCache.end() ) {
Debug d( "#lo#" );
ifVerbose( dbg() << "\"" << Base::str() << "\" located \"" << name.fullNameChain() << "\" from the cache" << endl );
return (*it).second;
} else {
LocateResult t;
m_locateCache.insert( std::make_pair( desc, t ) ); //Done to prevent expensive recursion.
t = Base::locateType( name, mode, dir, typeMask );
std::pair< typename LocateMap::iterator, bool > r = m_locateCache.insert( std::make_pair( desc, t ) );
if ( !r.second )
(*r.first).second = t;
#ifdef TEST_REMAP
typename LocateMap::iterator it = m_locateCache.find( desc );
if ( it == m_locateCache.end() ) dbgMajor() << "\"" << Base::str() << "\"remap failed with \"" << name.fullNameChain() << "\"" << endl;
#endif
return t;
}
}
virtual TQValueList<LocateResult> getBases() {
///@todo this needs a lookup for different includeFiles..
if ( m_haveBasesCache ) {
ifVerbose( dbg() << "\"" << Base::str() << "\" took base-info from the cache" << endl );
return m_basesCache;
} else {
m_basesCache = Base::getBases();
m_haveBasesCache = true;
return m_basesCache;
}
}
private:
LocateMap m_locateCache;
MemberMap m_memberCache;
ClassListMap m_classListCache;
TQValueList<LocateResult> m_basesCache;
bool m_haveBasesCache;
bool secondaryActive, primaryActive;
protected:
virtual typename Base::TypePointer clone() {
return new SimpleTypeCacheBinder<Base>( this );
}
virtual void invalidatePrimaryCache( bool onlyNegative ) {
//if( !m_memberCache.isEmpty() ) dbg() << "\"" << Base::str() << "\" primary caches cleared" << endl;
if ( !onlyNegative)
m_memberCache.clear();
else {
for ( typename MemberMap::iterator it = m_memberCache.begin(); it != m_memberCache.end(); ) {
if ( (*it).second.memberType == SimpleTypeImpl::MemberInfo::NotFound )
m_memberCache.erase( it++ );
else
++it;
}
}
m_classListCache.clear();
}
virtual void invalidateSecondaryCache() {
//if( !m_locateCache.isEmpty() ) dbg() << "\"" << Base::str() << "\" secondary caches cleared" << endl;
m_locateCache.clear();
m_haveBasesCache = false;
m_basesCache.clear();
}
virtual void setSecondaryCacheActive( bool active ) {
secondaryActive = active;
}
virtual void setPrimaryCacheActive( bool active ) {
primaryActive = active;
}
virtual void invalidateCache() {
invalidatePrimaryCache( false );
invalidateSecondaryCache();
};
};
//typedef SimpleTypeCacheBinder<SimpleTypeImpl> SimpleTypeImpl;
class SimpleTypeCodeModel;
class SimpleTypeCatalog;
class SimpleTypeNamespace;
class SimpleTypeCodeModelFunction;
class SimpleTypeCatalogFunction;
typedef SimpleTypeCacheBinder<SimpleTypeCodeModel> SimpleTypeCachedCodeModel;
typedef SimpleTypeCacheBinder<SimpleTypeCatalog> SimpleTypeCachedCatalog;
typedef SimpleTypeCacheBinder<SimpleTypeNamespace> SimpleTypeCachedNamespace;
typedef SimpleTypeCacheBinder<SimpleTypeCodeModelFunction> SimpleTypeCachedCodeModelFunction;
typedef SimpleTypeCacheBinder<SimpleTypeCatalogFunction> SimpleTypeCachedCatalogFunction;
#endif