| /* | 
 |  *  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 <cstdint> | 
 | #include <limits> | 
 | #include <set> | 
 | #include <string> | 
 | #include <type_traits> | 
 |  | 
 | #include "absl/strings/string_view.h" | 
 | #include "api/array_view.h" | 
 | #include "api/sequence_checker.h" | 
 | #include "rtc_base/checks.h" | 
 | #include "rtc_base/synchronization/mutex.h" | 
 | #include "rtc_base/system/no_unique_address.h" | 
 | #include "rtc_base/thread_annotations.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_{ | 
 |       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 | 
 |  | 
 |  | 
 | #endif  // RTC_BASE_UNIQUE_ID_GENERATOR_H_ |