diff options
author | Marc Mutz <marc.mutz@kdab.com> | 2013-09-21 17:42:33 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-10-05 00:25:13 +0200 |
commit | c012ee2940bc087720b4aa0d257540921cf9a139 (patch) | |
tree | 793b3b94c8e7560fb83c0597a2c323dcc8b42a53 | |
parent | d519b085d18b7a2a4b4035c994def4872ca798bb (diff) |
QObject: use per-thread storage for qFlagLocation()
qFlagLocation() uses a global char* array to transport source location
information from the connect() side to the metaobject side. The size
of the array is 2 (two), which just about suffices for a single connect()
statement.
Obviously, if more than one thread makes a (_any_) connection at the same
time, the data is useless and, worse, there's a data race.
The non-reentrancy of qFlagLocations() cannot and need not be fixed,
but use a per-thread flagged_locations array in QThreadData so threads
don't disturb each other.
Task-number: QTBUG-3680
Change-Id: If1797c60751f551694def69afee6fbe295bbe2d2
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 20 | ||||
-rw-r--r-- | src/corelib/thread/qthread_p.h | 21 |
2 files changed, 27 insertions, 14 deletions
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index cc689657d2..9b7a849bf5 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -2029,14 +2029,9 @@ void QObject::deleteLater() *****************************************************************************/ -const int flagged_locations_count = 2; -static const char* flagged_locations[flagged_locations_count] = {0}; - const char *qFlagLocation(const char *method) { - static int idx = 0; - flagged_locations[idx] = method; - idx = (idx+1) % flagged_locations_count; + QThreadData::current()->flaggedSignatures.store(method); return method; } @@ -2048,14 +2043,11 @@ static int extract_code(const char *member) static const char * extract_location(const char *member) { - for (int i = 0; i < flagged_locations_count; ++i) { - if (member == flagged_locations[i]) { - // signature includes location information after the first null-terminator - const char *location = member + qstrlen(member) + 1; - if (*location != '\0') - return location; - return 0; - } + if (QThreadData::current()->flaggedSignatures.contains(member)) { + // signature includes location information after the first null-terminator + const char *location = member + qstrlen(member) + 1; + if (*location != '\0') + return location; } return 0; } diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h index 5e4eedaac7..fa1f7414f1 100644 --- a/src/corelib/thread/qthread_p.h +++ b/src/corelib/thread/qthread_p.h @@ -242,6 +242,26 @@ public: return canWait; } + // This class provides per-thread (by way of being a QThreadData + // member) storage for qFlagLocation() + class FlaggedDebugSignatures + { + static const uint Count = 2; + + uint idx; + const char* locations[Count]; + + public: + FlaggedDebugSignatures() : idx(0) + { std::fill_n(locations, Count, static_cast<char*>(0)); } + + void store(const char* method) + { locations[idx++ % Count] = method; } + + bool contains(const char *method) const + { return std::find(locations, locations + Count, method) != locations + Count; } + }; + QThread *thread; Qt::HANDLE threadId; bool quitNow; @@ -252,6 +272,7 @@ public: bool canWait; QVector<void *> tls; bool isAdopted; + FlaggedDebugSignatures flaggedSignatures; }; class QScopedLoopLevelCounter |