1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker #include "base/supports_user_data.h" 6*6777b538SAndroid Build Coastguard Worker 7*6777b538SAndroid Build Coastguard Worker #include "base/feature_list.h" 8*6777b538SAndroid Build Coastguard Worker #include "base/sequence_checker.h" 9*6777b538SAndroid Build Coastguard Worker 10*6777b538SAndroid Build Coastguard Worker namespace base { 11*6777b538SAndroid Build Coastguard Worker Clone()12*6777b538SAndroid Build Coastguard Workerstd::unique_ptr<SupportsUserData::Data> SupportsUserData::Data::Clone() { 13*6777b538SAndroid Build Coastguard Worker return nullptr; 14*6777b538SAndroid Build Coastguard Worker } 15*6777b538SAndroid Build Coastguard Worker SupportsUserData()16*6777b538SAndroid Build Coastguard WorkerSupportsUserData::SupportsUserData() { 17*6777b538SAndroid Build Coastguard Worker // Harmless to construct on a different execution sequence to subsequent 18*6777b538SAndroid Build Coastguard Worker // usage. 19*6777b538SAndroid Build Coastguard Worker DETACH_FROM_SEQUENCE(sequence_checker_); 20*6777b538SAndroid Build Coastguard Worker } 21*6777b538SAndroid Build Coastguard Worker 22*6777b538SAndroid Build Coastguard Worker SupportsUserData::SupportsUserData(SupportsUserData&&) = default; 23*6777b538SAndroid Build Coastguard Worker SupportsUserData& SupportsUserData::operator=(SupportsUserData&&) = default; 24*6777b538SAndroid Build Coastguard Worker GetUserData(const void * key) const25*6777b538SAndroid Build Coastguard WorkerSupportsUserData::Data* SupportsUserData::GetUserData(const void* key) const { 26*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 27*6777b538SAndroid Build Coastguard Worker // Avoid null keys; they are too vulnerable to collision. 28*6777b538SAndroid Build Coastguard Worker DCHECK(key); 29*6777b538SAndroid Build Coastguard Worker auto found = user_data_.find(key); 30*6777b538SAndroid Build Coastguard Worker if (found != user_data_.end()) { 31*6777b538SAndroid Build Coastguard Worker return found->second.get(); 32*6777b538SAndroid Build Coastguard Worker } 33*6777b538SAndroid Build Coastguard Worker return nullptr; 34*6777b538SAndroid Build Coastguard Worker } 35*6777b538SAndroid Build Coastguard Worker TakeUserData(const void * key)36*6777b538SAndroid Build Coastguard Workerstd::unique_ptr<SupportsUserData::Data> SupportsUserData::TakeUserData( 37*6777b538SAndroid Build Coastguard Worker const void* key) { 38*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 39*6777b538SAndroid Build Coastguard Worker // Null keys are too vulnerable to collision. 40*6777b538SAndroid Build Coastguard Worker CHECK(key); 41*6777b538SAndroid Build Coastguard Worker auto found = user_data_.find(key); 42*6777b538SAndroid Build Coastguard Worker if (found != user_data_.end()) { 43*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SupportsUserData::Data> deowned; 44*6777b538SAndroid Build Coastguard Worker deowned.swap(found->second); 45*6777b538SAndroid Build Coastguard Worker user_data_.erase(key); 46*6777b538SAndroid Build Coastguard Worker return deowned; 47*6777b538SAndroid Build Coastguard Worker } 48*6777b538SAndroid Build Coastguard Worker return nullptr; 49*6777b538SAndroid Build Coastguard Worker } 50*6777b538SAndroid Build Coastguard Worker SetUserData(const void * key,std::unique_ptr<Data> data)51*6777b538SAndroid Build Coastguard Workervoid SupportsUserData::SetUserData(const void* key, 52*6777b538SAndroid Build Coastguard Worker std::unique_ptr<Data> data) { 53*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 54*6777b538SAndroid Build Coastguard Worker CHECK(!in_destructor_) << "Calling SetUserData() when SupportsUserData is " 55*6777b538SAndroid Build Coastguard Worker "being destroyed is not supported."; 56*6777b538SAndroid Build Coastguard Worker // Avoid null keys; they are too vulnerable to collision. 57*6777b538SAndroid Build Coastguard Worker DCHECK(key); 58*6777b538SAndroid Build Coastguard Worker if (data.get()) { 59*6777b538SAndroid Build Coastguard Worker user_data_[key] = std::move(data); 60*6777b538SAndroid Build Coastguard Worker } else { 61*6777b538SAndroid Build Coastguard Worker RemoveUserData(key); 62*6777b538SAndroid Build Coastguard Worker } 63*6777b538SAndroid Build Coastguard Worker } 64*6777b538SAndroid Build Coastguard Worker RemoveUserData(const void * key)65*6777b538SAndroid Build Coastguard Workervoid SupportsUserData::RemoveUserData(const void* key) { 66*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 67*6777b538SAndroid Build Coastguard Worker auto it = user_data_.find(key); 68*6777b538SAndroid Build Coastguard Worker if (it != user_data_.end()) { 69*6777b538SAndroid Build Coastguard Worker // Remove the entry from the map before deleting `owned_data` to avoid 70*6777b538SAndroid Build Coastguard Worker // reentrancy issues when `owned_data` owns `this`. Otherwise: 71*6777b538SAndroid Build Coastguard Worker // 72*6777b538SAndroid Build Coastguard Worker // 1. `RemoveUserData()` calls `erase()`. 73*6777b538SAndroid Build Coastguard Worker // 2. `erase()` deletes `owned_data`. 74*6777b538SAndroid Build Coastguard Worker // 3. `owned_data` deletes `this`. 75*6777b538SAndroid Build Coastguard Worker // 76*6777b538SAndroid Build Coastguard Worker // At this point, `erase()` is still on the stack even though the 77*6777b538SAndroid Build Coastguard Worker // backing map (owned by `this`) has already been destroyed, and it 78*6777b538SAndroid Build Coastguard Worker // may simply crash, cause a use-after-free, or any other number of 79*6777b538SAndroid Build Coastguard Worker // interesting things. 80*6777b538SAndroid Build Coastguard Worker auto owned_data = std::move(it->second); 81*6777b538SAndroid Build Coastguard Worker user_data_.erase(it); 82*6777b538SAndroid Build Coastguard Worker } 83*6777b538SAndroid Build Coastguard Worker } 84*6777b538SAndroid Build Coastguard Worker DetachFromSequence()85*6777b538SAndroid Build Coastguard Workervoid SupportsUserData::DetachFromSequence() { 86*6777b538SAndroid Build Coastguard Worker DETACH_FROM_SEQUENCE(sequence_checker_); 87*6777b538SAndroid Build Coastguard Worker } 88*6777b538SAndroid Build Coastguard Worker CloneDataFrom(const SupportsUserData & other)89*6777b538SAndroid Build Coastguard Workervoid SupportsUserData::CloneDataFrom(const SupportsUserData& other) { 90*6777b538SAndroid Build Coastguard Worker for (const auto& data_pair : other.user_data_) { 91*6777b538SAndroid Build Coastguard Worker auto cloned_data = data_pair.second->Clone(); 92*6777b538SAndroid Build Coastguard Worker if (cloned_data) { 93*6777b538SAndroid Build Coastguard Worker SetUserData(data_pair.first, std::move(cloned_data)); 94*6777b538SAndroid Build Coastguard Worker } 95*6777b538SAndroid Build Coastguard Worker } 96*6777b538SAndroid Build Coastguard Worker } 97*6777b538SAndroid Build Coastguard Worker ~SupportsUserData()98*6777b538SAndroid Build Coastguard WorkerSupportsUserData::~SupportsUserData() { 99*6777b538SAndroid Build Coastguard Worker if (!user_data_.empty()) { 100*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 101*6777b538SAndroid Build Coastguard Worker } 102*6777b538SAndroid Build Coastguard Worker in_destructor_ = true; 103*6777b538SAndroid Build Coastguard Worker absl::flat_hash_map<const void*, std::unique_ptr<Data>> user_data; 104*6777b538SAndroid Build Coastguard Worker user_data_.swap(user_data); 105*6777b538SAndroid Build Coastguard Worker // Now this->user_data_ is empty, and any destructors called transitively from 106*6777b538SAndroid Build Coastguard Worker // the destruction of |local_user_data| will see it that way instead of 107*6777b538SAndroid Build Coastguard Worker // examining a being-destroyed object. 108*6777b538SAndroid Build Coastguard Worker } 109*6777b538SAndroid Build Coastguard Worker ClearAllUserData()110*6777b538SAndroid Build Coastguard Workervoid SupportsUserData::ClearAllUserData() { 111*6777b538SAndroid Build Coastguard Worker DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 112*6777b538SAndroid Build Coastguard Worker user_data_.clear(); 113*6777b538SAndroid Build Coastguard Worker } 114*6777b538SAndroid Build Coastguard Worker 115*6777b538SAndroid Build Coastguard Worker } // namespace base 116