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 #include <type_traits>
      9 
     10 // Include NSObject.h directly because Foundation.h pulls in many dependencies.
     11 // (Approx 100k lines of code versus 1.5k for NSObject.h). scoped_nsobject gets
     12 // singled out because it is most typically included from other header files.
     13 #import <Foundation/NSObject.h>
     14 
     15 #include "base/compiler_specific.h"
     16 #include "base/mac/scoped_typeref.h"
     17 
     18 @class NSAutoreleasePool;
     19 
     20 namespace base {
     21 
     22 // scoped_nsobject<> is patterned after scoped_ptr<>, but maintains ownership
     23 // of an NSObject subclass object.  Style deviations here are solely for
     24 // compatibility with scoped_ptr<>'s interface, with which everyone is already
     25 // familiar.
     26 //
     27 // scoped_nsobject<> takes ownership of an object (in the constructor or in
     28 // reset()) by taking over the caller's existing ownership claim.  The caller
     29 // must own the object it gives to scoped_nsobject<>, and relinquishes an
     30 // ownership claim to that object.  scoped_nsobject<> does not call -retain,
     31 // callers have to call this manually if appropriate.
     32 //
     33 // scoped_nsprotocol<> has the same behavior as scoped_nsobject, but can be used
     34 // with protocols.
     35 //
     36 // scoped_nsobject<> is not to be used for NSAutoreleasePools. For
     37 // NSAutoreleasePools use ScopedNSAutoreleasePool from
     38 // scoped_nsautorelease_pool.h instead.
     39 // We check for bad uses of scoped_nsobject and NSAutoreleasePool at compile
     40 // time with a template specialization (see below).
     41 
     42 namespace internal {
     43 
     44 template <typename NST>
     45 struct ScopedNSProtocolTraits {
     46   static NST InvalidValue() { return nil; }
     47   static NST Retain(NST nst) { return [nst retain]; }
     48   static void Release(NST nst) { [nst release]; }
     49 };
     50 
     51 }  // namespace internal
     52 
     53 template <typename NST>
     54 class scoped_nsprotocol
     55     : public ScopedTypeRef<NST, internal::ScopedNSProtocolTraits<NST>> {
     56  public:
     57   using ScopedTypeRef<NST,
     58                       internal::ScopedNSProtocolTraits<NST>>::ScopedTypeRef;
     59 
     60   // Shift reference to the autorelease pool to be released later.
     61   NST autorelease() { return [this->release() autorelease]; }
     62 };
     63 
     64 // Free functions
     65 template <class C>
     66 void swap(scoped_nsprotocol<C>& p1, scoped_nsprotocol<C>& p2) {
     67   p1.swap(p2);
     68 }
     69 
     70 template <class C>
     71 bool operator==(C p1, const scoped_nsprotocol<C>& p2) {
     72   return p1 == p2.get();
     73 }
     74 
     75 template <class C>
     76 bool operator!=(C p1, const scoped_nsprotocol<C>& p2) {
     77   return p1 != p2.get();
     78 }
     79 
     80 template <typename NST>
     81 class scoped_nsobject : public scoped_nsprotocol<NST*> {
     82  public:
     83   using scoped_nsprotocol<NST*>::scoped_nsprotocol;
     84 
     85   static_assert(std::is_same<NST, NSAutoreleasePool>::value == false,
     86                 "Use ScopedNSAutoreleasePool instead");
     87 };
     88 
     89 // Specialization to make scoped_nsobject<id> work.
     90 template<>
     91 class scoped_nsobject<id> : public scoped_nsprotocol<id> {
     92  public:
     93   using scoped_nsprotocol<id>::scoped_nsprotocol;
     94 };
     95 
     96 }  // namespace base
     97 
     98 #endif  // BASE_MAC_SCOPED_NSOBJECT_H_
     99