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

Side by Side Diff: mojo/edk/system/memory.h

Issue 814543006: Move //mojo/{public, edk} underneath //third_party (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 5 years, 11 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 | « mojo/edk/system/mapping_table.cc ('k') | mojo/edk/system/memory.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #ifndef MOJO_EDK_SYSTEM_MEMORY_H_
6 #define MOJO_EDK_SYSTEM_MEMORY_H_
7
8 #include <stddef.h>
9 #include <stdint.h>
10 #include <string.h> // For |memcpy()|.
11
12 #include "base/macros.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "mojo/edk/system/system_impl_export.h"
15 #include "mojo/public/c/system/macros.h"
16
17 namespace mojo {
18 namespace system {
19
20 namespace internal {
21
22 // Removes |const| from |T| (available as |remove_const<T>::type|):
23 // TODO(vtl): Remove these once we have the C++11 |remove_const|.
24 template <typename T>
25 struct remove_const {
26 typedef T type;
27 };
28 template <typename T>
29 struct remove_const<const T> {
30 typedef T type;
31 };
32
33 // Yields |(const) char| if |T| is |(const) void|, else |T|:
34 template <typename T>
35 struct VoidToChar {
36 typedef T type;
37 };
38 template <>
39 struct VoidToChar<void> {
40 typedef char type;
41 };
42 template <>
43 struct VoidToChar<const void> {
44 typedef const char type;
45 };
46
47 // Checks (insofar as appropriate/possible) that |pointer| is a valid pointer to
48 // a buffer of the given size and alignment (both in bytes).
49 template <size_t size, size_t alignment>
50 void MOJO_SYSTEM_IMPL_EXPORT CheckUserPointer(const void* pointer);
51
52 // Checks (insofar as appropriate/possible) that |pointer| is a valid pointer to
53 // a buffer of |count| elements of the given size and alignment (both in bytes).
54 template <size_t size, size_t alignment>
55 void MOJO_SYSTEM_IMPL_EXPORT
56 CheckUserPointerWithCount(const void* pointer, size_t count);
57
58 // Checks (insofar as appropriate/possible) that |pointer| is a valid pointer to
59 // a buffer of the given size and alignment (both in bytes).
60 template <size_t alignment>
61 void MOJO_SYSTEM_IMPL_EXPORT
62 CheckUserPointerWithSize(const void* pointer, size_t size);
63
64 } // namespace internal
65
66 // Forward declarations so that they can be friended.
67 template <typename Type>
68 class UserPointerReader;
69 template <typename Type>
70 class UserPointerWriter;
71 template <typename Type>
72 class UserPointerReaderWriter;
73 template <class Options>
74 class UserOptionsReader;
75
76 // Provides a convenient way to implicitly get null |UserPointer<Type>|s.
77 struct NullUserPointer {};
78
79 // Represents a user pointer to a single |Type| (which must be POD), for Mojo
80 // primitive parameters.
81 //
82 // Use a const |Type| for in parameters, and non-const |Type|s for out and
83 // in-out parameters (in which case the |Put()| method is available).
84 template <typename Type>
85 class UserPointer {
86 private:
87 typedef typename internal::VoidToChar<Type>::type NonVoidType;
88
89 public:
90 // Instead of explicitly using these constructors, you can often use
91 // |MakeUserPointer()| (or |NullUserPointer()| for null pointers). (The common
92 // exception is when you have, e.g., a |char*| and want to get a
93 // |UserPointer<void>|.)
94 UserPointer() : pointer_(nullptr) {}
95 explicit UserPointer(Type* pointer) : pointer_(pointer) {}
96 // Allow implicit conversion from the "null user pointer".
97 UserPointer(NullUserPointer) : pointer_(nullptr) {}
98 ~UserPointer() {}
99
100 // Allow assignment from the "null user pointer".
101 UserPointer<Type>& operator=(NullUserPointer) {
102 pointer_ = nullptr;
103 return *this;
104 }
105
106 // Allow conversion to a "non-const" |UserPointer|.
107 operator UserPointer<const Type>() const {
108 return UserPointer<const Type>(pointer_);
109 }
110
111 bool IsNull() const { return !pointer_; }
112
113 // "Reinterpret casts" to a |UserPointer<ToType>|.
114 template <typename ToType>
115 UserPointer<ToType> ReinterpretCast() const {
116 return UserPointer<ToType>(reinterpret_cast<ToType*>(pointer_));
117 }
118
119 // Checks that this pointer points to a valid |Type| in the same way as
120 // |Get()| and |Put()|.
121 // TODO(vtl): Logically, there should be separate read checks and write
122 // checks.
123 void Check() const {
124 internal::CheckUserPointer<sizeof(NonVoidType), MOJO_ALIGNOF(NonVoidType)>(
125 pointer_);
126 }
127
128 // Checks that this pointer points to a valid array (of type |Type|, or just a
129 // buffer if |Type| is |void| or |const void|) of |count| elements (or bytes
130 // if |Type| is |void| or |const void|) in the same way as |GetArray()| and
131 // |PutArray()|.
132 // TODO(vtl): Logically, there should be separate read checks and write
133 // checks.
134 // TODO(vtl): Switch more things to use this.
135 void CheckArray(size_t count) const {
136 internal::CheckUserPointerWithCount<sizeof(NonVoidType),
137 MOJO_ALIGNOF(NonVoidType)>(pointer_,
138 count);
139 }
140
141 // Gets the value (of type |Type|, or a |char| if |Type| is |void|) pointed to
142 // by this user pointer. Use this when you'd use the rvalue |*user_pointer|,
143 // but be aware that this may be costly -- so if the value will be used
144 // multiple times, you should save it.
145 //
146 // (We want to force a copy here, so return |Type| not |const Type&|.)
147 NonVoidType Get() const {
148 Check();
149 internal::CheckUserPointer<sizeof(NonVoidType), MOJO_ALIGNOF(NonVoidType)>(
150 pointer_);
151 return *pointer_;
152 }
153
154 // Gets an array (of type |Type|, or just a buffer if |Type| is |void| or
155 // |const void|) of |count| elements (or bytes if |Type| is |void| or |const
156 // void|) from the location pointed to by this user pointer. Use this when
157 // you'd do something like |memcpy(destination, user_pointer, count *
158 // sizeof(Type)|.
159 void GetArray(typename internal::remove_const<Type>::type* destination,
160 size_t count) const {
161 CheckArray(count);
162 memcpy(destination, pointer_, count * sizeof(NonVoidType));
163 }
164
165 // Puts a value (of type |Type|, or of type |char| if |Type| is |void|) to the
166 // location pointed to by this user pointer. Use this when you'd use the
167 // lvalue |*user_pointer|. Since this may be costly, you should avoid using
168 // this (for the same user pointer) more than once.
169 //
170 // Note: This |Put()| method is not valid when |T| is const, e.g., |const
171 // uint32_t|, but it's okay to include them so long as this template is only
172 // implicitly instantiated (see 14.7.1 of the C++11 standard) and not
173 // explicitly instantiated. (On implicit instantiation, only the declarations
174 // need be valid, not the definitions.)
175 //
176 // In C++11, we could do something like:
177 // template <typename _Type = Type>
178 // typename enable_if<!is_const<_Type>::value &&
179 // !is_void<_Type>::value>::type Put(
180 // const _Type& value) { ... }
181 // (which obviously be correct), but C++03 doesn't allow default function
182 // template arguments.
183 void Put(const NonVoidType& value) {
184 Check();
185 *pointer_ = value;
186 }
187
188 // Puts an array (of type |Type|, or just a buffer if |Type| is |void|) with
189 // |count| elements (or bytes |Type| is |void|) to the location pointed to by
190 // this user pointer. Use this when you'd do something like
191 // |memcpy(user_pointer, source, count * sizeof(Type))|.
192 //
193 // Note: The same comments about the validity of |Put()| (except for the part
194 // about |void|) apply here.
195 void PutArray(const Type* source, size_t count) {
196 CheckArray(count);
197 memcpy(pointer_, source, count * sizeof(NonVoidType));
198 }
199
200 // Gets a |UserPointer| at offset |i| (in |Type|s) relative to this.
201 UserPointer At(size_t i) const {
202 return UserPointer(
203 static_cast<Type*>(static_cast<NonVoidType*>(pointer_) + i));
204 }
205
206 // Gets the value of the |UserPointer| as a |uintptr_t|. This should not be
207 // casted back to a pointer (and dereferenced), but may be used as a key for
208 // lookup or passed back to the user.
209 uintptr_t GetPointerValue() const {
210 return reinterpret_cast<uintptr_t>(pointer_);
211 }
212
213 // These provides safe (read-only/write-only/read-and-write) access to a
214 // |UserPointer<Type>| (probably pointing to an array) using just an ordinary
215 // pointer (obtained via |GetPointer()|).
216 //
217 // The memory returned by |GetPointer()| may be a copy of the original user
218 // memory, but should be modified only if the user is intended to eventually
219 // see the change.) If any changes are made, |Commit()| should be called to
220 // guarantee that the changes are written back to user memory (it may be
221 // called multiple times).
222 //
223 // Note: These classes are designed to allow fast, unsafe implementations (in
224 // which |GetPointer()| just returns the user pointer) if desired. Thus if
225 // |Commit()| is *not* called, changes may or may not be made visible to the
226 // user.
227 //
228 // Use these classes in the following way:
229 //
230 // MojoResult Core::PutFoos(UserPointer<const uint32_t> foos,
231 // uint32_t num_foos) {
232 // UserPointer<const uint32_t>::Reader foos_reader(foos, num_foos);
233 // return PutFoosImpl(foos_reader.GetPointer(), num_foos);
234 // }
235 //
236 // MojoResult Core::GetFoos(UserPointer<uint32_t> foos,
237 // uint32_t num_foos) {
238 // UserPointer<uint32_t>::Writer foos_writer(foos, num_foos);
239 // MojoResult rv = GetFoosImpl(foos.GetPointer(), num_foos);
240 // foos_writer.Commit();
241 // return rv;
242 // }
243 //
244 // TODO(vtl): Possibly, since we're not really being safe, we should just not
245 // copy for Release builds.
246 typedef UserPointerReader<Type> Reader;
247 typedef UserPointerWriter<Type> Writer;
248 typedef UserPointerReaderWriter<Type> ReaderWriter;
249
250 private:
251 friend class UserPointerReader<Type>;
252 friend class UserPointerReader<const Type>;
253 friend class UserPointerWriter<Type>;
254 friend class UserPointerReaderWriter<Type>;
255 template <class Options>
256 friend class UserOptionsReader;
257
258 Type* pointer_;
259 // Allow copy and assignment.
260 };
261
262 // Provides a convenient way to make a |UserPointer<Type>|.
263 template <typename Type>
264 inline UserPointer<Type> MakeUserPointer(Type* pointer) {
265 return UserPointer<Type>(pointer);
266 }
267
268 // Implementation of |UserPointer<Type>::Reader|.
269 template <typename Type>
270 class UserPointerReader {
271 private:
272 typedef typename internal::remove_const<Type>::type TypeNoConst;
273
274 public:
275 // Note: If |count| is zero, |GetPointer()| will always return null.
276 UserPointerReader(UserPointer<const Type> user_pointer, size_t count) {
277 Init(user_pointer.pointer_, count, true);
278 }
279 UserPointerReader(UserPointer<TypeNoConst> user_pointer, size_t count) {
280 Init(user_pointer.pointer_, count, true);
281 }
282
283 const Type* GetPointer() const { return buffer_.get(); }
284
285 private:
286 template <class Options>
287 friend class UserOptionsReader;
288
289 struct NoCheck {};
290 UserPointerReader(NoCheck,
291 UserPointer<const Type> user_pointer,
292 size_t count) {
293 Init(user_pointer.pointer_, count, false);
294 }
295
296 void Init(const Type* user_pointer, size_t count, bool check) {
297 if (count == 0)
298 return;
299
300 if (check) {
301 internal::CheckUserPointerWithCount<sizeof(Type), MOJO_ALIGNOF(Type)>(
302 user_pointer, count);
303 }
304 buffer_.reset(new TypeNoConst[count]);
305 memcpy(buffer_.get(), user_pointer, count * sizeof(Type));
306 }
307
308 scoped_ptr<TypeNoConst[]> buffer_;
309
310 DISALLOW_COPY_AND_ASSIGN(UserPointerReader);
311 };
312
313 // Implementation of |UserPointer<Type>::Writer|.
314 template <typename Type>
315 class UserPointerWriter {
316 public:
317 // Note: If |count| is zero, |GetPointer()| will always return null.
318 UserPointerWriter(UserPointer<Type> user_pointer, size_t count)
319 : user_pointer_(user_pointer), count_(count) {
320 if (count_ > 0) {
321 buffer_.reset(new Type[count_]);
322 memset(buffer_.get(), 0, count_ * sizeof(Type));
323 }
324 }
325
326 Type* GetPointer() const { return buffer_.get(); }
327
328 void Commit() {
329 internal::CheckUserPointerWithCount<sizeof(Type), MOJO_ALIGNOF(Type)>(
330 user_pointer_.pointer_, count_);
331 memcpy(user_pointer_.pointer_, buffer_.get(), count_ * sizeof(Type));
332 }
333
334 private:
335 UserPointer<Type> user_pointer_;
336 size_t count_;
337 scoped_ptr<Type[]> buffer_;
338
339 DISALLOW_COPY_AND_ASSIGN(UserPointerWriter);
340 };
341
342 // Implementation of |UserPointer<Type>::ReaderWriter|.
343 template <typename Type>
344 class UserPointerReaderWriter {
345 public:
346 // Note: If |count| is zero, |GetPointer()| will always return null.
347 UserPointerReaderWriter(UserPointer<Type> user_pointer, size_t count)
348 : user_pointer_(user_pointer), count_(count) {
349 if (count_ > 0) {
350 internal::CheckUserPointerWithCount<sizeof(Type), MOJO_ALIGNOF(Type)>(
351 user_pointer_.pointer_, count_);
352 buffer_.reset(new Type[count]);
353 memcpy(buffer_.get(), user_pointer.pointer_, count * sizeof(Type));
354 }
355 }
356
357 Type* GetPointer() const { return buffer_.get(); }
358 size_t GetCount() const { return count_; }
359
360 void Commit() {
361 internal::CheckUserPointerWithCount<sizeof(Type), MOJO_ALIGNOF(Type)>(
362 user_pointer_.pointer_, count_);
363 memcpy(user_pointer_.pointer_, buffer_.get(), count_ * sizeof(Type));
364 }
365
366 private:
367 UserPointer<Type> user_pointer_;
368 size_t count_;
369 scoped_ptr<Type[]> buffer_;
370
371 DISALLOW_COPY_AND_ASSIGN(UserPointerReaderWriter);
372 };
373
374 } // namespace system
375 } // namespace mojo
376
377 #endif // MOJO_EDK_SYSTEM_MEMORY_H_
OLDNEW
« no previous file with comments | « mojo/edk/system/mapping_table.cc ('k') | mojo/edk/system/memory.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698