Revision: 7272
          http://svn.sourceforge.net/mahogany/?rev=7272&view=rev
Author:   vadz
Date:     2007-05-18 05:21:41 -0700 (Fri, 18 May 2007)

Log Message:
-----------
speed up filter creation by caching their internal representation

Modified Paths:
--------------
    trunk/M/src/classes/MFilter.cpp
    trunk/M/src/classes/MFolder.cpp

Modified: trunk/M/src/classes/MFilter.cpp
===================================================================
--- trunk/M/src/classes/MFilter.cpp     2007-05-18 12:21:26 UTC (rev 7271)
+++ trunk/M/src/classes/MFilter.cpp     2007-05-18 12:21:41 UTC (rev 7272)
@@ -35,6 +35,7 @@
 
 #include "MFilter.h"
 #include "MFolder.h"
+#include "MAtExit.h"
 #include "modules/Filters.h"
 
 // ----------------------------------------------------------------------------
@@ -49,6 +50,30 @@
 #define MP_FILTER_GUIDESC  _T("Settings")
 
 // ----------------------------------------------------------------------------
+// private functions
+// ----------------------------------------------------------------------------
+
+// free the folder filters cache defined below
+static void CleanupFilterCache();
+
+// invalidate the cached representation of the given filter
+static void InvalidateFilter(const MFilter *filter);
+
+// ----------------------------------------------------------------------------
+// globals
+// ----------------------------------------------------------------------------
+
+// filter rules are relatively expensive to construct, so we cache them once we
+// created them in this hash map (its keys are the folder names)
+#include "wx/hashmap.h"
+WX_DECLARE_STRING_HASH_MAP(FilterRule *, FolderFiltersMap);
+
+static FolderFiltersMap gs_folderFilters;
+
+// ensure that filter rules are deleted on exit
+static MRunFunctionAtExit gs_runFilterCacheCleanup(CleanupFilterCache);
+
+// ----------------------------------------------------------------------------
 // private classes
 // ----------------------------------------------------------------------------
 
@@ -816,6 +841,8 @@
       {
          if ( m_dirty )
          {
+            InvalidateFilter(this);
+
             // write the values to the profile
             m_Profile->writeEntry(MP_FILTER_NAME, m_Name);
             if ( m_Settings )
@@ -956,6 +983,9 @@
       return false;
    }
 
+   // invalidating just one filter isn't enough
+   CleanupFilterCache();
+
    return true;
 }
 
@@ -983,11 +1013,56 @@
 // global functions
 // ----------------------------------------------------------------------------
 
+static void
+CleanupFilterCache()
+{
+   for ( FolderFiltersMap::const_iterator i = gs_folderFilters.begin();
+         i != gs_folderFilters.end();
+         ++i )
+   {
+      FilterRule * const rule = i->second;
+      if ( rule )
+         rule->DecRef();
+   }
+
+   gs_folderFilters.clear();
+}
+
+// this is used by MFolderFromProfile::SetFilter(): when a folders filter is
+// changed, it only affects this folder
+extern void
+InvalidateFilterForFolder(const MFolder *folder)
+{
+   CHECK_RET( folder, _T("InvalidateFilter: NULL parameter") );
+
+   gs_folderFilters.erase(folder->GetFullName());
+}
+
+// this is used by the code in this file when modifying individual filters, as
+// we don't know which folders use them, we simply invalidate the entire cache
+static void
+InvalidateFilter(const MFilter * /* filter */)
+{
+   CleanupFilterCache();
+}
+
 extern FilterRule *
 GetFilterForFolder(const MFolder *folder)
 {
    CHECK( folder, NULL, _T("GetFilterForFolder: NULL parameter") );
 
+   // check if we already have it in the cache
+   const String folderName = folder->GetFullName();
+   const FolderFiltersMap::iterator i = gs_folderFilters.find(folderName);
+   if ( i != gs_folderFilters.end() )
+   {
+      FilterRule * const rule = i->second;
+      if ( rule )
+         rule->IncRef();
+
+      return rule;
+   }
+
    // build a single program from all filter rules:
    String filterString;
    wxArrayString filters = folder->GetFilters();
@@ -1003,6 +1078,8 @@
    if ( filterString.empty() )
    {
       // no, nothing to do
+      gs_folderFilters[folderName] = NULL;
+
       return NULL;
    }
 
@@ -1011,6 +1088,8 @@
    {
       wxLogWarning(_("Filter module couldn't be loaded."));
 
+      // don't cache this failure: maybe we'll be able to load the module the
+      // next time
       return NULL;
    }
 
@@ -1027,5 +1106,11 @@
                  filterString.c_str(), folder->GetFullName().c_str());
    }
 
+   // cache the newly created rule and make sure it doesn't go away
+   gs_folderFilters[folderName] = filterRule;
+   if ( filterRule )
+      filterRule->IncRef();
+
    return filterRule;
 }
+

Modified: trunk/M/src/classes/MFolder.cpp
===================================================================
--- trunk/M/src/classes/MFolder.cpp     2007-05-18 12:21:26 UTC (rev 7271)
+++ trunk/M/src/classes/MFolder.cpp     2007-05-18 12:21:41 UTC (rev 7272)
@@ -951,6 +951,13 @@
 
 void MFolderFromProfile::SetFilters(const wxArrayString& filters)
 {
+   // this function is in MFilter.cpp but we only use it here so it's not in
+   // any header
+   extern void InvalidateFilterForFolder(const MFolder *);
+
+   // forget the cached filter representation
+   InvalidateFilterForFolder(this);
+
    m_profile->writeEntry(MP_FOLDER_FILTERS, strutil_flatten_array(filters));
 }
 


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Mahogany-cvsupdates mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mahogany-cvsupdates

Reply via email to