1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#ifndef BASE_MEMORY_SCOPED_NSOBJECT_H_ 6ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#define BASE_MEMORY_SCOPED_NSOBJECT_H_ 73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#import <Foundation/Foundation.h> 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/basictypes.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/compiler_specific.h" 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// scoped_nsobject<> is patterned after scoped_ptr<>, but maintains ownership 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// of an NSObject subclass object. Style deviations here are solely for 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// compatibility with scoped_ptr<>'s interface, with which everyone is already 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// familiar. 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// When scoped_nsobject<> takes ownership of an object (in the constructor or 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// in reset()), it takes over the caller's existing ownership claim. The 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// caller must own the object it gives to scoped_nsobject<>, and relinquishes 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// an ownership claim to that object. scoped_nsobject<> does not call 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// -retain. 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// scoped_nsobject<> is not to be used for NSAutoreleasePools. For 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// NSAutoreleasePools use ScopedNSAutoreleasePool from 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// scoped_nsautorelease_pool.h instead. 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// We check for bad uses of scoped_nsobject and NSAutoreleasePool at compile 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// time with a template specialization (see below). 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate<typename NST> 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass scoped_nsobject { 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott typedef NST* element_type; 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott explicit scoped_nsobject(NST* object = nil) 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : object_(object) { 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ~scoped_nsobject() { 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott [object_ release]; 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void reset(NST* object = nil) { 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We intentionally do not check that object != object_ as the caller must 44731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // already have an ownership claim over whatever it gives to 45731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // scoped_nsobject and ScopedCFTypeRef, whether it's in the constructor or 46731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // in a call to reset(). In either case, it relinquishes that claim and 47731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // the scoper assumes it. 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott [object_ release]; 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott object_ = object; 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool operator==(NST* that) const { return object_ == that; } 533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool operator!=(NST* that) const { return object_ != that; } 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott operator NST*() const { 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return object_; 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NST* get() const { 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return object_; 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void swap(scoped_nsobject& that) { 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NST* temp = that.object_; 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott that.object_ = object_; 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott object_ = temp; 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // scoped_nsobject<>::release() is like scoped_ptr<>::release. It is NOT 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // a wrapper for [object_ release]. To force a scoped_nsobject<> object to 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // call [object_ release], use scoped_nsobject<>::reset(). 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NST* release() WARN_UNUSED_RESULT { 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NST* temp = object_; 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott object_ = nil; 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return temp; 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NST* object_; 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DISALLOW_COPY_AND_ASSIGN(scoped_nsobject); 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Free functions 853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merricktemplate <class C> 863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid swap(scoped_nsobject<C>& p1, scoped_nsobject<C>& p2) { 873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick p1.swap(p2); 883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merricktemplate <class C> 913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool operator==(C* p1, const scoped_nsobject<C>& p2) { 923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return p1 == p2.get(); 933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merricktemplate <class C> 963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool operator!=(C* p1, const scoped_nsobject<C>& p2) { 973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return p1 != p2.get(); 983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Specialization to make scoped_nsobject<id> work. 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate<> 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass scoped_nsobject<id> { 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott typedef id element_type; 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott explicit scoped_nsobject(id object = nil) 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : object_(object) { 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ~scoped_nsobject() { 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott [object_ release]; 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void reset(id object = nil) { 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We intentionally do not check that object != object_ as the caller must 117731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // already have an ownership claim over whatever it gives to 118731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // scoped_nsobject and ScopedCFTypeRef, whether it's in the constructor or 119731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // in a call to reset(). In either case, it relinquishes that claim and 120731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // the scoper assumes it. 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott [object_ release]; 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott object_ = object; 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool operator==(id that) const { return object_ == that; } 1263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool operator!=(id that) const { return object_ != that; } 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott operator id() const { 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return object_; 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott id get() const { 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return object_; 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void swap(scoped_nsobject& that) { 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott id temp = that.object_; 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott that.object_ = object_; 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott object_ = temp; 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // scoped_nsobject<>::release() is like scoped_ptr<>::release. It is NOT 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // a wrapper for [object_ release]. To force a scoped_nsobject<> object to 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // call [object_ release], use scoped_nsobject<>::reset(). 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch id release() WARN_UNUSED_RESULT { 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott id temp = object_; 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott object_ = nil; 148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return temp; 149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott id object_; 153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DISALLOW_COPY_AND_ASSIGN(scoped_nsobject); 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Do not use scoped_nsobject for NSAutoreleasePools, use 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ScopedNSAutoreleasePool instead. This is a compile time check. See details 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// at top of header. 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttemplate<> 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass scoped_nsobject<NSAutoreleasePool> { 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott explicit scoped_nsobject(NSAutoreleasePool* object = nil); 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DISALLOW_COPY_AND_ASSIGN(scoped_nsobject); 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 167ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif // BASE_MEMORY_SCOPED_NSOBJECT_H_ 168