Skip to content

Commit

Permalink
Fix GPX provider is not thread safe!
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Jul 30, 2021
1 parent 531428d commit aa68824
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 13 deletions.
35 changes: 23 additions & 12 deletions src/providers/gpx/gpsdata.cpp
Expand Up @@ -24,6 +24,7 @@
#include <QTextStream>
#include <QObject>
#include <QSet>
#include <QMutexLocker>

#include "gpsdata.h"
#include "qgslogger.h"
Expand Down Expand Up @@ -140,6 +141,19 @@ void QgsTrack::writeXml( QTextStream &stream )
}


//
// QgsGpsData
//

QgsGpsData::DataMap QgsGpsData::sDataObjects;


#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
QMutex QgsGpsData::sDataObjectsMutex { QMutex::Recursive };
#else
QRecursiveMutex QgsGpsData::sDataObjectsMutex;
#endif

QgsGpsData::QgsGpsData()
{
xMin = std::numeric_limits<double>::max();
Expand Down Expand Up @@ -369,7 +383,9 @@ void QgsGpsData::writeXml( QTextStream &stream )
QgsGpsData *QgsGpsData::getData( const QString &fileName )
{
// if the data isn't there already, try to load it
if ( dataObjects.find( fileName ) == dataObjects.end() )
QMutexLocker lock( &sDataObjectsMutex );

if ( sDataObjects.find( fileName ) == sDataObjects.end() )
{
QFile file( fileName );
if ( !file.open( QIODevice::ReadOnly ) )
Expand Down Expand Up @@ -411,45 +427,40 @@ QgsGpsData *QgsGpsData::getData( const QString &fileName )

data->setNoDataExtent();

dataObjects[fileName] = qMakePair( data, 0 );
sDataObjects[fileName] = qMakePair( data, 0 );
}
else
{
QgsDebugMsg( fileName + " is already loaded" );
}

// return a pointer and increase the reference count for that file name
DataMap::iterator iter = dataObjects.find( fileName );
DataMap::iterator iter = sDataObjects.find( fileName );
++( iter.value().second );
return ( QgsGpsData * )( iter.value().first );
}


void QgsGpsData::releaseData( const QString &fileName )
{
QMutexLocker lock( &sDataObjectsMutex );

/* decrease the reference count for the file name (if it is used), and erase
it if the reference count becomes 0 */
DataMap::iterator iter = dataObjects.find( fileName );
if ( iter != dataObjects.end() )
DataMap::iterator iter = sDataObjects.find( fileName );
if ( iter != sDataObjects.end() )
{
QgsDebugMsg( "unrefing " + fileName );
if ( --( iter.value().second ) == 0 )
{
QgsDebugMsg( "No one's using " + fileName + ", I'll erase it" );
delete iter.value().first;
dataObjects.erase( iter );
sDataObjects.erase( iter );
}
}
}


// we have to initialize the static member
QgsGpsData::DataMap QgsGpsData::dataObjects;




bool QgsGPXHandler::startElement( const XML_Char *qName, const XML_Char **attr )
{

Expand Down
10 changes: 9 additions & 1 deletion src/providers/gpx/gpsdata.h
Expand Up @@ -24,6 +24,7 @@
#include <QString>
#include <QTextStream>
#include <QStack>
#include <QMutex>

#include "qgsrectangle.h"
#include "qgsfeatureid.h"
Expand Down Expand Up @@ -280,7 +281,14 @@ class QgsGpsData
* does reference counting, so several providers can use the same GPSData
* object.
*/
static DataMap dataObjects;
static DataMap sDataObjects;

//! Mutex for sDataObjects
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
static QMutex sDataObjectsMutex;
#else
static QRecursiveMutex sDataObjectsMutex;
#endif

};

Expand Down

0 comments on commit aa68824

Please sign in to comment.