123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- #ifndef BASE_LAZY_INSTANCE_H_
- #define BASE_LAZY_INSTANCE_H_
- #include <new> // For placement new.
- #include "base/atomicops.h"
- #include "base/check_op.h"
- #include "base/debug/leak_annotations.h"
- #include "base/lazy_instance_helpers.h"
- #include "base/threading/thread_restrictions.h"
- #define LAZY_INSTANCE_INITIALIZER {}
- namespace base {
- template <typename Type>
- struct LazyInstanceTraitsBase {
- static Type* New(void* instance) {
- DCHECK_EQ(reinterpret_cast<uintptr_t>(instance) & (alignof(Type) - 1), 0u);
-
-
- return new (instance) Type();
- }
- static void CallDestructor(Type* instance) {
-
- instance->~Type();
- }
- };
- namespace internal {
- template <typename Type>
- struct DestructorAtExitLazyInstanceTraits {
- static const bool kRegisterOnExit = true;
- #if DCHECK_IS_ON()
- static const bool kAllowedToAccessOnNonjoinableThread = false;
- #endif
- static Type* New(void* instance) {
- return LazyInstanceTraitsBase<Type>::New(instance);
- }
- static void Delete(Type* instance) {
- LazyInstanceTraitsBase<Type>::CallDestructor(instance);
- }
- };
- template <typename Type>
- struct LeakyLazyInstanceTraits {
- static const bool kRegisterOnExit = false;
- #if DCHECK_IS_ON()
- static const bool kAllowedToAccessOnNonjoinableThread = true;
- #endif
- static Type* New(void* instance) {
- ANNOTATE_SCOPED_MEMORY_LEAK;
- return LazyInstanceTraitsBase<Type>::New(instance);
- }
- static void Delete(Type* instance) {
- }
- };
- template <typename Type>
- struct ErrorMustSelectLazyOrDestructorAtExitForLazyInstance {};
- }
- template <
- typename Type,
- typename Traits =
- internal::ErrorMustSelectLazyOrDestructorAtExitForLazyInstance<Type>>
- class LazyInstance {
- public:
-
-
-
-
-
-
-
-
- typedef LazyInstance<Type, internal::LeakyLazyInstanceTraits<Type>> Leaky;
- typedef LazyInstance<Type, internal::DestructorAtExitLazyInstanceTraits<Type>>
- DestructorAtExit;
- Type& Get() {
- return *Pointer();
- }
- Type* Pointer() {
- #if DCHECK_IS_ON()
- if (!Traits::kAllowedToAccessOnNonjoinableThread)
- ThreadRestrictions::AssertSingletonAllowed();
- #endif
- return subtle::GetOrCreateLazyPointer(
- &private_instance_, &Traits::New, private_buf_,
- Traits::kRegisterOnExit ? OnExit : nullptr, this);
- }
-
-
- bool IsCreated() {
-
-
-
-
- return 0 != subtle::NoBarrier_Load(&private_instance_);
- }
-
-
-
- #if defined(OS_WIN)
- #pragma warning(push)
- #pragma warning(disable: 4324)
- #endif
-
-
-
- subtle::AtomicWord private_instance_;
-
- alignas(Type) char private_buf_[sizeof(Type)];
- #if defined(OS_WIN)
- #pragma warning(pop)
- #endif
- private:
- Type* instance() {
- return reinterpret_cast<Type*>(subtle::NoBarrier_Load(&private_instance_));
- }
-
-
-
- static void OnExit(void* lazy_instance) {
- LazyInstance<Type, Traits>* me =
- reinterpret_cast<LazyInstance<Type, Traits>*>(lazy_instance);
- Traits::Delete(me->instance());
- subtle::NoBarrier_Store(&me->private_instance_, 0);
- }
- };
- }
- #endif
|