Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(87)

Side by Side Diff: third_party/WebKit/Source/wtf/StdLibExtras.h

Issue 2680843006: Tidy DEFINE_(THREAD_SAFE_)STATIC_LOCAL() implementations. (Closed)
Patch Set: simplify DEFINE_THREAD_SAFE_STATIC_LOCAL() Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | third_party/WebKit/Source/wtf/Threading.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * 12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */ 24 */
25 25
26 #ifndef WTF_StdLibExtras_h 26 #ifndef WTF_StdLibExtras_h
27 #define WTF_StdLibExtras_h 27 #define WTF_StdLibExtras_h
28 28
29 #include <cstddef>
29 #include "base/numerics/safe_conversions.h" 30 #include "base/numerics/safe_conversions.h"
30 #include "wtf/Assertions.h" 31 #include "wtf/Assertions.h"
31 #include "wtf/CPU.h" 32 #include "wtf/CPU.h"
32 #include "wtf/LeakAnnotations.h" 33 #include "wtf/LeakAnnotations.h"
34 #include "wtf/Noncopyable.h"
33 #include "wtf/TypeTraits.h" 35 #include "wtf/TypeTraits.h"
34 #include <cstddef>
35 36
36 #if DCHECK_IS_ON() 37 #if DCHECK_IS_ON()
37 #include "wtf/Noncopyable.h"
38 #include "wtf/Threading.h" 38 #include "wtf/Threading.h"
39 #endif
39 40
40 class WTF_EXPORT StaticLocalVerifier { 41 // Use |DEFINE_STATIC_LOCAL()| to declare and define a static local variable
41 WTF_MAKE_NONCOPYABLE(StaticLocalVerifier); 42 // (|static T;|) so that it is leaked and its destructors are not called at
43 // exit. T may also be a Blink garbage collected object, in which case it is
44 // wrapped up by an off-heap |Persistent<T>| reference to the object, keeping
45 // it alive across GCs.
46 //
47 // A |DEFINE_STATIC_LOCAL()| static should only be used on the thread it was
48 // created on.
49 //
50 #define DEFINE_STATIC_LOCAL(Type, Name, Arguments) \
51 static WTF::StaticSingleton<Type> s_##Name( \
52 new WTF::StaticSingleton<Type>::WrapperType Arguments); \
53 Type& Name = s_##Name.get(false)
42 54
43 public: 55 // |DEFINE_THREAD_SAFE_STATIC_LOCAL()| is the cross-thread accessible variant
44 StaticLocalVerifier() 56 // of |DEFINE_STATIC_LOCAL()|; use it if the singleton can be accessed by
45 : m_safelyInitialized(WTF::isBeforeThreadCreated()), 57 // multiple threads.
46 m_thread(WTF::internal::currentThreadSyscall()) {} 58 //
47 59 // TODO: rename as DEFINE_CROSS_THREAD_STATIC_LOCAL() ?
48 bool isNotRacy() { 60 #define DEFINE_THREAD_SAFE_STATIC_LOCAL(Type, Name, Initializer) \
49 // Make sure that this 1) is safely initialized, 2) keeps being called 61 static WTF::StaticSingleton<Type> s_##Name(Initializer); \
50 // on the same thread, or 3) is called within 62 Type& Name = s_##Name.get(true)
51 // AtomicallyInitializedStatic (i.e. with a lock held).
52 return m_safelyInitialized ||
53 m_thread == WTF::internal::currentThreadSyscall() ||
54 WTF::isAtomicallyInitializedStaticMutexLockHeld();
55 }
56
57 private:
58 bool m_safelyInitialized;
59 ThreadIdentifier m_thread;
60 };
61 #endif
62 63
63 namespace blink { 64 namespace blink {
64 template <typename T> 65 template <typename T>
65 class Persistent; 66 class Persistent;
67
68 } // namespace blink
69
70 namespace WTF {
71
72 template <typename Type>
73 class StaticSingleton final {
74 WTF_MAKE_NONCOPYABLE(StaticSingleton);
75
76 public:
77 template <typename T,
78 bool = WTF::IsGarbageCollectedType<T>::value &&
79 !WTF::IsPersistentReferenceType<T>::value>
80 struct Wrapper {
81 using type = T;
82
83 static T& unwrap(T* singleton) { return *singleton; }
84 };
85
86 template <typename T>
87 struct Wrapper<T, true> {
88 using type = blink::Persistent<T>;
89
90 static T& unwrap(blink::Persistent<T>* singleton) {
91 DCHECK(singleton);
92 // If this assert triggers, you're supplying an empty ("()") 'Arguments'
93 // argument to DEFINE_STATIC_LOCAL() - it must be the heap object you wish
94 // to create as a static singleton and wrapped up with a Persistent
95 // reference.
96 DCHECK(*singleton);
97 return **singleton;
98 }
99 };
100
101 using WrapperType = typename Wrapper<Type>::type;
102
103 // To cooperate with leak detection(LSan) for Blink garbage collected objects,
104 // the objects owned by persistent local statics will in some cases have to be
105 // finalized prior to leak checking. This only applies to static references to
106 // Blink heap objects and what they transitively hold on to. Hence the
107 // LEAK_SANITIZER_REGISTER_STATIC_LOCAL() use, it taking care of the grungy
108 // details.
109
110 explicit StaticSingleton(WrapperType* instance)
111 : m_instance(LEAK_SANITIZER_REGISTER_STATIC_LOCAL(WrapperType, instance))
112 #if DCHECK_IS_ON()
113 ,
114 m_safelyInitialized(WTF::isBeforeThreadCreated()),
115 m_thread(WTF::internal::currentThreadSyscall())
116 #endif
117 {
118 }
119
120 Type& get(bool allowCrossThreadUse) const {
121 #if DCHECK_IS_ON()
122 DCHECK(isNotRacy(allowCrossThreadUse));
123 #endif
124 ALLOW_UNUSED_LOCAL(allowCrossThreadUse);
125 return Wrapper<Type>::unwrap(m_instance);
126 }
127
128 operator Type&() { return get(); }
129
130 private:
131 #if DCHECK_IS_ON()
132
133 bool isNotRacy(bool allowCrossThreadUse) const {
134 // Make sure that singleton is safely initialized, or
135 // keeps being called on the same thread if cross-thread
136 // use is not permitted.
137 return allowCrossThreadUse || m_safelyInitialized ||
sof 2017/02/17 06:37:01 fyi, https://codereview.chromium.org/2698953002/ h
138 m_thread == WTF::internal::currentThreadSyscall();
139 }
140 #endif
141
142 WrapperType* m_instance;
143 #if DCHECK_IS_ON()
144 bool m_safelyInitialized;
145 ThreadIdentifier m_thread;
146 #endif
66 }; 147 };
67 148
68 template <typename T, 149 } // namespace WTF
69 bool = WTF::IsGarbageCollectedType<T>::value &&
70 !WTF::IsPersistentReferenceType<T>::value>
71 class StaticLocalWrapper {
72 public:
73 using WrapType = T;
74
75 static T& unwrap(T* singleton) { return *singleton; }
76 };
77
78 template <typename T>
79 class StaticLocalWrapper<T, true> {
80 public:
81 using WrapType = blink::Persistent<T>;
82
83 static T& unwrap(blink::Persistent<T>* singleton) {
84 DCHECK(singleton);
85 // If this assert triggers, you're supplying an empty ("()") 'Arguments'
86 // argument to DEFINE_STATIC_LOCAL() - it must be the heap object you wish
87 // to create as a static singleton and wrapped up with a Persistent
88 // reference.
89 DCHECK(*singleton);
90 return **singleton;
91 }
92 };
93
94 #if DCHECK_IS_ON()
95 #define DEFINE_STATIC_LOCAL_CHECK_THREADSAFE_ACCESS(Name) \
96 static StaticLocalVerifier Name##StaticLocalVerifier; \
97 DCHECK(Name##StaticLocalVerifier.isNotRacy())
98 #else
99 #define DEFINE_STATIC_LOCAL_CHECK_THREADSAFE_ACCESS(Name)
100 #endif
101
102 // Use DEFINE_STATIC_LOCAL() to declare and define a static local variable
103 // (static T;) so that it is leaked and its destructors are not called at exit.
104 // T may also be a Blink garbage collected object, in which case it is
105 // wrapped up by an off-heap Persistent<T> reference to the object, keeping
106 // it alive across GCs.
107 //
108 // To cooperate with leak detection(LSan) for Blink garbage collected objects,
109 // the objects owned by persistent local statics will in some cases have to be
110 // finalized prior to leak checking. This only applies to static references to
111 // Blink heap objects and what they transitively hold on to. Hence the
112 // LEAK_SANITIZER_REGISTER_STATIC_LOCAL() use, it taking care of the grungy
113 // details.
114 //
115 #define DEFINE_STATIC_LOCAL(Type, Name, Arguments) \
116 DEFINE_STATIC_LOCAL_CHECK_THREADSAFE_ACCESS(Name); \
117 using WrappedTypeFor##Name = StaticLocalWrapper<Type>::WrapType; \
118 static WrappedTypeFor##Name* WrappedInstanceFor##Name = \
119 LEAK_SANITIZER_REGISTER_STATIC_LOCAL( \
120 WrappedTypeFor##Name, new WrappedTypeFor##Name Arguments); \
121 Type& Name = StaticLocalWrapper<Type>::unwrap(WrappedInstanceFor##Name);
122 150
123 // Use this to declare and define a static local pointer to a ref-counted object 151 // Use this to declare and define a static local pointer to a ref-counted object
124 // so that it is leaked so that the object's destructors are not called at 152 // so that it is leaked so that the object's destructors are not called at
125 // exit. This macro should be used with ref-counted objects rather than 153 // exit. This macro should be used with ref-counted objects rather than
126 // DEFINE_STATIC_LOCAL macro, as this macro does not lead to an extra memory 154 // DEFINE_STATIC_LOCAL macro, as this macro does not lead to an extra memory
127 // allocation. 155 // allocation.
128 #define DEFINE_STATIC_REF(type, name, arguments) \ 156 #define DEFINE_STATIC_REF(type, name, arguments) \
129 static type* name = PassRefPtr<type>(arguments).leakRef(); 157 static type* name = PassRefPtr<type>(arguments).leakRef();
130 158
131 /* 159 /*
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 enum NotNullTag { NotNull }; 267 enum NotNullTag { NotNull };
240 inline void* operator new(size_t, NotNullTag, void* location) { 268 inline void* operator new(size_t, NotNullTag, void* location) {
241 DCHECK(location); 269 DCHECK(location);
242 return location; 270 return location;
243 } 271 }
244 272
245 using WTF::bitwiseCast; 273 using WTF::bitwiseCast;
246 using WTF::safeCast; 274 using WTF::safeCast;
247 275
248 #endif // WTF_StdLibExtras_h 276 #endif // WTF_StdLibExtras_h
OLDNEW
« no previous file with comments | « no previous file | third_party/WebKit/Source/wtf/Threading.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698