1 // Copyright (c) 2012 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_NSOBJECT_H_ 6 #define BASE_MAC_SCOPED_NSOBJECT_H_ 7 8 #import <Foundation/Foundation.h> 9 #include "base/basictypes.h" 10 #include "base/compiler_specific.h" 11 12 namespace base { 13 14 // scoped_nsobject<> is patterned after scoped_ptr<>, but maintains ownership 15 // of an NSObject subclass object. Style deviations here are solely for 16 // compatibility with scoped_ptr<>'s interface, with which everyone is already 17 // familiar. 18 // 19 // scoped_nsobject<> takes ownership of an object (in the constructor or in 20 // reset()) by taking over the caller's existing ownership claim. The caller 21 // must own the object it gives to scoped_nsobject<>, and relinquishes an 22 // ownership claim to that object. scoped_nsobject<> does not call -retain, 23 // callers have to call this manually if appropriate. 24 // 25 // scoped_nsprotocol<> has the same behavior as scoped_nsobject, but can be used 26 // with protocols. 27 // 28 // scoped_nsobject<> is not to be used for NSAutoreleasePools. For 29 // NSAutoreleasePools use ScopedNSAutoreleasePool from 30 // scoped_nsautorelease_pool.h instead. 31 // We check for bad uses of scoped_nsobject and NSAutoreleasePool at compile 32 // time with a template specialization (see below). 33 34 template<typename NST> 35 class scoped_nsprotocol { 36 public: 37 explicit scoped_nsprotocol(NST object = nil) : object_(object) {} 38 39 scoped_nsprotocol(const scoped_nsprotocol<NST>& that) 40 : object_([that.object_ retain]) { 41 } 42 43 ~scoped_nsprotocol() { 44 [object_ release]; 45 } 46 47 scoped_nsprotocol& operator=(const scoped_nsprotocol<NST>& that) { 48 reset([that.get() retain]); 49 return *this; 50 } 51 52 void reset(NST object = nil) { 53 // We intentionally do not check that object != object_ as the caller must 54 // either already have an ownership claim over whatever it passes to this 55 // method, or call it with the |RETAIN| policy which will have ensured that 56 // the object is retained once more when reaching this point. 57 [object_ release]; 58 object_ = object; 59 } 60 61 bool operator==(NST that) const { return object_ == that; } 62 bool operator!=(NST that) const { return object_ != that; } 63 64 operator NST() const { 65 return object_; 66 } 67 68 NST get() const { 69 return object_; 70 } 71 72 void swap(scoped_nsprotocol& that) { 73 NST temp = that.object_; 74 that.object_ = object_; 75 object_ = temp; 76 } 77 78 // scoped_nsprotocol<>::release() is like scoped_ptr<>::release. It is NOT a 79 // wrapper for [object_ release]. To force a scoped_nsprotocol<> to call 80 // [object_ release], use scoped_nsprotocol<>::reset(). 81 NST release() WARN_UNUSED_RESULT { 82 NST temp = object_; 83 object_ = nil; 84 return temp; 85 } 86 87 // Shift reference to the autorelease pool to be released later. 88 NST autorelease() { 89 return [release() autorelease]; 90 } 91 92 private: 93 NST object_; 94 }; 95 96 // Free functions 97 template <class C> 98 void swap(scoped_nsprotocol<C>& p1, scoped_nsprotocol<C>& p2) { 99 p1.swap(p2); 100 } 101 102 template <class C> 103 bool operator==(C p1, const scoped_nsprotocol<C>& p2) { 104 return p1 == p2.get(); 105 } 106 107 template <class C> 108 bool operator!=(C p1, const scoped_nsprotocol<C>& p2) { 109 return p1 != p2.get(); 110 } 111 112 template<typename NST> 113 class scoped_nsobject : public scoped_nsprotocol<NST*> { 114 public: 115 explicit scoped_nsobject(NST* object = nil) 116 : scoped_nsprotocol<NST*>(object) {} 117 118 scoped_nsobject(const scoped_nsobject<NST>& that) 119 : scoped_nsprotocol<NST*>(that) { 120 } 121 122 scoped_nsobject& operator=(const scoped_nsobject<NST>& that) { 123 scoped_nsprotocol<NST*>::operator=(that); 124 return *this; 125 } 126 }; 127 128 // Specialization to make scoped_nsobject<id> work. 129 template<> 130 class scoped_nsobject<id> : public scoped_nsprotocol<id> { 131 public: 132 explicit scoped_nsobject(id object = nil) : scoped_nsprotocol<id>(object) {} 133 134 scoped_nsobject(const scoped_nsobject<id>& that) 135 : scoped_nsprotocol<id>(that) { 136 } 137 138 scoped_nsobject& operator=(const scoped_nsobject<id>& that) { 139 scoped_nsprotocol<id>::operator=(that); 140 return *this; 141 } 142 }; 143 144 // Do not use scoped_nsobject for NSAutoreleasePools, use 145 // ScopedNSAutoreleasePool instead. This is a compile time check. See details 146 // at top of header. 147 template<> 148 class scoped_nsobject<NSAutoreleasePool> { 149 private: 150 explicit scoped_nsobject(NSAutoreleasePool* object = nil); 151 DISALLOW_COPY_AND_ASSIGN(scoped_nsobject); 152 }; 153 154 } // namespace base 155 156 #endif // BASE_MAC_SCOPED_NSOBJECT_H_ 157