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