blob: 342dad7766372ca9cead5547092e37c3717ca0ca [file] [log] [blame]
Amit Hilbuchc63ddb22019-01-02 10:13:58 -08001/*
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 14:54:24 -080011#ifndef RTC_BASE_UNIQUE_ID_GENERATOR_H_
12#define RTC_BASE_UNIQUE_ID_GENERATOR_H_
Amit Hilbuchc63ddb22019-01-02 10:13:58 -080013
14#include <limits>
15#include <set>
16#include <string>
17
Ali Tofigh7fa90572022-03-17 15:47:49 +010018#include "absl/strings/string_view.h"
Amit Hilbuchc63ddb22019-01-02 10:13:58 -080019#include "api/array_view.h"
Tomas Gunnarsson64099bc2021-04-09 09:51:37 +020020#include "api/sequence_checker.h"
21#include "rtc_base/synchronization/mutex.h"
22#include "rtc_base/system/no_unique_address.h"
Amit Hilbuchc63ddb22019-01-02 10:13:58 -080023
Amit Hilbuchdbb49df2019-01-23 14:54:24 -080024namespace rtc {
Amit Hilbuchc63ddb22019-01-02 10:13:58 -080025
26// This class will generate numbers. A common use case is for identifiers.
27// The generated numbers will be unique, in the local scope of the generator.
28// This means that a generator will never generate the same number twice.
29// The generator can also be initialized with a sequence of known ids.
30// In such a case, it will never generate an id from that list.
31// Recommendedations:
32// * Prefer unsigned types.
33// * Prefer larger types (uint8_t will run out quickly).
34template <typename TIntegral>
35class UniqueNumberGenerator {
36 public:
37 typedef TIntegral value_type;
38 UniqueNumberGenerator();
39 // Creates a generator that will never return any value from the given list.
Amit Hilbuchdbb49df2019-01-23 14:54:24 -080040 explicit UniqueNumberGenerator(ArrayView<TIntegral> known_ids);
Amit Hilbuchc63ddb22019-01-02 10:13:58 -080041 ~UniqueNumberGenerator();
42
43 // Generates a number that this generator has never produced before.
44 // If there are no available numbers to generate, this method will fail
Artem Titov96e3b992021-07-26 16:03:14 +020045 // with an `RTC_CHECK`.
Amit Hilbuchc63ddb22019-01-02 10:13:58 -080046 TIntegral GenerateNumber();
47 TIntegral operator()() { return GenerateNumber(); }
48
Amit Hilbuchae3df542019-01-07 12:13:08 -080049 // Adds an id that this generator should no longer generate.
Elad Alonefc9a142019-02-08 23:35:59 +010050 // Return value indicates whether the ID was hitherto unknown.
51 bool AddKnownId(TIntegral value);
Amit Hilbuchae3df542019-01-07 12:13:08 -080052
Amit Hilbuchc63ddb22019-01-02 10:13:58 -080053 private:
Tomas Gunnarsson64099bc2021-04-09 09:51:37 +020054 RTC_NO_UNIQUE_ADDRESS webrtc::SequenceChecker sequence_checker_;
Amit Hilbuchc63ddb22019-01-02 10:13:58 -080055 static_assert(std::is_integral<TIntegral>::value, "Must be integral type.");
Tomas Gunnarsson64099bc2021-04-09 09:51:37 +020056 TIntegral counter_ RTC_GUARDED_BY(sequence_checker_);
57 std::set<TIntegral> known_ids_ RTC_GUARDED_BY(sequence_checker_);
Amit Hilbuchc63ddb22019-01-02 10:13:58 -080058};
59
60// This class will generate unique ids. Ids are 32 bit unsigned integers.
61// The generated ids will be unique, in the local scope of the generator.
62// This means that a generator will never generate the same id twice.
63// The generator can also be initialized with a sequence of known ids.
64// In such a case, it will never generate an id from that list.
65class UniqueRandomIdGenerator {
66 public:
67 typedef uint32_t value_type;
68 UniqueRandomIdGenerator();
69 // Create a generator that will never return any value from the given list.
Amit Hilbuchdbb49df2019-01-23 14:54:24 -080070 explicit UniqueRandomIdGenerator(ArrayView<uint32_t> known_ids);
Amit Hilbuchc63ddb22019-01-02 10:13:58 -080071 ~UniqueRandomIdGenerator();
72
73 // Generates a random id that this generator has never produced before.
74 // This method becomes more expensive with each use, as the probability of
75 // collision for the randomly generated numbers increases.
76 uint32_t GenerateId();
77 uint32_t operator()() { return GenerateId(); }
78
Amit Hilbuchae3df542019-01-07 12:13:08 -080079 // Adds an id that this generator should no longer generate.
Elad Alonefc9a142019-02-08 23:35:59 +010080 // Return value indicates whether the ID was hitherto unknown.
81 bool AddKnownId(uint32_t value);
Amit Hilbuchae3df542019-01-07 12:13:08 -080082
Amit Hilbuchc63ddb22019-01-02 10:13:58 -080083 private:
Tomas Gunnarsson64099bc2021-04-09 09:51:37 +020084 // TODO(bugs.webrtc.org/12666): This lock is needed due to an instance in
85 // SdpOfferAnswerHandler being shared between threads.
86 webrtc::Mutex mutex_;
87 std::set<uint32_t> known_ids_ RTC_GUARDED_BY(&mutex_);
Amit Hilbuchc63ddb22019-01-02 10:13:58 -080088};
89
90// This class will generate strings. A common use case is for identifiers.
91// The generated strings will be unique, in the local scope of the generator.
92// This means that a generator will never generate the same string twice.
93// The generator can also be initialized with a sequence of known ids.
94// In such a case, it will never generate an id from that list.
95class UniqueStringGenerator {
96 public:
97 typedef std::string value_type;
98 UniqueStringGenerator();
Amit Hilbuchdbb49df2019-01-23 14:54:24 -080099 explicit UniqueStringGenerator(ArrayView<std::string> known_ids);
Amit Hilbuchc63ddb22019-01-02 10:13:58 -0800100 ~UniqueStringGenerator();
101
102 std::string GenerateString();
103 std::string operator()() { return GenerateString(); }
104
Amit Hilbuchae3df542019-01-07 12:13:08 -0800105 // Adds an id that this generator should no longer generate.
Elad Alonefc9a142019-02-08 23:35:59 +0100106 // Return value indicates whether the ID was hitherto unknown.
Ali Tofigh7fa90572022-03-17 15:47:49 +0100107 bool AddKnownId(absl::string_view value);
Amit Hilbuchae3df542019-01-07 12:13:08 -0800108
Amit Hilbuchc63ddb22019-01-02 10:13:58 -0800109 private:
110 // This implementation will be simple and will generate "0", "1", ...
111 UniqueNumberGenerator<uint32_t> unique_number_generator_;
112};
113
114template <typename TIntegral>
Tomas Gunnarsson64099bc2021-04-09 09:51:37 +0200115UniqueNumberGenerator<TIntegral>::UniqueNumberGenerator() : counter_(0) {
116 sequence_checker_.Detach();
117}
Amit Hilbuchc63ddb22019-01-02 10:13:58 -0800118
119template <typename TIntegral>
120UniqueNumberGenerator<TIntegral>::UniqueNumberGenerator(
Amit Hilbuchdbb49df2019-01-23 14:54:24 -0800121 ArrayView<TIntegral> known_ids)
Tomas Gunnarsson64099bc2021-04-09 09:51:37 +0200122 : counter_(0), known_ids_(known_ids.begin(), known_ids.end()) {
123 sequence_checker_.Detach();
124}
Amit Hilbuchc63ddb22019-01-02 10:13:58 -0800125
126template <typename TIntegral>
127UniqueNumberGenerator<TIntegral>::~UniqueNumberGenerator() {}
128
129template <typename TIntegral>
130TIntegral UniqueNumberGenerator<TIntegral>::GenerateNumber() {
Tomas Gunnarsson64099bc2021-04-09 09:51:37 +0200131 RTC_DCHECK_RUN_ON(&sequence_checker_);
Amit Hilbuchc63ddb22019-01-02 10:13:58 -0800132 while (true) {
133 RTC_CHECK_LT(counter_, std::numeric_limits<TIntegral>::max());
134 auto pair = known_ids_.insert(counter_++);
135 if (pair.second) {
136 return *pair.first;
137 }
138 }
139}
140
Amit Hilbuchae3df542019-01-07 12:13:08 -0800141template <typename TIntegral>
Elad Alonefc9a142019-02-08 23:35:59 +0100142bool UniqueNumberGenerator<TIntegral>::AddKnownId(TIntegral value) {
Tomas Gunnarsson64099bc2021-04-09 09:51:37 +0200143 RTC_DCHECK_RUN_ON(&sequence_checker_);
Elad Alonefc9a142019-02-08 23:35:59 +0100144 return known_ids_.insert(value).second;
Amit Hilbuchae3df542019-01-07 12:13:08 -0800145}
Amit Hilbuchdbb49df2019-01-23 14:54:24 -0800146} // namespace rtc
Amit Hilbuchc63ddb22019-01-02 10:13:58 -0800147
Amit Hilbuchdbb49df2019-01-23 14:54:24 -0800148#endif // RTC_BASE_UNIQUE_ID_GENERATOR_H_