// // Copyright 2020 The Abseil Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #ifndef ABSL_FLAGS_INTERNAL_SEQUENCE_LOCK_H_ #define ABSL_FLAGS_INTERNAL_SEQUENCE_LOCK_H_ #include <stddef.h> #include <stdint.h> #include <atomic> #include <cassert> #include <cstring> #include "absl/base/optimization.h" namespace absl { ABSL_NAMESPACE_BEGIN namespace flags_internal { // Align 'x' up to the nearest 'align' bytes. inline constexpr size_t AlignUp(size_t x, size_t align) { … } // A SequenceLock implements lock-free reads. A sequence counter is incremented // before and after each write, and readers access the counter before and after // accessing the protected data. If the counter is verified to not change during // the access, and the sequence counter value was even, then the reader knows // that the read was race-free and valid. Otherwise, the reader must fall back // to a Mutex-based code path. // // This particular SequenceLock starts in an "uninitialized" state in which // TryRead() returns false. It must be enabled by calling MarkInitialized(). // This serves as a marker that the associated flag value has not yet been // initialized and a slow path needs to be taken. // // The memory reads and writes protected by this lock must use the provided // `TryRead()` and `Write()` functions. These functions behave similarly to // `memcpy()`, with one oddity: the protected data must be an array of // `std::atomic<uint64>`. This is to comply with the C++ standard, which // considers data races on non-atomic objects to be undefined behavior. See "Can // Seqlocks Get Along With Programming Language Memory Models?"[1] by Hans J. // Boehm for more details. // // [1] https://www.hpl.hp.com/techreports/2012/HPL-2012-68.pdf class SequenceLock { … }; } // namespace flags_internal ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_FLAGS_INTERNAL_SEQUENCE_LOCK_H_