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