summaryrefslogtreecommitdiffstats
path: root/languages/cpp/simpletypecachebinder.h
diff options
context:
space:
mode:
Diffstat (limited to 'languages/cpp/simpletypecachebinder.h')
-rw-r--r--languages/cpp/simpletypecachebinder.h348
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
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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;