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 BASE_MAC_SCOPED_TYPEREF_H_ 6 #define BASE_MAC_SCOPED_TYPEREF_H_ 7 8 #include "base/compiler_specific.h" 9 #include "base/logging.h" 10 #include "base/memory/scoped_policy.h" 11 12 namespace base { 13 14 // ScopedTypeRef<> is patterned after scoped_ptr<>, but maintains a ownership 15 // of a reference to any type that is maintained by Retain and Release methods. 16 // 17 // The Traits structure must provide the Retain and Release methods for type T. 18 // A default ScopedTypeRefTraits is used but not defined, and should be defined 19 // for each type to use this interface. For example, an appropriate definition 20 // of ScopedTypeRefTraits for CGLContextObj would be: 21 // 22 // template<> 23 // struct ScopedTypeRefTraits<CGLContextObj> { 24 // static CGLContextObj InvalidValue() { return nullptr; } 25 // static CGLContextObj Retain(CGLContextObj object) { 26 // CGLContextRetain(object); 27 // return object; 28 // } 29 // static void Release(CGLContextObj object) { CGLContextRelease(object); } 30 // }; 31 // 32 // For the many types that have pass-by-pointer create functions, the function 33 // InitializeInto() is provided to allow direct initialization and assumption 34 // of ownership of the object. For example, continuing to use the above 35 // CGLContextObj specialization: 36 // 37 // base::ScopedTypeRef<CGLContextObj> context; 38 // CGLCreateContext(pixel_format, share_group, context.InitializeInto()); 39 // 40 // For initialization with an existing object, the caller may specify whether 41 // the ScopedTypeRef<> being initialized is assuming the caller's existing 42 // ownership of the object (and should not call Retain in initialization) or if 43 // it should not assume this ownership and must create its own (by calling 44 // Retain in initialization). This behavior is based on the |policy| parameter, 45 // with |ASSUME| for the former and |RETAIN| for the latter. The default policy 46 // is to |ASSUME|. 47 48 template<typename T> 49 struct ScopedTypeRefTraits; 50 51 template<typename T, typename Traits = ScopedTypeRefTraits<T>> 52 class ScopedTypeRef { 53 public: 54 typedef T element_type; 55 56 ScopedTypeRef( 57 T object = Traits::InvalidValue(), 58 base::scoped_policy::OwnershipPolicy policy = base::scoped_policy::ASSUME) 59 : object_(object) { 60 if (object_ && policy == base::scoped_policy::RETAIN) 61 object_ = Traits::Retain(object_); 62 } 63 64 ScopedTypeRef(const ScopedTypeRef<T, Traits>& that) 65 : object_(that.object_) { 66 if (object_) 67 object_ = Traits::Retain(object_); 68 } 69 70 ~ScopedTypeRef() { 71 if (object_) 72 Traits::Release(object_); 73 } 74 75 ScopedTypeRef& operator=(const ScopedTypeRef<T, Traits>& that) { 76 reset(that.get(), base::scoped_policy::RETAIN); 77 return *this; 78 } 79 80 // This is to be used only to take ownership of objects that are created 81 // by pass-by-pointer create functions. To enforce this, require that the 82 // object be reset to NULL before this may be used. 83 T* InitializeInto() WARN_UNUSED_RESULT { 84 DCHECK(!object_); 85 return &object_; 86 } 87 88 void reset(T object = Traits::InvalidValue(), 89 base::scoped_policy::OwnershipPolicy policy = 90 base::scoped_policy::ASSUME) { 91 if (object && policy == base::scoped_policy::RETAIN) 92 object = Traits::Retain(object); 93 if (object_) 94 Traits::Release(object_); 95 object_ = object; 96 } 97 98 bool operator==(T that) const { 99 return object_ == that; 100 } 101 102 bool operator!=(T that) const { 103 return object_ != that; 104 } 105 106 operator T() const { 107 return object_; 108 } 109 110 T get() const { 111 return object_; 112 } 113 114 void swap(ScopedTypeRef& that) { 115 T temp = that.object_; 116 that.object_ = object_; 117 object_ = temp; 118 } 119 120 // ScopedTypeRef<>::release() is like scoped_ptr<>::release. It is NOT 121 // a wrapper for Release(). To force a ScopedTypeRef<> object to call 122 // Release(), use ScopedTypeRef<>::reset(). 123 T release() WARN_UNUSED_RESULT { 124 T temp = object_; 125 object_ = Traits::InvalidValue(); 126 return temp; 127 } 128 129 private: 130 T object_; 131 }; 132 133 } // namespace base 134 135 #endif // BASE_MAC_SCOPED_TYPEREF_H_ 136