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