|  | /* | 
|  | *  Copyright 2018 The WebRTC project authors. All Rights Reserved. | 
|  | * | 
|  | *  Use of this source code is governed by a BSD-style license | 
|  | *  that can be found in the LICENSE file in the root of the source | 
|  | *  tree. An additional intellectual property rights grant can be found | 
|  | *  in the file PATENTS.  All contributing project authors may | 
|  | *  be found in the AUTHORS file in the root of the source tree. | 
|  | */ | 
|  |  | 
|  | #ifndef RTC_BASE_UNIQUE_ID_GENERATOR_H_ | 
|  | #define RTC_BASE_UNIQUE_ID_GENERATOR_H_ | 
|  |  | 
|  | #include <limits> | 
|  | #include <set> | 
|  | #include <string> | 
|  |  | 
|  | #include "absl/strings/string_view.h" | 
|  | #include "api/array_view.h" | 
|  | #include "api/sequence_checker.h" | 
|  | #include "rtc_base/synchronization/mutex.h" | 
|  | #include "rtc_base/system/no_unique_address.h" | 
|  |  | 
|  | namespace webrtc { | 
|  |  | 
|  | // This class will generate numbers. A common use case is for identifiers. | 
|  | // The generated numbers will be unique, in the local scope of the generator. | 
|  | // This means that a generator will never generate the same number twice. | 
|  | // The generator can also be initialized with a sequence of known ids. | 
|  | // In such a case, it will never generate an id from that list. | 
|  | // Recommendedations: | 
|  | //  * Prefer unsigned types. | 
|  | //  * Prefer larger types (uint8_t will run out quickly). | 
|  | template <typename TIntegral> | 
|  | class UniqueNumberGenerator { | 
|  | public: | 
|  | typedef TIntegral value_type; | 
|  | UniqueNumberGenerator(); | 
|  | // Creates a generator that will never return any value from the given list. | 
|  | explicit UniqueNumberGenerator(ArrayView<TIntegral> known_ids); | 
|  | ~UniqueNumberGenerator(); | 
|  |  | 
|  | // Generates a number that this generator has never produced before. | 
|  | // If there are no available numbers to generate, this method will fail | 
|  | // with an `RTC_CHECK`. | 
|  | TIntegral GenerateNumber(); | 
|  |  | 
|  | // Alias for GenerateId, used for allowing typed testing | 
|  | TIntegral Generate() { return GenerateNumber(); } | 
|  |  | 
|  | // Adds an id that this generator should no longer generate. | 
|  | // Return value indicates whether the ID was hitherto unknown. | 
|  | bool AddKnownId(TIntegral value); | 
|  |  | 
|  | private: | 
|  | RTC_NO_UNIQUE_ADDRESS SequenceChecker sequence_checker_{ | 
|  | webrtc::SequenceChecker::kDetached}; | 
|  | static_assert(std::is_integral<TIntegral>::value, "Must be integral type."); | 
|  | TIntegral counter_ RTC_GUARDED_BY(sequence_checker_); | 
|  | std::set<TIntegral> known_ids_ RTC_GUARDED_BY(sequence_checker_); | 
|  | }; | 
|  |  | 
|  | // This class will generate unique ids. Ids are 32 bit unsigned integers. | 
|  | // The generated ids will be unique, in the local scope of the generator. | 
|  | // This means that a generator will never generate the same id twice. | 
|  | // The generator can also be initialized with a sequence of known ids. | 
|  | // In such a case, it will never generate an id from that list. | 
|  | class UniqueRandomIdGenerator { | 
|  | public: | 
|  | typedef uint32_t value_type; | 
|  | UniqueRandomIdGenerator(); | 
|  | // Create a generator that will never return any value from the given list. | 
|  | explicit UniqueRandomIdGenerator(ArrayView<uint32_t> known_ids); | 
|  | ~UniqueRandomIdGenerator(); | 
|  |  | 
|  | // Generates a random id that this generator has never produced before. | 
|  | // This method becomes more expensive with each use, as the probability of | 
|  | // collision for the randomly generated numbers increases. | 
|  | uint32_t GenerateId(); | 
|  |  | 
|  | // Alias for GenerateId, used for allowing typed testing | 
|  | uint32_t Generate() { return GenerateId(); } | 
|  |  | 
|  | // Adds an id that this generator should no longer generate. | 
|  | // Return value indicates whether the ID was hitherto unknown. | 
|  | bool AddKnownId(uint32_t value); | 
|  |  | 
|  | private: | 
|  | // TODO(bugs.webrtc.org/12666): This lock is needed due to an instance in | 
|  | // SdpOfferAnswerHandler being shared between threads. | 
|  | Mutex mutex_; | 
|  | std::set<uint32_t> known_ids_ RTC_GUARDED_BY(&mutex_); | 
|  | }; | 
|  |  | 
|  | // This class will generate strings. A common use case is for identifiers. | 
|  | // The generated strings will be unique, in the local scope of the generator. | 
|  | // This means that a generator will never generate the same string twice. | 
|  | // The generator can also be initialized with a sequence of known ids. | 
|  | // In such a case, it will never generate an id from that list. | 
|  | class UniqueStringGenerator { | 
|  | public: | 
|  | typedef std::string value_type; | 
|  | UniqueStringGenerator(); | 
|  | explicit UniqueStringGenerator(ArrayView<std::string> known_ids); | 
|  | ~UniqueStringGenerator(); | 
|  |  | 
|  | std::string GenerateString(); | 
|  | // Alias for GenerateString, used for allowing typed testing | 
|  | std::string Generate() { return GenerateString(); } | 
|  |  | 
|  | // Adds an id that this generator should no longer generate. | 
|  | // Return value indicates whether the ID was hitherto unknown. | 
|  | bool AddKnownId(absl::string_view value); | 
|  |  | 
|  | private: | 
|  | // This implementation will be simple and will generate "0", "1", ... | 
|  | UniqueNumberGenerator<uint32_t> unique_number_generator_; | 
|  | }; | 
|  |  | 
|  | template <typename TIntegral> | 
|  | UniqueNumberGenerator<TIntegral>::UniqueNumberGenerator() : counter_(0) {} | 
|  |  | 
|  | template <typename TIntegral> | 
|  | UniqueNumberGenerator<TIntegral>::UniqueNumberGenerator( | 
|  | ArrayView<TIntegral> known_ids) | 
|  | : counter_(0), known_ids_(known_ids.begin(), known_ids.end()) {} | 
|  |  | 
|  | template <typename TIntegral> | 
|  | UniqueNumberGenerator<TIntegral>::~UniqueNumberGenerator() {} | 
|  |  | 
|  | template <typename TIntegral> | 
|  | TIntegral UniqueNumberGenerator<TIntegral>::GenerateNumber() { | 
|  | RTC_DCHECK_RUN_ON(&sequence_checker_); | 
|  | while (true) { | 
|  | RTC_CHECK_LT(counter_, std::numeric_limits<TIntegral>::max()); | 
|  | auto pair = known_ids_.insert(counter_++); | 
|  | if (pair.second) { | 
|  | return *pair.first; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | template <typename TIntegral> | 
|  | bool UniqueNumberGenerator<TIntegral>::AddKnownId(TIntegral value) { | 
|  | RTC_DCHECK_RUN_ON(&sequence_checker_); | 
|  | return known_ids_.insert(value).second; | 
|  | } | 
|  | }  //  namespace webrtc | 
|  |  | 
|  | // Re-export symbols from the webrtc namespace for backwards compatibility. | 
|  | // TODO(bugs.webrtc.org/4222596): Remove once all references are updated. | 
|  | namespace rtc { | 
|  | using ::webrtc::UniqueNumberGenerator; | 
|  | using ::webrtc::UniqueRandomIdGenerator; | 
|  | using ::webrtc::UniqueStringGenerator; | 
|  | }  // namespace rtc | 
|  |  | 
|  | #endif  // RTC_BASE_UNIQUE_ID_GENERATOR_H_ |