Home | History | Annotate | Download | only in mac
      1 // Copyright (c) 2012 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_MAC_SCOPED_NSOBJECT_H_
      6 #define BASE_MAC_SCOPED_NSOBJECT_H_
      7 
      8 #import <Foundation/Foundation.h>
      9 #include "base/basictypes.h"
     10 #include "base/compiler_specific.h"
     11 
     12 namespace base {
     13 
     14 // scoped_nsobject<> is patterned after scoped_ptr<>, but maintains ownership
     15 // of an NSObject subclass object.  Style deviations here are solely for
     16 // compatibility with scoped_ptr<>'s interface, with which everyone is already
     17 // familiar.
     18 //
     19 // scoped_nsobject<> takes ownership of an object (in the constructor or in
     20 // reset()) by taking over the caller's existing ownership claim.  The caller
     21 // must own the object it gives to scoped_nsobject<>, and relinquishes an
     22 // ownership claim to that object.  scoped_nsobject<> does not call -retain,
     23 // callers have to call this manually if appropriate.
     24 //
     25 // scoped_nsprotocol<> has the same behavior as scoped_nsobject, but can be used
     26 // with protocols.
     27 //
     28 // scoped_nsobject<> is not to be used for NSAutoreleasePools. For
     29 // NSAutoreleasePools use ScopedNSAutoreleasePool from
     30 // scoped_nsautorelease_pool.h instead.
     31 // We check for bad uses of scoped_nsobject and NSAutoreleasePool at compile
     32 // time with a template specialization (see below).
     33 
     34 template<typename NST>
     35 class scoped_nsprotocol {
     36  public:
     37   explicit scoped_nsprotocol(NST object = nil) : object_(object) {}
     38 
     39   scoped_nsprotocol(const scoped_nsprotocol<NST>& that)
     40       : object_([that.object_ retain]) {
     41   }
     42 
     43   ~scoped_nsprotocol() {
     44     [object_ release];
     45   }
     46 
     47   scoped_nsprotocol& operator=(const scoped_nsprotocol<NST>& that) {
     48     reset([that.get() retain]);
     49     return *this;
     50   }
     51 
     52   void reset(NST object = nil) {
     53     // We intentionally do not check that object != object_ as the caller must
     54     // either already have an ownership claim over whatever it passes to this
     55     // method, or call it with the |RETAIN| policy which will have ensured that
     56     // the object is retained once more when reaching this point.
     57     [object_ release];
     58     object_ = object;
     59   }
     60 
     61   bool operator==(NST that) const { return object_ == that; }
     62   bool operator!=(NST that) const { return object_ != that; }
     63 
     64   operator NST() const {
     65     return object_;
     66   }
     67 
     68   NST get() const {
     69     return object_;
     70   }
     71 
     72   void swap(scoped_nsprotocol& that) {
     73     NST temp = that.object_;
     74     that.object_ = object_;
     75     object_ = temp;
     76   }
     77 
     78   // scoped_nsprotocol<>::release() is like scoped_ptr<>::release.  It is NOT a
     79   // wrapper for [object_ release].  To force a scoped_nsprotocol<> to call
     80   // [object_ release], use scoped_nsprotocol<>::reset().
     81   NST release() WARN_UNUSED_RESULT {
     82     NST temp = object_;
     83     object_ = nil;
     84     return temp;
     85   }
     86 
     87   // Shift reference to the autorelease pool to be released later.
     88   NST autorelease() {
     89     return [release() autorelease];
     90   }
     91 
     92  private:
     93   NST object_;
     94 };
     95 
     96 // Free functions
     97 template <class C>
     98 void swap(scoped_nsprotocol<C>& p1, scoped_nsprotocol<C>& p2) {
     99   p1.swap(p2);
    100 }
    101 
    102 template <class C>
    103 bool operator==(C p1, const scoped_nsprotocol<C>& p2) {
    104   return p1 == p2.get();
    105 }
    106 
    107 template <class C>
    108 bool operator!=(C p1, const scoped_nsprotocol<C>& p2) {
    109   return p1 != p2.get();
    110 }
    111 
    112 template<typename NST>
    113 class scoped_nsobject : public scoped_nsprotocol<NST*> {
    114  public:
    115   explicit scoped_nsobject(NST* object = nil)
    116       : scoped_nsprotocol<NST*>(object) {}
    117 
    118   scoped_nsobject(const scoped_nsobject<NST>& that)
    119       : scoped_nsprotocol<NST*>(that) {
    120   }
    121 
    122   scoped_nsobject& operator=(const scoped_nsobject<NST>& that) {
    123     scoped_nsprotocol<NST*>::operator=(that);
    124     return *this;
    125   }
    126 };
    127 
    128 // Specialization to make scoped_nsobject<id> work.
    129 template<>
    130 class scoped_nsobject<id> : public scoped_nsprotocol<id> {
    131  public:
    132   explicit scoped_nsobject(id object = nil) : scoped_nsprotocol<id>(object) {}
    133 
    134   scoped_nsobject(const scoped_nsobject<id>& that)
    135       : scoped_nsprotocol<id>(that) {
    136   }
    137 
    138   scoped_nsobject& operator=(const scoped_nsobject<id>& that) {
    139     scoped_nsprotocol<id>::operator=(that);
    140     return *this;
    141   }
    142 };
    143 
    144 // Do not use scoped_nsobject for NSAutoreleasePools, use
    145 // ScopedNSAutoreleasePool instead. This is a compile time check. See details
    146 // at top of header.
    147 template<>
    148 class scoped_nsobject<NSAutoreleasePool> {
    149  private:
    150   explicit scoped_nsobject(NSAutoreleasePool* object = nil);
    151   DISALLOW_COPY_AND_ASSIGN(scoped_nsobject);
    152 };
    153 
    154 }  // namespace base
    155 
    156 #endif  // BASE_MAC_SCOPED_NSOBJECT_H_
    157