Skip to content

Commit

Permalink
Don't use thread_local on mingw or OpenBSD builds
Browse files Browse the repository at this point in the history
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
  • Loading branch information
nyalldawson committed Nov 5, 2017
1 parent d269f34 commit 265be41
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 2 deletions.
20 changes: 19 additions & 1 deletion CMakeLists.txt
Expand Up @@ -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.")

Expand Down Expand Up @@ -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(
Expand Down
2 changes: 2 additions & 0 deletions cmake_templates/qgsconfig.h.in
Expand Up @@ -60,5 +60,7 @@

#cmakedefine HAVE_3D

#cmakedefine USE_THREAD_LOCAL

#endif

27 changes: 26 additions & 1 deletion src/core/qgscoordinatetransform_p.cpp
Expand Up @@ -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()
{
Expand Down Expand Up @@ -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();
Expand All @@ -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;
}
Expand Down Expand Up @@ -335,4 +361,3 @@ void QgsCoordinateTransformPrivate::freeProj()
}

///@endcond

10 changes: 10 additions & 0 deletions src/core/qgscoordinatetransform_p.h
Expand Up @@ -18,6 +18,7 @@
#define QGSCOORDINATETRANSFORMPRIVATE_H

#define SIP_NO_FILE
#include "qgsconfig.h"

/// @cond PRIVATE

Expand All @@ -31,6 +32,11 @@
//

#include <QSharedData>

#ifndef USE_THREAD_LOCAL
#include <QThreadStorage>
#endif

#include "qgscoordinatereferencesystem.h"

typedef void *projPJ;
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 265be41

Please sign in to comment.