Home | History | Annotate | Download | only in memory
      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).
     29 template<typename NST>
     30 class 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
     85 template <class C>
     86 void swap(scoped_nsobject<C>& p1, scoped_nsobject<C>& p2) {
     87   p1.swap(p2);
     88 }
     89 
     90 template <class C>
     91 bool operator==(C* p1, const scoped_nsobject<C>& p2) {
     92   return p1 == p2.get();
     93 }
     94 
     95 template <class C>
     96 bool operator!=(C* p1, const scoped_nsobject<C>& p2) {
     97   return p1 != p2.get();
     98 }
     99 
    100 
    101 // Specialization to make scoped_nsobject<id> work.
    102 template<>
    103 class 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.
    160 template<>
    161 class 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