Browse Source

Fixed a bug where ThreadLocalValue would inadvertently share its value between different instances of the same Type

tags/2021-05-28
hogliux 8 years ago
parent
commit
41f7835119
3 changed files with 67 additions and 18 deletions
  1. +3
    -0
      modules/juce_core/system/juce_CompilerSupport.h
  2. +57
    -1
      modules/juce_core/threads/juce_Thread.cpp
  3. +7
    -17
      modules/juce_core/threads/juce_ThreadLocalValue.h

+ 3
- 0
modules/juce_core/system/juce_CompilerSupport.h View File

@@ -44,6 +44,7 @@
#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406
#define JUCE_STDLIB_HAS_STD_FUNCTION_SUPPORT 1
#define JUCE_COMPILER_SUPPORTS_THREAD_LOCAL 1
#endif
#ifndef JUCE_EXCEPTIONS_DISABLED
@@ -67,6 +68,7 @@
#if (defined (_LIBCPP_VERSION) || ! (JUCE_MAC || JUCE_IOS))
#define JUCE_STDLIB_HAS_STD_FUNCTION_SUPPORT 1
#define JUCE_COMPILER_SUPPORTS_THREAD_LOCAL 1
#endif
#if __has_feature (cxx_generalized_initializers) && (defined (_LIBCPP_VERSION) || ! (JUCE_MAC || JUCE_IOS))
@@ -106,6 +108,7 @@
#define JUCE_COMPILER_SUPPORTS_VARIADIC_TEMPLATES 1
#define JUCE_DELETED_FUNCTION = delete
#define JUCE_STDLIB_HAS_STD_FUNCTION_SUPPORT 1
#define JUCE_COMPILER_SUPPORTS_THREAD_LOCAL 1
#endif
#if _MSC_VER >= 1900


+ 57
- 1
modules/juce_core/threads/juce_Thread.cpp View File

@@ -277,9 +277,9 @@ bool JUCE_CALLTYPE Process::isRunningUnderDebugger() noexcept
return juce_isRunningUnderDebugger();
}
//==============================================================================
#if JUCE_UNIT_TESTS
//==============================================================================
class AtomicTests : public UnitTest
{
public:
@@ -401,4 +401,60 @@ public:
static AtomicTests atomicUnitTests;
//==============================================================================
class ThreadLocalValueUnitTest : public UnitTest, private Thread
{
public:
ThreadLocalValueUnitTest()
: UnitTest ("ThreadLocalValue"),
Thread ("ThreadLocalValue Thread")
{}
void runTest() override
{
beginTest ("values are thread local");
{
ThreadLocalValue<int> threadLocal;
sharedThreadLocal = &threadLocal;
sharedThreadLocal.get()->get() = 1;
startThread();
signalThreadShouldExit();
waitForThreadToExit (-1);
mainThreadResult = sharedThreadLocal.get()->get();
expectEquals (mainThreadResult.get(), 1);
expectEquals (auxThreadResult.get(), 2);
}
beginTest ("values are per-instance");
{
ThreadLocalValue<int> a, b;
a.get() = 1;
b.get() = 2;
expectEquals (a.get(), 1);
expectEquals (b.get(), 2);
}
}
private:
Atomic<int> mainThreadResult, auxThreadResult;
Atomic<ThreadLocalValue<int>*> sharedThreadLocal;
void run() override
{
sharedThreadLocal.get()->get() = 2;
auxThreadResult = sharedThreadLocal.get()->get();
}
};
ThreadLocalValueUnitTest threadLocalValueUnitTest;
#endif

+ 7
- 17
modules/juce_core/threads/juce_ThreadLocalValue.h View File

@@ -22,13 +22,6 @@
#pragma once
// (NB: on win32, native thread-locals aren't possible in a dynamically loaded DLL in XP).
#if ! ((JUCE_MSVC && (JUCE_64BIT || ! defined (JucePlugin_PluginCode))) \
|| (JUCE_MAC && JUCE_CLANG && defined (MAC_OS_X_VERSION_10_7) \
&& MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7))
#define JUCE_NO_COMPILER_THREAD_LOCAL 1
#endif
//==============================================================================
/**
Provides cross-platform support for thread-local objects.
@@ -61,7 +54,7 @@ public:
*/
~ThreadLocalValue()
{
#if JUCE_NO_COMPILER_THREAD_LOCAL
#if ! JUCE_COMPILER_SUPPORTS_THREAD_LOCAL
for (ObjectHolder* o = first.value; o != nullptr;)
{
ObjectHolder* const next = o->next;
@@ -102,7 +95,10 @@ public:
*/
Type& get() const noexcept
{
#if JUCE_NO_COMPILER_THREAD_LOCAL
#if JUCE_COMPILER_SUPPORTS_THREAD_LOCAL
static thread_local HashMap<const void*, Type> holder;
return holder.getReference (this);
#else
const Thread::ThreadID threadId = Thread::getCurrentThreadId();
for (ObjectHolder* o = first.get(); o != nullptr; o = o->next)
@@ -136,12 +132,6 @@ public:
while (! first.compareAndSetBool (newObject, newObject->next));
return newObject->object;
#elif JUCE_MAC
static __thread Type object;
return object;
#elif JUCE_MSVC
static __declspec(thread) Type object;
return object;
#endif
}
@@ -150,7 +140,7 @@ public:
*/
void releaseCurrentThreadStorage()
{
#if JUCE_NO_COMPILER_THREAD_LOCAL
#if ! JUCE_COMPILER_SUPPORTS_THREAD_LOCAL
const Thread::ThreadID threadId = Thread::getCurrentThreadId();
for (ObjectHolder* o = first.get(); o != nullptr; o = o->next)
@@ -166,7 +156,7 @@ public:
private:
//==============================================================================
#if JUCE_NO_COMPILER_THREAD_LOCAL
#if ! JUCE_COMPILER_SUPPORTS_THREAD_LOCAL
struct ObjectHolder
{
ObjectHolder (const Thread::ThreadID& tid)


Loading…
Cancel
Save