OLD | NEW |
| (Empty) |
1 // Copyright 2014 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_PUBLIC_CPP_BINDINGS_STRUCT_PTR_H_ | |
6 #define MOJO_PUBLIC_CPP_BINDINGS_STRUCT_PTR_H_ | |
7 | |
8 #include <new> | |
9 | |
10 #include "mojo/public/cpp/bindings/type_converter.h" | |
11 #include "mojo/public/cpp/environment/logging.h" | |
12 #include "mojo/public/cpp/system/macros.h" | |
13 | |
14 namespace mojo { | |
15 namespace internal { | |
16 | |
17 template <typename Struct> | |
18 class StructHelper { | |
19 public: | |
20 template <typename Ptr> | |
21 static void Initialize(Ptr* ptr) { | |
22 ptr->Initialize(); | |
23 } | |
24 }; | |
25 | |
26 } // namespace internal | |
27 | |
28 template <typename Struct> | |
29 class StructPtr { | |
30 MOJO_MOVE_ONLY_TYPE(StructPtr) | |
31 | |
32 public: | |
33 | |
34 StructPtr() : ptr_(nullptr) {} | |
35 StructPtr(decltype(nullptr)) : ptr_(nullptr) {} | |
36 | |
37 ~StructPtr() { delete ptr_; } | |
38 | |
39 StructPtr& operator=(decltype(nullptr)) { | |
40 reset(); | |
41 return *this; | |
42 } | |
43 | |
44 StructPtr(StructPtr&& other) : ptr_(nullptr) { Take(&other); } | |
45 StructPtr& operator=(StructPtr&& other) { | |
46 Take(&other); | |
47 return *this; | |
48 } | |
49 | |
50 template <typename U> | |
51 U To() const { | |
52 return TypeConverter<U, StructPtr>::Convert(*this); | |
53 } | |
54 | |
55 void reset() { | |
56 if (ptr_) { | |
57 delete ptr_; | |
58 ptr_ = nullptr; | |
59 } | |
60 } | |
61 | |
62 bool is_null() const { return ptr_ == nullptr; } | |
63 | |
64 Struct& operator*() const { | |
65 MOJO_DCHECK(ptr_); | |
66 return *ptr_; | |
67 } | |
68 Struct* operator->() const { | |
69 MOJO_DCHECK(ptr_); | |
70 return ptr_; | |
71 } | |
72 Struct* get() const { return ptr_; } | |
73 | |
74 void Swap(StructPtr* other) { std::swap(ptr_, other->ptr_); } | |
75 | |
76 // Please note that calling this method will fail compilation if the value | |
77 // type |Struct| doesn't have a Clone() method defined (which usually means | |
78 // that it contains Mojo handles). | |
79 StructPtr Clone() const { return is_null() ? StructPtr() : ptr_->Clone(); } | |
80 | |
81 bool Equals(const StructPtr& other) const { | |
82 if (is_null() || other.is_null()) | |
83 return is_null() && other.is_null(); | |
84 return ptr_->Equals(*other.ptr_); | |
85 } | |
86 | |
87 private: | |
88 typedef Struct* StructPtr::*Testable; | |
89 | |
90 public: | |
91 operator Testable() const { return ptr_ ? &StructPtr::ptr_ : 0; } | |
92 | |
93 private: | |
94 friend class internal::StructHelper<Struct>; | |
95 void Initialize() { | |
96 MOJO_DCHECK(!ptr_); | |
97 ptr_ = new Struct(); | |
98 } | |
99 | |
100 void Take(StructPtr* other) { | |
101 reset(); | |
102 Swap(other); | |
103 } | |
104 | |
105 Struct* ptr_; | |
106 }; | |
107 | |
108 // Designed to be used when Struct is small and copyable. | |
109 template <typename Struct> | |
110 class InlinedStructPtr { | |
111 MOJO_MOVE_ONLY_TYPE(InlinedStructPtr); | |
112 | |
113 public: | |
114 | |
115 InlinedStructPtr() : is_null_(true) {} | |
116 InlinedStructPtr(decltype(nullptr)) : is_null_(true) {} | |
117 | |
118 ~InlinedStructPtr() {} | |
119 | |
120 InlinedStructPtr& operator=(decltype(nullptr)) { | |
121 reset(); | |
122 return *this; | |
123 } | |
124 | |
125 InlinedStructPtr(InlinedStructPtr&& other) : is_null_(true) { Take(&other); } | |
126 InlinedStructPtr& operator=(InlinedStructPtr&& other) { | |
127 Take(&other); | |
128 return *this; | |
129 } | |
130 | |
131 template <typename U> | |
132 U To() const { | |
133 return TypeConverter<U, InlinedStructPtr>::Convert(*this); | |
134 } | |
135 | |
136 void reset() { | |
137 is_null_ = true; | |
138 value_. ~Struct(); | |
139 new (&value_) Struct(); | |
140 } | |
141 | |
142 bool is_null() const { return is_null_; } | |
143 | |
144 Struct& operator*() const { | |
145 MOJO_DCHECK(!is_null_); | |
146 return value_; | |
147 } | |
148 Struct* operator->() const { | |
149 MOJO_DCHECK(!is_null_); | |
150 return &value_; | |
151 } | |
152 Struct* get() const { return &value_; } | |
153 | |
154 void Swap(InlinedStructPtr* other) { | |
155 std::swap(value_, other->value_); | |
156 std::swap(is_null_, other->is_null_); | |
157 } | |
158 | |
159 InlinedStructPtr Clone() const { | |
160 return is_null() ? InlinedStructPtr() : value_.Clone(); | |
161 } | |
162 bool Equals(const InlinedStructPtr& other) const { | |
163 if (is_null() || other.is_null()) | |
164 return is_null() && other.is_null(); | |
165 return value_.Equals(other.value_); | |
166 } | |
167 | |
168 private: | |
169 typedef Struct InlinedStructPtr::*Testable; | |
170 | |
171 public: | |
172 operator Testable() const { return is_null_ ? 0 : &InlinedStructPtr::value_; } | |
173 | |
174 private: | |
175 friend class internal::StructHelper<Struct>; | |
176 void Initialize() { is_null_ = false; } | |
177 | |
178 void Take(InlinedStructPtr* other) { | |
179 reset(); | |
180 Swap(other); | |
181 } | |
182 | |
183 mutable Struct value_; | |
184 bool is_null_; | |
185 }; | |
186 | |
187 } // namespace mojo | |
188 | |
189 #endif // MOJO_PUBLIC_CPP_BINDINGS_STRUCT_PTR_H_ | |
OLD | NEW |