Don't use thread_local on mingw or OpenBSD builds

MingW has broken support for thread_local, so force disabling it
see
https://sourceforge.net/p/mingw-w64/bugs/445/
https://sourceforge.net/p/mingw-w64/bugs/527/
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80816

also OpenBSD has no thread_local support, see https://issues.qgis.org/issues/17351

So on these platforms we fall back to using QThreadStorage.

Fixes #17351
This commit is contained in:
Nyall Dawson 2017-11-06 09:16:12 +10:00
parent d269f34b58
commit 265be41d7c
4 changed files with 57 additions and 2 deletions

View File

@ -142,6 +142,24 @@ IF(WITH_CORE)
ENDIF (OSGEARTHQT_LIBRARY)
ENDIF (WITH_GLOBE)
SET (WITH_THREAD_LOCAL TRUE CACHE BOOL "Determines whether std::thread_local should be used")
MARK_AS_ADVANCED(WITH_THREAD_LOCAL)
IF (MINGW OR CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
# MingW has broken support for thread_local, so force disabling it
# see
# https://sourceforge.net/p/mingw-w64/bugs/445/
# https://sourceforge.net/p/mingw-w64/bugs/527/
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80816
# also OpenBSD has no thread_local support, see https://issues.qgis.org/issues/17351
ELSE (MINGW OR CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
IF (WITH_THREAD_LOCAL)
SET (USE_THREAD_LOCAL TRUE) # used in qgsconfig.h
ENDIF (WITH_THREAD_LOCAL)
ENDIF (MINGW OR CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
# Compile flag. Make it possible to turn it off.
SET (PEDANTIC TRUE CACHE BOOL "Determines if we should compile in pedantic mode.")
@ -736,7 +754,7 @@ ENDIF (WITH_CORE)
####################################################
# clang-tidy
SET (WITH_CLANG_TIDY FALSE CACHE BOOL "Use Clang tidy")
MARK_AS_ADVANCED(WITH_CORE)
MARK_AS_ADVANCED(WITH_CLANG_TIDY)
IF (WITH_CORE)
IF(WITH_CLANG_TIDY)
FIND_PROGRAM(

View File

@ -60,5 +60,7 @@
#cmakedefine HAVE_3D
#cmakedefine USE_THREAD_LOCAL
#endif

View File

@ -29,7 +29,11 @@ extern "C"
/// @cond PRIVATE
#ifdef USE_THREAD_LOCAL
thread_local QgsProjContextStore QgsCoordinateTransformPrivate::mProjContext;
#else
QThreadStorage< QgsProjContextStore * > QgsCoordinateTransformPrivate::mProjContext;
#endif
QgsProjContextStore::QgsProjContextStore()
{
@ -185,7 +189,22 @@ QPair<projPJ, projPJ> QgsCoordinateTransformPrivate::threadLocalProjData()
{
mProjLock.lockForRead();
#ifdef USE_THREAD_LOCAL
QMap < uintptr_t, QPair< projPJ, projPJ > >::const_iterator it = mProjProjections.constFind( reinterpret_cast< uintptr_t>( mProjContext.get() ) );
#else
projCtx pContext = nullptr;
if ( mProjContext.hasLocalData() )
{
pContext = mProjContext.localData()->get();
}
else
{
mProjContext.setLocalData( new QgsProjContextStore() );
pContext = mProjContext.localData()->get();
}
QMap < uintptr_t, QPair< projPJ, projPJ > >::const_iterator it = mProjProjections.constFind( reinterpret_cast< uintptr_t>( pContext ) );
#endif
if ( it != mProjProjections.constEnd() )
{
QPair<projPJ, projPJ> res = it.value();
@ -196,9 +215,16 @@ QPair<projPJ, projPJ> QgsCoordinateTransformPrivate::threadLocalProjData()
// proj projections don't exist yet, so we need to create
mProjLock.unlock();
mProjLock.lockForWrite();
#ifdef USE_THREAD_LOCAL
QPair<projPJ, projPJ> res = qMakePair( pj_init_plus_ctx( mProjContext.get(), mSourceProjString.toUtf8() ),
pj_init_plus_ctx( mProjContext.get(), mDestProjString.toUtf8() ) );
mProjProjections.insert( reinterpret_cast< uintptr_t>( mProjContext.get() ), res );
#else
QPair<projPJ, projPJ> res = qMakePair( pj_init_plus_ctx( pContext, mSourceProjString.toUtf8() ),
pj_init_plus_ctx( pContext, mDestProjString.toUtf8() ) );
mProjProjections.insert( reinterpret_cast< uintptr_t>( pContext ), res );
#endif
mProjLock.unlock();
return res;
}
@ -335,4 +361,3 @@ void QgsCoordinateTransformPrivate::freeProj()
}
///@endcond

View File

@ -18,6 +18,7 @@
#define QGSCOORDINATETRANSFORMPRIVATE_H
#define SIP_NO_FILE
#include "qgsconfig.h"
/// @cond PRIVATE
@ -31,6 +32,11 @@
//
#include <QSharedData>
#ifndef USE_THREAD_LOCAL
#include <QThreadStorage>
#endif
#include "qgscoordinatereferencesystem.h"
typedef void *projPJ;
@ -100,7 +106,11 @@ class QgsCoordinateTransformPrivate : public QSharedData
* Thread local proj context storage. A new proj context will be created
* for every thread.
*/
#ifdef USE_THREAD_LOCAL
static thread_local QgsProjContextStore mProjContext;
#else
static QThreadStorage< QgsProjContextStore * > mProjContext;
#endif
QReadWriteLock mProjLock;
QMap < uintptr_t, QPair< projPJ, projPJ > > mProjProjections;