1 /*
2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 *
10 */
11
12 #ifndef SDK_OBJC_HELPERS_SCOPED_CFTYPEREF_H_
13 #define SDK_OBJC_HELPERS_SCOPED_CFTYPEREF_H_
14
15 #include <CoreFoundation/CoreFoundation.h>
16 namespace rtc {
17
18 // RETAIN: ScopedTypeRef should retain the object when it takes
19 // ownership.
20 // ASSUME: Assume the object already has already been retained.
21 // ScopedTypeRef takes over ownership.
22 enum class RetainPolicy { RETAIN, ASSUME };
23
24 namespace internal {
25 template <typename T>
26 struct CFTypeRefTraits {
InvalidValueCFTypeRefTraits27 static T InvalidValue() { return nullptr; }
ReleaseCFTypeRefTraits28 static void Release(T ref) { CFRelease(ref); }
RetainCFTypeRefTraits29 static T Retain(T ref) {
30 CFRetain(ref);
31 return ref;
32 }
33 };
34
35 template <typename T, typename Traits>
36 class ScopedTypeRef {
37 public:
ScopedTypeRef()38 ScopedTypeRef() : ptr_(Traits::InvalidValue()) {}
ScopedTypeRef(T ptr)39 explicit ScopedTypeRef(T ptr) : ptr_(ptr) {}
ScopedTypeRef(T ptr,RetainPolicy policy)40 ScopedTypeRef(T ptr, RetainPolicy policy) : ScopedTypeRef(ptr) {
41 if (ptr_ && policy == RetainPolicy::RETAIN)
42 Traits::Retain(ptr_);
43 }
44
ScopedTypeRef(const ScopedTypeRef<T,Traits> & rhs)45 ScopedTypeRef(const ScopedTypeRef<T, Traits>& rhs) : ptr_(rhs.ptr_) {
46 if (ptr_)
47 ptr_ = Traits::Retain(ptr_);
48 }
49
~ScopedTypeRef()50 ~ScopedTypeRef() {
51 if (ptr_) {
52 Traits::Release(ptr_);
53 }
54 }
55
get()56 T get() const { return ptr_; }
57 T operator->() const { return ptr_; }
58 explicit operator bool() const { return ptr_; }
59
60 bool operator!() const { return !ptr_; }
61
62 ScopedTypeRef& operator=(const T& rhs) {
63 if (ptr_)
64 Traits::Release(ptr_);
65 ptr_ = rhs;
66 return *this;
67 }
68
69 ScopedTypeRef& operator=(const ScopedTypeRef<T, Traits>& rhs) {
70 reset(rhs.get(), RetainPolicy::RETAIN);
71 return *this;
72 }
73
74 // This is intended to take ownership of objects that are
75 // created by pass-by-pointer initializers.
InitializeInto()76 T* InitializeInto() {
77 RTC_DCHECK(!ptr_);
78 return &ptr_;
79 }
80
81 void reset(T ptr, RetainPolicy policy = RetainPolicy::ASSUME) {
82 if (ptr && policy == RetainPolicy::RETAIN)
83 Traits::Retain(ptr);
84 if (ptr_)
85 Traits::Release(ptr_);
86 ptr_ = ptr;
87 }
88
release()89 T release() {
90 T temp = ptr_;
91 ptr_ = Traits::InvalidValue();
92 return temp;
93 }
94
95 private:
96 T ptr_;
97 };
98 } // namespace internal
99
100 template <typename T>
101 using ScopedCFTypeRef =
102 internal::ScopedTypeRef<T, internal::CFTypeRefTraits<T>>;
103
104 template <typename T>
AdoptCF(T cftype)105 static ScopedCFTypeRef<T> AdoptCF(T cftype) {
106 return ScopedCFTypeRef<T>(cftype, RetainPolicy::RETAIN);
107 }
108
109 template <typename T>
ScopedCF(T cftype)110 static ScopedCFTypeRef<T> ScopedCF(T cftype) {
111 return ScopedCFTypeRef<T>(cftype);
112 }
113
114 } // namespace rtc
115
116 #endif // SDK_OBJC_HELPERS_SCOPED_CFTYPEREF_H_
117