OpenShot Library | OpenShotAudio 0.2.2
juce_ThreadLocalValue.h
1
2/** @weakgroup juce_core-threads
3 * @{
4 */
5/*
6 ==============================================================================
7
8 This file is part of the JUCE library.
9 Copyright (c) 2017 - ROLI Ltd.
10
11 JUCE is an open source library subject to commercial or open-source
12 licensing.
13
14 The code included in this file is provided under the terms of the ISC license
15 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
16 To use, copy, modify, and/or distribute this software for any purpose with or
17 without fee is hereby granted provided that the above copyright notice and
18 this permission notice appear in all copies.
19
20 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
21 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
22 DISCLAIMED.
23
24 ==============================================================================
25*/
26
27namespace juce
28{
29
30//==============================================================================
31/**
32 Provides cross-platform support for thread-local objects.
33
34 This class holds an internal list of objects of the templated type, keeping
35 an instance for each thread that requests one. The first time a thread attempts
36 to access its value, an object is created and added to the list for that thread.
37
38 Typically, you'll probably want to create a static instance of a ThreadLocalValue
39 object, or hold one within a singleton.
40
41 The templated class for your value must be a primitive type, or a simple POD struct.
42
43 When a thread no longer needs to use its value, it can call releaseCurrentThreadStorage()
44 to allow the storage to be re-used by another thread. If a thread exits without calling
45 this method, the object storage will be left allocated until the ThreadLocalValue object
46 is deleted.
47
48 @tags{Core}
49*/
50template <typename Type>
52{
53public:
54 /** */
55 ThreadLocalValue() = default;
56
57 /** Destructor.
58 When this object is deleted, all the value objects for all threads will be deleted.
59 */
61 {
62 for (auto* o = first.get(); o != nullptr;)
63 {
64 auto* next = o->next;
65 delete o;
66 o = next;
67 }
68 }
69
70 /** Returns a reference to this thread's instance of the value.
71 Note that the first time a thread tries to access the value, an instance of the
72 value object will be created - so if your value's class has a non-trivial
73 constructor, be aware that this method could invoke it.
74 */
75 Type& operator*() const noexcept { return get(); }
76
77 /** Returns a pointer to this thread's instance of the value.
78 Note that the first time a thread tries to access the value, an instance of the
79 value object will be created - so if your value's class has a non-trivial
80 constructor, be aware that this method could invoke it.
81 */
82 operator Type*() const noexcept { return &get(); }
83
84 /** Accesses a method or field of the value object.
85 Note that the first time a thread tries to access the value, an instance of the
86 value object will be created - so if your value's class has a non-trivial
87 constructor, be aware that this method could invoke it.
88 */
89 Type* operator->() const noexcept { return &get(); }
90
91 /** Assigns a new value to the thread-local object. */
92 ThreadLocalValue& operator= (const Type& newValue) { get() = newValue; return *this; }
93
94 /** Returns a reference to this thread's instance of the value.
95 Note that the first time a thread tries to access the value, an instance of the
96 value object will be created - so if your value's class has a non-trivial
97 constructor, be aware that this method could invoke it.
98 */
99 Type& get() const noexcept
100 {
101 auto threadId = Thread::getCurrentThreadId();
102 ObjectHolder* o = nullptr;
103
104 for (o = first.get(); o != nullptr; o = o->next)
105 if (o->threadId.get() == threadId)
106 return o->object;
107
108 for (o = first.get(); o != nullptr; o = o->next)
109 if (o->threadId.compareAndSetBool (threadId, nullptr))
110 break;
111
112 if (o != nullptr)
113 o->object = Type();
114 else
115 for (o = new ObjectHolder (threadId, first.get());
116 ! first.compareAndSetBool (o, o->next);
117 o->next = first.get());
118
119 return o->object;
120 }
121
122 /** Called by a thread before it terminates, to allow this class to release
123 any storage associated with the thread.
124 */
126 {
127 auto threadId = Thread::getCurrentThreadId();
128
129 for (auto* o = first.get(); o != nullptr; o = o->next)
130 if (o->threadId.compareAndSetBool (nullptr, threadId))
131 return;
132 }
133
134private:
135 //==============================================================================
136 struct ObjectHolder
137 {
138 ObjectHolder (Thread::ThreadID idToUse, ObjectHolder* n) : threadId (idToUse), next (n), object() {}
139
140 Atomic<Thread::ThreadID> threadId;
141 ObjectHolder* next;
142 Type object;
143
144 JUCE_DECLARE_NON_COPYABLE (ObjectHolder)
145 };
146
147 mutable Atomic<ObjectHolder*> first;
148
149 JUCE_DECLARE_NON_COPYABLE (ThreadLocalValue)
150};
151
152} // namespace juce
153
154/** @}*/
Provides cross-platform support for thread-local objects.
Type & operator*() const noexcept
Returns a reference to this thread's instance of the value.
Type * operator->() const noexcept
Accesses a method or field of the value object.
void releaseCurrentThreadStorage()
Called by a thread before it terminates, to allow this class to release any storage associated with t...
Type & get() const noexcept
Returns a reference to this thread's instance of the value.
ThreadLocalValue & operator=(const Type &newValue)
Assigns a new value to the thread-local object.
void * ThreadID
A value type used for thread IDs.
Definition: juce_Thread.h:308
static ThreadID JUCE_CALLTYPE getCurrentThreadId()
Returns an id that identifies the caller thread.
Type get() const noexcept
Atomically reads and returns the current value.
Definition: juce_Atomic.h:68
bool compareAndSetBool(Type newValue, Type valueToCompare) noexcept
Atomically compares this value with a target value, and if it is equal, sets this to be equal to a ne...
Definition: juce_Atomic.h:100