Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-11-15 09:01:14

0001 // Copyright 2019 The Abseil Authors.
0002 //
0003 // Licensed under the Apache License, Version 2.0 (the "License");
0004 // you may not use this file except in compliance with the License.
0005 // You may obtain a copy of the License at
0006 //
0007 //      https://www.apache.org/licenses/LICENSE-2.0
0008 //
0009 // Unless required by applicable law or agreed to in writing, software
0010 // distributed under the License is distributed on an "AS IS" BASIS,
0011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0012 // See the License for the specific language governing permissions and
0013 // limitations under the License.
0014 
0015 #include "absl/base/config.h"
0016 #include "absl/strings/internal/cordz_handle.h"
0017 #include "absl/strings/internal/cordz_info.h"
0018 
0019 #ifndef ABSL_STRINGS_INTERNAL_CORDZ_SAMPLE_TOKEN_H_
0020 #define ABSL_STRINGS_INTERNAL_CORDZ_SAMPLE_TOKEN_H_
0021 
0022 namespace absl {
0023 ABSL_NAMESPACE_BEGIN
0024 namespace cord_internal {
0025 
0026 // The existence of a CordzSampleToken guarantees that a reader can traverse the
0027 // global_cordz_infos_head linked-list without needing to hold a mutex. When a
0028 // CordzSampleToken exists, all CordzInfo objects that would be destroyed are
0029 // instead appended to a deletion queue. When the CordzSampleToken is destroyed,
0030 // it will also clean up any of these CordzInfo objects.
0031 //
0032 // E.g., ST are CordzSampleToken objects and CH are CordzHandle objects.
0033 //   ST1 <- CH1 <- CH2 <- ST2 <- CH3 <- global_delete_queue_tail
0034 //
0035 // This list tracks that CH1 and CH2 were created after ST1, so the thread
0036 // holding ST1 might have a reference to CH1, CH2, ST2, and CH3. However, ST2
0037 // was created later, so the thread holding the ST2 token cannot have a
0038 // reference to ST1, CH1, or CH2. If ST1 is cleaned up first, that thread will
0039 // delete ST1, CH1, and CH2. If instead ST2 is cleaned up first, that thread
0040 // will only delete ST2.
0041 //
0042 // If ST1 is cleaned up first, the new list will be:
0043 //   ST2 <- CH3 <- global_delete_queue_tail
0044 //
0045 // If ST2 is cleaned up first, the new list will be:
0046 //   ST1 <- CH1 <- CH2 <- CH3 <- global_delete_queue_tail
0047 //
0048 // All new CordzHandle objects are appended to the list, so if a new thread
0049 // comes along before either ST1 or ST2 are cleaned up, the new list will be:
0050 //   ST1 <- CH1 <- CH2 <- ST2 <- CH3 <- ST3 <- global_delete_queue_tail
0051 //
0052 // A thread must hold the global_delete_queue_mu mutex whenever it's altering
0053 // this list.
0054 //
0055 // It is safe for thread that holds a CordzSampleToken to read
0056 // global_cordz_infos at any time since the objects it is able to retrieve will
0057 // not be deleted while the CordzSampleToken exists.
0058 class CordzSampleToken : public CordzSnapshot {
0059  public:
0060   class Iterator {
0061    public:
0062     using iterator_category = std::input_iterator_tag;
0063     using value_type = const CordzInfo&;
0064     using difference_type = ptrdiff_t;
0065     using pointer = const CordzInfo*;
0066     using reference = value_type;
0067 
0068     Iterator() = default;
0069 
0070     Iterator& operator++();
0071     Iterator operator++(int);
0072     friend bool operator==(const Iterator& lhs, const Iterator& rhs);
0073     friend bool operator!=(const Iterator& lhs, const Iterator& rhs);
0074     reference operator*() const;
0075     pointer operator->() const;
0076 
0077    private:
0078     friend class CordzSampleToken;
0079     explicit Iterator(const CordzSampleToken* token);
0080 
0081     const CordzSampleToken* token_ = nullptr;
0082     pointer current_ = nullptr;
0083   };
0084 
0085   CordzSampleToken() = default;
0086   CordzSampleToken(const CordzSampleToken&) = delete;
0087   CordzSampleToken& operator=(const CordzSampleToken&) = delete;
0088 
0089   Iterator begin() { return Iterator(this); }
0090   Iterator end() { return Iterator(); }
0091 };
0092 
0093 }  // namespace cord_internal
0094 ABSL_NAMESPACE_END
0095 }  // namespace absl
0096 
0097 #endif  // ABSL_STRINGS_INTERNAL_CORDZ_SAMPLE_TOKEN_H_