Bug 1861709 replace AudioCallbackDriver::ThreadRunning() assertions that mean to...
[gecko.git] / widget / cocoa / CFTypeRefPtr.h
blob185355777eb75f5f94b379407f694ae8526c20e5
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef CFTypeRefPtr_h
8 #define CFTypeRefPtr_h
10 #include "mozilla/Assertions.h"
11 #include "mozilla/Attributes.h"
12 #include "mozilla/DbgMacro.h"
13 #include "mozilla/HashFunctions.h"
15 // A smart pointer for CoreFoundation classes which does reference counting.
17 // Manual reference counting:
19 // UInt32 someNumber = 10;
20 // CFNumberRef numberObject =
21 // CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &someNumber);
22 // // do something with numberObject
23 // CFRelease(numberObject);
25 // Automatic reference counting using CFTypeRefPtr:
27 // UInt32 someNumber = 10;
28 // auto numberObject =
29 // CFTypeRefPtr<CFNumberRef>::WrapUnderCreateRule(
30 // CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &someNumber));
31 // // do something with numberObject
32 // // no CFRelease
34 template <class PtrT>
35 class CFTypeRefPtr {
36 private:
37 void assign_with_CFRetain(PtrT aRawPtr) {
38 CFRetain(aRawPtr);
39 assign_assuming_CFRetain(aRawPtr);
42 void assign_assuming_CFRetain(PtrT aNewPtr) {
43 PtrT oldPtr = mRawPtr;
44 mRawPtr = aNewPtr;
45 if (oldPtr) {
46 CFRelease(oldPtr);
50 private:
51 PtrT mRawPtr;
53 public:
54 ~CFTypeRefPtr() {
55 if (mRawPtr) {
56 CFRelease(mRawPtr);
60 // Constructors
62 CFTypeRefPtr() : mRawPtr(nullptr) {}
64 CFTypeRefPtr(const CFTypeRefPtr<PtrT>& aSmartPtr)
65 : mRawPtr(aSmartPtr.mRawPtr) {
66 if (mRawPtr) {
67 CFRetain(mRawPtr);
71 CFTypeRefPtr(CFTypeRefPtr<PtrT>&& aRefPtr) : mRawPtr(aRefPtr.mRawPtr) {
72 aRefPtr.mRawPtr = nullptr;
75 MOZ_IMPLICIT CFTypeRefPtr(decltype(nullptr)) : mRawPtr(nullptr) {}
77 // There is no constructor from a raw pointer value.
78 // Use one of the static WrapUnder*Rule methods below instead.
80 static CFTypeRefPtr<PtrT> WrapUnderCreateRule(PtrT aRawPtr) {
81 CFTypeRefPtr<PtrT> ptr;
82 ptr.AssignUnderCreateRule(aRawPtr);
83 return ptr;
86 static CFTypeRefPtr<PtrT> WrapUnderGetRule(PtrT aRawPtr) {
87 CFTypeRefPtr<PtrT> ptr;
88 ptr.AssignUnderGetRule(aRawPtr);
89 return ptr;
92 // Assignment operators
94 CFTypeRefPtr<PtrT>& operator=(decltype(nullptr)) {
95 assign_assuming_CFRetain(nullptr);
96 return *this;
99 CFTypeRefPtr<PtrT>& operator=(const CFTypeRefPtr<PtrT>& aRhs) {
100 assign_with_CFRetain(aRhs.mRawPtr);
101 return *this;
104 CFTypeRefPtr<PtrT>& operator=(CFTypeRefPtr<PtrT>&& aRefPtr) {
105 assign_assuming_CFRetain(aRefPtr.mRawPtr);
106 aRefPtr.mRawPtr = nullptr;
107 return *this;
110 // There is no operator= for a raw pointer value.
111 // Use one of the AssignUnder*Rule methods below instead.
113 CFTypeRefPtr<PtrT>& AssignUnderCreateRule(PtrT aRawPtr) {
114 // Freshly-created objects come with a retain count of 1.
115 assign_assuming_CFRetain(aRawPtr);
116 return *this;
119 CFTypeRefPtr<PtrT>& AssignUnderGetRule(PtrT aRawPtr) {
120 assign_with_CFRetain(aRawPtr);
121 return *this;
124 // Other pointer operators
126 // This is the only way to get the raw pointer out of the smart pointer.
127 // There is no implicit conversion to a raw pointer.
128 PtrT get() const { return mRawPtr; }
130 // Don't allow implicit conversion of temporary CFTypeRefPtr to raw pointer,
131 // because the refcount might be one and the pointer will immediately become
132 // invalid.
133 operator PtrT() const&& = delete;
134 // Also don't allow implicit conversion of non-temporary CFTypeRefPtr.
135 operator PtrT() const& = delete;
137 // These let you null-check a pointer without calling get().
138 explicit operator bool() const { return !!mRawPtr; }
141 template <class PtrT>
142 inline bool operator==(const CFTypeRefPtr<PtrT>& aLhs,
143 const CFTypeRefPtr<PtrT>& aRhs) {
144 return aLhs.get() == aRhs.get();
147 template <class PtrT>
148 inline bool operator!=(const CFTypeRefPtr<PtrT>& aLhs,
149 const CFTypeRefPtr<PtrT>& aRhs) {
150 return !(aLhs == aRhs);
153 // Comparing an |CFTypeRefPtr| to |nullptr|
155 template <class PtrT>
156 inline bool operator==(const CFTypeRefPtr<PtrT>& aLhs, decltype(nullptr)) {
157 return aLhs.get() == nullptr;
160 template <class PtrT>
161 inline bool operator==(decltype(nullptr), const CFTypeRefPtr<PtrT>& aRhs) {
162 return nullptr == aRhs.get();
165 template <class PtrT>
166 inline bool operator!=(const CFTypeRefPtr<PtrT>& aLhs, decltype(nullptr)) {
167 return aLhs.get() != nullptr;
170 template <class PtrT>
171 inline bool operator!=(decltype(nullptr), const CFTypeRefPtr<PtrT>& aRhs) {
172 return nullptr != aRhs.get();
175 // MOZ_DBG support
177 template <class PtrT>
178 std::ostream& operator<<(std::ostream& aOut, const CFTypeRefPtr<PtrT>& aObj) {
179 return mozilla::DebugValue(aOut, aObj.get());
182 // std::hash support (e.g. for unordered_map)
183 namespace std {
184 template <class PtrT>
185 struct hash<CFTypeRefPtr<PtrT>> {
186 typedef CFTypeRefPtr<PtrT> argument_type;
187 typedef std::size_t result_type;
188 result_type operator()(argument_type const& aPtr) const {
189 return mozilla::HashGeneric(reinterpret_cast<uintptr_t>(aPtr.get()));
192 } // namespace std
194 #endif /* CFTypeRefPtr_h */