blob: 3e2f9d70729cbd8a4070643b51714895407ba01d [file] [log] [blame]
Amit Hilbuchc63ddb22019-01-02 18:13:581/*
2 * Copyright 2018 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Amit Hilbuchdbb49df2019-01-23 22:54:2411#ifndef RTC_BASE_UNIQUE_ID_GENERATOR_H_
12#define RTC_BASE_UNIQUE_ID_GENERATOR_H_
Amit Hilbuchc63ddb22019-01-02 18:13:5813
14#include <limits>
15#include <set>
16#include <string>
17
18#include "api/array_view.h"
Tomas Gunnarsson64099bc2021-04-09 07:51:3719#include "api/sequence_checker.h"
20#include "rtc_base/synchronization/mutex.h"
21#include "rtc_base/system/no_unique_address.h"
Amit Hilbuchc63ddb22019-01-02 18:13:5822
Amit Hilbuchdbb49df2019-01-23 22:54:2423namespace rtc {
Amit Hilbuchc63ddb22019-01-02 18:13:5824
25// This class will generate numbers. A common use case is for identifiers.
26// The generated numbers will be unique, in the local scope of the generator.
27// This means that a generator will never generate the same number twice.
28// The generator can also be initialized with a sequence of known ids.
29// In such a case, it will never generate an id from that list.
30// Recommendedations:
31// * Prefer unsigned types.
32// * Prefer larger types (uint8_t will run out quickly).
33template <typename TIntegral>
34class UniqueNumberGenerator {
35 public:
36 typedef TIntegral value_type;
37 UniqueNumberGenerator();
38 // Creates a generator that will never return any value from the given list.
Amit Hilbuchdbb49df2019-01-23 22:54:2439 explicit UniqueNumberGenerator(ArrayView<TIntegral> known_ids);
Amit Hilbuchc63ddb22019-01-02 18:13:5840 ~UniqueNumberGenerator();
41
42 // Generates a number that this generator has never produced before.
43 // If there are no available numbers to generate, this method will fail
Artem Titov96e3b992021-07-26 14:03:1444 // with an `RTC_CHECK`.
Amit Hilbuchc63ddb22019-01-02 18:13:5845 TIntegral GenerateNumber();
46 TIntegral operator()() { return GenerateNumber(); }
47
Amit Hilbuchae3df542019-01-07 20:13:0848 // Adds an id that this generator should no longer generate.
Elad Alonefc9a142019-02-08 22:35:5949 // Return value indicates whether the ID was hitherto unknown.
50 bool AddKnownId(TIntegral value);
Amit Hilbuchae3df542019-01-07 20:13:0851
Amit Hilbuchc63ddb22019-01-02 18:13:5852 private:
Tomas Gunnarsson64099bc2021-04-09 07:51:3753 RTC_NO_UNIQUE_ADDRESS webrtc::SequenceChecker sequence_checker_;
Amit Hilbuchc63ddb22019-01-02 18:13:5854 static_assert(std::is_integral<TIntegral>::value, "Must be integral type.");
Tomas Gunnarsson64099bc2021-04-09 07:51:3755 TIntegral counter_ RTC_GUARDED_BY(sequence_checker_);
56 std::set<TIntegral> known_ids_ RTC_GUARDED_BY(sequence_checker_);
Amit Hilbuchc63ddb22019-01-02 18:13:5857};
58
59// This class will generate unique ids. Ids are 32 bit unsigned integers.
60// The generated ids will be unique, in the local scope of the generator.
61// This means that a generator will never generate the same id twice.
62// The generator can also be initialized with a sequence of known ids.
63// In such a case, it will never generate an id from that list.
64class UniqueRandomIdGenerator {
65 public:
66 typedef uint32_t value_type;
67 UniqueRandomIdGenerator();
68 // Create a generator that will never return any value from the given list.
Amit Hilbuchdbb49df2019-01-23 22:54:2469 explicit UniqueRandomIdGenerator(ArrayView<uint32_t> known_ids);
Amit Hilbuchc63ddb22019-01-02 18:13:5870 ~UniqueRandomIdGenerator();
71
72 // Generates a random id that this generator has never produced before.
73 // This method becomes more expensive with each use, as the probability of
74 // collision for the randomly generated numbers increases.
75 uint32_t GenerateId();
76 uint32_t operator()() { return GenerateId(); }
77
Amit Hilbuchae3df542019-01-07 20:13:0878 // Adds an id that this generator should no longer generate.
Elad Alonefc9a142019-02-08 22:35:5979 // Return value indicates whether the ID was hitherto unknown.
80 bool AddKnownId(uint32_t value);
Amit Hilbuchae3df542019-01-07 20:13:0881
Amit Hilbuchc63ddb22019-01-02 18:13:5882 private:
Tomas Gunnarsson64099bc2021-04-09 07:51:3783 // TODO(bugs.webrtc.org/12666): This lock is needed due to an instance in
84 // SdpOfferAnswerHandler being shared between threads.
85 webrtc::Mutex mutex_;
86 std::set<uint32_t> known_ids_ RTC_GUARDED_BY(&mutex_);
Amit Hilbuchc63ddb22019-01-02 18:13:5887};
88
89// This class will generate strings. A common use case is for identifiers.
90// The generated strings will be unique, in the local scope of the generator.
91// This means that a generator will never generate the same string twice.
92// The generator can also be initialized with a sequence of known ids.
93// In such a case, it will never generate an id from that list.
94class UniqueStringGenerator {
95 public:
96 typedef std::string value_type;
97 UniqueStringGenerator();
Amit Hilbuchdbb49df2019-01-23 22:54:2498 explicit UniqueStringGenerator(ArrayView<std::string> known_ids);
Amit Hilbuchc63ddb22019-01-02 18:13:5899 ~UniqueStringGenerator();
100
101 std::string GenerateString();
102 std::string operator()() { return GenerateString(); }
103
Amit Hilbuchae3df542019-01-07 20:13:08104 // Adds an id that this generator should no longer generate.
Elad Alonefc9a142019-02-08 22:35:59105 // Return value indicates whether the ID was hitherto unknown.
106 bool AddKnownId(const std::string& value);
Amit Hilbuchae3df542019-01-07 20:13:08107
Amit Hilbuchc63ddb22019-01-02 18:13:58108 private:
109 // This implementation will be simple and will generate "0", "1", ...
110 UniqueNumberGenerator<uint32_t> unique_number_generator_;
111};
112
113template <typename TIntegral>
Tomas Gunnarsson64099bc2021-04-09 07:51:37114UniqueNumberGenerator<TIntegral>::UniqueNumberGenerator() : counter_(0) {
115 sequence_checker_.Detach();
116}
Amit Hilbuchc63ddb22019-01-02 18:13:58117
118template <typename TIntegral>
119UniqueNumberGenerator<TIntegral>::UniqueNumberGenerator(
Amit Hilbuchdbb49df2019-01-23 22:54:24120 ArrayView<TIntegral> known_ids)
Tomas Gunnarsson64099bc2021-04-09 07:51:37121 : counter_(0), known_ids_(known_ids.begin(), known_ids.end()) {
122 sequence_checker_.Detach();
123}
Amit Hilbuchc63ddb22019-01-02 18:13:58124
125template <typename TIntegral>
126UniqueNumberGenerator<TIntegral>::~UniqueNumberGenerator() {}
127
128template <typename TIntegral>
129TIntegral UniqueNumberGenerator<TIntegral>::GenerateNumber() {
Tomas Gunnarsson64099bc2021-04-09 07:51:37130 RTC_DCHECK_RUN_ON(&sequence_checker_);
Amit Hilbuchc63ddb22019-01-02 18:13:58131 while (true) {
132 RTC_CHECK_LT(counter_, std::numeric_limits<TIntegral>::max());
133 auto pair = known_ids_.insert(counter_++);
134 if (pair.second) {
135 return *pair.first;
136 }
137 }
138}
139
Amit Hilbuchae3df542019-01-07 20:13:08140template <typename TIntegral>
Elad Alonefc9a142019-02-08 22:35:59141bool UniqueNumberGenerator<TIntegral>::AddKnownId(TIntegral value) {
Tomas Gunnarsson64099bc2021-04-09 07:51:37142 RTC_DCHECK_RUN_ON(&sequence_checker_);
Elad Alonefc9a142019-02-08 22:35:59143 return known_ids_.insert(value).second;
Amit Hilbuchae3df542019-01-07 20:13:08144}
Amit Hilbuchdbb49df2019-01-23 22:54:24145} // namespace rtc
Amit Hilbuchc63ddb22019-01-02 18:13:58146
Amit Hilbuchdbb49df2019-01-23 22:54:24147#endif // RTC_BASE_UNIQUE_ID_GENERATOR_H_