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