scoped_nsobject.h revision ddb351dbec246cf1fab5ec20d2d5520909041de1
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).
29template<typename NST>
30class scoped_nsobject {
31 public:
32  typedef NST* element_type;
33
34  explicit scoped_nsobject(NST* object = nil)
35      : object_(object) {
36  }
37
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
59  NST* get() const {
60    return object_;
61  }
62
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().
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
85template <class C>
86void swap(scoped_nsobject<C>& p1, scoped_nsobject<C>& p2) {
87  p1.swap(p2);
88}
89
90template <class C>
91bool operator==(C* p1, const scoped_nsobject<C>& p2) {
92  return p1 == p2.get();
93}
94
95template <class C>
96bool operator!=(C* p1, const scoped_nsobject<C>& p2) {
97  return p1 != p2.get();
98}
99
100
101// Specialization to make scoped_nsobject<id> work.
102template<>
103class scoped_nsobject<id> {
104 public:
105  typedef id element_type;
106
107  explicit scoped_nsobject(id object = nil)
108      : object_(object) {
109  }
110
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
128  operator id() const {
129    return object_;
130  }
131
132  id get() const {
133    return object_;
134  }
135
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().
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.
160template<>
161class 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