1 // Copyright 2020 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef DEVICE_VR_ANDROID_ARCORE_ADDRESS_TO_ID_MAP_H_ 6 #define DEVICE_VR_ANDROID_ARCORE_ADDRESS_TO_ID_MAP_H_ 7 8 #include "base/check.h" 9 #include "base/optional.h" 10 #include "base/stl_util.h" 11 12 #include <unordered_map> 13 14 namespace device { 15 16 // Wrapper class used to generate an Id for a given address. Allows looking up 17 // the Id for an address at a later time, or removing the mapping when desired. 18 // Ids generated will be monotonically increasing from 1, and are suitable to 19 // be passed over mojo. The Ids should be directly exposable from blink if 20 // desired. 21 // Note that IdType must be constructable from a uint64_t, and should most often 22 // be a util::IdTypeU64 type. 23 template <typename IdType> 24 class AddressToIdMap { 25 public: 26 // Helper struct to provide a cleaner return interface than a std::pair for 27 // CreateOrGetId. 28 struct CreateOrGetIdResult { 29 // The found or newly created Id corresponding to the supplied address. 30 IdType id; 31 32 // Whether or not the above Id was newly created (true), or found (false). 33 bool created; 34 CreateOrGetIdResultCreateOrGetIdResult35 CreateOrGetIdResult(IdType id, bool created) : id(id), created(created) {} 36 }; 37 38 // Retrieves or creates an id for the corresponding address. CreateOrGetId(void * address)39 CreateOrGetIdResult CreateOrGetId(void* address) { 40 auto it = address_to_id_.find(address); 41 if (it != address_to_id_.end()) { 42 return {it->second, false}; 43 } 44 45 CHECK(next_id_ != std::numeric_limits<uint64_t>::max()) 46 << "preventing ID overflow"; 47 48 uint64_t current_id = next_id_; 49 next_id_++; 50 address_to_id_.emplace(address, current_id); 51 52 return {IdType(current_id), true}; 53 } 54 55 // Gets the id for the corresponding address, if it's available. GetId(void * address)56 base::Optional<IdType> GetId(void* address) const { 57 auto it = address_to_id_.find(address); 58 if (it == address_to_id_.end()) { 59 return base::nullopt; 60 } 61 62 return it->second; 63 } 64 65 // Used to "erase" a particular id->address mapping, such that lookup methods 66 // for the given address will fail. This will result in a new id being 67 // generated if the address is passed into CreateOrGetId. 68 template <class Predicate> EraseIf(Predicate pred)69 size_t EraseIf(Predicate pred) { 70 return base::EraseIf(address_to_id_, pred); 71 } 72 73 private: 74 // The HashMaps used in blink do not allow Ids that evaluate to 0. Thus, we 75 // start generating Ids from 1, so that the first IdType does not cause any 76 // issues in blink. 77 uint64_t next_id_ = 1; 78 std::unordered_map<void*, IdType> address_to_id_; 79 }; 80 81 } // namespace device 82 83 #endif // DEVICE_VR_ANDROID_ARCORE_ADDRESS_TO_ID_MAP_H_ 84