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 17namespace mojo { 18namespace system { 19 20namespace 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|. 24template <typename T> 25struct remove_const { 26 typedef T type; 27}; 28template <typename T> 29struct remove_const<const T> { 30 typedef T type; 31}; 32 33// Yields |(const) char| if |T| is |(const) void|, else |T|: 34template <typename T> 35struct VoidToChar { 36 typedef T type; 37}; 38template <> 39struct VoidToChar<void> { 40 typedef char type; 41}; 42template <> 43struct 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). 49template <size_t size, size_t alignment> 50void 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). 54template <size_t size, size_t alignment> 55void 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). 60template <size_t alignment> 61void 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. 67template <typename Type> 68class UserPointerReader; 69template <typename Type> 70class UserPointerWriter; 71template <typename Type> 72class UserPointerReaderWriter; 73template <class Options> 74class UserOptionsReader; 75 76// Provides a convenient way to implicitly get null |UserPointer<Type>|s. 77struct 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). 84template <typename Type> 85class 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>|. 263template <typename Type> 264inline UserPointer<Type> MakeUserPointer(Type* pointer) { 265 return UserPointer<Type>(pointer); 266} 267 268// Implementation of |UserPointer<Type>::Reader|. 269template <typename Type> 270class 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|. 314template <typename Type> 315class 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|. 343template <typename Type> 344class 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_ 378