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> Initialize(Ptr * 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 StructPtr()32 StructPtr() : ptr_(NULL) {} ~StructPtr()33 ~StructPtr() { 34 delete ptr_; 35 } 36 StructPtr(RValue other)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> To()44 U To() const { 45 return TypeConverter<StructPtr, U>::ConvertTo(*this); 46 } 47 reset()48 void reset() { 49 if (ptr_) { 50 delete ptr_; 51 ptr_ = NULL; 52 } 53 } 54 is_null()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 } get()65 Struct* get() const { return ptr_; } 66 Swap(StructPtr * other)67 void Swap(StructPtr* other) { 68 std::swap(ptr_, other->ptr_); 69 } 70 71 private: 72 typedef Struct* StructPtr::*Testable; 73 74 public: Testable()75 operator Testable() const { return ptr_ ? &StructPtr::ptr_ : 0; } 76 77 private: 78 friend class internal::StructHelper<Struct>; Initialize()79 void Initialize() { assert(!ptr_); ptr_ = new Struct(); } 80 Take(StructPtr * other)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 InlinedStructPtr()96 InlinedStructPtr() : is_null_(true) {} ~InlinedStructPtr()97 ~InlinedStructPtr() {} 98 InlinedStructPtr(RValue other)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> To()106 U To() const { 107 return TypeConverter<InlinedStructPtr, U>::ConvertTo(*this); 108 } 109 reset()110 void reset() { 111 is_null_ = true; 112 value_.~Struct(); 113 new (&value_) Struct(); 114 } 115 is_null()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 } get()126 Struct* get() const { return &value_; } 127 Swap(InlinedStructPtr * other)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: Testable()137 operator Testable() const { return is_null_ ? 0 : &InlinedStructPtr::value_; } 138 139 private: 140 friend class internal::StructHelper<Struct>; Initialize()141 void Initialize() { is_null_ = false; } 142 Take(InlinedStructPtr * other)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