diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | 114a878c64ce6f8223cfd22d76a20eb16d177e5e (patch) | |
tree | acaf47eb0fa12142d3896416a69e74cbf5a72242 /languages/cpp/simpletypecachebinder.h | |
download | tdevelop-114a878c64ce6f8223cfd22d76a20eb16d177e5e.tar.gz tdevelop-114a878c64ce6f8223cfd22d76a20eb16d177e5e.zip |
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdevelop@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'languages/cpp/simpletypecachebinder.h')
-rw-r--r-- | languages/cpp/simpletypecachebinder.h | 348 |
1 files changed, 348 insertions, 0 deletions
diff --git a/languages/cpp/simpletypecachebinder.h b/languages/cpp/simpletypecachebinder.h new file mode 100644 index 00000000..0cc5e2b0 --- /dev/null +++ b/languages/cpp/simpletypecachebinder.h @@ -0,0 +1,348 @@ +/*************************************************************************** + 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; + //QString 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; + QString 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 QString& a = fullName; //m_desc.fullNameChain(); + const QString& 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, QValueList<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 QValueList<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 { + QValueList<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 QValueList<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; + QValueList<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; |