Skip to content

Commit

Permalink
Add some debugging asserts to ensure that layer renderers
Browse files Browse the repository at this point in the history
are used in a thread safe way
  • Loading branch information
nyalldawson committed Nov 19, 2017
1 parent a0c6e05 commit af5b2a7
Show file tree
Hide file tree
Showing 14 changed files with 68 additions and 13 deletions.
1 change: 0 additions & 1 deletion python/core/symbology/qgsnullsymbolrenderer.sip
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ class QgsNullSymbolRenderer : QgsFeatureRenderer
virtual QgsSymbol *originalSymbolForFeature( QgsFeature &feature, QgsRenderContext &context );

virtual bool renderFeature( QgsFeature &feature, QgsRenderContext &context, int layer = -1, bool selected = false, bool drawVertexMarker = false );
virtual void startRender( QgsRenderContext &context, const QgsFields &fields );
virtual void stopRender( QgsRenderContext &context );
virtual bool willRenderFeature( QgsFeature &feat, QgsRenderContext &context );

Expand Down
4 changes: 2 additions & 2 deletions python/core/symbology/qgsrenderer.sip
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ return a new renderer - used by default in vector layers
:rtype: set of str
%End

virtual void startRender( QgsRenderContext &context, const QgsFields &fields ) = 0;
virtual void startRender( QgsRenderContext &context, const QgsFields &fields );
%Docstring
Must be called when a new render cycle is started. A call to startRender() must always
be followed by a corresponding call to stopRender() after all features have been rendered.
Expand All @@ -127,7 +127,7 @@ return a new renderer - used by default in vector layers
the renderer should instead be cloned and startRender()/stopRender() called on the clone.
%End

virtual void stopRender( QgsRenderContext &context ) = 0;
virtual void stopRender( QgsRenderContext &context );
%Docstring
Must be called when a render cycle has finished, to allow the renderer to clean up.

Expand Down
4 changes: 4 additions & 0 deletions src/core/symbology/qgs25drenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,15 @@ QgsFeatureRenderer *Qgs25DRenderer::create( QDomElement &element, const QgsReadW

void Qgs25DRenderer::startRender( QgsRenderContext &context, const QgsFields &fields )
{
QgsFeatureRenderer::startRender( context, fields );

mSymbol->startRender( context, fields );
}

void Qgs25DRenderer::stopRender( QgsRenderContext &context )
{
QgsFeatureRenderer::stopRender( context );

mSymbol->stopRender( context );
}

Expand Down
4 changes: 4 additions & 0 deletions src/core/symbology/qgscategorizedsymbolrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,8 @@ void QgsCategorizedSymbolRenderer::sortByLabel( Qt::SortOrder order )

void QgsCategorizedSymbolRenderer::startRender( QgsRenderContext &context, const QgsFields &fields )
{
QgsFeatureRenderer::startRender( context, fields );

mCounting = context.rendererScale() == 0.0;

// make sure that the hash table is up to date
Expand All @@ -398,6 +400,8 @@ void QgsCategorizedSymbolRenderer::startRender( QgsRenderContext &context, const

void QgsCategorizedSymbolRenderer::stopRender( QgsRenderContext &context )
{
QgsFeatureRenderer::stopRender( context );

Q_FOREACH ( const QgsRendererCategory &cat, mCategories )
{
cat.symbol()->stopRender( context );
Expand Down
4 changes: 4 additions & 0 deletions src/core/symbology/qgsgraduatedsymbolrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,8 @@ QgsSymbol *QgsGraduatedSymbolRenderer::originalSymbolForFeature( QgsFeature &fea

void QgsGraduatedSymbolRenderer::startRender( QgsRenderContext &context, const QgsFields &fields )
{
QgsFeatureRenderer::startRender( context, fields );

mCounting = context.rendererScale() == 0.0;

// find out classification attribute index from name
Expand All @@ -386,6 +388,8 @@ void QgsGraduatedSymbolRenderer::startRender( QgsRenderContext &context, const Q

void QgsGraduatedSymbolRenderer::stopRender( QgsRenderContext &context )
{
QgsFeatureRenderer::stopRender( context );

Q_FOREACH ( const QgsRendererRange &range, mRanges )
{
if ( !range.symbol() )
Expand Down
5 changes: 4 additions & 1 deletion src/core/symbology/qgsheatmaprenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ void QgsHeatmapRenderer::initializeValues( QgsRenderContext &context )

void QgsHeatmapRenderer::startRender( QgsRenderContext &context, const QgsFields &fields )
{
Q_UNUSED( fields );
QgsFeatureRenderer::startRender( context, fields );

if ( !context.painter() )
{
return;
Expand Down Expand Up @@ -212,6 +213,8 @@ double QgsHeatmapRenderer::triangularKernel( const double distance, const int ba

void QgsHeatmapRenderer::stopRender( QgsRenderContext &context )
{
QgsFeatureRenderer::stopRender( context );

renderImage( context );
mWeightExpression.reset();
}
Expand Down
4 changes: 4 additions & 0 deletions src/core/symbology/qgsinvertedpolygonrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ void QgsInvertedPolygonRenderer::checkLegendSymbolItem( const QString &key, bool

void QgsInvertedPolygonRenderer::startRender( QgsRenderContext &context, const QgsFields &fields )
{
QgsFeatureRenderer::startRender( context, fields );

if ( !mSubRenderer )
{
return;
Expand Down Expand Up @@ -243,6 +245,8 @@ bool QgsInvertedPolygonRenderer::renderFeature( QgsFeature &feature, QgsRenderCo

void QgsInvertedPolygonRenderer::stopRender( QgsRenderContext &context )
{
QgsFeatureRenderer::stopRender( context );

if ( !mSubRenderer )
{
return;
Expand Down
8 changes: 2 additions & 6 deletions src/core/symbology/qgsnullsymbolrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,10 @@ bool QgsNullSymbolRenderer::renderFeature( QgsFeature &feature, QgsRenderContext
return true;
}

void QgsNullSymbolRenderer::startRender( QgsRenderContext &context, const QgsFields &fields )
{
Q_UNUSED( context );
Q_UNUSED( fields );
}

void QgsNullSymbolRenderer::stopRender( QgsRenderContext &context )
{
QgsFeatureRenderer::stopRender( context );

if ( mSymbol )
{
mSymbol->stopRender( context );
Expand Down
1 change: 0 additions & 1 deletion src/core/symbology/qgsnullsymbolrenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ class CORE_EXPORT QgsNullSymbolRenderer : public QgsFeatureRenderer
virtual QgsSymbol *originalSymbolForFeature( QgsFeature &feature, QgsRenderContext &context ) override;

virtual bool renderFeature( QgsFeature &feature, QgsRenderContext &context, int layer = -1, bool selected = false, bool drawVertexMarker = false ) override;
virtual void startRender( QgsRenderContext &context, const QgsFields &fields ) override;
virtual void stopRender( QgsRenderContext &context ) override;
virtual bool willRenderFeature( QgsFeature &feat, QgsRenderContext &context ) override;

Expand Down
4 changes: 4 additions & 0 deletions src/core/symbology/qgspointdistancerenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,8 @@ bool QgsPointDistanceRenderer::willRenderFeature( QgsFeature &feat, QgsRenderCon

void QgsPointDistanceRenderer::startRender( QgsRenderContext &context, const QgsFields &fields )
{
QgsFeatureRenderer::startRender( context, fields );

mRenderer->startRender( context, fields );

mClusteredGroups.clear();
Expand Down Expand Up @@ -315,6 +317,8 @@ void QgsPointDistanceRenderer::startRender( QgsRenderContext &context, const Qgs

void QgsPointDistanceRenderer::stopRender( QgsRenderContext &context )
{
QgsFeatureRenderer::stopRender( context );

//printInfoDisplacementGroups(); //just for debugging

Q_FOREACH ( const ClusteredGroup &group, mClusteredGroups )
Expand Down
25 changes: 25 additions & 0 deletions src/core/symbology/qgsrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,38 @@ QSet< QString > QgsFeatureRenderer::legendKeysForFeature( QgsFeature &feature, Q
return QSet< QString >();
}

void QgsFeatureRenderer::startRender( QgsRenderContext &, const QgsFields & )
{
#ifdef QGISDEBUG
if ( !mThread )
{
mThread = QThread::currentThread();
}
else
{
Q_ASSERT_X( mThread == QThread::currentThread(), "QgsFeatureRenderer::startRender", "startRender called in a different thread - use a cloned renderer instead" );
}
#endif
}

void QgsFeatureRenderer::stopRender( QgsRenderContext & )
{
#ifdef QGISDEBUG
Q_ASSERT_X( mThread == QThread::currentThread(), "QgsFeatureRenderer::stopRender", "stopRender called in a different thread - use a cloned renderer instead" );
#endif
}

bool QgsFeatureRenderer::filterNeedsGeometry() const
{
return false;
}

bool QgsFeatureRenderer::renderFeature( QgsFeature &feature, QgsRenderContext &context, int layer, bool selected, bool drawVertexMarker )
{
#ifdef QGISDEBUG
Q_ASSERT_X( mThread == QThread::currentThread(), "QgsFeatureRenderer::renderFeature", "renderFeature called in a different thread - use a cloned renderer instead" );
#endif

QgsSymbol *symbol = symbolForFeature( feature, context );
if ( !symbol )
return false;
Expand Down
9 changes: 7 additions & 2 deletions src/core/symbology/qgsrenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ class CORE_EXPORT QgsFeatureRenderer
* \warning This method is not thread safe. Before calling startRender() in a non-main thread,
* the renderer should instead be cloned and startRender()/stopRender() called on the clone.
*/
virtual void startRender( QgsRenderContext &context, const QgsFields &fields ) = 0;
virtual void startRender( QgsRenderContext &context, const QgsFields &fields );

/**
* Must be called when a render cycle has finished, to allow the renderer to clean up.
Expand All @@ -174,7 +174,7 @@ class CORE_EXPORT QgsFeatureRenderer
*
* \see startRender()
*/
virtual void stopRender( QgsRenderContext &context ) = 0;
virtual void stopRender( QgsRenderContext &context );

/**
* If a renderer does not require all the features this method may be overridden
Expand Down Expand Up @@ -524,6 +524,11 @@ class CORE_EXPORT QgsFeatureRenderer
QgsFeatureRenderer &operator=( const QgsFeatureRenderer & );
#endif

#ifdef QGISDEBUG
//! Pointer to thread in which startRender was first called
QThread *mThread = nullptr;
#endif

Q_DISABLE_COPY( QgsFeatureRenderer )
};

Expand Down
4 changes: 4 additions & 0 deletions src/core/symbology/qgsrulebasedrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,8 @@ bool QgsRuleBasedRenderer::renderFeature( QgsFeature &feature,

void QgsRuleBasedRenderer::startRender( QgsRenderContext &context, const QgsFields &fields )
{
QgsFeatureRenderer::startRender( context, fields );

// prepare active children
mRootRule->startRender( context, fields, mFilter );

Expand All @@ -849,6 +851,8 @@ void QgsRuleBasedRenderer::startRender( QgsRenderContext &context, const QgsFiel

void QgsRuleBasedRenderer::stopRender( QgsRenderContext &context )
{
QgsFeatureRenderer::stopRender( context );

//
// do the actual rendering
//
Expand Down
4 changes: 4 additions & 0 deletions src/core/symbology/qgssinglesymbolrenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ QgsSymbol *QgsSingleSymbolRenderer::originalSymbolForFeature( QgsFeature &featur

void QgsSingleSymbolRenderer::startRender( QgsRenderContext &context, const QgsFields &fields )
{
QgsFeatureRenderer::startRender( context, fields );

if ( !mSymbol )
return;

Expand All @@ -62,6 +64,8 @@ void QgsSingleSymbolRenderer::startRender( QgsRenderContext &context, const QgsF

void QgsSingleSymbolRenderer::stopRender( QgsRenderContext &context )
{
QgsFeatureRenderer::stopRender( context );

if ( !mSymbol )
return;

Expand Down

0 comments on commit af5b2a7

Please sign in to comment.