Skip to content

Commit

Permalink
Merge pull request #4561 from nyalldawson/proj_thread2
Browse files Browse the repository at this point in the history
Avoid using thread unsafe proj API - approach 2
  • Loading branch information
nyalldawson committed May 16, 2017
2 parents 59c9743 + 5201eb2 commit 7e345a7
Show file tree
Hide file tree
Showing 7 changed files with 427 additions and 307 deletions.
10 changes: 7 additions & 3 deletions src/app/qgscustomprojectiondialog.cpp
Expand Up @@ -453,8 +453,8 @@ void QgsCustomProjectionDialog::on_pbnCalculate_clicked()
//
// We must check the prj def is valid!
//

projPJ myProj = pj_init_plus( teParameters->toPlainText().toLocal8Bit().data() );
projCtx pContext = pj_ctx_alloc();
projPJ myProj = pj_init_plus_ctx( pContext, teParameters->toPlainText().toLocal8Bit().data() );

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

Expand All @@ -465,6 +465,7 @@ void QgsCustomProjectionDialog::on_pbnCalculate_clicked()
projectedX->setText( QLatin1String( "" ) );
projectedY->setText( QLatin1String( "" ) );
pj_free( myProj );
pj_ctx_free( pContext );
return;

}
Expand All @@ -480,10 +481,11 @@ void QgsCustomProjectionDialog::on_pbnCalculate_clicked()
projectedX->setText( QLatin1String( "" ) );
projectedY->setText( QLatin1String( "" ) );
pj_free( myProj );
pj_ctx_free( pContext );
return;
}

projPJ wgs84Proj = pj_init_plus( GEOPROJ4.toLocal8Bit().data() ); //defined in qgis.h
projPJ wgs84Proj = pj_init_plus_ctx( pContext, GEOPROJ4.toLocal8Bit().data() ); //defined in qgis.h

if ( !wgs84Proj )
{
Expand All @@ -492,6 +494,7 @@ void QgsCustomProjectionDialog::on_pbnCalculate_clicked()
projectedX->setText( QLatin1String( "" ) );
projectedY->setText( QLatin1String( "" ) );
pj_free( wgs84Proj );
pj_ctx_free( pContext );
return;
}

Expand All @@ -517,6 +520,7 @@ void QgsCustomProjectionDialog::on_pbnCalculate_clicked()
//
pj_free( myProj );
pj_free( wgs84Proj );
pj_ctx_free( pContext );

}

Expand Down
1 change: 1 addition & 0 deletions src/core/CMakeLists.txt
Expand Up @@ -128,6 +128,7 @@ SET(QGIS_CORE_SRCS
qgscontexthelp.cpp
qgscoordinatereferencesystem.cpp
qgscoordinatetransform.cpp
qgscoordinatetransform_p.cpp
qgscoordinateutils.cpp
qgscredentials.cpp
qgscrscache.cpp
Expand Down
13 changes: 9 additions & 4 deletions src/core/qgscoordinatereferencesystem.cpp
Expand Up @@ -1099,16 +1099,18 @@ void QgsCoordinateReferenceSystem::setProj4String( const QString &proj4String )
// e.g if they lack a +ellps parameter, it will automatically add +ellps=WGS84, but as
// we use the original mProj4 with QgsCoordinateTransform, it will fail to initialize
// so better detect it now.
projPJ proj = pj_init_plus( proj4String.trimmed().toLatin1().constData() );
projCtx pContext = pj_ctx_alloc();
projPJ proj = pj_init_plus_ctx( pContext, proj4String.trimmed().toLatin1().constData() );
if ( !proj )
{
QgsDebugMsgLevel( "proj.4 string rejected by pj_init_plus()", 4 );
QgsDebugMsgLevel( "proj.4 string rejected by pj_init_plus_ctx()", 4 );
d->mIsValid = false;
}
else
{
pj_free( proj );
}
pj_ctx_free( pContext );
d->mWkt.clear();
setMapUnits();
}
Expand Down Expand Up @@ -2020,6 +2022,8 @@ int QgsCoordinateReferenceSystem::syncDatabase()
sqlite3_errmsg( database ) );
}

projCtx pContext = pj_ctx_alloc();

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

QString input = QStringLiteral( "+init=%1:%2" ).arg( QString( auth_name ).toLower(), auth_id );
projPJ pj = pj_init_plus( input.toLatin1() );
projPJ pj = pj_init_plus_ctx( pContext, input.toLatin1() );
if ( !pj )
{
input = QStringLiteral( "+init=%1:%2" ).arg( QString( auth_name ).toUpper(), auth_id );
pj = pj_init_plus( input.toLatin1() );
pj = pj_init_plus_ctx( pContext, input.toLatin1() );
}

if ( pj )
Expand Down Expand Up @@ -2099,6 +2103,7 @@ int QgsCoordinateReferenceSystem::syncDatabase()
sqlite3_finalize( select );
#endif

pj_ctx_free( pContext );

if ( sqlite3_exec( database, "COMMIT", nullptr, nullptr, nullptr ) != SQLITE_OK )
{
Expand Down
24 changes: 14 additions & 10 deletions src/core/qgscoordinatetransform.cpp
Expand Up @@ -474,8 +474,12 @@ void QgsCoordinateTransform::transformCoords( int numPoints, double *x, double *

// if the source/destination projection is lat/long, convert the points to radians
// prior to transforming
if ( ( pj_is_latlong( d->mDestinationProjection ) && ( direction == ReverseTransform ) )
|| ( pj_is_latlong( d->mSourceProjection ) && ( direction == ForwardTransform ) ) )
QPair<projPJ, projPJ> projData = d->threadLocalProjData();
projPJ sourceProj = projData.first;
projPJ destProj = projData.second;

if ( ( pj_is_latlong( destProj ) && ( direction == ReverseTransform ) )
|| ( pj_is_latlong( sourceProj ) && ( direction == ForwardTransform ) ) )
{
for ( int i = 0; i < numPoints; ++i )
{
Expand All @@ -487,13 +491,13 @@ void QgsCoordinateTransform::transformCoords( int numPoints, double *x, double *
int projResult;
if ( direction == ReverseTransform )
{
projResult = pj_transform( d->mDestinationProjection, d->mSourceProjection, numPoints, 0, x, y, z );
projResult = pj_transform( destProj, sourceProj, numPoints, 0, x, y, z );
}
else
{
Q_ASSERT( d->mSourceProjection );
Q_ASSERT( d->mDestinationProjection );
projResult = pj_transform( d->mSourceProjection, d->mDestinationProjection, numPoints, 0, x, y, z );
Q_ASSERT( sourceProj );
Q_ASSERT( destProj );
projResult = pj_transform( sourceProj, destProj, numPoints, 0, x, y, z );
}

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

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

char *srcdef = pj_get_def( d->mSourceProjection, 0 );
char *dstdef = pj_get_def( d->mDestinationProjection, 0 );
char *srcdef = pj_get_def( sourceProj, 0 );
char *dstdef = pj_get_def( destProj, 0 );

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

// if the result is lat/long, convert the results from radians back
// to degrees
if ( ( pj_is_latlong( d->mDestinationProjection ) && ( direction == ForwardTransform ) )
|| ( pj_is_latlong( d->mSourceProjection ) && ( direction == ReverseTransform ) ) )
if ( ( pj_is_latlong( destProj ) && ( direction == ForwardTransform ) )
|| ( pj_is_latlong( sourceProj ) && ( direction == ReverseTransform ) ) )
{
for ( int i = 0; i < numPoints; ++i )
{
Expand Down
2 changes: 1 addition & 1 deletion src/core/qgscoordinatetransform.h
Expand Up @@ -280,7 +280,7 @@ class CORE_EXPORT QgsCoordinateTransform

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

QExplicitlySharedDataPointer<QgsCoordinateTransformPrivate> d;
mutable QExplicitlySharedDataPointer<QgsCoordinateTransformPrivate> d;
};

//! Output stream operator
Expand Down

0 comments on commit 7e345a7

Please sign in to comment.