Chromium Code Reviews| 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..cf6a5eddd80ff39b3a3378e4f43043b3df6798e6 100644 |
| --- a/third_party/WebKit/Source/wtf/StdLibExtras.h |
| +++ b/third_party/WebKit/Source/wtf/StdLibExtras.h |
| @@ -26,26 +26,98 @@ |
| #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); |
| +// 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. |
| +// |
| +#define DEFINE_STATIC_LOCAL(Type, Name, Arguments) \ |
| + static WTF::StaticSingleton<Type> s_##Name( \ |
| + new WTF::StaticSingleton<Type>::WrapperType Arguments); \ |
| + Type& Name = s_##Name.get() |
| + |
| +namespace blink { |
| +template <typename T> |
| +class Persistent; |
| + |
| +} // namespace blink |
| + |
| +namespace WTF { |
| + |
| +template <typename Type> |
| +class StaticSingleton final { |
| + WTF_MAKE_NONCOPYABLE(StaticSingleton); |
| public: |
| - StaticLocalVerifier() |
| - : m_safelyInitialized(WTF::isBeforeThreadCreated()), |
| - m_thread(WTF::internal::currentThreadSyscall()) {} |
| + 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() const { |
| +#if DCHECK_IS_ON() |
| + DCHECK(isNotRacy()); |
| +#endif |
| + return Wrapper<Type>::unwrap(m_instance); |
| + } |
| - bool isNotRacy() { |
| + operator Type&() { return get(); } |
| + |
| + private: |
| +#if DCHECK_IS_ON() |
| + |
| + bool isNotRacy() const { |
| // 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). |
| @@ -53,72 +125,16 @@ class WTF_EXPORT StaticLocalVerifier { |
| m_thread == WTF::internal::currentThreadSyscall() || |
| WTF::isAtomicallyInitializedStaticMutexLockHeld(); |
|
dcheng
2017/02/15 08:29:56
Since we have threadsafe function-local statics by
sof
2017/02/15 08:44:57
https://codereview.chromium.org/874203002#msg11 co
|
| } |
| +#endif |
| - private: |
| + WrapperType* m_instance; |
| +#if DCHECK_IS_ON() |
| bool m_safelyInitialized; |
| ThreadIdentifier m_thread; |
| -}; |
| #endif |
| - |
| -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; |
| - |
| - static T& unwrap(T* singleton) { return *singleton; } |
| -}; |
| - |
| -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; |
| - } |
| -}; |
| - |
| -#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) |
| -#endif |
| - |
| -// 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); |
| +} // 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 |