Skip to content

Commit 265be41

Browse files
committed
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
1 parent d269f34 commit 265be41

File tree

4 files changed

+57
-2
lines changed

4 files changed

+57
-2
lines changed

CMakeLists.txt

+19-1
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,24 @@ IF(WITH_CORE)
142142
ENDIF (OSGEARTHQT_LIBRARY)
143143
ENDIF (WITH_GLOBE)
144144

145+
SET (WITH_THREAD_LOCAL TRUE CACHE BOOL "Determines whether std::thread_local should be used")
146+
MARK_AS_ADVANCED(WITH_THREAD_LOCAL)
147+
148+
IF (MINGW OR CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
149+
# MingW has broken support for thread_local, so force disabling it
150+
# see
151+
# https://sourceforge.net/p/mingw-w64/bugs/445/
152+
# https://sourceforge.net/p/mingw-w64/bugs/527/
153+
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80816
154+
155+
# also OpenBSD has no thread_local support, see https://issues.qgis.org/issues/17351
156+
157+
ELSE (MINGW OR CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
158+
IF (WITH_THREAD_LOCAL)
159+
SET (USE_THREAD_LOCAL TRUE) # used in qgsconfig.h
160+
ENDIF (WITH_THREAD_LOCAL)
161+
ENDIF (MINGW OR CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" OR CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
162+
145163
# Compile flag. Make it possible to turn it off.
146164
SET (PEDANTIC TRUE CACHE BOOL "Determines if we should compile in pedantic mode.")
147165

@@ -736,7 +754,7 @@ ENDIF (WITH_CORE)
736754
####################################################
737755
# clang-tidy
738756
SET (WITH_CLANG_TIDY FALSE CACHE BOOL "Use Clang tidy")
739-
MARK_AS_ADVANCED(WITH_CORE)
757+
MARK_AS_ADVANCED(WITH_CLANG_TIDY)
740758
IF (WITH_CORE)
741759
IF(WITH_CLANG_TIDY)
742760
FIND_PROGRAM(

cmake_templates/qgsconfig.h.in

+2
Original file line numberDiff line numberDiff line change
@@ -60,5 +60,7 @@
6060

6161
#cmakedefine HAVE_3D
6262

63+
#cmakedefine USE_THREAD_LOCAL
64+
6365
#endif
6466

src/core/qgscoordinatetransform_p.cpp

+26-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,11 @@ extern "C"
2929

3030
/// @cond PRIVATE
3131

32+
#ifdef USE_THREAD_LOCAL
3233
thread_local QgsProjContextStore QgsCoordinateTransformPrivate::mProjContext;
34+
#else
35+
QThreadStorage< QgsProjContextStore * > QgsCoordinateTransformPrivate::mProjContext;
36+
#endif
3337

3438
QgsProjContextStore::QgsProjContextStore()
3539
{
@@ -185,7 +189,22 @@ QPair<projPJ, projPJ> QgsCoordinateTransformPrivate::threadLocalProjData()
185189
{
186190
mProjLock.lockForRead();
187191

192+
#ifdef USE_THREAD_LOCAL
188193
QMap < uintptr_t, QPair< projPJ, projPJ > >::const_iterator it = mProjProjections.constFind( reinterpret_cast< uintptr_t>( mProjContext.get() ) );
194+
#else
195+
projCtx pContext = nullptr;
196+
if ( mProjContext.hasLocalData() )
197+
{
198+
pContext = mProjContext.localData()->get();
199+
}
200+
else
201+
{
202+
mProjContext.setLocalData( new QgsProjContextStore() );
203+
pContext = mProjContext.localData()->get();
204+
}
205+
QMap < uintptr_t, QPair< projPJ, projPJ > >::const_iterator it = mProjProjections.constFind( reinterpret_cast< uintptr_t>( pContext ) );
206+
#endif
207+
189208
if ( it != mProjProjections.constEnd() )
190209
{
191210
QPair<projPJ, projPJ> res = it.value();
@@ -196,9 +215,16 @@ QPair<projPJ, projPJ> QgsCoordinateTransformPrivate::threadLocalProjData()
196215
// proj projections don't exist yet, so we need to create
197216
mProjLock.unlock();
198217
mProjLock.lockForWrite();
218+
219+
#ifdef USE_THREAD_LOCAL
199220
QPair<projPJ, projPJ> res = qMakePair( pj_init_plus_ctx( mProjContext.get(), mSourceProjString.toUtf8() ),
200221
pj_init_plus_ctx( mProjContext.get(), mDestProjString.toUtf8() ) );
201222
mProjProjections.insert( reinterpret_cast< uintptr_t>( mProjContext.get() ), res );
223+
#else
224+
QPair<projPJ, projPJ> res = qMakePair( pj_init_plus_ctx( pContext, mSourceProjString.toUtf8() ),
225+
pj_init_plus_ctx( pContext, mDestProjString.toUtf8() ) );
226+
mProjProjections.insert( reinterpret_cast< uintptr_t>( pContext ), res );
227+
#endif
202228
mProjLock.unlock();
203229
return res;
204230
}
@@ -335,4 +361,3 @@ void QgsCoordinateTransformPrivate::freeProj()
335361
}
336362

337363
///@endcond
338-

src/core/qgscoordinatetransform_p.h

+10
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#define QGSCOORDINATETRANSFORMPRIVATE_H
1919

2020
#define SIP_NO_FILE
21+
#include "qgsconfig.h"
2122

2223
/// @cond PRIVATE
2324

@@ -31,6 +32,11 @@
3132
//
3233

3334
#include <QSharedData>
35+
36+
#ifndef USE_THREAD_LOCAL
37+
#include <QThreadStorage>
38+
#endif
39+
3440
#include "qgscoordinatereferencesystem.h"
3541

3642
typedef void *projPJ;
@@ -100,7 +106,11 @@ class QgsCoordinateTransformPrivate : public QSharedData
100106
* Thread local proj context storage. A new proj context will be created
101107
* for every thread.
102108
*/
109+
#ifdef USE_THREAD_LOCAL
103110
static thread_local QgsProjContextStore mProjContext;
111+
#else
112+
static QThreadStorage< QgsProjContextStore * > mProjContext;
113+
#endif
104114

105115
QReadWriteLock mProjLock;
106116
QMap < uintptr_t, QPair< projPJ, projPJ > > mProjProjections;

0 commit comments

Comments
 (0)