Index: third_party/WebKit/Source/wtf/StdLibExtras.h |
diff --git a/third_party/WebKit/Source/wtf/StdLibExtras.h b/third_party/WebKit/Source/wtf/StdLibExtras.h |
index 26ba1d8d02958298aacfc73daea5743ccbbce201..d2633948b98bd909e46ffdcac39b7d20d50e03e4 100644 |
--- a/third_party/WebKit/Source/wtf/StdLibExtras.h |
+++ b/third_party/WebKit/Source/wtf/StdLibExtras.h |
@@ -26,99 +26,127 @@ |
#ifndef WTF_StdLibExtras_h |
#define WTF_StdLibExtras_h |
+#include <cstddef> |
#include "base/numerics/safe_conversions.h" |
#include "wtf/Assertions.h" |
#include "wtf/CPU.h" |
#include "wtf/LeakAnnotations.h" |
+#include "wtf/Noncopyable.h" |
#include "wtf/TypeTraits.h" |
-#include <cstddef> |
#if DCHECK_IS_ON() |
-#include "wtf/Noncopyable.h" |
#include "wtf/Threading.h" |
+#endif |
-class WTF_EXPORT StaticLocalVerifier { |
- WTF_MAKE_NONCOPYABLE(StaticLocalVerifier); |
- |
- public: |
- StaticLocalVerifier() |
- : m_safelyInitialized(WTF::isBeforeThreadCreated()), |
- m_thread(WTF::internal::currentThreadSyscall()) {} |
- |
- bool isNotRacy() { |
- // Make sure that this 1) is safely initialized, 2) keeps being called |
- // on the same thread, or 3) is called within |
- // AtomicallyInitializedStatic (i.e. with a lock held). |
- return m_safelyInitialized || |
- m_thread == WTF::internal::currentThreadSyscall() || |
- WTF::isAtomicallyInitializedStaticMutexLockHeld(); |
- } |
+// Use |DEFINE_STATIC_LOCAL()| to declare and define a static local variable |
+// (|static T;|) so that it is leaked and its destructors are not called at |
+// exit. T may also be a Blink garbage collected object, in which case it is |
+// wrapped up by an off-heap |Persistent<T>| reference to the object, keeping |
+// it alive across GCs. |
+// |
+// A |DEFINE_STATIC_LOCAL()| static should only be used on the thread it was |
+// created on. |
+// |
+#define DEFINE_STATIC_LOCAL(Type, Name, Arguments) \ |
+ static WTF::StaticSingleton<Type> s_##Name( \ |
+ new WTF::StaticSingleton<Type>::WrapperType Arguments); \ |
+ Type& Name = s_##Name.get(false) |
- private: |
- bool m_safelyInitialized; |
- ThreadIdentifier m_thread; |
-}; |
-#endif |
+// |DEFINE_THREAD_SAFE_STATIC_LOCAL()| is the cross-thread accessible variant |
+// of |DEFINE_STATIC_LOCAL()|; use it if the singleton can be accessed by |
+// multiple threads. |
+// |
+// TODO: rename as DEFINE_CROSS_THREAD_STATIC_LOCAL() ? |
+#define DEFINE_THREAD_SAFE_STATIC_LOCAL(Type, Name, Initializer) \ |
+ static WTF::StaticSingleton<Type> s_##Name(Initializer); \ |
+ Type& Name = s_##Name.get(true) |
namespace blink { |
template <typename T> |
class Persistent; |
-}; |
-template <typename T, |
- bool = WTF::IsGarbageCollectedType<T>::value && |
- !WTF::IsPersistentReferenceType<T>::value> |
-class StaticLocalWrapper { |
- public: |
- using WrapType = T; |
+} // namespace blink |
- static T& unwrap(T* singleton) { return *singleton; } |
-}; |
+namespace WTF { |
+ |
+template <typename Type> |
+class StaticSingleton final { |
+ WTF_MAKE_NONCOPYABLE(StaticSingleton); |
-template <typename T> |
-class StaticLocalWrapper<T, true> { |
public: |
- using WrapType = blink::Persistent<T>; |
- |
- static T& unwrap(blink::Persistent<T>* singleton) { |
- DCHECK(singleton); |
- // If this assert triggers, you're supplying an empty ("()") 'Arguments' |
- // argument to DEFINE_STATIC_LOCAL() - it must be the heap object you wish |
- // to create as a static singleton and wrapped up with a Persistent |
- // reference. |
- DCHECK(*singleton); |
- return **singleton; |
+ template <typename T, |
+ bool = WTF::IsGarbageCollectedType<T>::value && |
+ !WTF::IsPersistentReferenceType<T>::value> |
+ struct Wrapper { |
+ using type = T; |
+ |
+ static T& unwrap(T* singleton) { return *singleton; } |
+ }; |
+ |
+ template <typename T> |
+ struct Wrapper<T, true> { |
+ using type = blink::Persistent<T>; |
+ |
+ static T& unwrap(blink::Persistent<T>* singleton) { |
+ DCHECK(singleton); |
+ // If this assert triggers, you're supplying an empty ("()") 'Arguments' |
+ // argument to DEFINE_STATIC_LOCAL() - it must be the heap object you wish |
+ // to create as a static singleton and wrapped up with a Persistent |
+ // reference. |
+ DCHECK(*singleton); |
+ return **singleton; |
+ } |
+ }; |
+ |
+ using WrapperType = typename Wrapper<Type>::type; |
+ |
+ // To cooperate with leak detection(LSan) for Blink garbage collected objects, |
+ // the objects owned by persistent local statics will in some cases have to be |
+ // finalized prior to leak checking. This only applies to static references to |
+ // Blink heap objects and what they transitively hold on to. Hence the |
+ // LEAK_SANITIZER_REGISTER_STATIC_LOCAL() use, it taking care of the grungy |
+ // details. |
+ |
+ explicit StaticSingleton(WrapperType* instance) |
+ : m_instance(LEAK_SANITIZER_REGISTER_STATIC_LOCAL(WrapperType, instance)) |
+#if DCHECK_IS_ON() |
+ , |
+ m_safelyInitialized(WTF::isBeforeThreadCreated()), |
+ m_thread(WTF::internal::currentThreadSyscall()) |
+#endif |
+ { |
} |
-}; |
+ Type& get(bool allowCrossThreadUse) const { |
#if DCHECK_IS_ON() |
-#define DEFINE_STATIC_LOCAL_CHECK_THREADSAFE_ACCESS(Name) \ |
- static StaticLocalVerifier Name##StaticLocalVerifier; \ |
- DCHECK(Name##StaticLocalVerifier.isNotRacy()) |
-#else |
-#define DEFINE_STATIC_LOCAL_CHECK_THREADSAFE_ACCESS(Name) |
+ DCHECK(isNotRacy(allowCrossThreadUse)); |
#endif |
+ ALLOW_UNUSED_LOCAL(allowCrossThreadUse); |
+ return Wrapper<Type>::unwrap(m_instance); |
+ } |
-// Use DEFINE_STATIC_LOCAL() to declare and define a static local variable |
-// (static T;) so that it is leaked and its destructors are not called at exit. |
-// T may also be a Blink garbage collected object, in which case it is |
-// wrapped up by an off-heap Persistent<T> reference to the object, keeping |
-// it alive across GCs. |
-// |
-// To cooperate with leak detection(LSan) for Blink garbage collected objects, |
-// the objects owned by persistent local statics will in some cases have to be |
-// finalized prior to leak checking. This only applies to static references to |
-// Blink heap objects and what they transitively hold on to. Hence the |
-// LEAK_SANITIZER_REGISTER_STATIC_LOCAL() use, it taking care of the grungy |
-// details. |
-// |
-#define DEFINE_STATIC_LOCAL(Type, Name, Arguments) \ |
- DEFINE_STATIC_LOCAL_CHECK_THREADSAFE_ACCESS(Name); \ |
- using WrappedTypeFor##Name = StaticLocalWrapper<Type>::WrapType; \ |
- static WrappedTypeFor##Name* WrappedInstanceFor##Name = \ |
- LEAK_SANITIZER_REGISTER_STATIC_LOCAL( \ |
- WrappedTypeFor##Name, new WrappedTypeFor##Name Arguments); \ |
- Type& Name = StaticLocalWrapper<Type>::unwrap(WrappedInstanceFor##Name); |
+ operator Type&() { return get(); } |
+ |
+ private: |
+#if DCHECK_IS_ON() |
+ |
+ bool isNotRacy(bool allowCrossThreadUse) const { |
+ // Make sure that singleton is safely initialized, or |
+ // keeps being called on the same thread if cross-thread |
+ // use is not permitted. |
+ return allowCrossThreadUse || m_safelyInitialized || |
sof
2017/02/17 06:37:01
fyi, https://codereview.chromium.org/2698953002/ h
|
+ m_thread == WTF::internal::currentThreadSyscall(); |
+ } |
+#endif |
+ |
+ WrapperType* m_instance; |
+#if DCHECK_IS_ON() |
+ bool m_safelyInitialized; |
+ ThreadIdentifier m_thread; |
+#endif |
+}; |
+ |
+} // namespace WTF |
// Use this to declare and define a static local pointer to a ref-counted object |
// so that it is leaked so that the object's destructors are not called at |