summaryrefslogtreecommitdiffstats
path: root/base/scoped_nsobject.h
blob: a9783e0003d94ecd080481e14ec3a941dae5aedd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef BASE_SCOPED_NSOBJECT_H_
#define BASE_SCOPED_NSOBJECT_H_
#pragma once

#import <Foundation/Foundation.h>
#include "base/basictypes.h"
#include "base/compiler_specific.h"

// scoped_nsobject<> is patterned after scoped_ptr<>, but maintains ownership
// of an NSObject subclass object.  Style deviations here are solely for
// compatibility with scoped_ptr<>'s interface, with which everyone is already
// familiar.
//
// When scoped_nsobject<> takes ownership of an object (in the constructor or
// in reset()), it takes over the caller's existing ownership claim.  The
// caller must own the object it gives to scoped_nsobject<>, and relinquishes
// an ownership claim to that object.  scoped_nsobject<> does not call
// -retain.
//
// scoped_nsobject<> is not to be used for NSAutoreleasePools. For
// NSAutoreleasePools use ScopedNSAutoreleasePool from
// scoped_nsautorelease_pool.h instead.
// We check for bad uses of scoped_nsobject and NSAutoreleasePool at compile
// time with a template specialization (see below).
template<typename NST>
class scoped_nsobject {
 public:
  typedef NST* element_type;

  explicit scoped_nsobject(NST* object = nil)
      : object_(object) {
  }

  ~scoped_nsobject() {
    [object_ release];
  }

  void reset(NST* object = nil) {
    // We intentionally do not check that object != object_ as the caller must
    // already have an ownership claim over whatever it gives to
    // scoped_nsobject and ScopedCFTypeRef, whether it's in the constructor or
    // in a call to reset().  In either case, it relinquishes that claim and
    // the scoper assumes it.
    [object_ release];
    object_ = object;
  }

  bool operator==(NST* that) const { return object_ == that; }
  bool operator!=(NST* that) const { return object_ != that; }

  operator NST*() const {
    return object_;
  }

  NST* get() const {
    return object_;
  }

  void swap(scoped_nsobject& that) {
    NST* temp = that.object_;
    that.object_ = object_;
    object_ = temp;
  }

  // scoped_nsobject<>::release() is like scoped_ptr<>::release.  It is NOT
  // a wrapper for [object_ release].  To force a scoped_nsobject<> object to
  // call [object_ release], use scoped_nsobject<>::reset().
  NST* release() WARN_UNUSED_RESULT {
    NST* temp = object_;
    object_ = nil;
    return temp;
  }

 private:
  NST* object_;

  DISALLOW_COPY_AND_ASSIGN(scoped_nsobject);
};

// Free functions
template <class C>
void swap(scoped_nsobject<C>& p1, scoped_nsobject<C>& p2) {
  p1.swap(p2);
}

template <class C>
bool operator==(C* p1, const scoped_nsobject<C>& p2) {
  return p1 == p2.get();
}

template <class C>
bool operator!=(C* p1, const scoped_nsobject<C>& p2) {
  return p1 != p2.get();
}


// Specialization to make scoped_nsobject<id> work.
template<>
class scoped_nsobject<id> {
 public:
  typedef id element_type;

  explicit scoped_nsobject(id object = nil)
      : object_(object) {
  }

  ~scoped_nsobject() {
    [object_ release];
  }

  void reset(id object = nil) {
    // We intentionally do not check that object != object_ as the caller must
    // already have an ownership claim over whatever it gives to
    // scoped_nsobject and ScopedCFTypeRef, whether it's in the constructor or
    // in a call to reset().  In either case, it relinquishes that claim and
    // the scoper assumes it.
    [object_ release];
    object_ = object;
  }

  bool operator==(id that) const { return object_ == that; }
  bool operator!=(id that) const { return object_ != that; }

  operator id() const {
    return object_;
  }

  id get() const {
    return object_;
  }

  void swap(scoped_nsobject& that) {
    id temp = that.object_;
    that.object_ = object_;
    object_ = temp;
  }

  // scoped_nsobject<>::release() is like scoped_ptr<>::release.  It is NOT
  // a wrapper for [object_ release].  To force a scoped_nsobject<> object to
  // call [object_ release], use scoped_nsobject<>::reset().
  id release() WARN_UNUSED_RESULT {
    id temp = object_;
    object_ = nil;
    return temp;
  }

 private:
  id object_;

  DISALLOW_COPY_AND_ASSIGN(scoped_nsobject);
};

// Do not use scoped_nsobject for NSAutoreleasePools, use
// ScopedNSAutoreleasePool instead. This is a compile time check. See details
// at top of header.
template<>
class scoped_nsobject<NSAutoreleasePool> {
 private:
  explicit scoped_nsobject(NSAutoreleasePool* object = nil);
  DISALLOW_COPY_AND_ASSIGN(scoped_nsobject);
};

#endif  // BASE_SCOPED_NSOBJECT_H_