Skip to content

Commit

Permalink
QgsCoordinateTransformContext must be thread safe
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Dec 15, 2017
1 parent 5131258 commit 7af5545
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 15 deletions.
4 changes: 4 additions & 0 deletions python/core/qgscoordinatetransformcontext.sip
Expand Up @@ -27,6 +27,10 @@ class QgsCoordinateTransformContext
addSourceDatumTransform() then this datum transform will be used. The same logic
applies for destination CRS transforms set using addDestinationDatumTransform().

.. note::

QgsCoordinateTransformContext objects are thread safe for read and write.

.. note::

QgsCoordinateTransformContext objects are implicitly shared.
Expand Down
49 changes: 37 additions & 12 deletions src/core/qgscoordinatetransformcontext.cpp
Expand Up @@ -34,14 +34,21 @@ QgsCoordinateTransformContext &QgsCoordinateTransformContext::operator=( const Q
void QgsCoordinateTransformContext::clear()
{
d.detach();
// play it safe
d->mLock.lockForWrite();
d->mSourceDestDatumTransforms.clear();
d->mSourceDatumTransforms.clear();
d->mDestDatumTransforms.clear();
d->mLock.unlock();
}

QMap<QString, int> QgsCoordinateTransformContext::sourceDatumTransforms() const
{
return d->mSourceDatumTransforms;
d->mLock.lockForRead();
auto res = d->mSourceDatumTransforms;
res.detach();
d->mLock.unlock();
return res;
}

bool QgsCoordinateTransformContext::addSourceDatumTransform( const QgsCoordinateReferenceSystem &crs, int transform )
Expand All @@ -50,19 +57,26 @@ bool QgsCoordinateTransformContext::addSourceDatumTransform( const QgsCoordinate
return false;

d.detach();
d->mLock.lockForWrite();
if ( transform == -1 )
{
d->mSourceDatumTransforms.remove( crs.authid() );
return true;
}

d->mSourceDatumTransforms.insert( crs.authid(), transform );
else
{
d->mSourceDatumTransforms.insert( crs.authid(), transform );
}
d->mLock.unlock();
return true;
}

QMap<QString, int> QgsCoordinateTransformContext::destinationDatumTransforms() const
{
return d->mDestDatumTransforms;
d->mLock.lockForRead();
auto res = d->mDestDatumTransforms;
res.detach();
d->mLock.unlock();
return res;
}

bool QgsCoordinateTransformContext::addDestinationDatumTransform( const QgsCoordinateReferenceSystem &crs, int transform )
Expand All @@ -71,19 +85,27 @@ bool QgsCoordinateTransformContext::addDestinationDatumTransform( const QgsCoord
return false;

d.detach();

d->mLock.lockForWrite();
if ( transform == -1 )
{
d->mDestDatumTransforms.remove( crs.authid() );
return true;
}

d->mDestDatumTransforms.insert( crs.authid(), transform );
else
{
d->mDestDatumTransforms.insert( crs.authid(), transform );
}
d->mLock.unlock();
return true;
}

QMap<QPair<QString, QString>, QPair<int, int> > QgsCoordinateTransformContext::sourceDestinationDatumTransforms() const
{
return d->mSourceDestDatumTransforms;
d->mLock.lockForRead();
auto res = d->mSourceDestDatumTransforms;
res.detach();
d->mLock.unlock();
return res;
}

bool QgsCoordinateTransformContext::addSourceDestinationDatumTransform( const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs, int sourceTransform, int destinationTransform )
Expand All @@ -92,13 +114,16 @@ bool QgsCoordinateTransformContext::addSourceDestinationDatumTransform( const Qg
return false;

d.detach();
d->mLock.lockForWrite();
if ( sourceTransform == -1 || destinationTransform == -1 )
{
d->mSourceDestDatumTransforms.remove( qMakePair( sourceCrs.authid(), destinationCrs.authid() ) );
return true;
}

d->mSourceDestDatumTransforms.insert( qMakePair( sourceCrs.authid(), destinationCrs.authid() ), qMakePair( sourceTransform, destinationTransform ) );
else
{
d->mSourceDestDatumTransforms.insert( qMakePair( sourceCrs.authid(), destinationCrs.authid() ), qMakePair( sourceTransform, destinationTransform ) );
}
d->mLock.unlock();
return true;
}

Expand Down
2 changes: 2 additions & 0 deletions src/core/qgscoordinatetransformcontext.h
Expand Up @@ -44,6 +44,8 @@
* addSourceDatumTransform() then this datum transform will be used. The same logic
* applies for destination CRS transforms set using addDestinationDatumTransform().
*
* \note QgsCoordinateTransformContext objects are thread safe for read and write.
*
* \note QgsCoordinateTransformContext objects are implicitly shared.
*
* \since QGIS 3.0
Expand Down
11 changes: 8 additions & 3 deletions src/core/qgscoordinatetransformcontext_p.h
Expand Up @@ -47,10 +47,12 @@ class QgsCoordinateTransformContextPrivate : public QSharedData

QgsCoordinateTransformContextPrivate( const QgsCoordinateTransformContextPrivate &other )
: QSharedData( other )
, mSourceDestDatumTransforms( other.mSourceDestDatumTransforms )
, mSourceDatumTransforms( other.mSourceDatumTransforms )
, mDestDatumTransforms( other.mDestDatumTransforms )
{
other.mLock.lockForRead();
mSourceDestDatumTransforms = other.mSourceDestDatumTransforms;
mSourceDatumTransforms = other.mSourceDatumTransforms;
mDestDatumTransforms = other.mDestDatumTransforms;
other.mLock.unlock();
}

/**
Expand All @@ -65,6 +67,9 @@ class QgsCoordinateTransformContextPrivate : public QSharedData
//! Mapping for datum transforms to use for destination CRS
QMap< QString, int > mDestDatumTransforms;

//! Mutex for making QgsCoordinateTransformContextPrivate thread safe
mutable QReadWriteLock mLock;

};


Expand Down

0 comments on commit 7af5545

Please sign in to comment.