| // Copyright 2018 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/metrics/ukm_source_id.h" |
| |
| #include "base/atomic_sequence_num.h" |
| #include "base/logging.h" |
| #include "base/rand_util.h" |
| |
| namespace base { |
| |
| namespace { |
| |
| const int64_t kLowBitsMask = (INT64_C(1) << 32) - 1; |
| const int64_t kNumTypeBits = 2; |
| const int64_t kTypeMask = (INT64_C(1) << kNumTypeBits) - 1; |
| |
| } // namespace |
| |
| // static |
| UkmSourceId UkmSourceId::New() { |
| // Generate some bits which are unique to this process, so we can generate |
| // IDs independently in different processes. IDs generated by this method may |
| // collide, but it should be sufficiently rare enough to not impact data |
| // quality. |
| const static int64_t process_id_bits = |
| static_cast<int64_t>(RandUint64()) & ~kLowBitsMask; |
| // Generate some bits which are unique within the process, using a counter. |
| static AtomicSequenceNumber seq; |
| UkmSourceId local_id = FromOtherId(seq.GetNext() + 1, UkmSourceId::Type::UKM); |
| // Combine the local and process bits to generate a unique ID. |
| return UkmSourceId((local_id.value_ & kLowBitsMask) | process_id_bits); |
| } |
| |
| // static |
| UkmSourceId UkmSourceId::FromOtherId(int64_t other_id, UkmSourceId::Type type) { |
| const int64_t type_bits = static_cast<int64_t>(type); |
| DCHECK_EQ(type_bits, type_bits & kTypeMask); |
| // Stores the the type ID in the low bits of the source id, and shift the rest |
| // of the ID to make room. This could cause the original ID to overflow, but |
| // that should be rare enough that it won't matter for UKM's purposes. |
| return UkmSourceId((other_id << kNumTypeBits) | type_bits); |
| } |
| |
| UkmSourceId::Type UkmSourceId::GetType() const { |
| return static_cast<UkmSourceId::Type>(value_ & kTypeMask); |
| } |
| |
| } // namespace base |