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