Repo created
This commit is contained in:
parent
81b91f4139
commit
f8c34fa5ee
22732 changed files with 4815320 additions and 2 deletions
101
TMessagesProj/jni/voip/webrtc/base/lazy_instance_helpers.h
Normal file
101
TMessagesProj/jni/voip/webrtc/base/lazy_instance_helpers.h
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
// 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/logging.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_
|
||||
Loading…
Add table
Add a link
Reference in a new issue