Skip to content

Commit 7e345a7

Browse files
authored
Merge pull request #4561 from nyalldawson/proj_thread2
Avoid using thread unsafe proj API - approach 2
2 parents 59c9743 + 5201eb2 commit 7e345a7

7 files changed

+427
-307
lines changed

src/app/qgscustomprojectiondialog.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -453,8 +453,8 @@ void QgsCustomProjectionDialog::on_pbnCalculate_clicked()
453453
//
454454
// We must check the prj def is valid!
455455
//
456-
457-
projPJ myProj = pj_init_plus( teParameters->toPlainText().toLocal8Bit().data() );
456+
projCtx pContext = pj_ctx_alloc();
457+
projPJ myProj = pj_init_plus_ctx( pContext, teParameters->toPlainText().toLocal8Bit().data() );
458458

459459
QgsDebugMsg( QString( "My proj: %1" ).arg( teParameters->toPlainText() ) );
460460

@@ -465,6 +465,7 @@ void QgsCustomProjectionDialog::on_pbnCalculate_clicked()
465465
projectedX->setText( QLatin1String( "" ) );
466466
projectedY->setText( QLatin1String( "" ) );
467467
pj_free( myProj );
468+
pj_ctx_free( pContext );
468469
return;
469470

470471
}
@@ -480,10 +481,11 @@ void QgsCustomProjectionDialog::on_pbnCalculate_clicked()
480481
projectedX->setText( QLatin1String( "" ) );
481482
projectedY->setText( QLatin1String( "" ) );
482483
pj_free( myProj );
484+
pj_ctx_free( pContext );
483485
return;
484486
}
485487

486-
projPJ wgs84Proj = pj_init_plus( GEOPROJ4.toLocal8Bit().data() ); //defined in qgis.h
488+
projPJ wgs84Proj = pj_init_plus_ctx( pContext, GEOPROJ4.toLocal8Bit().data() ); //defined in qgis.h
487489

488490
if ( !wgs84Proj )
489491
{
@@ -492,6 +494,7 @@ void QgsCustomProjectionDialog::on_pbnCalculate_clicked()
492494
projectedX->setText( QLatin1String( "" ) );
493495
projectedY->setText( QLatin1String( "" ) );
494496
pj_free( wgs84Proj );
497+
pj_ctx_free( pContext );
495498
return;
496499
}
497500

@@ -517,6 +520,7 @@ void QgsCustomProjectionDialog::on_pbnCalculate_clicked()
517520
//
518521
pj_free( myProj );
519522
pj_free( wgs84Proj );
523+
pj_ctx_free( pContext );
520524

521525
}
522526

src/core/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ SET(QGIS_CORE_SRCS
128128
qgscontexthelp.cpp
129129
qgscoordinatereferencesystem.cpp
130130
qgscoordinatetransform.cpp
131+
qgscoordinatetransform_p.cpp
131132
qgscoordinateutils.cpp
132133
qgscredentials.cpp
133134
qgscrscache.cpp

src/core/qgscoordinatereferencesystem.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1099,16 +1099,18 @@ void QgsCoordinateReferenceSystem::setProj4String( const QString &proj4String )
10991099
// e.g if they lack a +ellps parameter, it will automatically add +ellps=WGS84, but as
11001100
// we use the original mProj4 with QgsCoordinateTransform, it will fail to initialize
11011101
// so better detect it now.
1102-
projPJ proj = pj_init_plus( proj4String.trimmed().toLatin1().constData() );
1102+
projCtx pContext = pj_ctx_alloc();
1103+
projPJ proj = pj_init_plus_ctx( pContext, proj4String.trimmed().toLatin1().constData() );
11031104
if ( !proj )
11041105
{
1105-
QgsDebugMsgLevel( "proj.4 string rejected by pj_init_plus()", 4 );
1106+
QgsDebugMsgLevel( "proj.4 string rejected by pj_init_plus_ctx()", 4 );
11061107
d->mIsValid = false;
11071108
}
11081109
else
11091110
{
11101111
pj_free( proj );
11111112
}
1113+
pj_ctx_free( pContext );
11121114
d->mWkt.clear();
11131115
setMapUnits();
11141116
}
@@ -2020,6 +2022,8 @@ int QgsCoordinateReferenceSystem::syncDatabase()
20202022
sqlite3_errmsg( database ) );
20212023
}
20222024

2025+
projCtx pContext = pj_ctx_alloc();
2026+
20232027
#if !defined(PJ_VERSION) || PJ_VERSION!=470
20242028
sql = QStringLiteral( "select auth_name,auth_id,parameters from tbl_srs WHERE auth_name<>'EPSG' AND NOT deprecated AND NOT noupdate" );
20252029
if ( sqlite3_prepare( database, sql.toLatin1(), sql.size(), &select, &tail ) == SQLITE_OK )
@@ -2031,11 +2035,11 @@ int QgsCoordinateReferenceSystem::syncDatabase()
20312035
const char *params = reinterpret_cast< const char * >( sqlite3_column_text( select, 2 ) );
20322036

20332037
QString input = QStringLiteral( "+init=%1:%2" ).arg( QString( auth_name ).toLower(), auth_id );
2034-
projPJ pj = pj_init_plus( input.toLatin1() );
2038+
projPJ pj = pj_init_plus_ctx( pContext, input.toLatin1() );
20352039
if ( !pj )
20362040
{
20372041
input = QStringLiteral( "+init=%1:%2" ).arg( QString( auth_name ).toUpper(), auth_id );
2038-
pj = pj_init_plus( input.toLatin1() );
2042+
pj = pj_init_plus_ctx( pContext, input.toLatin1() );
20392043
}
20402044

20412045
if ( pj )
@@ -2099,6 +2103,7 @@ int QgsCoordinateReferenceSystem::syncDatabase()
20992103
sqlite3_finalize( select );
21002104
#endif
21012105

2106+
pj_ctx_free( pContext );
21022107

21032108
if ( sqlite3_exec( database, "COMMIT", nullptr, nullptr, nullptr ) != SQLITE_OK )
21042109
{

src/core/qgscoordinatetransform.cpp

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -474,8 +474,12 @@ void QgsCoordinateTransform::transformCoords( int numPoints, double *x, double *
474474

475475
// if the source/destination projection is lat/long, convert the points to radians
476476
// prior to transforming
477-
if ( ( pj_is_latlong( d->mDestinationProjection ) && ( direction == ReverseTransform ) )
478-
|| ( pj_is_latlong( d->mSourceProjection ) && ( direction == ForwardTransform ) ) )
477+
QPair<projPJ, projPJ> projData = d->threadLocalProjData();
478+
projPJ sourceProj = projData.first;
479+
projPJ destProj = projData.second;
480+
481+
if ( ( pj_is_latlong( destProj ) && ( direction == ReverseTransform ) )
482+
|| ( pj_is_latlong( sourceProj ) && ( direction == ForwardTransform ) ) )
479483
{
480484
for ( int i = 0; i < numPoints; ++i )
481485
{
@@ -487,13 +491,13 @@ void QgsCoordinateTransform::transformCoords( int numPoints, double *x, double *
487491
int projResult;
488492
if ( direction == ReverseTransform )
489493
{
490-
projResult = pj_transform( d->mDestinationProjection, d->mSourceProjection, numPoints, 0, x, y, z );
494+
projResult = pj_transform( destProj, sourceProj, numPoints, 0, x, y, z );
491495
}
492496
else
493497
{
494-
Q_ASSERT( d->mSourceProjection );
495-
Q_ASSERT( d->mDestinationProjection );
496-
projResult = pj_transform( d->mSourceProjection, d->mDestinationProjection, numPoints, 0, x, y, z );
498+
Q_ASSERT( sourceProj );
499+
Q_ASSERT( destProj );
500+
projResult = pj_transform( sourceProj, destProj, numPoints, 0, x, y, z );
497501
}
498502

499503
if ( projResult != 0 )
@@ -515,8 +519,8 @@ void QgsCoordinateTransform::transformCoords( int numPoints, double *x, double *
515519

516520
QString dir = ( direction == ForwardTransform ) ? QObject::tr( "forward transform" ) : QObject::tr( "inverse transform" );
517521

518-
char *srcdef = pj_get_def( d->mSourceProjection, 0 );
519-
char *dstdef = pj_get_def( d->mDestinationProjection, 0 );
522+
char *srcdef = pj_get_def( sourceProj, 0 );
523+
char *dstdef = pj_get_def( destProj, 0 );
520524

521525
QString msg = QObject::tr( "%1 of\n"
522526
"%2"
@@ -538,8 +542,8 @@ void QgsCoordinateTransform::transformCoords( int numPoints, double *x, double *
538542

539543
// if the result is lat/long, convert the results from radians back
540544
// to degrees
541-
if ( ( pj_is_latlong( d->mDestinationProjection ) && ( direction == ForwardTransform ) )
542-
|| ( pj_is_latlong( d->mSourceProjection ) && ( direction == ReverseTransform ) ) )
545+
if ( ( pj_is_latlong( destProj ) && ( direction == ForwardTransform ) )
546+
|| ( pj_is_latlong( sourceProj ) && ( direction == ReverseTransform ) ) )
543547
{
544548
for ( int i = 0; i < numPoints; ++i )
545549
{

src/core/qgscoordinatetransform.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ class CORE_EXPORT QgsCoordinateTransform
280280

281281
static void searchDatumTransform( const QString &sql, QList< int > &transforms );
282282

283-
QExplicitlySharedDataPointer<QgsCoordinateTransformPrivate> d;
283+
mutable QExplicitlySharedDataPointer<QgsCoordinateTransformPrivate> d;
284284
};
285285

286286
//! Output stream operator

0 commit comments

Comments
 (0)