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