Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(853)

Side by Side Diff: base/id_map.h

Issue 2340813003: Switch base::IDMap to use unique_ptr. (Closed)
Patch Set: unique_ptr<> versions of Add/AddWithId Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | content/browser/service_worker/service_worker_context_core.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef BASE_ID_MAP_H_ 5 #ifndef BASE_ID_MAP_H_
6 #define BASE_ID_MAP_H_ 6 #define BASE_ID_MAP_H_
7 7
8 #include <stddef.h> 8 #include <stddef.h>
9 #include <stdint.h> 9 #include <stdint.h>
10 #include <memory>
10 #include <set> 11 #include <set>
12 #include <type_traits>
13 #include <utility>
11 14
12 #include "base/containers/hash_tables.h" 15 #include "base/containers/hash_tables.h"
13 #include "base/logging.h" 16 #include "base/logging.h"
14 #include "base/macros.h" 17 #include "base/macros.h"
15 #include "base/sequence_checker.h" 18 #include "base/sequence_checker.h"
16 19
17 // Ownership semantics - own pointer means the pointer is deleted in Remove() 20 // Ownership semantics - own pointer means the pointer is deleted in Remove()
18 // & during destruction 21 // & during destruction
19 enum IDMapOwnershipSemantics { 22 enum IDMapOwnershipSemantics {
20 IDMapExternalPointer, 23 IDMapExternalPointer,
(...skipping 12 matching lines...) Expand all
33 // This class does not have a virtual destructor, do not inherit from it when 36 // This class does not have a virtual destructor, do not inherit from it when
34 // ownership semantics are set to own because pointers will leak. 37 // ownership semantics are set to own because pointers will leak.
35 template <typename T, 38 template <typename T,
36 IDMapOwnershipSemantics OS = IDMapExternalPointer, 39 IDMapOwnershipSemantics OS = IDMapExternalPointer,
37 typename K = int32_t> 40 typename K = int32_t>
38 class IDMap { 41 class IDMap {
39 public: 42 public:
40 using KeyType = K; 43 using KeyType = K;
41 44
42 private: 45 private:
43 typedef base::hash_map<KeyType, T*> HashTable; 46 using V = typename std::
47 conditional<OS == IDMapExternalPointer, T*, std::unique_ptr<T>>::type;
48 using HashTable = base::hash_map<KeyType, V>;
44 49
45 public: 50 public:
46 IDMap() : iteration_depth_(0), next_id_(1), check_on_null_data_(false) { 51 IDMap() : iteration_depth_(0), next_id_(1), check_on_null_data_(false) {
47 // A number of consumers of IDMap create it on one thread but always 52 // A number of consumers of IDMap create it on one thread but always
48 // access it from a different, but consistent, thread (or sequence) 53 // access it from a different, but consistent, thread (or sequence)
49 // post-construction. The first call to CalledOnValidSequence() will re-bind 54 // post-construction. The first call to CalledOnValidSequence() will re-bind
50 // it. 55 // it.
51 sequence_checker_.DetachFromSequence(); 56 sequence_checker_.DetachFromSequence();
52 } 57 }
53 58
54 ~IDMap() { 59 ~IDMap() {
55 // Many IDMap's are static, and hence will be destroyed on the main 60 // Many IDMap's are static, and hence will be destroyed on the main
56 // thread. However, all the accesses may take place on another thread (or 61 // thread. However, all the accesses may take place on another thread (or
57 // sequence), such as the IO thread. Detaching again to clean this up. 62 // sequence), such as the IO thread. Detaching again to clean this up.
58 sequence_checker_.DetachFromSequence(); 63 sequence_checker_.DetachFromSequence();
59 Releaser<OS, 0>::release_all(&data_);
60 } 64 }
61 65
62 // Sets whether Add and Replace should DCHECK if passed in NULL data. 66 // Sets whether Add and Replace should DCHECK if passed in NULL data.
63 // Default is false. 67 // Default is false.
64 void set_check_on_null_data(bool value) { check_on_null_data_ = value; } 68 void set_check_on_null_data(bool value) { check_on_null_data_ = value; }
65 69
66 // Adds a view with an automatically generated unique ID. See AddWithID. 70 // Adds a view with an automatically generated unique ID. See AddWithID.
67 KeyType Add(T* data) { 71 // (This unique_ptr<> variant will not compile in IDMapExternalPointer mode.)
68 DCHECK(sequence_checker_.CalledOnValidSequence()); 72 KeyType Add(std::unique_ptr<T> data) {
69 DCHECK(!check_on_null_data_ || data); 73 return AddInternal(std::move(data));
70 KeyType this_id = next_id_;
71 DCHECK(data_.find(this_id) == data_.end()) << "Inserting duplicate item";
72 data_[this_id] = data;
73 next_id_++;
74 return this_id;
75 } 74 }
76 75
77 // Adds a new data member with the specified ID. The ID must not be in 76 // Adds a new data member with the specified ID. The ID must not be in
78 // the list. The caller either must generate all unique IDs itself and use 77 // the list. The caller either must generate all unique IDs itself and use
79 // this function, or allow this object to generate IDs and call Add. These 78 // this function, or allow this object to generate IDs and call Add. These
80 // two methods may not be mixed, or duplicate IDs may be generated 79 // two methods may not be mixed, or duplicate IDs may be generated.
80 // (This unique_ptr<> variant will not compile in IDMapExternalPointer mode.)
81 void AddWithID(std::unique_ptr<T> data, KeyType id) {
82 AddWithIDInternal(std::move(data), id);
83 }
84
85 // http://crbug.com/647091: Raw pointer Add()s in IDMapOwnPointer mode are
86 // deprecated. Users of IDMapOwnPointer should transition to the unique_ptr
87 // variant above, and the following methods should only be used in
88 // IDMapExternalPointer mode.
89 KeyType Add(T* data) {
90 return AddInternal(V(data));
91 }
81 void AddWithID(T* data, KeyType id) { 92 void AddWithID(T* data, KeyType id) {
82 DCHECK(sequence_checker_.CalledOnValidSequence()); 93 AddWithIDInternal(V(data), id);
83 DCHECK(!check_on_null_data_ || data);
84 DCHECK(data_.find(id) == data_.end()) << "Inserting duplicate item";
85 data_[id] = data;
86 } 94 }
87 95
88 void Remove(KeyType id) { 96 void Remove(KeyType id) {
89 DCHECK(sequence_checker_.CalledOnValidSequence()); 97 DCHECK(sequence_checker_.CalledOnValidSequence());
90 typename HashTable::iterator i = data_.find(id); 98 typename HashTable::iterator i = data_.find(id);
91 if (i == data_.end()) { 99 if (i == data_.end()) {
92 NOTREACHED() << "Attempting to remove an item not in the list"; 100 NOTREACHED() << "Attempting to remove an item not in the list";
93 return; 101 return;
94 } 102 }
95 103
96 if (iteration_depth_ == 0) { 104 if (iteration_depth_ == 0) {
97 Releaser<OS, 0>::release(i->second);
98 data_.erase(i); 105 data_.erase(i);
99 } else { 106 } else {
100 removed_ids_.insert(id); 107 removed_ids_.insert(id);
101 } 108 }
102 } 109 }
103 110
104 // Replaces the value for |id| with |new_data| and returns a pointer to the 111 // Replaces the value for |id| with |new_data| and returns the existing value
105 // existing value. If there is no entry for |id|, the map is not altered and 112 // (as a unique_ptr<> if in IDMapOwnPointer mode). Should only be called with
106 // nullptr is returned. The OwnershipSemantics of the map have no effect on 113 // an already added id.
107 // how the existing value is treated, the IDMap does not delete the existing 114 V Replace(KeyType id, V new_data) {
108 // value being replaced.
109 T* Replace(KeyType id, T* new_data) {
110 DCHECK(sequence_checker_.CalledOnValidSequence()); 115 DCHECK(sequence_checker_.CalledOnValidSequence());
111 DCHECK(!check_on_null_data_ || new_data); 116 DCHECK(!check_on_null_data_ || new_data);
112 typename HashTable::iterator i = data_.find(id); 117 typename HashTable::iterator i = data_.find(id);
113 if (i == data_.end()) { 118 DCHECK(i != data_.end());
114 NOTREACHED() << "Attempting to replace an item not in the list";
115 return nullptr;
116 }
117 119
118 T* temp = i->second; 120 std::swap(i->second, new_data);
119 i->second = new_data; 121 return new_data;
120 return temp;
121 } 122 }
122 123
123 void Clear() { 124 void Clear() {
124 DCHECK(sequence_checker_.CalledOnValidSequence()); 125 DCHECK(sequence_checker_.CalledOnValidSequence());
125 if (iteration_depth_ == 0) { 126 if (iteration_depth_ == 0) {
126 Releaser<OS, 0>::release_all(&data_); 127 data_.clear();
127 } else { 128 } else {
128 for (typename HashTable::iterator i = data_.begin(); 129 for (typename HashTable::iterator i = data_.begin();
129 i != data_.end(); ++i) 130 i != data_.end(); ++i)
130 removed_ids_.insert(i->first); 131 removed_ids_.insert(i->first);
131 } 132 }
132 } 133 }
133 134
134 bool IsEmpty() const { 135 bool IsEmpty() const {
135 DCHECK(sequence_checker_.CalledOnValidSequence()); 136 DCHECK(sequence_checker_.CalledOnValidSequence());
136 return size() == 0u; 137 return size() == 0u;
137 } 138 }
138 139
139 T* Lookup(KeyType id) const { 140 T* Lookup(KeyType id) const {
140 DCHECK(sequence_checker_.CalledOnValidSequence()); 141 DCHECK(sequence_checker_.CalledOnValidSequence());
141 typename HashTable::const_iterator i = data_.find(id); 142 typename HashTable::const_iterator i = data_.find(id);
142 if (i == data_.end()) 143 if (i == data_.end())
143 return NULL; 144 return nullptr;
144 return i->second; 145 return &*i->second;
145 } 146 }
146 147
147 size_t size() const { 148 size_t size() const {
148 DCHECK(sequence_checker_.CalledOnValidSequence()); 149 DCHECK(sequence_checker_.CalledOnValidSequence());
149 return data_.size() - removed_ids_.size(); 150 return data_.size() - removed_ids_.size();
150 } 151 }
151 152
152 #if defined(UNIT_TEST) 153 #if defined(UNIT_TEST)
153 int iteration_depth() const { 154 int iteration_depth() const {
154 return iteration_depth_; 155 return iteration_depth_;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 return iter_ == map_->data_.end(); 196 return iter_ == map_->data_.end();
196 } 197 }
197 198
198 KeyType GetCurrentKey() const { 199 KeyType GetCurrentKey() const {
199 DCHECK(map_->sequence_checker_.CalledOnValidSequence()); 200 DCHECK(map_->sequence_checker_.CalledOnValidSequence());
200 return iter_->first; 201 return iter_->first;
201 } 202 }
202 203
203 ReturnType* GetCurrentValue() const { 204 ReturnType* GetCurrentValue() const {
204 DCHECK(map_->sequence_checker_.CalledOnValidSequence()); 205 DCHECK(map_->sequence_checker_.CalledOnValidSequence());
205 return iter_->second; 206 return &*iter_->second;
206 } 207 }
207 208
208 void Advance() { 209 void Advance() {
209 DCHECK(map_->sequence_checker_.CalledOnValidSequence()); 210 DCHECK(map_->sequence_checker_.CalledOnValidSequence());
210 ++iter_; 211 ++iter_;
211 SkipRemovedEntries(); 212 SkipRemovedEntries();
212 } 213 }
213 214
214 private: 215 private:
215 void Init() { 216 void Init() {
(...skipping 11 matching lines...) Expand all
227 } 228 }
228 229
229 IDMap<T, OS, K>* map_; 230 IDMap<T, OS, K>* map_;
230 typename HashTable::const_iterator iter_; 231 typename HashTable::const_iterator iter_;
231 }; 232 };
232 233
233 typedef Iterator<T> iterator; 234 typedef Iterator<T> iterator;
234 typedef Iterator<const T> const_iterator; 235 typedef Iterator<const T> const_iterator;
235 236
236 private: 237 private:
238 KeyType AddInternal(V data) {
239 DCHECK(sequence_checker_.CalledOnValidSequence());
240 DCHECK(!check_on_null_data_ || data);
241 KeyType this_id = next_id_;
242 DCHECK(data_.find(this_id) == data_.end()) << "Inserting duplicate item";
243 data_[this_id] = std::move(data);
244 next_id_++;
245 return this_id;
246 }
237 247
238 // The dummy parameter is there because C++ standard does not allow 248 void AddWithIDInternal(V data, KeyType id) {
239 // explicitly specialized templates inside classes 249 DCHECK(sequence_checker_.CalledOnValidSequence());
240 template<IDMapOwnershipSemantics OI, int dummy> struct Releaser { 250 DCHECK(!check_on_null_data_ || data);
241 static inline void release(T* ptr) {} 251 DCHECK(data_.find(id) == data_.end()) << "Inserting duplicate item";
242 static inline void release_all(HashTable* table) {} 252 data_[id] = std::move(data);
243 }; 253 }
244
245 template<int dummy> struct Releaser<IDMapOwnPointer, dummy> {
246 static inline void release(T* ptr) { delete ptr;}
247 static inline void release_all(HashTable* table) {
248 for (typename HashTable::iterator i = table->begin();
249 i != table->end(); ++i) {
250 delete i->second;
251 }
252 table->clear();
253 }
254 };
255 254
256 void Compact() { 255 void Compact() {
257 DCHECK_EQ(0, iteration_depth_); 256 DCHECK_EQ(0, iteration_depth_);
258 for (const auto& i : removed_ids_) 257 for (const auto& i : removed_ids_)
259 Remove(i); 258 Remove(i);
260 removed_ids_.clear(); 259 removed_ids_.clear();
261 } 260 }
262 261
263 // Keep track of how many iterators are currently iterating on us to safely 262 // Keep track of how many iterators are currently iterating on us to safely
264 // handle removing items during iteration. 263 // handle removing items during iteration.
(...skipping 11 matching lines...) Expand all
276 275
277 // See description above setter. 276 // See description above setter.
278 bool check_on_null_data_; 277 bool check_on_null_data_;
279 278
280 base::SequenceChecker sequence_checker_; 279 base::SequenceChecker sequence_checker_;
281 280
282 DISALLOW_COPY_AND_ASSIGN(IDMap); 281 DISALLOW_COPY_AND_ASSIGN(IDMap);
283 }; 282 };
284 283
285 #endif // BASE_ID_MAP_H_ 284 #endif // BASE_ID_MAP_H_
OLDNEW
« no previous file with comments | « no previous file | content/browser/service_worker/service_worker_context_core.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698