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