Add constinit global string holder classes#1512
Open
yukawa wants to merge 1 commit into
Open
Conversation
63b14a5 to
5c38653
Compare
These are utility classes for global strings whose value is known only
at runtime. They are motivated by the on-going effort to remove
Singleton<T>, which has surfaced several places in system_util.cc
(directory caches, user-SID lookup, program-invocation-name holder)
where the singleton wraps a string lookup that must run *after* the
surrounding modules are ready.
A function-local static std::string would be the obvious replacement,
but reintroduces two issues that Singleton<T> callers have learnt to
avoid:
* On Windows, function-local static initialization is not safe to
invoke from DllMain because the compiler-generated guard can take
locks that interact badly with the Loader Lock.
* The resulting destructor runs at process exit in unspecified order
relative to other globals.
Both classes address these keeping all foreign code outside the publish
lock and by being trivially destructible (unless
MOZC_NO_ATOMIC_FLAG_WAIT is specified).
ConstInitImmutableString is the publish-once, read-many variant. It
takes an IdempotentInitializer function pointer that is invoked
lock-free on the first GetOrInit(), so the class is safe to use from
DllMain even when the initializer itself acquires the Loader Lock.
Subsequent reads return a string_view over stable, NUL-terminated
storage on a lock-free fast path:
#include "base/strings/const_init_immutable_string.h"
constinit mozc::ConstInitImmutableString<256> g_program_files_x86(
[]() -> std::string { return ComputeProgramFilesX86Path(); });
absl::string_view path = g_program_files_x86.GetOrInit();
ConstInitMutableString is the set-many, snapshot-read variant. Set()
atomically replaces the stored value; Get() returns a std::string
snapshot under a lock-protected copy.
#include "base/strings/const_init_mutable_string.h"
constinit mozc::ConstInitMutableString<256> g_invocation_name;
void Init(absl::string_view name) { g_invocation_name.Set(name); }
std::string GetName() { return g_invocation_name.Get(); }
For platforms where std::atomic_flag::wait() is disallowed in favor of
absl::Mutex, MOZC_NO_ATOMIC_FLAG_WAIT macro is provided to switch the
implementation to the absl::Mutex-based one. This guarantees that
std::atomic_flag::wait() is used only for "client" build flavors in
"mozc_select".
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
These are utility classes for global strings whose value is known only at runtime. They are motivated by the on-going effort to remove
Singleton<T>, which has surfaced several places in system_util.cc (directory caches, user-SID lookup, program-invocation-name holder) where the singleton wraps a string lookup that must run after the surrounding modules are ready.A function-local
static std::stringwould be the obvious replacement, but reintroduces two issues thatSingleton<T>callers have learnt to avoid:DllMainbecause the compiler-generated guard can take locks that interact badly with the Loader Lock.Both classes address these keeping all foreign code outside the publish lock and by being trivially destructible (unless
MOZC_NO_ATOMIC_FLAG_WAITis specified).ConstInitImmutableStringis the publish-once, read-many variant. It takes anIdempotentInitializerfunction pointer that is invoked lock-free on the firstGetOrInit(), so the class is safe to use fromDllMaineven when the initializer itself acquires the Loader Lock. Subsequent reads return astring_viewover stable, NUL-terminated storage on a lock-free fast path:ConstInitMutableStringis the set-many, snapshot-read variant.Set()atomically replaces the stored value;Get()returns astd::stringsnapshot under a lock-protected copy.For platforms where
std::atomic_flag::wait()is disallowed in favor ofabsl::Mutex,MOZC_NO_ATOMIC_FLAG_WAITmacro is provided to switch the implementation to theabsl::Mutex-based one. This guarantees thatstd::atomic_flag::wait()is used only forclientbuild flavors inmozc_select.Issue IDs
N/A
Steps to test new behaviors (if any)
bazelisk test //base/strings/... --build_tests_only