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
|
// Copyright (c) 2012 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_MAC_SCOPED_NSOBJECT_H_
#define BASE_MAC_SCOPED_NSOBJECT_H_
#import <Foundation/Foundation.h>
#include "base/basictypes.h"
#include "base/compiler_specific.h"
namespace base {
// 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.
//
// scoped_nsobject<> takes ownership of an object (in the constructor or in
// reset()) by taking 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,
// callers have to call this manually if appropriate.
//
// scoped_nsprotocol<> has the same behavior as scoped_nsobject, but can be used
// with protocols.
//
// 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_nsprotocol {
public:
explicit scoped_nsprotocol(NST object = nil) : object_(object) {}
scoped_nsprotocol(const scoped_nsprotocol<NST>& that)
: object_([that.object_ retain]) {
}
~scoped_nsprotocol() {
[object_ release];
}
scoped_nsprotocol& operator=(const scoped_nsprotocol<NST>& that) {
reset([that.get() retain]);
return *this;
}
void reset(NST object = nil) {
// We intentionally do not check that object != object_ as the caller must
// either already have an ownership claim over whatever it passes to this
// method, or call it with the |RETAIN| policy which will have ensured that
// the object is retained once more when reaching this point.
[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_nsprotocol& that) {
NST temp = that.object_;
that.object_ = object_;
object_ = temp;
}
// scoped_nsprotocol<>::release() is like scoped_ptr<>::release. It is NOT a
// wrapper for [object_ release]. To force a scoped_nsprotocol<> to call
// [object_ release], use scoped_nsprotocol<>::reset().
NST release() WARN_UNUSED_RESULT {
NST temp = object_;
object_ = nil;
return temp;
}
// Shift reference to the autorelease pool to be released later.
NST autorelease() {
return [release() autorelease];
}
private:
NST object_;
};
// Free functions
template <class C>
void swap(scoped_nsprotocol<C>& p1, scoped_nsprotocol<C>& p2) {
p1.swap(p2);
}
template <class C>
bool operator==(C p1, const scoped_nsprotocol<C>& p2) {
return p1 == p2.get();
}
template <class C>
bool operator!=(C p1, const scoped_nsprotocol<C>& p2) {
return p1 != p2.get();
}
template<typename NST>
class scoped_nsobject : public scoped_nsprotocol<NST*> {
public:
explicit scoped_nsobject(NST* object = nil)
: scoped_nsprotocol<NST*>(object) {}
scoped_nsobject(const scoped_nsobject<NST>& that)
: scoped_nsprotocol<NST*>(that) {
}
scoped_nsobject& operator=(const scoped_nsobject<NST>& that) {
scoped_nsprotocol<NST*>::operator=(that);
return *this;
}
};
// Specialization to make scoped_nsobject<id> work.
template<>
class scoped_nsobject<id> : public scoped_nsprotocol<id> {
public:
explicit scoped_nsobject(id object = nil) : scoped_nsprotocol<id>(object) {}
scoped_nsobject(const scoped_nsobject<id>& that)
: scoped_nsprotocol<id>(that) {
}
scoped_nsobject& operator=(const scoped_nsobject<id>& that) {
scoped_nsprotocol<id>::operator=(that);
return *this;
}
};
// 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);
};
} // namespace base
#endif // BASE_MAC_SCOPED_NSOBJECT_H_
|