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