lazy_instance_helpers.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. // Copyright 2018 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef BASE_LAZY_INSTANCE_HELPERS_H_
  5. #define BASE_LAZY_INSTANCE_HELPERS_H_
  6. #include <atomic>
  7. #include <cstdint>
  8. #include "base/base_export.h"
  9. #include "base/check.h"
  10. // Helper methods used by LazyInstance and a few other base APIs for thread-safe
  11. // lazy construction.
  12. namespace base {
  13. namespace internal {
  14. // Our AtomicWord doubles as a spinlock, where a value of
  15. // kLazyInstanceStateCreating means the spinlock is being held for creation.
  16. constexpr uintptr_t kLazyInstanceStateCreating = 1;
  17. // Helper for GetOrCreateLazyPointer(). Checks if instance needs to be created.
  18. // If so returns true otherwise if another thread has beat us, waits for
  19. // instance to be created and returns false.
  20. BASE_EXPORT bool NeedsLazyInstance(std::atomic<uintptr_t>& state);
  21. // Helper for GetOrCreateLazyPointer(). After creating an instance, this is
  22. // called to register the dtor to be called at program exit and to update the
  23. // atomic state to hold the |new_instance|
  24. BASE_EXPORT void CompleteLazyInstance(std::atomic<uintptr_t>& state,
  25. uintptr_t new_instance,
  26. void (*destructor)(void*),
  27. void* destructor_arg);
  28. } // namespace internal
  29. namespace subtle {
  30. // If |state| is uninitialized (zero), constructs a value using
  31. // |creator_func(creator_arg)|, stores it into |state| and registers
  32. // |destructor(destructor_arg)| to be called when the current AtExitManager goes
  33. // out of scope. Then, returns the value stored in |state|. It is safe to have
  34. // concurrent calls to this function with the same |state|. |creator_func| may
  35. // return nullptr if it doesn't want to create an instance anymore (e.g. on
  36. // shutdown), it is from then on required to return nullptr to all callers (ref.
  37. // StaticMemorySingletonTraits). In that case, callers need to synchronize
  38. // before |creator_func| may return a non-null instance again (ref.
  39. // StaticMemorySingletonTraits::ResurectForTesting()).
  40. // Implementation note on |creator_func/creator_arg|. It makes for ugly adapters
  41. // but it avoids redundant template instantiations (e.g. saves 27KB in
  42. // chrome.dll) because linker is able to fold these for multiple Types but
  43. // couldn't with the more advanced CreatorFunc template type which in turn
  44. // improves code locality (and application startup) -- ref.
  45. // https://chromium-review.googlesource.com/c/chromium/src/+/530984/5/base/lazy_instance.h#140,
  46. // worsened by https://chromium-review.googlesource.com/c/chromium/src/+/868013
  47. // and caught then as https://crbug.com/804034.
  48. template <typename Type>
  49. Type* GetOrCreateLazyPointer(std::atomic<uintptr_t>& state,
  50. Type* (*creator_func)(void*),
  51. void* creator_arg,
  52. void (*destructor)(void*),
  53. void* destructor_arg) {
  54. DCHECK(creator_func);
  55. // If any bit in the created mask is true, the instance has already been
  56. // fully constructed.
  57. constexpr uintptr_t kLazyInstanceCreatedMask =
  58. ~internal::kLazyInstanceStateCreating;
  59. // We will hopefully have fast access when the instance is already created.
  60. // Since a thread sees |state| == 0 or kLazyInstanceStateCreating at most
  61. // once, the load is taken out of NeedsLazyInstance() as a fast-path. The load
  62. // has acquire memory ordering as a thread which sees |state| > creating needs
  63. // to acquire visibility over the associated data. Pairing Release_Store is in
  64. // CompleteLazyInstance().
  65. uintptr_t instance = state.load(std::memory_order_acquire);
  66. if (!(instance & kLazyInstanceCreatedMask)) {
  67. if (internal::NeedsLazyInstance(state)) {
  68. // This thread won the race and is now responsible for creating the
  69. // instance and storing it back into |state|.
  70. instance = reinterpret_cast<uintptr_t>((*creator_func)(creator_arg));
  71. internal::CompleteLazyInstance(state, instance, destructor,
  72. destructor_arg);
  73. } else {
  74. // This thread lost the race but now has visibility over the constructed
  75. // instance (NeedsLazyInstance() doesn't return until the constructing
  76. // thread releases the instance via CompleteLazyInstance()).
  77. instance = state.load(std::memory_order_acquire);
  78. DCHECK(instance & kLazyInstanceCreatedMask);
  79. }
  80. }
  81. return reinterpret_cast<Type*>(instance);
  82. }
  83. } // namespace subtle
  84. } // namespace base
  85. #endif // BASE_LAZY_INSTANCE_HELPERS_H_