Skip to content
Permalink
Browse files

Thread safety for get_feature

  • Loading branch information
m-kuhn committed Aug 2, 2018
1 parent 62a56b1 commit 11b26831917d865eef25506de45c1436956f884c
@@ -52,6 +52,13 @@ this source.
Returns the coordinate reference system for features retrieved from this source.

.. versionadded:: 3.0
%End

QString id() const;
%Docstring
Returns the layer id of the source layer.

.. versionadded:: 3.4
%End

protected:
@@ -63,6 +70,7 @@ Returns the coordinate reference system for features retrieved from this source.




};


@@ -43,6 +43,7 @@
#include "qgscolorramp.h"
#include "qgsfieldformatterregistry.h"
#include "qgsfieldformatter.h"
#include "qgsvectorlayerfeatureiterator.h"

const QString QgsExpressionFunction::helpText() const
{
@@ -3582,24 +3583,25 @@ static QVariant fcnGetFeatureById( const QVariantList &values, const QgsExpressi
static QVariant fcnGetFeature( const QVariantList &values, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction * )
{
//arguments: 1. layer id / name, 2. key attribute, 3. eq value
QgsVectorLayer *vl = QgsExpressionUtils::getVectorLayer( values.at( 0 ), parent );

std::unique_ptr<QgsVectorLayerFeatureSource> featureSource = QgsExpressionUtils::getFeatureSource( values.at( 0 ), parent );

//no layer found
if ( !vl )
if ( !featureSource )
{
return QVariant();
}

QString attribute = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
int attributeId = vl->fields().lookupField( attribute );
int attributeId = featureSource->fields().lookupField( attribute );
if ( attributeId == -1 )
{
return QVariant();
}

const QVariant &attVal = values.at( 2 );

const QString cacheValueKey = QStringLiteral( "getfeature:%1:%2:%3" ).arg( vl->id(), QString::number( attributeId ), attVal.toString() );
const QString cacheValueKey = QStringLiteral( "getfeature:%1:%2:%3" ).arg( featureSource->id(), QString::number( attributeId ), attVal.toString() );
if ( context && context->hasCachedValue( cacheValueKey ) )
{
return context->cachedValue( cacheValueKey );
@@ -3613,7 +3615,7 @@ static QVariant fcnGetFeature( const QVariantList &values, const QgsExpressionCo
{
req.setFlags( QgsFeatureRequest::NoGeometry );
}
QgsFeatureIterator fIt = vl->getFeatures( req );
QgsFeatureIterator fIt = featureSource->getFeatures( req );

QgsFeature fet;
QVariant res;
@@ -23,6 +23,7 @@
#include "qgsexpression.h"
#include "qgscolorramp.h"
#include "qgsvectorlayer.h"
#include "qgsvectorlayerfeatureiterator.h"
#include "qgsrasterlayer.h"
#include "qgsproject.h"
#include "qgsrelationmanager.h"
@@ -351,6 +352,34 @@ class QgsExpressionUtils
return ml;
}

static std::unique_ptr<QgsVectorLayerFeatureSource> getFeatureSource( const QVariant &value, QgsExpression *e )
{
std::unique_ptr<QgsVectorLayerFeatureSource> featureSource;

auto getFeatureSource = [ &value, e, &featureSource ]
{
QgsVectorLayer *layer = getVectorLayer( value, e );

if ( layer )
{
featureSource.reset( new QgsVectorLayerFeatureSource( layer ) );
}
};

#if QT_VERSION >= QT_VERSION_CHECK( 5, 10, 0 )
// Make sure we only deal with the vector layer on the main thread where it lives.
// Anything else risks a crash.
if ( QThread::currentThread() == qApp->thread() )
getFeatureSource();
else
QMetaObject::invokeMethod( qApp, getFeatureSource, Qt::BlockingQueuedConnection );
#else
getFeatureSource();
#endif

return featureSource;
}

static QgsVectorLayer *getVectorLayer( const QVariant &value, QgsExpression *e )
{
return qobject_cast<QgsVectorLayer *>( getMapLayer( value, e ) );
@@ -32,6 +32,7 @@ QgsVectorLayerFeatureSource::QgsVectorLayerFeatureSource( const QgsVectorLayer *
QMutexLocker locker( &layer->mFeatureSourceConstructorMutex );
mProviderFeatureSource = layer->dataProvider()->featureSource();
mFields = layer->fields();
mId = layer->id();

// update layer's join caches if necessary
if ( layer->mJoinBuffer->containsJoins() )
@@ -107,6 +108,11 @@ QgsCoordinateReferenceSystem QgsVectorLayerFeatureSource::crs() const
return mCrs;
}

QString QgsVectorLayerFeatureSource::id() const
{
return mId;
}


QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayerFeatureSource *source, bool ownSource, const QgsFeatureRequest &request )
: QgsAbstractFeatureIteratorFromSource<QgsVectorLayerFeatureSource>( source, ownSource, request )
@@ -78,6 +78,13 @@ class CORE_EXPORT QgsVectorLayerFeatureSource : public QgsAbstractFeatureSource
*/
QgsCoordinateReferenceSystem crs() const;

/**
* Returns the layer id of the source layer.
*
* \since QGIS 3.4
*/
QString id() const;

protected:

QgsAbstractFeatureSource *mProviderFeatureSource = nullptr;
@@ -88,6 +95,8 @@ class CORE_EXPORT QgsVectorLayerFeatureSource : public QgsAbstractFeatureSource

QgsFields mFields;

QString mId;

QgsExpressionContextScope mLayerScope;

bool mHasEditBuffer;

0 comments on commit 11b2683

Please sign in to comment.
You can’t perform that action at this time.