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.
349 lines
12 KiB
349 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 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
|
|
// kate: indent-mode csands; tab-width 4;
|