OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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_SYSTEM_MEMORY_H_ | 5 #ifndef MOJO_SYSTEM_MEMORY_H_ |
6 #define MOJO_SYSTEM_MEMORY_H_ | 6 #define MOJO_SYSTEM_MEMORY_H_ |
7 | 7 |
8 #include <stddef.h> | 8 #include <stddef.h> |
9 #include <stdint.h> | |
10 #include <string.h> // For |memcpy()|. | |
9 | 11 |
12 #include "base/macros.h" | |
13 #include "base/memory/scoped_ptr.h" | |
10 #include "mojo/public/c/system/macros.h" | 14 #include "mojo/public/c/system/macros.h" |
11 #include "mojo/system/system_impl_export.h" | 15 #include "mojo/system/system_impl_export.h" |
12 | 16 |
13 namespace mojo { | 17 namespace mojo { |
14 namespace system { | 18 namespace system { |
15 | 19 |
16 namespace internal { | 20 namespace internal { |
17 | 21 |
22 // Removes |const| from |T| (available as |remove_const<T>::type|): | |
darin (slow to review)
2014/07/24 16:55:38
Add a TODO about removing these once we can assume
viettrungluu
2014/07/24 17:09:05
Done.
| |
23 template <typename T> struct remove_const { typedef T type; }; | |
24 template <typename T> struct remove_const<const T> { typedef T type; }; | |
25 | |
26 // Yields |(const) char| if |T| is |(const) void|, else |T|: | |
27 template <typename T> struct void_to_char { typedef T type; }; | |
darin (slow to review)
2014/07/24 16:55:38
Should this be VoidToChar? The lower_case name is
viettrungluu
2014/07/24 17:09:05
Done.
| |
28 template <> struct void_to_char<void> { typedef char type; }; | |
29 template <> struct void_to_char<const void> { typedef const char type; }; | |
30 | |
31 template <size_t size, size_t alignment> | |
32 void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointerHelper(const void* pointer); | |
33 | |
34 template <size_t size, size_t alignment> | |
35 void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointerWithCountHelper( | |
36 const void* pointer, | |
37 size_t count); | |
38 | |
39 // TODO(vtl): Delete all the |Verify...()| things (and replace them with | |
40 // |Check...()|. | |
18 template <size_t size, size_t alignment> | 41 template <size_t size, size_t alignment> |
19 bool MOJO_SYSTEM_IMPL_EXPORT VerifyUserPointerHelper(const void* pointer); | 42 bool MOJO_SYSTEM_IMPL_EXPORT VerifyUserPointerHelper(const void* pointer); |
20 | 43 |
21 // Note: This is also used by options_validation.h. | 44 // Note: This is also used by options_validation.h. |
22 template <size_t size, size_t alignment> | 45 template <size_t size, size_t alignment> |
23 bool MOJO_SYSTEM_IMPL_EXPORT VerifyUserPointerWithCountHelper( | 46 bool MOJO_SYSTEM_IMPL_EXPORT VerifyUserPointerWithCountHelper( |
24 const void* pointer, | 47 const void* pointer, |
25 size_t count); | 48 size_t count); |
26 | 49 |
50 // Forward declarations so that they can be friended. | |
51 template <typename Type> class UserPointerReader; | |
52 template <typename Type> class UserPointerWriter; | |
53 template <typename Type> class UserPointerReaderWriter; | |
54 | |
27 } // namespace internal | 55 } // namespace internal |
28 | 56 |
29 // Verify (insofar as possible/necessary) that a |T| can be read from the user | 57 // Verify (insofar as possible/necessary) that a |T| can be read from the user |
30 // |pointer|. | 58 // |pointer|. |
31 template <typename T> | 59 template <typename T> |
32 bool VerifyUserPointer(const T* pointer) { | 60 bool VerifyUserPointer(const T* pointer) { |
33 return internal::VerifyUserPointerHelper<sizeof(T), MOJO_ALIGNOF(T)>(pointer); | 61 return internal::VerifyUserPointerHelper<sizeof(T), MOJO_ALIGNOF(T)>(pointer); |
34 } | 62 } |
35 | 63 |
36 // Verify (insofar as possible/necessary) that |count| |T|s can be read from the | 64 // Verify (insofar as possible/necessary) that |count| |T|s can be read from the |
37 // user |pointer|; |count| may be zero. (This is done carefully since |count * | 65 // user |pointer|; |count| may be zero. (This is done carefully since |count * |
38 // sizeof(T)| may overflow a |size_t|.) | 66 // sizeof(T)| may overflow a |size_t|.) |
39 template <typename T> | 67 template <typename T> |
40 bool VerifyUserPointerWithCount(const T* pointer, size_t count) { | 68 bool VerifyUserPointerWithCount(const T* pointer, size_t count) { |
41 return internal::VerifyUserPointerWithCountHelper<sizeof(T), | 69 return internal::VerifyUserPointerWithCountHelper<sizeof(T), |
42 MOJO_ALIGNOF(T)>(pointer, | 70 MOJO_ALIGNOF(T)>(pointer, |
43 count); | 71 count); |
44 } | 72 } |
45 | 73 |
46 // Verify that |size| bytes (which may be zero) can be read from the user | 74 // Verify that |size| bytes (which may be zero) can be read from the user |
47 // |pointer|, and that |pointer| has the specified |alignment| (if |size| is | 75 // |pointer|, and that |pointer| has the specified |alignment| (if |size| is |
48 // nonzero). | 76 // nonzero). |
49 template <size_t alignment> | 77 template <size_t alignment> |
50 bool MOJO_SYSTEM_IMPL_EXPORT VerifyUserPointerWithSize(const void* pointer, | 78 bool MOJO_SYSTEM_IMPL_EXPORT VerifyUserPointerWithSize(const void* pointer, |
51 size_t size); | 79 size_t size); |
52 | 80 |
81 // Provides a convenient way to implicitly get null |UserPointer<Type>|s. | |
82 struct NullUserPointer {}; | |
83 | |
84 // Represents a user pointer to a single |Type| (which must be POD), for Mojo | |
85 // primitive parameters. | |
86 // | |
87 // Use a const |Type| for in parameters, and non-const |Type|s for out and | |
88 // in-out parameters (in which case the |Put()| method is available). | |
89 template <typename Type> | |
90 class UserPointer { | |
91 public: | |
92 // Instead of explicitly using these constructors, you can often use | |
93 // |MakeUserPointer()| (or |NullUserPointer()| for null pointers). (The common | |
94 // exception is when you have, e.g., a |char*| and want to get a | |
95 // |UserPointer<void>|.) | |
96 UserPointer() : pointer_(NULL) {} | |
97 explicit UserPointer(Type* pointer) : pointer_(pointer) {} | |
98 // Allow implicit conversion from the "null user pointer". | |
99 UserPointer(NullUserPointer) : pointer_(NULL) {} | |
100 ~UserPointer() {} | |
101 | |
102 // Allow assignment from the "null user pointer". | |
103 UserPointer<Type>& operator=(NullUserPointer) { | |
104 pointer_ = NULL; | |
105 return *this; | |
106 } | |
107 | |
108 // Allow conversion to a "non-const" |UserPointer|. | |
109 operator UserPointer<const Type>() const { | |
110 return UserPointer<const Type>(pointer_); | |
111 } | |
112 | |
113 bool IsNull() const { | |
114 return !pointer_; | |
115 } | |
116 | |
117 // We want to force a copy here, so return |Type| not |const Type&|. | |
118 Type Get() const { | |
119 internal::CheckUserPointerHelper<sizeof(Type), | |
120 MOJO_ALIGNOF(Type)>(pointer_); | |
121 return *pointer_; | |
122 } | |
123 | |
124 // Note: This |Put()| method is not valid when |T| is const, e.g., |const | |
125 // uint32_t|, but it's okay to include them so long as this template is only | |
126 // implicitly instantiated (see 14.7.1 of the C++11 standard) and not | |
127 // explicitly instantiated. (On implicit instantiation, only the declarations | |
128 // need be valid, not the definitions.) | |
129 // | |
130 // If |Type| is |void|, we "convert" it to |char|, so that it makes sense. | |
131 // (Otherwise, we'd need a suitable specialization to exclude |Put()|.) | |
132 // | |
133 // In C++11, we could do something like: | |
134 // template <typename _Type = Type> | |
135 // typename enable_if<!is_const<_Type>::value && | |
136 // !is_void<_Type>::value>::type Put( | |
137 // const _Type& value) { ... } | |
138 // (which obviously be correct), but C++03 doesn't allow default function | |
139 // template arguments. | |
140 void Put(const typename internal::void_to_char<Type>::type& value) { | |
141 internal::CheckUserPointerHelper<sizeof(Type), | |
142 MOJO_ALIGNOF(Type)>(pointer_); | |
143 *pointer_ = value; | |
144 } | |
145 | |
146 UserPointer At(size_t i) const { | |
147 return UserPointer(pointer_ + i); | |
148 } | |
149 | |
150 // TODO(vtl): This is temporary. Get rid of this. (We should pass | |
151 // |UserPointer<>|s along appropriately, or access data in a safe way | |
152 // everywhere.) | |
153 Type* GetPointerUnsafe() const { | |
154 return pointer_; | |
155 } | |
156 | |
157 // These provides safe (read-only/write-only/read-and-write) access to a | |
158 // |UserPointer<Type>| (probably pointing to an array) using just an ordinary | |
159 // pointer (obtained via |GetPointer()|). | |
160 // | |
161 // The memory returned by |GetPointer()| may be a copy of the original user | |
162 // memory, but should be modified only if the user is intended to eventually | |
163 // see the change.) If any changes are made, |Commit()| should be called to | |
164 // guarantee that the changes are written back to user memory (it may be | |
165 // called multiple times). | |
166 // | |
167 // Note: These classes are designed to allow fast, unsafe implementations (in | |
168 // which |GetPointer()| just returns the user pointer) if desired. Thus if | |
169 // |Commit()| is *not* called, changes may or may not be made visible to the | |
170 // user. | |
171 // | |
172 // Use these classes in the following way: | |
173 // | |
174 // MojoResult Core::PutFoos(UserPointer<const uint32_t> foos, | |
175 // uint32_t num_foos) { | |
176 // UserPointer<const uint32_t>::Reader foos_reader(foos, num_foos); | |
177 // return PutFoosImpl(foos_reader.GetPointer(), num_foos); | |
178 // } | |
179 // | |
180 // MojoResult Core::GetFoos(UserPointer<uint32_t> foos, | |
181 // uint32_t num_foos) { | |
182 // UserPointer<uint32_t>::Writer foos_writer(foos, num_foos); | |
183 // MojoResult rv = GetFoosImpl(foos.GetPointer(), num_foos); | |
184 // foos_writer.Commit(); | |
185 // return rv; | |
186 // } | |
187 // | |
188 // TODO(vtl): Possibly, since we're not really being safe, we should just not | |
189 // copy for Release builds. | |
190 typedef internal::UserPointerReader<Type> Reader; | |
191 typedef internal::UserPointerWriter<Type> Writer; | |
192 typedef internal::UserPointerReaderWriter<Type> ReaderWriter; | |
193 | |
194 private: | |
195 friend class internal::UserPointerReader<Type>; | |
196 friend class internal::UserPointerWriter<Type>; | |
197 friend class internal::UserPointerReaderWriter<Type>; | |
198 | |
199 Type* pointer_; | |
200 // Allow copy and assignment. | |
201 }; | |
202 | |
203 // Provides a convenient way to make a |UserPointer<Type>|. | |
204 template <typename Type> | |
205 inline UserPointer<Type> MakeUserPointer(Type* pointer) { | |
206 return UserPointer<Type>(pointer); | |
207 } | |
208 | |
209 namespace internal { | |
darin (slow to review)
2014/07/24 16:55:38
hmm... do these really belong in the internal name
viettrungluu
2014/07/24 17:09:05
Yeah, I wasn't sure. Done, since you're probably r
| |
210 | |
211 // Implementation of |UserPointer<Type>::Reader|. | |
212 template <typename Type> | |
213 class UserPointerReader { | |
214 private: | |
215 typedef typename internal::remove_const<Type>::type TypeNoConst; | |
216 | |
217 public: | |
218 UserPointerReader(UserPointer<const Type> user_pointer, size_t count) { | |
219 Init(user_pointer.pointer_, count); | |
220 } | |
221 UserPointerReader(UserPointer<TypeNoConst> user_pointer, size_t count) { | |
222 Init(user_pointer.pointer_, count); | |
223 } | |
224 | |
225 const Type* GetPointer() const { return buffer_.get(); } | |
226 | |
227 private: | |
228 void Init(const Type* user_pointer, size_t count) { | |
229 internal::CheckUserPointerWithCountHelper< | |
230 sizeof(Type), MOJO_ALIGNOF(Type)>(user_pointer, count); | |
231 buffer_.reset(new TypeNoConst[count]); | |
232 memcpy(buffer_.get(), user_pointer, count * sizeof(Type)); | |
233 } | |
234 | |
235 scoped_ptr<TypeNoConst[]> buffer_; | |
236 | |
237 DISALLOW_COPY_AND_ASSIGN(UserPointerReader); | |
238 }; | |
239 | |
240 // Implementation of |UserPointer<Type>::Writer|. | |
241 template <typename Type> | |
242 class UserPointerWriter { | |
243 public: | |
244 UserPointerWriter(UserPointer<Type> user_pointer, size_t count) | |
245 : user_pointer_(user_pointer), | |
246 count_(count) { | |
247 buffer_.reset(new Type[count_]); | |
248 memset(buffer_.get(), 0, count_ * sizeof(Type)); | |
249 } | |
250 | |
251 Type* GetPointer() const { return buffer_.get(); } | |
252 | |
253 void Commit() { | |
254 internal::CheckUserPointerWithCountHelper< | |
255 sizeof(Type), MOJO_ALIGNOF(Type)>(user_pointer_.pointer_, count_); | |
256 memcpy(user_pointer_.pointer_, buffer_.get(), count_ * sizeof(Type)); | |
257 } | |
258 | |
259 private: | |
260 UserPointer<Type> user_pointer_; | |
261 size_t count_; | |
262 scoped_ptr<Type[]> buffer_; | |
263 | |
264 DISALLOW_COPY_AND_ASSIGN(UserPointerWriter); | |
265 }; | |
266 | |
267 // Implementation of |UserPointer<Type>::ReaderWriter|. | |
268 template <typename Type> | |
269 class UserPointerReaderWriter { | |
270 public: | |
271 UserPointerReaderWriter(UserPointer<Type> user_pointer, size_t count) | |
272 : user_pointer_(user_pointer), | |
273 count_(count) { | |
274 internal::CheckUserPointerWithCountHelper< | |
275 sizeof(Type), MOJO_ALIGNOF(Type)>(user_pointer_.pointer_, count_); | |
276 buffer_.reset(new Type[count]); | |
277 memcpy(buffer_.get(), user_pointer.pointer_, count * sizeof(Type)); | |
278 } | |
279 | |
280 Type* GetPointer() const { return buffer_.get(); } | |
281 size_t GetCount() const { return count_; } | |
282 | |
283 void Commit() { | |
284 internal::CheckUserPointerWithCountHelper< | |
285 sizeof(Type), MOJO_ALIGNOF(Type)>(user_pointer_.pointer_, count_); | |
286 memcpy(user_pointer_.pointer_, buffer_.get(), count_ * sizeof(Type)); | |
287 } | |
288 | |
289 private: | |
290 UserPointer<Type> user_pointer_; | |
291 size_t count_; | |
292 scoped_ptr<Type[]> buffer_; | |
293 | |
294 DISALLOW_COPY_AND_ASSIGN(UserPointerReaderWriter); | |
295 }; | |
296 | |
297 } // namespace internal | |
298 | |
299 // Represents a user pointer that will never be dereferenced by the system. The | |
300 // pointer value (i.e., the address) may be as a key for lookup, or may be a | |
301 // value that is only passed to the user at some point. | |
302 template <typename Type> | |
303 class UserPointerValue { | |
304 public: | |
305 UserPointerValue() : pointer_() {} | |
306 explicit UserPointerValue(Type* pointer) : pointer_(pointer) {} | |
307 ~UserPointerValue() {} | |
308 | |
309 // Returns the *value* of the pointer, which shouldn't be cast back to a | |
310 // pointer and dereferenced. | |
311 uintptr_t GetValue() const { | |
312 return reinterpret_cast<uintptr_t>(pointer_); | |
313 } | |
314 | |
315 private: | |
316 Type* pointer_; | |
317 // Allow copy and assignment. | |
318 }; | |
319 | |
320 // Provides a convenient way to make a |UserPointerValue<Type>|. | |
321 template <typename Type> | |
322 inline UserPointerValue<Type> MakeUserPointerValue(Type* pointer) { | |
323 return UserPointerValue<Type>(pointer); | |
324 } | |
325 | |
53 } // namespace system | 326 } // namespace system |
54 } // namespace mojo | 327 } // namespace mojo |
55 | 328 |
56 #endif // MOJO_SYSTEM_MEMORY_H_ | 329 #endif // MOJO_SYSTEM_MEMORY_H_ |
OLD | NEW |