• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "base/logging.h"
11 #include "base/macros.h"
12 #include "mojo/public/cpp/bindings/type_converter.h"
13 
14 namespace mojo {
15 namespace internal {
16 
17 template <typename Struct>
18 class StructHelper {
19  public:
20   template <typename Ptr>
Initialize(Ptr * ptr)21   static void Initialize(Ptr* ptr) {
22     ptr->Initialize();
23   }
24 };
25 
26 }  // namespace internal
27 
28 // Smart pointer wrapping a mojom structure with move-only semantics.
29 template <typename S>
30 class StructPtr {
31  public:
32   using Struct = S;
33 
StructPtr()34   StructPtr() : ptr_(nullptr) {}
StructPtr(decltype (nullptr))35   StructPtr(decltype(nullptr)) : ptr_(nullptr) {}
36 
~StructPtr()37   ~StructPtr() { delete ptr_; }
38 
decltype(nullptr)39   StructPtr& operator=(decltype(nullptr)) {
40     reset();
41     return *this;
42   }
43 
StructPtr(StructPtr && other)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>
To()51   U To() const {
52     return TypeConverter<U, StructPtr>::Convert(*this);
53   }
54 
reset()55   void reset() {
56     if (ptr_) {
57       delete ptr_;
58       ptr_ = nullptr;
59     }
60   }
61 
is_null()62   bool is_null() const { return ptr_ == nullptr; }
63 
64   Struct& operator*() const {
65     DCHECK(ptr_);
66     return *ptr_;
67   }
68   Struct* operator->() const {
69     DCHECK(ptr_);
70     return ptr_;
71   }
get()72   Struct* get() const { return ptr_; }
73 
Swap(StructPtr * other)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).
Clone()79   StructPtr Clone() const { return is_null() ? StructPtr() : ptr_->Clone(); }
80 
Equals(const StructPtr & other)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   // TODO(dcheng): Use an explicit conversion operator.
89   typedef Struct* StructPtr::*Testable;
90 
91  public:
Testable()92   operator Testable() const { return ptr_ ? &StructPtr::ptr_ : 0; }
93 
94  private:
95   friend class internal::StructHelper<Struct>;
96 
97   // Forbid the == and != operators explicitly, otherwise StructPtr will be
98   // converted to Testable to do == or != comparison.
99   template <typename T>
100   bool operator==(const StructPtr<T>& other) const = delete;
101   template <typename T>
102   bool operator!=(const StructPtr<T>& other) const = delete;
103 
Initialize()104   void Initialize() {
105     DCHECK(!ptr_);
106     ptr_ = new Struct();
107   }
108 
Take(StructPtr * other)109   void Take(StructPtr* other) {
110     reset();
111     Swap(other);
112   }
113 
114   Struct* ptr_;
115 
116   DISALLOW_COPY_AND_ASSIGN(StructPtr);
117 };
118 
119 // Designed to be used when Struct is small and copyable.
120 template <typename S>
121 class InlinedStructPtr {
122  public:
123   using Struct = S;
124 
InlinedStructPtr()125   InlinedStructPtr() : is_null_(true) {}
InlinedStructPtr(decltype (nullptr))126   InlinedStructPtr(decltype(nullptr)) : is_null_(true) {}
127 
~InlinedStructPtr()128   ~InlinedStructPtr() {}
129 
decltype(nullptr)130   InlinedStructPtr& operator=(decltype(nullptr)) {
131     reset();
132     return *this;
133   }
134 
InlinedStructPtr(InlinedStructPtr && other)135   InlinedStructPtr(InlinedStructPtr&& other) : is_null_(true) { Take(&other); }
136   InlinedStructPtr& operator=(InlinedStructPtr&& other) {
137     Take(&other);
138     return *this;
139   }
140 
141   template <typename U>
To()142   U To() const {
143     return TypeConverter<U, InlinedStructPtr>::Convert(*this);
144   }
145 
reset()146   void reset() {
147     is_null_ = true;
148     value_. ~Struct();
149     new (&value_) Struct();
150   }
151 
is_null()152   bool is_null() const { return is_null_; }
153 
154   Struct& operator*() const {
155     DCHECK(!is_null_);
156     return value_;
157   }
158   Struct* operator->() const {
159     DCHECK(!is_null_);
160     return &value_;
161   }
get()162   Struct* get() const { return &value_; }
163 
Swap(InlinedStructPtr * other)164   void Swap(InlinedStructPtr* other) {
165     std::swap(value_, other->value_);
166     std::swap(is_null_, other->is_null_);
167   }
168 
Clone()169   InlinedStructPtr Clone() const {
170     return is_null() ? InlinedStructPtr() : value_.Clone();
171   }
Equals(const InlinedStructPtr & other)172   bool Equals(const InlinedStructPtr& other) const {
173     if (is_null() || other.is_null())
174       return is_null() && other.is_null();
175     return value_.Equals(other.value_);
176   }
177 
178  private:
179   // TODO(dcheng): Use an explicit conversion operator.
180   typedef Struct InlinedStructPtr::*Testable;
181 
182  public:
Testable()183   operator Testable() const { return is_null_ ? 0 : &InlinedStructPtr::value_; }
184 
185  private:
186   friend class internal::StructHelper<Struct>;
187 
188   // Forbid the == and != operators explicitly, otherwise InlinedStructPtr will
189   // be converted to Testable to do == or != comparison.
190   template <typename T>
191   bool operator==(const InlinedStructPtr<T>& other) const = delete;
192   template <typename T>
193   bool operator!=(const InlinedStructPtr<T>& other) const = delete;
194 
Initialize()195   void Initialize() { is_null_ = false; }
196 
Take(InlinedStructPtr * other)197   void Take(InlinedStructPtr* other) {
198     reset();
199     Swap(other);
200   }
201 
202   mutable Struct value_;
203   bool is_null_;
204 
205   DISALLOW_COPY_AND_ASSIGN(InlinedStructPtr);
206 };
207 
208 }  // namespace mojo
209 
210 #endif  // MOJO_PUBLIC_CPP_BINDINGS_STRUCT_PTR_H_
211