From 0a976765870f164048378a054af1b8904f2ecdb1 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 11 Feb 2000 20:38:04 +0000 Subject: [PATCH] added an extremely simple cell attr cache (yet it catches 80% of acccesses) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@5974 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/generic/grid.h | 22 +++++++ src/generic/grid.cpp | 119 ++++++++++++++++++++++++++++++++------ 2 files changed, 123 insertions(+), 18 deletions(-) diff --git a/include/wx/generic/grid.h b/include/wx/generic/grid.h index 8bd6959381..a6fc79412b 100644 --- a/include/wx/generic/grid.h +++ b/include/wx/generic/grid.h @@ -134,6 +134,7 @@ public: // it until the matching DecRef() is called void IncRef() { m_nRef++; } void DecRef() { if ( !--m_nRef ) delete this; } + void SafeIncRef() { if ( this ) IncRef(); } void SafeDecRef() { if ( this ) DecRef(); } // setters @@ -1026,6 +1027,27 @@ protected: // doesn't have any yet or the existing one if it does // // DecRef() must be called on the returned pointer, as usual + wxGridCellAttr *GetOrCreateCellAttr(int row, int col) const; + + // cell attribute cache (currently we only cache 1, may be will do + // more/better later) + struct CachedAttr + { + int row, col; + wxGridCellAttr *attr; + } m_attrCache; + + // invalidates the attribute cache + void ClearAttrCache(); + + // adds an attribute to cache + void CacheAttr(int row, int col, wxGridCellAttr *attr) const; + + // looks for an attr in cache, returns TRUE if found + bool LookupAttr(int row, int col, wxGridCellAttr **attr) const; + + // looks for the attr in cache, if not found asks the table and caches the + // result wxGridCellAttr *GetCellAttr(int row, int col) const; wxGridCellCoordsArray m_cellsExposed; diff --git a/src/generic/grid.cpp b/src/generic/grid.cpp index 8f8fcddd87..157ec1f569 100644 --- a/src/generic/grid.cpp +++ b/src/generic/grid.cpp @@ -180,7 +180,15 @@ private: #define WXGRID_DRAW_LINES 1 #endif -////////////////////////////////////////////////////////////////////// +// ---------------------------------------------------------------------------- +// globals +// ---------------------------------------------------------------------------- + +//#define DEBUG_ATTR_CACHE +#ifdef DEBUG_ATTR_CACHE + static size_t gs_nAttrCacheHits = 0; + static size_t gs_nAttrCacheMisses = 0; +#endif // DEBUG_ATTR_CACHE wxGridCellCoords wxGridNoCellCoords( -1, -1 ); wxRect wxGridNoCellRect( -1, -1, -1, -1 ); @@ -1249,6 +1257,16 @@ wxGrid::wxGrid( wxWindow *parent, wxGrid::~wxGrid() { + ClearAttrCache(); + +#ifdef DEBUG_ATTR_CACHE + size_t total = gs_nAttrCacheHits + gs_nAttrCacheMisses; + wxPrintf(_T("wxGrid attribute cache statistics: " + "total: %u, hits: %u (%u%%)\n"), + total, gs_nAttrCacheHits, + total ? (gs_nAttrCacheHits*100) / total : 0); +#endif + delete m_defaultRenderer; delete m_table; } @@ -1345,6 +1363,9 @@ void wxGrid::Init() m_labelTextColour = wxColour( _T("BLACK") ); + // init attr cache + m_attrCache.row = -1; + // TODO: something better than this ? // m_labelFont = this->GetFont(); @@ -4665,11 +4686,9 @@ wxGridCellRenderer *wxGrid::GetCellRenderer(int row, int col) // access to cell attributes // ---------------------------------------------------------------------------- -// TODO VZ: we must cache the attr to allow only retrieveing it once! - wxColour wxGrid::GetCellBackgroundColour(int row, int col) { - wxGridCellAttr *attr = m_table ? m_table->GetAttr(row, col) : NULL; + wxGridCellAttr *attr = GetCellAttr(row, col); wxColour colour; if ( attr && attr->HasBackgroundColour() ) @@ -4684,7 +4703,7 @@ wxColour wxGrid::GetCellBackgroundColour(int row, int col) wxColour wxGrid::GetCellTextColour( int row, int col ) { - wxGridCellAttr *attr = m_table ? m_table->GetAttr(row, col) : NULL; + wxGridCellAttr *attr = GetCellAttr(row, col); wxColour colour; if ( attr && attr->HasTextColour() ) @@ -4699,7 +4718,7 @@ wxColour wxGrid::GetCellTextColour( int row, int col ) wxFont wxGrid::GetCellFont( int row, int col ) { - wxGridCellAttr *attr = m_table ? m_table->GetAttr(row, col) : NULL; + wxGridCellAttr *attr = GetCellAttr(row, col); wxFont font; if ( attr && attr->HasFont() ) @@ -4714,7 +4733,7 @@ wxFont wxGrid::GetCellFont( int row, int col ) void wxGrid::GetCellAlignment( int row, int col, int *horiz, int *vert ) { - wxGridCellAttr *attr = m_table ? m_table->GetAttr(row, col) : NULL; + wxGridCellAttr *attr = GetCellAttr(row, col); if ( attr && attr->HasAlignment() ) attr->GetAlignment(horiz, vert); @@ -4746,17 +4765,81 @@ bool wxGrid::CanHaveAttributes() return TRUE; } +void wxGrid::ClearAttrCache() +{ + if ( m_attrCache.row != -1 ) + { + m_attrCache.attr->SafeDecRef(); + m_attrCache.row = -1; + } +} + +void wxGrid::CacheAttr(int row, int col, wxGridCellAttr *attr) const +{ + wxGrid *self = (wxGrid *)this; // const_cast + + self->ClearAttrCache(); + self->m_attrCache.row = row; + self->m_attrCache.col = col; + self->m_attrCache.attr = attr; + attr->SafeIncRef(); +} + +bool wxGrid::LookupAttr(int row, int col, wxGridCellAttr **attr) const +{ + if ( row == m_attrCache.row && col == m_attrCache.col ) + { + *attr = m_attrCache.attr; + (*attr)->SafeIncRef(); + +#ifdef DEBUG_ATTR_CACHE + gs_nAttrCacheHits++; +#endif + + return TRUE; + } + else + { +#ifdef DEBUG_ATTR_CACHE + gs_nAttrCacheMisses++; +#endif + return FALSE; + } +} + wxGridCellAttr *wxGrid::GetCellAttr(int row, int col) const { - wxGridCellAttr *attr = m_table->GetAttr(row, col); - if ( !attr ) + wxGridCellAttr *attr; + if ( !LookupAttr(row, col, &attr) ) { - attr = new wxGridCellAttr; + attr = m_table ? m_table->GetAttr(row, col) : (wxGridCellAttr *)NULL; + CacheAttr(row, col, attr); + } - // artificially inc the ref count to match DecRef() in caller - attr->IncRef(); + return attr; +} + +wxGridCellAttr *wxGrid::GetOrCreateCellAttr(int row, int col) const +{ + wxGridCellAttr *attr; + if ( !LookupAttr(row, col, &attr) || !attr ) + { + wxASSERT_MSG( m_table, + _T("we may only be called if CanHaveAttributes() " + "returned TRUE and then m_table should be !NULL") ); + + attr = m_table->GetAttr(row, col); + if ( !attr ) + { + attr = new wxGridCellAttr; + + // artificially inc the ref count to match DecRef() in caller + attr->IncRef(); + + m_table->SetAttr(attr, row, col); + } - m_table->SetAttr(attr, row, col); + CacheAttr(row, col, attr); } return attr; @@ -4766,7 +4849,7 @@ void wxGrid::SetCellBackgroundColour( int row, int col, const wxColour& colour ) { if ( CanHaveAttributes() ) { - wxGridCellAttr *attr = GetCellAttr(row, col); + wxGridCellAttr *attr = GetOrCreateCellAttr(row, col); attr->SetBackgroundColour(colour); attr->DecRef(); } @@ -4776,7 +4859,7 @@ void wxGrid::SetCellTextColour( int row, int col, const wxColour& colour ) { if ( CanHaveAttributes() ) { - wxGridCellAttr *attr = GetCellAttr(row, col); + wxGridCellAttr *attr = GetOrCreateCellAttr(row, col); attr->SetTextColour(colour); attr->DecRef(); } @@ -4786,7 +4869,7 @@ void wxGrid::SetCellFont( int row, int col, const wxFont& font ) { if ( CanHaveAttributes() ) { - wxGridCellAttr *attr = GetCellAttr(row, col); + wxGridCellAttr *attr = GetOrCreateCellAttr(row, col); attr->SetFont(font); attr->DecRef(); } @@ -4796,7 +4879,7 @@ void wxGrid::SetCellAlignment( int row, int col, int horiz, int vert ) { if ( CanHaveAttributes() ) { - wxGridCellAttr *attr = GetCellAttr(row, col); + wxGridCellAttr *attr = GetOrCreateCellAttr(row, col); attr->SetAlignment(horiz, vert); attr->DecRef(); } @@ -4806,7 +4889,7 @@ void wxGrid::SetCellRenderer(int row, int col, wxGridCellRenderer *renderer) { if ( CanHaveAttributes() ) { - wxGridCellAttr *attr = GetCellAttr(row, col); + wxGridCellAttr *attr = GetOrCreateCellAttr(row, col); attr->SetRenderer(renderer); attr->DecRef(); } -- 2.45.2