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/. */
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
37 void assign_with_CFRetain(PtrT aRawPtr
) {
39 assign_assuming_CFRetain(aRawPtr
);
42 void assign_assuming_CFRetain(PtrT aNewPtr
) {
43 PtrT oldPtr
= mRawPtr
;
62 CFTypeRefPtr() : mRawPtr(nullptr) {}
64 CFTypeRefPtr(const CFTypeRefPtr
<PtrT
>& aSmartPtr
)
65 : mRawPtr(aSmartPtr
.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
);
86 static CFTypeRefPtr
<PtrT
> WrapUnderGetRule(PtrT aRawPtr
) {
87 CFTypeRefPtr
<PtrT
> ptr
;
88 ptr
.AssignUnderGetRule(aRawPtr
);
92 // Assignment operators
94 CFTypeRefPtr
<PtrT
>& operator=(decltype(nullptr)) {
95 assign_assuming_CFRetain(nullptr);
99 CFTypeRefPtr
<PtrT
>& operator=(const CFTypeRefPtr
<PtrT
>& aRhs
) {
100 assign_with_CFRetain(aRhs
.mRawPtr
);
104 CFTypeRefPtr
<PtrT
>& operator=(CFTypeRefPtr
<PtrT
>&& aRefPtr
) {
105 assign_assuming_CFRetain(aRefPtr
.mRawPtr
);
106 aRefPtr
.mRawPtr
= nullptr;
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
);
119 CFTypeRefPtr
<PtrT
>& AssignUnderGetRule(PtrT aRawPtr
) {
120 assign_with_CFRetain(aRawPtr
);
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
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();
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)
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()));
194 #endif /* CFTypeRefPtr_h */