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/environment/logging.h" 11 #include "mojo/public/cpp/system/macros.h" 12 13 namespace mojo { 14 namespace internal { 15 16 template <typename Struct> 17 class StructHelper { 18 public: 19 template <typename Ptr> Initialize(Ptr * ptr)20 static void Initialize(Ptr* ptr) { ptr->Initialize(); } 21 }; 22 23 } // namespace internal 24 25 template <typename Struct> 26 class StructPtr { 27 MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(StructPtr, RValue); 28 public: 29 typedef typename Struct::Data_ Data_; 30 StructPtr()31 StructPtr() : ptr_(NULL) {} ~StructPtr()32 ~StructPtr() { 33 delete ptr_; 34 } 35 StructPtr(RValue other)36 StructPtr(RValue other) : ptr_(NULL) { Take(other.object); } 37 StructPtr& operator=(RValue other) { 38 Take(other.object); 39 return *this; 40 } 41 42 template <typename U> To()43 U To() const { 44 return TypeConverter<U, StructPtr>::Convert(*this); 45 } 46 reset()47 void reset() { 48 if (ptr_) { 49 delete ptr_; 50 ptr_ = NULL; 51 } 52 } 53 is_null()54 bool is_null() const { return ptr_ == NULL; } 55 56 Struct& operator*() const { 57 MOJO_DCHECK(ptr_); 58 return *ptr_; 59 } 60 Struct* operator->() const { 61 MOJO_DCHECK(ptr_); 62 return ptr_; 63 } get()64 Struct* get() const { return ptr_; } 65 Swap(StructPtr * other)66 void Swap(StructPtr* other) { 67 std::swap(ptr_, other->ptr_); 68 } 69 70 private: 71 typedef Struct* StructPtr::*Testable; 72 73 public: Testable()74 operator Testable() const { return ptr_ ? &StructPtr::ptr_ : 0; } 75 76 private: 77 friend class internal::StructHelper<Struct>; Initialize()78 void Initialize() { 79 MOJO_DCHECK(!ptr_); 80 ptr_ = new Struct(); 81 } 82 Take(StructPtr * other)83 void Take(StructPtr* other) { 84 reset(); 85 Swap(other); 86 } 87 88 Struct* ptr_; 89 }; 90 91 // Designed to be used when Struct is small and copyable. 92 template <typename Struct> 93 class InlinedStructPtr { 94 MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(InlinedStructPtr, RValue); 95 public: 96 typedef typename Struct::Data_ Data_; 97 InlinedStructPtr()98 InlinedStructPtr() : is_null_(true) {} ~InlinedStructPtr()99 ~InlinedStructPtr() {} 100 InlinedStructPtr(RValue other)101 InlinedStructPtr(RValue other) : is_null_(true) { Take(other.object); } 102 InlinedStructPtr& operator=(RValue other) { 103 Take(other.object); 104 return *this; 105 } 106 107 template <typename U> To()108 U To() const { 109 return TypeConverter<U, InlinedStructPtr>::Convert(*this); 110 } 111 reset()112 void reset() { 113 is_null_ = true; 114 value_.~Struct(); 115 new (&value_) Struct(); 116 } 117 is_null()118 bool is_null() const { return is_null_; } 119 120 Struct& operator*() const { 121 MOJO_DCHECK(!is_null_); 122 return value_; 123 } 124 Struct* operator->() const { 125 MOJO_DCHECK(!is_null_); 126 return &value_; 127 } get()128 Struct* get() const { return &value_; } 129 Swap(InlinedStructPtr * other)130 void Swap(InlinedStructPtr* other) { 131 std::swap(value_, other->value_); 132 std::swap(is_null_, other->is_null_); 133 } 134 135 private: 136 typedef Struct InlinedStructPtr::*Testable; 137 138 public: Testable()139 operator Testable() const { return is_null_ ? 0 : &InlinedStructPtr::value_; } 140 141 private: 142 friend class internal::StructHelper<Struct>; Initialize()143 void Initialize() { is_null_ = false; } 144 Take(InlinedStructPtr * other)145 void Take(InlinedStructPtr* other) { 146 reset(); 147 Swap(other); 148 } 149 150 mutable Struct value_; 151 bool is_null_; 152 }; 153 154 } // namespace mojo 155 156 #endif // MOJO_PUBLIC_CPP_BINDINGS_STRUCT_PTR_H_ 157