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

Side by Side Diff: mojo/public/cpp/bindings/struct_ptr.h

Issue 2339413004: Allow Mojo structs as map keys (Closed)
Patch Set: Remove left-over import 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
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 MOJO_PUBLIC_CPP_BINDINGS_STRUCT_PTR_H_ 5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_STRUCT_PTR_H_
6 #define MOJO_PUBLIC_CPP_BINDINGS_STRUCT_PTR_H_ 6 #define MOJO_PUBLIC_CPP_BINDINGS_STRUCT_PTR_H_
7 7
8 #include <functional>
8 #include <new> 9 #include <new>
9 10
10 #include "base/logging.h" 11 #include "base/logging.h"
11 #include "base/macros.h" 12 #include "base/macros.h"
12 #include "mojo/public/cpp/bindings/type_converter.h" 13 #include "mojo/public/cpp/bindings/type_converter.h"
13 14
14 namespace mojo { 15 namespace mojo {
15 namespace internal { 16 namespace internal {
16 17
18 constexpr size_t kHashSeed = 31;
19
17 template <typename Struct> 20 template <typename Struct>
18 class StructHelper { 21 class StructHelper {
19 public: 22 public:
20 template <typename Ptr> 23 template <typename Ptr>
21 static void Initialize(Ptr* ptr) { 24 static void Initialize(Ptr* ptr) {
22 ptr->Initialize(); 25 ptr->Initialize();
23 } 26 }
24 }; 27 };
25 28
26 } // namespace internal 29 } // namespace internal
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 // type |Struct| doesn't have a Clone() method defined (which usually means 80 // type |Struct| doesn't have a Clone() method defined (which usually means
78 // that it contains Mojo handles). 81 // that it contains Mojo handles).
79 StructPtr Clone() const { return is_null() ? StructPtr() : ptr_->Clone(); } 82 StructPtr Clone() const { return is_null() ? StructPtr() : ptr_->Clone(); }
80 83
81 bool Equals(const StructPtr& other) const { 84 bool Equals(const StructPtr& other) const {
82 if (is_null() || other.is_null()) 85 if (is_null() || other.is_null())
83 return is_null() && other.is_null(); 86 return is_null() && other.is_null();
84 return ptr_->Equals(*other.ptr_); 87 return ptr_->Equals(*other.ptr_);
85 } 88 }
86 89
90 // For use in WTF::HashMap only:
91 bool isHashTableDeletedValue() const {
yzshen1 2016/09/20 23:44:40 Does it feel cleaner if we have these WTF-only fun
yzshen1 2016/09/21 23:17:52 This comment is not replied yet. (Besides, if thes
tibell 2016/09/22 05:17:23 Done.
92 return ptr_ == reinterpret_cast<Struct*>(1u);
93 }
94
95 // For use in WTF::HashMap only:
96 static void constructDeletedValue(mojo::StructPtr<S>& slot) {
97 // Dirty trick: implant an invalid pointer in |ptr_|. Destructor isn't
98 // called for deleted buckets, so this is okay.
99 new (&slot) StructPtr();
100 slot.ptr_ = reinterpret_cast<Struct*>(1u);
101 }
102
87 private: 103 private:
88 // TODO(dcheng): Use an explicit conversion operator. 104 // TODO(dcheng): Use an explicit conversion operator.
89 typedef Struct* StructPtr::*Testable; 105 typedef Struct* StructPtr::*Testable;
90 106
91 public: 107 public:
92 operator Testable() const { return ptr_ ? &StructPtr::ptr_ : 0; } 108 operator Testable() const { return ptr_ ? &StructPtr::ptr_ : 0; }
93 109
94 private: 110 private:
95 friend class internal::StructHelper<Struct>; 111 friend class internal::StructHelper<Struct>;
96 112
97 // Forbid the == and != operators explicitly, otherwise StructPtr will be
98 // converted to Testable to do == or != comparison.
yzshen1 2016/09/20 23:44:40 If you would like to allow == and !=, please fix t
tibell 2016/09/21 07:10:53 Done.
99 template <typename T>
100 bool operator==(const StructPtr<T>& other) const = delete;
101 template <typename T>
102 bool operator!=(const StructPtr<T>& other) const = delete;
103
104 void Initialize() { 113 void Initialize() {
105 DCHECK(!ptr_); 114 DCHECK(!ptr_);
106 ptr_ = new Struct(); 115 ptr_ = new Struct();
107 } 116 }
108 117
109 void Take(StructPtr* other) { 118 void Take(StructPtr* other) {
110 reset(); 119 reset();
111 Swap(other); 120 Swap(other);
112 } 121 }
113 122
114 Struct* ptr_; 123 Struct* ptr_;
115 124
116 DISALLOW_COPY_AND_ASSIGN(StructPtr); 125 DISALLOW_COPY_AND_ASSIGN(StructPtr);
117 }; 126 };
118 127
119 // Designed to be used when Struct is small and copyable. 128 // Designed to be used when Struct is small and copyable.
120 template <typename S> 129 template <typename S>
121 class InlinedStructPtr { 130 class InlinedStructPtr {
122 public: 131 public:
123 using Struct = S; 132 using Struct = S;
124 133
125 InlinedStructPtr() : is_null_(true) {} 134 InlinedStructPtr() : state_(NIL) {}
126 InlinedStructPtr(decltype(nullptr)) : is_null_(true) {} 135 InlinedStructPtr(decltype(nullptr)) : state_(NIL) {}
127 136
128 ~InlinedStructPtr() {} 137 ~InlinedStructPtr() {}
129 138
130 InlinedStructPtr& operator=(decltype(nullptr)) { 139 InlinedStructPtr& operator=(decltype(nullptr)) {
131 reset(); 140 reset();
132 return *this; 141 return *this;
133 } 142 }
134 143
135 InlinedStructPtr(InlinedStructPtr&& other) : is_null_(true) { Take(&other); } 144 InlinedStructPtr(InlinedStructPtr&& other) : state_(NIL) { Take(&other); }
136 InlinedStructPtr& operator=(InlinedStructPtr&& other) { 145 InlinedStructPtr& operator=(InlinedStructPtr&& other) {
137 Take(&other); 146 Take(&other);
138 return *this; 147 return *this;
139 } 148 }
140 149
141 template <typename U> 150 template <typename U>
142 U To() const { 151 U To() const {
143 return TypeConverter<U, InlinedStructPtr>::Convert(*this); 152 return TypeConverter<U, InlinedStructPtr>::Convert(*this);
144 } 153 }
145 154
146 void reset() { 155 void reset() {
147 is_null_ = true; 156 state_ = NIL;
148 value_. ~Struct(); 157 value_. ~Struct();
149 new (&value_) Struct(); 158 new (&value_) Struct();
150 } 159 }
151 160
152 bool is_null() const { return is_null_; } 161 bool is_null() const { return state_ == NIL; }
153 162
154 Struct& operator*() const { 163 Struct& operator*() const {
155 DCHECK(!is_null_); 164 DCHECK(state_ == VALID);
156 return value_; 165 return value_;
157 } 166 }
158 Struct* operator->() const { 167 Struct* operator->() const {
159 DCHECK(!is_null_); 168 DCHECK(state_ == VALID);
160 return &value_; 169 return &value_;
161 } 170 }
162 Struct* get() const { return &value_; } 171 Struct* get() const { return &value_; }
163 172
164 void Swap(InlinedStructPtr* other) { 173 void Swap(InlinedStructPtr* other) {
165 std::swap(value_, other->value_); 174 std::swap(value_, other->value_);
166 std::swap(is_null_, other->is_null_); 175 std::swap(state_, other->state_);
167 } 176 }
168 177
169 InlinedStructPtr Clone() const { 178 InlinedStructPtr Clone() const {
170 return is_null() ? InlinedStructPtr() : value_.Clone(); 179 return is_null() ? InlinedStructPtr() : value_.Clone();
171 } 180 }
172 bool Equals(const InlinedStructPtr& other) const { 181 bool Equals(const InlinedStructPtr& other) const {
173 if (is_null() || other.is_null()) 182 if (is_null() || other.is_null())
174 return is_null() && other.is_null(); 183 return is_null() && other.is_null();
175 return value_.Equals(other.value_); 184 return value_.Equals(other.value_);
176 } 185 }
177 186
187 // For use in WTF::HashMap only:
188 bool isHashTableDeletedValue() const { return state_ == DELETED; }
189
190 // For use in WTF::HashMap only:
191 static void constructDeletedValue(mojo::InlinedStructPtr<S>& slot) {
192 slot = InlinedStructPtr();
Sam McNally 2016/09/21 04:57:58 Should this be constructing an InlinedStructPtr in
tibell 2016/09/21 07:10:53 Done.
193 slot.state_ = DELETED;
194 }
195
178 private: 196 private:
179 // TODO(dcheng): Use an explicit conversion operator. 197 // TODO(dcheng): Use an explicit conversion operator.
180 typedef Struct InlinedStructPtr::*Testable; 198 typedef Struct InlinedStructPtr::*Testable;
181 199
182 public: 200 public:
183 operator Testable() const { return is_null_ ? 0 : &InlinedStructPtr::value_; } 201 operator Testable() const {
202 return is_null() ? 0 : &InlinedStructPtr::value_;
203 }
184 204
185 private: 205 private:
186 friend class internal::StructHelper<Struct>; 206 friend class internal::StructHelper<Struct>;
187 207
188 // Forbid the == and != operators explicitly, otherwise InlinedStructPtr will 208 void Initialize() { state_ = VALID; }
yzshen1 2016/09/20 23:44:40 Please consider fixing TODO on line 197. :)
tibell 2016/09/21 07:10:53 Done.
189 // be converted to Testable to do == or != comparison.
190 template <typename T>
191 bool operator==(const InlinedStructPtr<T>& other) const = delete;
192 template <typename T>
193 bool operator!=(const InlinedStructPtr<T>& other) const = delete;
194
195 void Initialize() { is_null_ = false; }
196 209
197 void Take(InlinedStructPtr* other) { 210 void Take(InlinedStructPtr* other) {
198 reset(); 211 reset();
199 Swap(other); 212 Swap(other);
200 } 213 }
201 214
215 enum State {
216 VALID,
217 NIL,
yzshen1 2016/09/20 23:44:40 I think NULL might be more commonly used.
tibell 2016/09/21 07:10:53 It will collide with the standard NULL macro. :)
yzshen1 2016/09/21 23:17:52 Ah, of course. :)
218 DELETED, // For use in WTF::HashMap only
219 };
220
202 mutable Struct value_; 221 mutable Struct value_;
203 bool is_null_; 222 State state_;
204 223
205 DISALLOW_COPY_AND_ASSIGN(InlinedStructPtr); 224 DISALLOW_COPY_AND_ASSIGN(InlinedStructPtr);
206 }; 225 };
207 226
208 } // namespace mojo 227 } // namespace mojo
209 228
229 namespace std {
230
231 template <typename T>
232 struct hash<mojo::StructPtr<T>> {
233 size_t operator()(const mojo::StructPtr<T>& value) const {
234 return mojo::internal::Hash(mojo::internal::kHashSeed, *value.get());
235 }
236 };
237
238 template <typename T>
239 struct hash<mojo::InlinedStructPtr<T>> {
240 size_t operator()(const mojo::InlinedStructPtr<T>& value) const {
241 return mojo::internal::Hash(mojo::internal::kHashSeed, *value.get());
242 }
243 };
244
245 } // namespace std
246
210 #endif // MOJO_PUBLIC_CPP_BINDINGS_STRUCT_PTR_H_ 247 #endif // MOJO_PUBLIC_CPP_BINDINGS_STRUCT_PTR_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698