Upstream version 11.40.271.0
[platform/framework/web/crosswalk.git] / src / mojo / edk / system / memory.h
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_EDK_SYSTEM_MEMORY_H_
6 #define MOJO_EDK_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/edk/system/system_impl_export.h"
15 #include "mojo/public/c/system/macros.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_EDK_SYSTEM_MEMORY_H_