| OLD | NEW |
| (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_SYSTEM_MEMORY_H_ | |
| 6 #define MOJO_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/public/c/system/macros.h" | |
| 15 #include "mojo/system/system_impl_export.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_SYSTEM_MEMORY_H_ | |
| OLD | NEW |