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.
5 #ifndef MOJO_EDK_SYSTEM_MEMORY_H_
6 #define MOJO_EDK_SYSTEM_MEMORY_H_
10 #include <string.h> // For |memcpy()|.
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"
22 // Removes |const| from |T| (available as |remove_const<T>::type|):
23 // TODO(vtl): Remove these once we have the C++11 |remove_const|.
29 struct remove_const
<const T
> {
33 // Yields |(const) char| if |T| is |(const) void|, else |T|:
39 struct VoidToChar
<void> {
43 struct VoidToChar
<const void> {
44 typedef const char type
;
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
);
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
);
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
);
64 } // namespace internal
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
;
76 // Provides a convenient way to implicitly get null |UserPointer<Type>|s.
77 struct NullUserPointer
{};
79 // Represents a user pointer to a single |Type| (which must be POD), for Mojo
80 // primitive parameters.
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
>
87 typedef typename
internal::VoidToChar
<Type
>::type NonVoidType
;
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) {}
100 // Allow assignment from the "null user pointer".
101 UserPointer
<Type
>& operator=(NullUserPointer
) {
106 // Allow conversion to a "non-const" |UserPointer|.
107 operator UserPointer
<const Type
>() const {
108 return UserPointer
<const Type
>(pointer_
);
111 bool IsNull() const { return !pointer_
; }
113 // "Reinterpret casts" to a |UserPointer<ToType>|.
114 template <typename ToType
>
115 UserPointer
<ToType
> ReinterpretCast() const {
116 return UserPointer
<ToType
>(reinterpret_cast<ToType
*>(pointer_
));
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
124 internal::CheckUserPointer
<sizeof(NonVoidType
), MOJO_ALIGNOF(NonVoidType
)>(
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
132 // TODO(vtl): Logically, there should be separate read checks and write
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_
,
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.
146 // (We want to force a copy here, so return |Type| not |const Type&|.)
147 NonVoidType
Get() const {
149 internal::CheckUserPointer
<sizeof(NonVoidType
), MOJO_ALIGNOF(NonVoidType
)>(
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 *
159 void GetArray(typename
internal::remove_const
<Type
>::type
* destination
,
160 size_t count
) const {
162 memcpy(destination
, pointer_
, count
* sizeof(NonVoidType
));
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.
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.)
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
) {
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))|.
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
) {
197 memcpy(pointer_
, source
, count
* sizeof(NonVoidType
));
200 // Gets a |UserPointer| at offset |i| (in |Type|s) relative to this.
201 UserPointer
At(size_t i
) const {
203 static_cast<Type
*>(static_cast<NonVoidType
*>(pointer_
) + i
));
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_
);
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()|).
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).
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
228 // Use these classes in the following way:
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);
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();
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
;
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
;
259 // Allow copy and assignment.
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
);
268 // Implementation of |UserPointer<Type>::Reader|.
269 template <typename Type
>
270 class UserPointerReader
{
272 typedef typename
internal::remove_const
<Type
>::type TypeNoConst
;
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);
279 UserPointerReader(UserPointer
<TypeNoConst
> user_pointer
, size_t count
) {
280 Init(user_pointer
.pointer_
, count
, true);
283 const Type
* GetPointer() const { return buffer_
.get(); }
286 template <class Options
>
287 friend class UserOptionsReader
;
290 UserPointerReader(NoCheck
,
291 UserPointer
<const Type
> user_pointer
,
293 Init(user_pointer
.pointer_
, count
, false);
296 void Init(const Type
* user_pointer
, size_t count
, bool check
) {
301 internal::CheckUserPointerWithCount
<sizeof(Type
), MOJO_ALIGNOF(Type
)>(
302 user_pointer
, count
);
304 buffer_
.reset(new TypeNoConst
[count
]);
305 memcpy(buffer_
.get(), user_pointer
, count
* sizeof(Type
));
308 scoped_ptr
<TypeNoConst
[]> buffer_
;
310 DISALLOW_COPY_AND_ASSIGN(UserPointerReader
);
313 // Implementation of |UserPointer<Type>::Writer|.
314 template <typename Type
>
315 class UserPointerWriter
{
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
) {
321 buffer_
.reset(new Type
[count_
]);
322 memset(buffer_
.get(), 0, count_
* sizeof(Type
));
326 Type
* GetPointer() const { return buffer_
.get(); }
329 internal::CheckUserPointerWithCount
<sizeof(Type
), MOJO_ALIGNOF(Type
)>(
330 user_pointer_
.pointer_
, count_
);
331 memcpy(user_pointer_
.pointer_
, buffer_
.get(), count_
* sizeof(Type
));
335 UserPointer
<Type
> user_pointer_
;
337 scoped_ptr
<Type
[]> buffer_
;
339 DISALLOW_COPY_AND_ASSIGN(UserPointerWriter
);
342 // Implementation of |UserPointer<Type>::ReaderWriter|.
343 template <typename Type
>
344 class UserPointerReaderWriter
{
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
) {
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
));
357 Type
* GetPointer() const { return buffer_
.get(); }
358 size_t GetCount() const { return count_
; }
361 internal::CheckUserPointerWithCount
<sizeof(Type
), MOJO_ALIGNOF(Type
)>(
362 user_pointer_
.pointer_
, count_
);
363 memcpy(user_pointer_
.pointer_
, buffer_
.get(), count_
* sizeof(Type
));
367 UserPointer
<Type
> user_pointer_
;
369 scoped_ptr
<Type
[]> buffer_
;
371 DISALLOW_COPY_AND_ASSIGN(UserPointerReaderWriter
);
374 } // namespace system
377 #endif // MOJO_EDK_SYSTEM_MEMORY_H_