123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- // Copyright 2018 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #ifndef BASE_LAZY_INSTANCE_INTERNAL_H_
- #define BASE_LAZY_INSTANCE_INTERNAL_H_
- #include "base/atomicops.h"
- #include "base/base_export.h"
- #include "base/check.h"
- // Helper methods used by LazyInstance and a few other base APIs for thread-safe
- // lazy construction.
- namespace base {
- namespace internal {
- // Our AtomicWord doubles as a spinlock, where a value of
- // kLazyInstanceStateCreating means the spinlock is being held for creation.
- constexpr subtle::AtomicWord kLazyInstanceStateCreating = 1;
- // Helper for GetOrCreateLazyPointer(). Checks if instance needs to be created.
- // If so returns true otherwise if another thread has beat us, waits for
- // instance to be created and returns false.
- BASE_EXPORT bool NeedsLazyInstance(subtle::AtomicWord* state);
- // Helper for GetOrCreateLazyPointer(). After creating an instance, this is
- // called to register the dtor to be called at program exit and to update the
- // atomic state to hold the |new_instance|
- BASE_EXPORT void CompleteLazyInstance(subtle::AtomicWord* state,
- subtle::AtomicWord new_instance,
- void (*destructor)(void*),
- void* destructor_arg);
- } // namespace internal
- namespace subtle {
- // If |state| is uninitialized (zero), constructs a value using
- // |creator_func(creator_arg)|, stores it into |state| and registers
- // |destructor(destructor_arg)| to be called when the current AtExitManager goes
- // out of scope. Then, returns the value stored in |state|. It is safe to have
- // concurrent calls to this function with the same |state|. |creator_func| may
- // return nullptr if it doesn't want to create an instance anymore (e.g. on
- // shutdown), it is from then on required to return nullptr to all callers (ref.
- // StaticMemorySingletonTraits). In that case, callers need to synchronize
- // before |creator_func| may return a non-null instance again (ref.
- // StaticMemorySingletonTraits::ResurectForTesting()).
- // Implementation note on |creator_func/creator_arg|. It makes for ugly adapters
- // but it avoids redundant template instantiations (e.g. saves 27KB in
- // chrome.dll) because linker is able to fold these for multiple Types but
- // couldn't with the more advanced CreatorFunc template type which in turn
- // improves code locality (and application startup) -- ref.
- // https://chromium-review.googlesource.com/c/chromium/src/+/530984/5/base/lazy_instance.h#140,
- // worsened by https://chromium-review.googlesource.com/c/chromium/src/+/868013
- // and caught then as https://crbug.com/804034.
- template <typename Type>
- Type* GetOrCreateLazyPointer(subtle::AtomicWord* state,
- Type* (*creator_func)(void*),
- void* creator_arg,
- void (*destructor)(void*),
- void* destructor_arg) {
- DCHECK(state);
- DCHECK(creator_func);
- // If any bit in the created mask is true, the instance has already been
- // fully constructed.
- constexpr subtle::AtomicWord kLazyInstanceCreatedMask =
- ~internal::kLazyInstanceStateCreating;
- // We will hopefully have fast access when the instance is already created.
- // Since a thread sees |state| == 0 or kLazyInstanceStateCreating at most
- // once, the load is taken out of NeedsLazyInstance() as a fast-path. The load
- // has acquire memory ordering as a thread which sees |state| > creating needs
- // to acquire visibility over the associated data. Pairing Release_Store is in
- // CompleteLazyInstance().
- subtle::AtomicWord instance = subtle::Acquire_Load(state);
- if (!(instance & kLazyInstanceCreatedMask)) {
- if (internal::NeedsLazyInstance(state)) {
- // This thread won the race and is now responsible for creating the
- // instance and storing it back into |state|.
- instance =
- reinterpret_cast<subtle::AtomicWord>((*creator_func)(creator_arg));
- internal::CompleteLazyInstance(state, instance, destructor,
- destructor_arg);
- } else {
- // This thread lost the race but now has visibility over the constructed
- // instance (NeedsLazyInstance() doesn't return until the constructing
- // thread releases the instance via CompleteLazyInstance()).
- instance = subtle::Acquire_Load(state);
- DCHECK(instance & kLazyInstanceCreatedMask);
- }
- }
- return reinterpret_cast<Type*>(instance);
- }
- } // namespace subtle
- } // namespace base
- #endif // BASE_LAZY_INSTANCE_INTERNAL_H_
|