Shaka Player Embedded
cfref.h
Go to the documentation of this file.
1 // Copyright 2017 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef SHAKA_EMBEDDED_UTIL_CF_REF_H_
16 #define SHAKA_EMBEDDED_UTIL_CF_REF_H_
17 
18 #ifdef __APPLE__
19 
20 # include <CoreFoundation/CoreFoundation.h>
21 
22 # include <memory>
23 # include <type_traits>
24 
25 namespace shaka {
26 namespace util {
27 
28 // Defines a type and a singleton to signal which overload to use. These can
29 // be used with the CFRef constructors to use different reference semantics.
30 // CFRef(absorb_ref, GetValue()) // The ref already has an extra ref count.
31 // CFRef(acquire_ref, GetValue()) // Acquires the ref first.
32 struct absorb_ref_t {};
33 extern absorb_ref_t absorb_ref;
34 struct acquire_ref_t {};
35 extern acquire_ref_t acquire_ref;
36 
41 template <typename T>
42 struct RefTypeTraits {
47  static constexpr const bool AcquireWithRaw = false;
48 
53  static T Duplicate(T arg) {
54  if (arg)
55  CFRetain(arg);
56  return arg;
57  }
58 
62  static void Release(T arg) {
63  if (arg)
64  CFRelease(arg);
65  }
66 };
67 
68 
74 template <typename T>
75 class CFRef {
76  public:
77  using traits = RefTypeTraits<T>;
78  using value_type = T;
79 
80  CFRef() : ptr_(nullptr) {}
81  CFRef(std::nullptr_t) : ptr_(nullptr) {} // NOLINT(runtime/explicit)
82  CFRef(T arg) // NOLINT(runtime/explicit)
83  : ptr_(traits::AcquireWithRaw ? traits::Duplicate(arg) : arg) {}
84  CFRef(absorb_ref_t, T arg) : ptr_(arg) {}
85  CFRef(acquire_ref_t, T arg) : ptr_(traits::Duplicate(arg)) {}
86  CFRef(const CFRef& other) : ptr_(traits::Duplicate(other.ptr_)) {}
87  CFRef(CFRef&& other) : ptr_(other.Detach()) {}
88  // Careful, these assume that if U is compatible with T, that the
89  // Duplicate/Release methods are compatible.
90  template <typename U>
91  CFRef(const CFRef<U>& other) : ptr_(traits::Duplicate(other.ptr_)) {}
92  template <typename U>
93  CFRef(CFRef<U>&& other) : ptr_(other.Detach()) {}
94  ~CFRef() {
95  Release();
96  }
97 
98  CFRef& operator=(const CFRef& other) {
99  Release();
100  ptr_ = traits::Duplicate(other);
101  return *this;
102  }
103  CFRef& operator=(CFRef&& other) {
104  Release();
105  ptr_ = other.Detach();
106  return *this;
107  }
108  CFRef& operator=(T other) {
109  Release();
110  ptr_ = traits::AcquireWithRaw ? traits::Duplicate(other) : other;
111  return *this;
112  }
113 
120  operator T() const {
121  return ptr_;
122  }
123 
128  T Detach() {
129  T ret = ptr_;
130  ptr_ = nullptr;
131  return ret;
132  }
133 
134  private:
135  template <typename U>
136  friend class CFRef;
137 
138  void Release() {
139  traits::Release(ptr_);
140  ptr_ = nullptr;
141  }
142 
143  T ptr_;
144 };
145 
146 } // namespace util
147 } // namespace shaka
148 
149 #endif // __APPLE__
150 
151 #endif // SHAKA_EMBEDDED_UTIL_CF_REF_H_