Skip to content

Commit 2480e26

Browse files
committed
Revert "Utilise thread safe proj API within QgsCoordinateTransform"
This reverts commit af3370d. This commit is not safe for 2.18.9 - remerge after release
1 parent 6768c89 commit 2480e26

3 files changed

Lines changed: 54 additions & 115 deletions

File tree

‎src/core/qgscoordinatereferencesystem.cpp‎

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -907,8 +907,7 @@ void QgsCoordinateReferenceSystem::setProj4String( const QString& theProj4String
907907
// e.g if they lack a +ellps parameter, it will automatically add +ellps=WGS84, but as
908908
// we use the original mProj4 with QgsCoordinateTransform, it will fail to initialize
909909
// so better detect it now.
910-
projCtx pContext = pj_ctx_alloc();
911-
projPJ theProj = pj_init_plus_ctx( pContext, theProj4String.trimmed().toLatin1().constData() );
910+
projPJ theProj = pj_init_plus( theProj4String.trimmed().toLatin1().constData() );
912911
if ( !theProj )
913912
{
914913
QgsDebugMsg( "proj.4 string rejected by pj_init_plus()" );
@@ -918,7 +917,6 @@ void QgsCoordinateReferenceSystem::setProj4String( const QString& theProj4String
918917
{
919918
pj_free( theProj );
920919
}
921-
pj_ctx_free( pContext );
922920
d->mWkt.clear();
923921
setMapUnits();
924922

@@ -1860,8 +1858,6 @@ int QgsCoordinateReferenceSystem::syncDb()
18601858
sqlite3_errmsg( database ) );
18611859
}
18621860

1863-
projCtx pContext = pj_ctx_alloc();
1864-
18651861
#if !defined(PJ_VERSION) || PJ_VERSION!=470
18661862
sql = QString( "select auth_name,auth_id,parameters from tbl_srs WHERE auth_name<>'EPSG' AND NOT deprecated AND NOT noupdate" );
18671863
if ( sqlite3_prepare( database, sql.toAscii(), sql.size(), &select, &tail ) == SQLITE_OK )
@@ -1873,11 +1869,11 @@ int QgsCoordinateReferenceSystem::syncDb()
18731869
const char *params = reinterpret_cast< const char * >( sqlite3_column_text( select, 2 ) );
18741870

18751871
QString input = QString( "+init=%1:%2" ).arg( QString( auth_name ).toLower(), auth_id );
1876-
projPJ pj = pj_init_plus_ctx( pContext, input.toAscii() );
1872+
projPJ pj = pj_init_plus( input.toAscii() );
18771873
if ( !pj )
18781874
{
18791875
input = QString( "+init=%1:%2" ).arg( QString( auth_name ).toUpper(), auth_id );
1880-
pj = pj_init_plus_ctx( pContext, input.toAscii() );
1876+
pj = pj_init_plus( input.toAscii() );
18811877
}
18821878

18831879
if ( pj )
@@ -1940,7 +1936,6 @@ int QgsCoordinateReferenceSystem::syncDb()
19401936
#endif
19411937

19421938
OSRDestroySpatialReference( crs );
1943-
pj_ctx_free( pContext );
19441939

19451940
if ( sqlite3_exec( database, "COMMIT", nullptr, nullptr, nullptr ) != SQLITE_OK )
19461941
{

‎src/core/qgscoordinatetransform.cpp‎

Lines changed: 43 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,12 @@ extern "C"
3737
// if defined shows all information about transform to stdout
3838
// #define COORDINATE_TRANSFORM_VERBOSE
3939

40-
QThreadStorage< QgsCoordinateTransform::QgsProjContextStore* > QgsCoordinateTransform::mProjContext;
41-
4240
QgsCoordinateTransform::QgsCoordinateTransform()
4341
: QObject()
4442
, mShortCircuit( false )
4543
, mInitialisedFlag( false )
44+
, mSourceProjection( nullptr )
45+
, mDestinationProjection( nullptr )
4646
, mSourceDatumTransform( -1 )
4747
, mDestinationDatumTransform( -1 )
4848
{
@@ -53,6 +53,8 @@ QgsCoordinateTransform::QgsCoordinateTransform( const QgsCoordinateReferenceSyst
5353
: QObject()
5454
, mShortCircuit( false )
5555
, mInitialisedFlag( false )
56+
, mSourceProjection( nullptr )
57+
, mDestinationProjection( nullptr )
5658
, mSourceDatumTransform( -1 )
5759
, mDestinationDatumTransform( -1 )
5860
{
@@ -67,6 +69,8 @@ QgsCoordinateTransform::QgsCoordinateTransform( long theSourceSrsId, long theDes
6769
, mInitialisedFlag( false )
6870
, mSourceCRS( QgsCRSCache::instance()->crsBySrsId( theSourceSrsId ) )
6971
, mDestCRS( QgsCRSCache::instance()->crsBySrsId( theDestSrsId ) )
72+
, mSourceProjection( nullptr )
73+
, mDestinationProjection( nullptr )
7074
, mSourceDatumTransform( -1 )
7175
, mDestinationDatumTransform( -1 )
7276
{
@@ -76,6 +80,8 @@ QgsCoordinateTransform::QgsCoordinateTransform( long theSourceSrsId, long theDes
7680
QgsCoordinateTransform::QgsCoordinateTransform( const QString& theSourceCRS, const QString& theDestCRS )
7781
: QObject()
7882
, mInitialisedFlag( false )
83+
, mSourceProjection( nullptr )
84+
, mDestinationProjection( nullptr )
7985
, mSourceDatumTransform( -1 )
8086
, mDestinationDatumTransform( -1 )
8187
{
@@ -94,6 +100,8 @@ QgsCoordinateTransform::QgsCoordinateTransform( long theSourceSrid,
94100
QgsCoordinateReferenceSystem::CrsType theSourceCRSType )
95101
: QObject()
96102
, mInitialisedFlag( false )
103+
, mSourceProjection( nullptr )
104+
, mDestinationProjection( nullptr )
97105
, mSourceDatumTransform( -1 )
98106
, mDestinationDatumTransform( -1 )
99107
{
@@ -110,7 +118,15 @@ QgsCoordinateTransform::QgsCoordinateTransform( long theSourceSrid,
110118

111119
QgsCoordinateTransform::~QgsCoordinateTransform()
112120
{
113-
freeProj();
121+
// free the proj objects
122+
if ( mSourceProjection )
123+
{
124+
pj_free( mSourceProjection );
125+
}
126+
if ( mDestinationProjection )
127+
{
128+
pj_free( mDestinationProjection );
129+
}
114130
}
115131

116132
QgsCoordinateTransform* QgsCoordinateTransform::clone() const
@@ -164,47 +180,49 @@ void QgsCoordinateTransform::initialise()
164180

165181
bool useDefaultDatumTransform = ( mSourceDatumTransform == - 1 && mDestinationDatumTransform == -1 );
166182

167-
freeProj();
183+
// init the projections (destination and source)
168184

169-
mSourceProjString = mSourceCRS.toProj4();
185+
pj_free( mSourceProjection );
186+
QString sourceProjString = mSourceCRS.toProj4();
170187
if ( !useDefaultDatumTransform )
171188
{
172-
mSourceProjString = stripDatumTransform( mSourceProjString );
189+
sourceProjString = stripDatumTransform( sourceProjString );
173190
}
174191
if ( mSourceDatumTransform != -1 )
175192
{
176-
mSourceProjString += ( ' ' + datumTransformString( mSourceDatumTransform ) );
193+
sourceProjString += ( ' ' + datumTransformString( mSourceDatumTransform ) );
177194
}
178195

179-
mDestProjString = mDestCRS.toProj4();
196+
pj_free( mDestinationProjection );
197+
QString destProjString = mDestCRS.toProj4();
180198
if ( !useDefaultDatumTransform )
181199
{
182-
mDestProjString = stripDatumTransform( mDestProjString );
200+
destProjString = stripDatumTransform( destProjString );
183201
}
184202
if ( mDestinationDatumTransform != -1 )
185203
{
186-
mDestProjString += ( ' ' + datumTransformString( mDestinationDatumTransform ) );
204+
destProjString += ( ' ' + datumTransformString( mDestinationDatumTransform ) );
187205
}
188206

189207
if ( !useDefaultDatumTransform )
190208
{
191-
addNullGridShifts( mSourceProjString, mDestProjString );
209+
addNullGridShifts( sourceProjString, destProjString );
192210
}
193211

194-
// create proj projections for current thread
195-
QPair< projPJ, projPJ > res = threadLocalProjData();
212+
mSourceProjection = pj_init_plus( sourceProjString.toUtf8() );
213+
mDestinationProjection = pj_init_plus( destProjString.toUtf8() );
196214

197215
#ifdef COORDINATE_TRANSFORM_VERBOSE
198216
QgsDebugMsg( "From proj : " + mSourceCRS.toProj4() );
199217
QgsDebugMsg( "To proj : " + mDestCRS.toProj4() );
200218
#endif
201219

202220
mInitialisedFlag = true;
203-
if ( !res.second )
221+
if ( !mDestinationProjection )
204222
{
205223
mInitialisedFlag = false;
206224
}
207-
if ( !res.first )
225+
if ( !mSourceProjection )
208226
{
209227
mInitialisedFlag = false;
210228
}
@@ -643,12 +661,8 @@ void QgsCoordinateTransform::transformCoords( int numPoints, double *x, double *
643661
QString dir;
644662
// if the source/destination projection is lat/long, convert the points to radians
645663
// prior to transforming
646-
QPair< projPJ, projPJ > projData = threadLocalProjData();
647-
projPJ sourceProj = projData.first;
648-
projPJ destProj = projData.second;
649-
650-
if (( pj_is_latlong( destProj ) && ( direction == ReverseTransform ) )
651-
|| ( pj_is_latlong( sourceProj ) && ( direction == ForwardTransform ) ) )
664+
if (( pj_is_latlong( mDestinationProjection ) && ( direction == ReverseTransform ) )
665+
|| ( pj_is_latlong( mSourceProjection ) && ( direction == ForwardTransform ) ) )
652666
{
653667
for ( int i = 0; i < numPoints; ++i )
654668
{
@@ -660,13 +674,13 @@ void QgsCoordinateTransform::transformCoords( int numPoints, double *x, double *
660674
int projResult;
661675
if ( direction == ReverseTransform )
662676
{
663-
projResult = pj_transform( destProj, sourceProj, numPoints, 0, x, y, z );
677+
projResult = pj_transform( mDestinationProjection, mSourceProjection, numPoints, 0, x, y, z );
664678
}
665679
else
666680
{
667-
Q_ASSERT( sourceProj );
668-
Q_ASSERT( destProj );
669-
projResult = pj_transform( sourceProj, destProj, numPoints, 0, x, y, z );
681+
Q_ASSERT( mSourceProjection );
682+
Q_ASSERT( mDestinationProjection );
683+
projResult = pj_transform( mSourceProjection, mDestinationProjection, numPoints, 0, x, y, z );
670684
}
671685

672686
if ( projResult != 0 )
@@ -688,8 +702,8 @@ void QgsCoordinateTransform::transformCoords( int numPoints, double *x, double *
688702

689703
dir = ( direction == ForwardTransform ) ? tr( "forward transform" ) : tr( "inverse transform" );
690704

691-
char *srcdef = pj_get_def( sourceProj, 0 );
692-
char *dstdef = pj_get_def( destProj, 0 );
705+
char *srcdef = pj_get_def( mSourceProjection, 0 );
706+
char *dstdef = pj_get_def( mDestinationProjection, 0 );
693707

694708
QString msg = tr( "%1 of\n"
695709
"%2"
@@ -714,8 +728,8 @@ void QgsCoordinateTransform::transformCoords( int numPoints, double *x, double *
714728

715729
// if the result is lat/long, convert the results from radians back
716730
// to degrees
717-
if (( pj_is_latlong( destProj ) && ( direction == ForwardTransform ) )
718-
|| ( pj_is_latlong( sourceProj ) && ( direction == ReverseTransform ) ) )
731+
if (( pj_is_latlong( mDestinationProjection ) && ( direction == ForwardTransform ) )
732+
|| ( pj_is_latlong( mSourceProjection ) && ( direction == ReverseTransform ) ) )
719733
{
720734
for ( int i = 0; i < numPoints; ++i )
721735
{
@@ -1041,56 +1055,3 @@ void QgsCoordinateTransform::addNullGridShifts( QString& srcProjString, QString&
10411055
destProjString += " +nadgrids=@null";
10421056
}
10431057
}
1044-
1045-
QPair<projPJ, projPJ> QgsCoordinateTransform::threadLocalProjData() const
1046-
{
1047-
mProjLock.lockForRead();
1048-
projCtx pContext = nullptr;
1049-
if ( mProjContext.hasLocalData() )
1050-
pContext = mProjContext.localData()->get();
1051-
else
1052-
{
1053-
mProjContext.setLocalData( new QgsProjContextStore() );
1054-
pContext = mProjContext.localData()->get();
1055-
}
1056-
1057-
QMap< uintptr_t, QPair< projPJ, projPJ > >::const_iterator it = mProjProjections.constFind( reinterpret_cast< uintptr_t >( pContext ) );
1058-
if ( it != mProjProjections.constEnd() )
1059-
{
1060-
QPair< projPJ, projPJ > res = it.value();
1061-
mProjLock.unlock();
1062-
return res;
1063-
}
1064-
1065-
// proj projections don't exist yet, so we need to create
1066-
mProjLock.unlock();
1067-
mProjLock.lockForWrite();
1068-
QPair< projPJ, projPJ > res = qMakePair( pj_init_plus_ctx( pContext, mSourceProjString.toUtf8() ),
1069-
pj_init_plus_ctx( pContext, mDestProjString.toUtf8() ) );
1070-
mProjProjections.insert( reinterpret_cast< uintptr_t >( pContext ), res );
1071-
mProjLock.unlock();
1072-
return res;
1073-
}
1074-
1075-
void QgsCoordinateTransform::freeProj()
1076-
{
1077-
mProjLock.lockForWrite();
1078-
QMap< uintptr_t, QPair< projPJ, projPJ > >::const_iterator it = mProjProjections.constBegin();
1079-
for ( ; it != mProjProjections.constEnd(); ++it )
1080-
{
1081-
pj_free( it.value().first );
1082-
pj_free( it.value().second );
1083-
}
1084-
mProjProjections.clear();
1085-
mProjLock.unlock();
1086-
}
1087-
1088-
QgsCoordinateTransform::QgsProjContextStore::QgsProjContextStore()
1089-
{
1090-
context = pj_ctx_alloc();
1091-
}
1092-
1093-
QgsCoordinateTransform::QgsProjContextStore::~QgsProjContextStore()
1094-
{
1095-
pj_ctx_free( context );
1096-
}

‎src/core/qgscoordinatetransform.h‎

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@
1919

2020
//qt includes
2121
#include <QObject>
22-
#include <QThreadStorage>
23-
#include <QReadWriteLock>
2422

2523
//qgis includes
2624
#include "qgspoint.h"
@@ -36,7 +34,6 @@ class QPolygonF;
3634
#include <vector>
3735

3836
typedef void* projPJ;
39-
typedef void* projCtx;
4037
class QString;
4138

4239
/** \ingroup core
@@ -277,26 +274,15 @@ class CORE_EXPORT QgsCoordinateTransform : public QObject
277274
*/
278275
QgsCoordinateReferenceSystem mDestCRS;
279276

280-
QString mSourceProjString;
281-
QString mDestProjString;
282-
283-
class QgsProjContextStore
284-
{
285-
public:
286-
287-
QgsProjContextStore();
288-
~QgsProjContextStore();
289-
290-
projCtx get() { return context; }
291-
292-
private:
293-
294-
projCtx context;
295-
};
277+
/*!
278+
* Proj4 data structure of the source projection (layer coordinate system)
279+
*/
280+
projPJ mSourceProjection;
296281

297-
static QThreadStorage< QgsProjContextStore* > mProjContext;
298-
mutable QReadWriteLock mProjLock;
299-
mutable QMap< uintptr_t, QPair< projPJ, projPJ > > mProjProjections;
282+
/*!
283+
* Proj4 data structure of the destination projection (map canvas coordinate system)
284+
*/
285+
projPJ mDestinationProjection;
300286

301287
int mSourceDatumTransform;
302288
int mDestinationDatumTransform;
@@ -311,9 +297,6 @@ class CORE_EXPORT QgsCoordinateTransform : public QObject
311297
static void searchDatumTransform( const QString& sql, QList< int >& transforms );
312298
/** In certain situations, null grid shifts have to be added to src / dst proj string*/
313299
void addNullGridShifts( QString& srcProjString, QString& destProjString );
314-
315-
QPair< projPJ, projPJ > threadLocalProjData() const;
316-
void freeProj();
317300
};
318301

319302
//! Output stream operator

0 commit comments

Comments
 (0)