[Marble-commits] KDE/kdeedu/marble/src/lib

Jens-Michael Hoffmann jensmh at gmx.de
Tue Mar 23 10:46:16 CET 2010


SVN commit 1106571 by jmhoffmann:

Fix memory management of TextureTiles.

TextureTiles are created by the TileLoader, which might need to hold a
reference to the TextureTile in case of an outdated tile until the update
arrives. The TextureTiles referenced by TileLoader (using m_waitingForUpdate)
had to be protected from destruction in ~StackedTile by checking the state of
the tile. Ownership of TextureTile was transferred from TileLoader to
StackedTile not after completion of TileLoader::loadTile, but after an
eventual update arrived.

This approach is complicated and error prone and a misuse of the tile state.
Besides it made improvements/fixes in the reload functionality quite difficult.
Using QSharePointer here fixes all these issues and make improvements for
reload possible/more easy.

 M  +9 -17     StackedTile.cpp  
 M  +2 -1      StackedTile.h  
 M  +2 -1      StackedTileLoader.cpp  
 M  +4 -3      StackedTile_p.h  
 M  +5 -4      TileLoader.cpp  
 M  +3 -2      TileLoader.h  


--- trunk/KDE/kdeedu/marble/src/lib/StackedTile.cpp #1106570:1106571
@@ -70,14 +70,6 @@
 {
       delete [] jumpTable32;
       delete [] jumpTable8;
-
-      QVector<TextureTile*>::const_iterator pos = m_tiles.constBegin();
-      QVector<TextureTile*>::const_iterator const end = m_tiles.constEnd();
-      for (; pos != end; ++pos )
-          // only delete tiles with stateUptodate as the other ones are managed
-          // by the TileLoader until they are fully up to date.
-          if ( (*pos)->state() == TextureTile::StateUptodate )
-              delete *pos;
 }
 
 uint StackedTilePrivate::pixel( int x, int y ) const
@@ -212,12 +204,12 @@
     return topLeftValue;
 }
 
-inline void StackedTilePrivate::mergeCopyToResult( TextureTile const * const other )
+inline void StackedTilePrivate::mergeCopyToResult( QSharedPointer<TextureTile> const & other )
 {
     m_resultTile = other->image()->copy();
 }
 
-void StackedTilePrivate::mergeMultiplyToResult( TextureTile const * const other )
+void StackedTilePrivate::mergeMultiplyToResult( QSharedPointer<TextureTile> const & other )
 {
     // for this operation we assume that the tiles have the same size
     QImage const * const otherImage = other->image();
@@ -264,8 +256,8 @@
 bool StackedTile::isExpired() const
 {
     bool result = false;
-    QVector<TextureTile*>::const_iterator pos = d->m_tiles.constBegin();
-    QVector<TextureTile*>::const_iterator const end = d->m_tiles.constEnd();
+    QVector<QSharedPointer<TextureTile> >::const_iterator pos = d->m_tiles.constBegin();
+    QVector<QSharedPointer<TextureTile> >::const_iterator const end = d->m_tiles.constEnd();
     for (; pos != end; ++pos )
         result |= (*pos)->isExpired();
     return result;
@@ -281,7 +273,7 @@
     d->m_forMergedLayerDecorator = true;
 }
 
-void StackedTile::addTile( TextureTile * const tile )
+void StackedTile::addTile( QSharedPointer<TextureTile> const & tile )
 {
     d->m_tiles.append( tile );
     deriveCompletionState();
@@ -290,8 +282,8 @@
 void StackedTile::deriveCompletionState()
 {
     QMap<TextureTile::State, int> count;
-    QVector<TextureTile*>::const_iterator pos = d->m_tiles.constBegin();
-    QVector<TextureTile*>::const_iterator const end = d->m_tiles.constEnd();
+    QVector<QSharedPointer<TextureTile> >::const_iterator pos = d->m_tiles.constBegin();
+    QVector<QSharedPointer<TextureTile> >::const_iterator const end = d->m_tiles.constEnd();
     for (; pos != end; ++pos )
         ++count[ (*pos)->state() ];
 
@@ -378,8 +370,8 @@
 void StackedTile::initResultTile()
 {
     Q_ASSERT( hasTiles() );
-    QVector<TextureTile*>::const_iterator pos = d->m_tiles.constBegin();
-    QVector<TextureTile*>::const_iterator const end = d->m_tiles.constEnd();
+    QVector<QSharedPointer<TextureTile> >::const_iterator pos = d->m_tiles.constBegin();
+    QVector<QSharedPointer<TextureTile> >::const_iterator const end = d->m_tiles.constEnd();
     for (; pos != end; ++pos )
         if ( (*pos)->state() != TextureTile::StateEmpty )
             switch ( (*pos)->mergeRule() ) {
--- trunk/KDE/kdeedu/marble/src/lib/StackedTile.h #1106570:1106571
@@ -17,6 +17,7 @@
 #ifndef MARBLE_STACKED_TILE_H
 #define MARBLE_STACKED_TILE_H
 
+#include <QtCore/QSharedPointer>
 #include <QtGui/QColor>
 
 #include "AbstractTile.h"
@@ -72,7 +73,7 @@
     Q_DECLARE_PRIVATE( StackedTile )
     Q_DISABLE_COPY( StackedTile )
 
-    void addTile( TextureTile * const );
+    void addTile( QSharedPointer<TextureTile> const & );
     void deriveCompletionState();
     void initJumpTables();
     bool hasTiles() const;
--- trunk/KDE/kdeedu/marble/src/lib/StackedTileLoader.cpp #1106570:1106571
@@ -191,7 +191,8 @@
                                    stackedTileId.x(), stackedTileId.y() );
         mDebug() << "StackedTileLoader::loadTile: tile" << textureLayer->sourceDir()
                  << simpleTileId.toString();
-        TextureTile * const simpleTile = d->m_tileLoader->loadTile( stackedTileId, simpleTileId );
+        QSharedPointer<TextureTile> const simpleTile = d->m_tileLoader->loadTile( stackedTileId,
+                                                                                  simpleTileId );
         // hack to try clouds, first tile is not handled here, MergeCopy is the default,
         // the merge rule for following tiles is set to MergeMultiply here
         if ( simpleTile && tile->hasTiles() )
--- trunk/KDE/kdeedu/marble/src/lib/StackedTile_p.h #1106570:1106571
@@ -20,6 +20,7 @@
 
 #include "AbstractTile_p.h"
 
+#include <QtCore/QSharedPointer>
 #include <QtCore/QVector>
 #include <QtGui/QImage>
 
@@ -35,7 +36,7 @@
     uchar   **jumpTable8;
     uint    **jumpTable32;
 
-    QVector<TextureTile*> m_tiles;
+    QVector<QSharedPointer<TextureTile> > m_tiles;
     QImage    m_resultTile;
 
     int       m_depth;
@@ -47,8 +48,8 @@
 
     inline uint pixel( int x, int y ) const;
     inline uint pixelF( qreal x, qreal y, const QRgb& pixel ) const;
-    void mergeCopyToResult( TextureTile const * const tile );
-    void mergeMultiplyToResult( TextureTile const * const tile );
+    void mergeCopyToResult( QSharedPointer<TextureTile> const & tile );
+    void mergeMultiplyToResult( QSharedPointer<TextureTile> const & tile );
 };
 
 }
--- trunk/KDE/kdeedu/marble/src/lib/TileLoader.cpp #1106570:1106571
@@ -42,7 +42,7 @@
 //     - if not expired: create TextureTile, set state to "uptodate", return it => done
 //     - if expired: create TextureTile, state is set to Expired by default, trigger dl,
 
-TextureTile * TileLoader::loadTile( TileId const & stackedTileId, TileId const & tileId )
+QSharedPointer<TextureTile> TileLoader::loadTile( TileId const & stackedTileId, TileId const & tileId )
 {
     QString const fileName = tileFileName( tileId );
     QFileInfo const fileInfo( fileName );
@@ -50,7 +50,7 @@
         // file is there, so create and return a tile object in any case,
         // but check if an update should be triggered
         GeoSceneTexture const * const textureLayer = findTextureLayer( tileId );
-        TextureTile * const tile = new TextureTile( tileId, fileName );
+        QSharedPointer<TextureTile> const tile( new TextureTile( tileId, fileName ));
         tile->setStackedTileId( stackedTileId );
         tile->setLastModified( fileInfo.lastModified() );
         tile->setExpireSecs( textureLayer->expire() );
@@ -68,7 +68,7 @@
 
     // tile was not locally available => trigger download and look for tiles in other levels
     // for scaling
-    TextureTile * const tile = new TextureTile( tileId );
+    QSharedPointer<TextureTile> const tile( new TextureTile( tileId ));
     tile->setStackedTileId( stackedTileId );
     m_waitingForUpdate.insert( tileId, tile );
     triggerDownload( tileId );
@@ -86,7 +86,8 @@
 void TileLoader::updateTile( QByteArray const & data, QString const & tileId )
 {
     TileId const id = TileId::fromString( tileId );
-    TextureTile * const tile = m_waitingForUpdate.value( id, 0 );
+    QSharedPointer<TextureTile> const tile =
+        m_waitingForUpdate.value( id, QSharedPointer<TextureTile>() );
     // preliminary fix for reload map crash
     // TODO: fix properly
     if ( !tile )
--- trunk/KDE/kdeedu/marble/src/lib/TileLoader.h #1106570:1106571
@@ -18,6 +18,7 @@
 
 #include <QtCore/QHash>
 #include <QtCore/QObject>
+#include <QtCore/QSharedPointer>
 #include <QtCore/QString>
 
 #include "TileId.h"
@@ -41,7 +42,7 @@
  public:
     TileLoader( MapThemeManager const * const, HttpDownloadManager * const );
 
-    TextureTile * loadTile( TileId const & stackedTileId, TileId const & tileId );
+    QSharedPointer<TextureTile> loadTile( TileId const & stackedTileId, TileId const & tileId );
     void setTextureLayers( QHash<uint, GeoSceneTexture*> const & );
 
  public Q_SLOTS:
@@ -67,7 +68,7 @@
 
     // contains tiles, for which a download has been triggered
     // because the tile was not there at all or is expired.
-    QHash<TileId, TextureTile*> m_waitingForUpdate;
+    QHash<TileId, QSharedPointer<TextureTile> > m_waitingForUpdate;
 };
 
 inline void TileLoader::setTextureLayers( QHash<uint, GeoSceneTexture*> const & layers )


More information about the Marble-commits mailing list