Skip to content

Commit 7af5545

Browse files
committed
QgsCoordinateTransformContext must be thread safe
1 parent 5131258 commit 7af5545

4 files changed

+51
-15
lines changed

python/core/qgscoordinatetransformcontext.sip

+4
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ class QgsCoordinateTransformContext
2727
addSourceDatumTransform() then this datum transform will be used. The same logic
2828
applies for destination CRS transforms set using addDestinationDatumTransform().
2929

30+
.. note::
31+
32+
QgsCoordinateTransformContext objects are thread safe for read and write.
33+
3034
.. note::
3135

3236
QgsCoordinateTransformContext objects are implicitly shared.

src/core/qgscoordinatetransformcontext.cpp

+37-12
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,21 @@ QgsCoordinateTransformContext &QgsCoordinateTransformContext::operator=( const Q
3434
void QgsCoordinateTransformContext::clear()
3535
{
3636
d.detach();
37+
// play it safe
38+
d->mLock.lockForWrite();
3739
d->mSourceDestDatumTransforms.clear();
3840
d->mSourceDatumTransforms.clear();
3941
d->mDestDatumTransforms.clear();
42+
d->mLock.unlock();
4043
}
4144

4245
QMap<QString, int> QgsCoordinateTransformContext::sourceDatumTransforms() const
4346
{
44-
return d->mSourceDatumTransforms;
47+
d->mLock.lockForRead();
48+
auto res = d->mSourceDatumTransforms;
49+
res.detach();
50+
d->mLock.unlock();
51+
return res;
4552
}
4653

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

5259
d.detach();
60+
d->mLock.lockForWrite();
5361
if ( transform == -1 )
5462
{
5563
d->mSourceDatumTransforms.remove( crs.authid() );
56-
return true;
5764
}
58-
59-
d->mSourceDatumTransforms.insert( crs.authid(), transform );
65+
else
66+
{
67+
d->mSourceDatumTransforms.insert( crs.authid(), transform );
68+
}
69+
d->mLock.unlock();
6070
return true;
6171
}
6272

6373
QMap<QString, int> QgsCoordinateTransformContext::destinationDatumTransforms() const
6474
{
65-
return d->mDestDatumTransforms;
75+
d->mLock.lockForRead();
76+
auto res = d->mDestDatumTransforms;
77+
res.detach();
78+
d->mLock.unlock();
79+
return res;
6680
}
6781

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

7387
d.detach();
88+
89+
d->mLock.lockForWrite();
7490
if ( transform == -1 )
7591
{
7692
d->mDestDatumTransforms.remove( crs.authid() );
77-
return true;
7893
}
79-
80-
d->mDestDatumTransforms.insert( crs.authid(), transform );
94+
else
95+
{
96+
d->mDestDatumTransforms.insert( crs.authid(), transform );
97+
}
98+
d->mLock.unlock();
8199
return true;
82100
}
83101

84102
QMap<QPair<QString, QString>, QPair<int, int> > QgsCoordinateTransformContext::sourceDestinationDatumTransforms() const
85103
{
86-
return d->mSourceDestDatumTransforms;
104+
d->mLock.lockForRead();
105+
auto res = d->mSourceDestDatumTransforms;
106+
res.detach();
107+
d->mLock.unlock();
108+
return res;
87109
}
88110

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

94116
d.detach();
117+
d->mLock.lockForWrite();
95118
if ( sourceTransform == -1 || destinationTransform == -1 )
96119
{
97120
d->mSourceDestDatumTransforms.remove( qMakePair( sourceCrs.authid(), destinationCrs.authid() ) );
98-
return true;
99121
}
100-
101-
d->mSourceDestDatumTransforms.insert( qMakePair( sourceCrs.authid(), destinationCrs.authid() ), qMakePair( sourceTransform, destinationTransform ) );
122+
else
123+
{
124+
d->mSourceDestDatumTransforms.insert( qMakePair( sourceCrs.authid(), destinationCrs.authid() ), qMakePair( sourceTransform, destinationTransform ) );
125+
}
126+
d->mLock.unlock();
102127
return true;
103128
}
104129

src/core/qgscoordinatetransformcontext.h

+2
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444
* addSourceDatumTransform() then this datum transform will be used. The same logic
4545
* applies for destination CRS transforms set using addDestinationDatumTransform().
4646
*
47+
* \note QgsCoordinateTransformContext objects are thread safe for read and write.
48+
*
4749
* \note QgsCoordinateTransformContext objects are implicitly shared.
4850
*
4951
* \since QGIS 3.0

src/core/qgscoordinatetransformcontext_p.h

+8-3
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,12 @@ class QgsCoordinateTransformContextPrivate : public QSharedData
4747

4848
QgsCoordinateTransformContextPrivate( const QgsCoordinateTransformContextPrivate &other )
4949
: QSharedData( other )
50-
, mSourceDestDatumTransforms( other.mSourceDestDatumTransforms )
51-
, mSourceDatumTransforms( other.mSourceDatumTransforms )
52-
, mDestDatumTransforms( other.mDestDatumTransforms )
5350
{
51+
other.mLock.lockForRead();
52+
mSourceDestDatumTransforms = other.mSourceDestDatumTransforms;
53+
mSourceDatumTransforms = other.mSourceDatumTransforms;
54+
mDestDatumTransforms = other.mDestDatumTransforms;
55+
other.mLock.unlock();
5456
}
5557

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

70+
//! Mutex for making QgsCoordinateTransformContextPrivate thread safe
71+
mutable QReadWriteLock mLock;
72+
6873
};
6974

7075

0 commit comments

Comments
 (0)