Changeset 267591 in webkit
- Timestamp:
- Sep 25, 2020, 1:36:50 PM (6 years ago)
- Location:
- trunk/Source
- Files:
-
- 21 edited
-
JavaScriptCore/ChangeLog (modified) (1 diff)
-
JavaScriptCore/runtime/CachedTypes.cpp (modified) (1 diff)
-
WTF/ChangeLog (modified) (1 diff)
-
WTF/wtf/CompactRefPtrTuple.h (modified) (2 diffs)
-
WTF/wtf/Forward.h (modified) (2 diffs)
-
WTF/wtf/RefPtr.h (modified) (13 diffs)
-
WebCore/ChangeLog (modified) (1 diff)
-
WebCore/Modules/webaudio/AudioBufferSourceNode.cpp (modified) (1 diff)
-
WebCore/Modules/webaudio/AudioBufferSourceNode.h (modified) (1 diff)
-
WebCore/Modules/webaudio/AudioNode.cpp (modified) (6 diffs)
-
WebCore/Modules/webaudio/AudioNode.h (modified) (3 diffs)
-
WebCore/Modules/webaudio/AudioNodeInput.cpp (modified) (3 diffs)
-
WebCore/Modules/webaudio/AudioNodeOutput.cpp (modified) (5 diffs)
-
WebCore/Modules/webaudio/AudioNodeOutput.h (modified) (1 diff)
-
WebCore/Modules/webaudio/BaseAudioContext.cpp (modified) (7 diffs)
-
WebCore/Modules/webaudio/BaseAudioContext.h (modified) (3 diffs)
-
WebCore/Modules/webaudio/ScriptProcessorNode.cpp (modified) (2 diffs)
-
WebCore/platform/graphics/cairo/RefPtrCairo.cpp (modified) (12 diffs)
-
WebCore/platform/graphics/cairo/RefPtrCairo.h (modified) (1 diff)
-
WebCore/platform/graphics/freetype/RefPtrFontconfig.cpp (modified) (4 diffs)
-
WebCore/platform/graphics/freetype/RefPtrFontconfig.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r267564 r267591 1 2020-09-25 Chris Dumez <cdumez@apple.com> 2 3 Get rid of AudioNode::RefType 4 https://bugs.webkit.org/show_bug.cgi?id=216945 5 6 Reviewed by Darin Adler. 7 8 * runtime/CachedTypes.cpp: 9 (JSC::CachedRefPtr::decode const): 10 1 11 2020-09-25 Alexey Shvayka <shvaikalesh@gmail.com> 2 12 -
trunk/Source/JavaScriptCore/runtime/CachedTypes.cpp
r264488 r267591 555 555 if (isNewAllocation) { 556 556 decoder.addFinalizer([=] { 557 derefIfNotNull(decodedPtr);557 WTF::DefaultRefDerefTraits<Source>::derefIfNotNull(decodedPtr); 558 558 }); 559 559 } 560 refIfNotNull(decodedPtr);560 WTF::DefaultRefDerefTraits<Source>::refIfNotNull(decodedPtr); 561 561 return adoptRef(decodedPtr); 562 562 } -
trunk/Source/WTF/ChangeLog
r267562 r267591 1 2020-09-25 Chris Dumez <cdumez@apple.com> 2 3 Get rid of AudioNode::RefType 4 https://bugs.webkit.org/show_bug.cgi?id=216945 5 6 Reviewed by Darin Adler. 7 8 Add third template parameter to RefPtr allowing to define the traits 9 from incrementing / decrementing the refcount. The default traits 10 call ref() / deref() but this can now be customized to call other 11 functions. 12 13 * wtf/CompactRefPtrTuple.h: 14 * wtf/Forward.h: 15 * wtf/RefPtr.h: 16 (WTF::DefaultRefDerefTraits::refIfNotNull): 17 (WTF::DefaultRefDerefTraits::derefIfNotNull): 18 (WTF::RefPtr::RefPtr): 19 (WTF::RefPtr::~RefPtr): 20 (WTF::V>::RefPtr): 21 (WTF::V>::leakRef): 22 (WTF::=): 23 (WTF::V>::swap): 24 (WTF::swap): 25 (WTF::operator==): 26 (WTF::operator!=): 27 (WTF::static_pointer_cast): 28 (WTF::adoptRef): 29 (WTF::is): 30 1 31 2020-09-25 Antti Koivisto <antti@apple.com> 2 32 -
trunk/Source/WTF/wtf/CompactRefPtrTuple.h
r257295 r267591 40 40 ~CompactRefPtrTuple() 41 41 { 42 derefIfNotNull(m_data.pointer());42 WTF::DefaultRefDerefTraits<T>::derefIfNotNull(m_data.pointer()); 43 43 } 44 44 … … 50 50 void setPointer(T* pointer) 51 51 { 52 refIfNotNull(pointer);52 WTF::DefaultRefDerefTraits<T>::refIfNotNull(pointer); 53 53 auto* old = m_data.pointer(); 54 54 m_data.setPointer(pointer); 55 derefIfNotNull(old);55 WTF::DefaultRefDerefTraits<T>::derefIfNotNull(old); 56 56 } 57 57 -
trunk/Source/WTF/wtf/Forward.h
r264533 r267591 60 60 61 61 template<typename> struct DumbPtrTraits; 62 template<typename> struct DefaultRefDerefTraits; 62 63 63 64 template<typename> class CompletionHandler; … … 70 71 template<typename T, size_t = alignof(T)> class PackedAlignedPtr; 71 72 template<typename T, typename = DumbPtrTraits<T>> class Ref; 72 template<typename T, typename = DumbPtrTraits<T> > class RefPtr;73 template<typename T, typename = DumbPtrTraits<T>, typename = DefaultRefDerefTraits<T>> class RefPtr; 73 74 template<typename> class StringBuffer; 74 75 template<typename> class StringParsingBuffer; -
trunk/Source/WTF/wtf/RefPtr.h
r254881 r267591 30 30 namespace WTF { 31 31 32 template<typename T, typename PtrTraits> class RefPtr; 33 template<typename T, typename PtrTraits = DumbPtrTraits<T>> RefPtr<T, PtrTraits> adoptRef(T*); 34 35 template<typename T> ALWAYS_INLINE void refIfNotNull(T* ptr) 36 { 37 if (LIKELY(ptr != nullptr)) 38 ptr->ref(); 39 } 40 41 template<typename T> ALWAYS_INLINE void derefIfNotNull(T* ptr) 42 { 43 if (LIKELY(ptr != nullptr)) 44 ptr->deref(); 45 } 46 47 template<typename T, typename Traits> 32 template<typename T> struct DefaultRefDerefTraits { 33 static ALWAYS_INLINE void refIfNotNull(T* ptr) 34 { 35 if (LIKELY(ptr != nullptr)) 36 ptr->ref(); 37 } 38 39 static ALWAYS_INLINE void derefIfNotNull(T* ptr) 40 { 41 if (LIKELY(ptr != nullptr)) 42 ptr->deref(); 43 } 44 }; 45 46 template<typename T, typename PtrTraits, typename RefDerefTraits> class RefPtr; 47 template<typename T, typename PtrTraits = DumbPtrTraits<T>, typename RefDerefTraits = DefaultRefDerefTraits<T>> RefPtr<T, PtrTraits, RefDerefTraits> adoptRef(T*); 48 49 template<typename T, typename _PtrTraits, typename _RefDerefTraits> 48 50 class RefPtr { 49 51 WTF_MAKE_FAST_ALLOCATED; 50 52 public: 51 using PtrTraits = Traits; 53 using PtrTraits = _PtrTraits; 54 using RefDerefTraits = _RefDerefTraits; 52 55 typedef T ValueType; 53 56 typedef ValueType* PtrType; … … 56 59 57 60 ALWAYS_INLINE constexpr RefPtr() : m_ptr(nullptr) { } 58 ALWAYS_INLINE RefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); }59 ALWAYS_INLINE RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { refIfNotNull(PtrTraits::unwrap(m_ptr)); }60 template<typename X, typename Y > RefPtr(const RefPtr<X, Y>& o) : m_ptr(o.get()) {refIfNotNull(PtrTraits::unwrap(m_ptr)); }61 ALWAYS_INLINE RefPtr(T* ptr) : m_ptr(ptr) { RefDerefTraits::refIfNotNull(ptr); } 62 ALWAYS_INLINE RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { RefDerefTraits::refIfNotNull(PtrTraits::unwrap(m_ptr)); } 63 template<typename X, typename Y, typename Z> RefPtr(const RefPtr<X, Y, Z>& o) : m_ptr(o.get()) { RefDerefTraits::refIfNotNull(PtrTraits::unwrap(m_ptr)); } 61 64 62 65 ALWAYS_INLINE RefPtr(RefPtr&& o) : m_ptr(o.leakRef()) { } 63 template<typename X, typename Y > RefPtr(RefPtr<X, Y>&& o) : m_ptr(o.leakRef()) { }66 template<typename X, typename Y, typename Z> RefPtr(RefPtr<X, Y, Z>&& o) : m_ptr(o.leakRef()) { } 64 67 template<typename X, typename Y> RefPtr(Ref<X, Y>&&); 65 68 … … 68 71 bool isHashTableDeletedValue() const { return PtrTraits::isHashTableDeletedValue(m_ptr); } 69 72 70 ALWAYS_INLINE ~RefPtr() { derefIfNotNull(PtrTraits::exchange(m_ptr, nullptr)); }73 ALWAYS_INLINE ~RefPtr() { RefDerefTraits::derefIfNotNull(PtrTraits::exchange(m_ptr, nullptr)); } 71 74 72 75 T* get() const { return PtrTraits::unwrap(m_ptr); } … … 91 94 RefPtr& operator=(T*); 92 95 RefPtr& operator=(std::nullptr_t); 93 template<typename X, typename Y > RefPtr& operator=(const RefPtr<X, Y>&);96 template<typename X, typename Y, typename Z> RefPtr& operator=(const RefPtr<X, Y, Z>&); 94 97 RefPtr& operator=(RefPtr&&); 95 template<typename X, typename Y > RefPtr& operator=(RefPtr<X, Y>&&);98 template<typename X, typename Y, typename Z> RefPtr& operator=(RefPtr<X, Y, Z>&&); 96 99 template<typename X> RefPtr& operator=(Ref<X>&&); 97 100 98 template<typename X, typename Y > void swap(RefPtr<X, Y>&);101 template<typename X, typename Y, typename Z> void swap(RefPtr<X, Y, Z>&); 99 102 100 103 RefPtr copyRef() && = delete; … … 104 107 void unspecifiedBoolTypeInstance() const { } 105 108 106 friend RefPtr adoptRef<T, PtrTraits >(T*);107 template<typename X, typename Y > friend class RefPtr;109 friend RefPtr adoptRef<T, PtrTraits, RefDerefTraits>(T*); 110 template<typename X, typename Y, typename Z> friend class RefPtr; 108 111 109 112 enum AdoptTag { Adopt }; … … 113 116 }; 114 117 115 template<typename T, typename U >118 template<typename T, typename U, typename V> 116 119 template<typename X, typename Y> 117 inline RefPtr<T, U >::RefPtr(Ref<X, Y>&& reference)120 inline RefPtr<T, U, V>::RefPtr(Ref<X, Y>&& reference) 118 121 : m_ptr(&reference.leakRef()) 119 122 { 120 123 } 121 124 122 template<typename T, typename U >123 inline T* RefPtr<T, U >::leakRef()125 template<typename T, typename U, typename V> 126 inline T* RefPtr<T, U, V>::leakRef() 124 127 { 125 128 return U::exchange(m_ptr, nullptr); 126 129 } 127 130 128 template<typename T, typename U >129 inline RefPtr<T, U >& RefPtr<T, U>::operator=(const RefPtr& o)131 template<typename T, typename U, typename V> 132 inline RefPtr<T, U, V>& RefPtr<T, U, V>::operator=(const RefPtr& o) 130 133 { 131 134 RefPtr ptr = o; … … 134 137 } 135 138 136 template<typename T, typename U >137 template<typename X, typename Y >138 inline RefPtr<T, U >& RefPtr<T, U>::operator=(const RefPtr<X, Y>& o)139 template<typename T, typename U, typename V> 140 template<typename X, typename Y, typename Z> 141 inline RefPtr<T, U, V>& RefPtr<T, U, V>::operator=(const RefPtr<X, Y, Z>& o) 139 142 { 140 143 RefPtr ptr = o; … … 143 146 } 144 147 145 template<typename T, typename U >146 inline RefPtr<T, U >& RefPtr<T, U>::operator=(T* optr)148 template<typename T, typename U, typename V> 149 inline RefPtr<T, U, V>& RefPtr<T, U, V>::operator=(T* optr) 147 150 { 148 151 RefPtr ptr = optr; … … 151 154 } 152 155 153 template<typename T, typename U >154 inline RefPtr<T, U >& RefPtr<T, U>::operator=(std::nullptr_t)155 { 156 derefIfNotNull(U::exchange(m_ptr, nullptr));157 return *this; 158 } 159 160 template<typename T, typename U >161 inline RefPtr<T, U >& RefPtr<T, U>::operator=(RefPtr&& o)156 template<typename T, typename U, typename V> 157 inline RefPtr<T, U, V>& RefPtr<T, U, V>::operator=(std::nullptr_t) 158 { 159 V::derefIfNotNull(U::exchange(m_ptr, nullptr)); 160 return *this; 161 } 162 163 template<typename T, typename U, typename V> 164 inline RefPtr<T, U, V>& RefPtr<T, U, V>::operator=(RefPtr&& o) 162 165 { 163 166 RefPtr ptr = WTFMove(o); … … 166 169 } 167 170 168 template<typename T, typename U >169 template<typename X, typename Y >170 inline RefPtr<T, U >& RefPtr<T, U>::operator=(RefPtr<X, Y>&& o)171 template<typename T, typename U, typename V> 172 template<typename X, typename Y, typename Z> 173 inline RefPtr<T, U, V>& RefPtr<T, U, V>::operator=(RefPtr<X, Y, Z>&& o) 171 174 { 172 175 RefPtr ptr = WTFMove(o); … … 175 178 } 176 179 177 template<typename T, typename V >180 template<typename T, typename V, typename W> 178 181 template<typename U> 179 inline RefPtr<T, V >& RefPtr<T, V>::operator=(Ref<U>&& reference)182 inline RefPtr<T, V, W>& RefPtr<T, V, W>::operator=(Ref<U>&& reference) 180 183 { 181 184 RefPtr ptr = WTFMove(reference); … … 184 187 } 185 188 186 template<class T, typename U >187 template<typename X, typename Y >188 inline void RefPtr<T, U >::swap(RefPtr<X, Y>& o)189 template<class T, typename U, typename V> 190 template<typename X, typename Y, typename Z> 191 inline void RefPtr<T, U, V>::swap(RefPtr<X, Y, Z>& o) 189 192 { 190 193 U::swap(m_ptr, o.m_ptr); 191 194 } 192 195 193 template<typename T, typename U, typename X, typename Y, typename = std::enable_if_t<!std::is_same<U, DumbPtrTraits<T>>::value || !std::is_same<Y, DumbPtrTraits<X>>::value>>194 inline void swap(RefPtr<T, U >& a, RefPtr<X, Y>& b)196 template<typename T, typename U, typename V, typename X, typename Y, typename Z, typename = std::enable_if_t<!std::is_same<U, DumbPtrTraits<T>>::value || !std::is_same<Y, DumbPtrTraits<X>>::value>> 197 inline void swap(RefPtr<T, U, V>& a, RefPtr<X, Y, Z>& b) 195 198 { 196 199 a.swap(b); 197 200 } 198 201 199 template<typename T, typename U, typename X, typename Y>200 inline bool operator==(const RefPtr<T, U >& a, const RefPtr<X, Y>& b)202 template<typename T, typename U, typename V, typename X, typename Y, typename Z> 203 inline bool operator==(const RefPtr<T, U, V>& a, const RefPtr<X, Y, Z>& b) 201 204 { 202 205 return a.get() == b.get(); 203 206 } 204 207 205 template<typename T, typename U, typename X>206 inline bool operator==(const RefPtr<T, U >& a, X* b)208 template<typename T, typename U, typename V, typename X> 209 inline bool operator==(const RefPtr<T, U, V>& a, X* b) 207 210 { 208 211 return a.get() == b; 209 212 } 210 213 211 template<typename T, typename X, typename Y >212 inline bool operator==(T* a, const RefPtr<X, Y >& b)214 template<typename T, typename X, typename Y, typename Z> 215 inline bool operator==(T* a, const RefPtr<X, Y, Z>& b) 213 216 { 214 217 return a == b.get(); 215 218 } 216 219 217 template<typename T, typename U, typename X, typename Y>218 inline bool operator!=(const RefPtr<T, U >& a, const RefPtr<X, Y>& b)220 template<typename T, typename U, typename V, typename X, typename Y, typename Z> 221 inline bool operator!=(const RefPtr<T, U, V>& a, const RefPtr<X, Y, Z>& b) 219 222 { 220 223 return a.get() != b.get(); 221 224 } 222 225 223 template<typename T, typename U, typename X>224 inline bool operator!=(const RefPtr<T, U >& a, X* b)226 template<typename T, typename U, typename V, typename X> 227 inline bool operator!=(const RefPtr<T, U, V>& a, X* b) 225 228 { 226 229 return a.get() != b; 227 230 } 228 231 229 template<typename T, typename X, typename Y >230 inline bool operator!=(T* a, const RefPtr<X, Y >& b)232 template<typename T, typename X, typename Y, typename Z> 233 inline bool operator!=(T* a, const RefPtr<X, Y, Z>& b) 231 234 { 232 235 return a != b.get(); 233 236 } 234 237 235 template<typename T, typename U = DumbPtrTraits<T>, typename X, typename Y>236 inline RefPtr<T, U > static_pointer_cast(const RefPtr<X, Y>& p)237 { 238 return RefPtr<T, U >(static_cast<T*>(p.get()));239 } 240 241 template <typename T, typename U >242 struct IsSmartPtr<RefPtr<T, U >> {238 template<typename T, typename U = DumbPtrTraits<T>, typename V = DefaultRefDerefTraits<T>, typename X, typename Y, typename Z> 239 inline RefPtr<T, U, V> static_pointer_cast(const RefPtr<X, Y, Z>& p) 240 { 241 return RefPtr<T, U, V>(static_cast<T*>(p.get())); 242 } 243 244 template <typename T, typename U, typename V> 245 struct IsSmartPtr<RefPtr<T, U, V>> { 243 246 static constexpr bool value = true; 244 247 }; 245 248 246 template<typename T, typename U >247 inline RefPtr<T, U > adoptRef(T* p)249 template<typename T, typename U, typename V> 250 inline RefPtr<T, U, V> adoptRef(T* p) 248 251 { 249 252 adopted(p); 250 return RefPtr<T, U >(p, RefPtr<T, U>::Adopt);253 return RefPtr<T, U, V>(p, RefPtr<T, U, V>::Adopt); 251 254 } 252 255 … … 261 264 } 262 265 263 template<typename ExpectedType, typename ArgType, typename PtrTraits >264 inline bool is(RefPtr<ArgType, PtrTraits >& source)266 template<typename ExpectedType, typename ArgType, typename PtrTraits, typename RefDerefTraits> 267 inline bool is(RefPtr<ArgType, PtrTraits, RefDerefTraits>& source) 265 268 { 266 269 return is<ExpectedType>(source.get()); 267 270 } 268 271 269 template<typename ExpectedType, typename ArgType, typename PtrTraits >270 inline bool is(const RefPtr<ArgType, PtrTraits >& source)272 template<typename ExpectedType, typename ArgType, typename PtrTraits, typename RefDerefTraits> 273 inline bool is(const RefPtr<ArgType, PtrTraits, RefDerefTraits>& source) 271 274 { 272 275 return is<ExpectedType>(source.get()); -
trunk/Source/WebCore/ChangeLog
r267590 r267591 1 2020-09-25 Chris Dumez <cdumez@apple.com> 2 3 Get rid of AudioNode::RefType 4 https://bugs.webkit.org/show_bug.cgi?id=216945 5 6 Reviewed by Darin Adler. 7 8 Previously, the node had ref()/deref() function taking a RefType parameter. 9 The RefType would be used to determine which counter should be incremented 10 or decremented: either m_normalRefCount or m_connectionRefCount. 11 12 In a previous patch, I have already ported code that was calling ref() / deref() 13 explicitly with RefTypeNormal to use RefPtr<> instead. This patch goes further by: 14 1. Dropping the RefType parameter to ref() / deref(). ref() / deref() now increment 15 or decrement m_normalRefCount only. Clients are expected to use RefPtr to handle 16 ref counting. 17 2. Introduce new incrementConnectionCount() / decrementConnectionCount() to increment 18 or decrement m_connectionRefCount. To reduce the chance of leakage, clients should 19 not call these functions directly anymore. Instead, they use use the new 20 AudioConnectionRefPtr<> pointer type to handle the connection ref counting for them. 21 AudioConnectionRefPtr<> is a RefPtr<> which special traits causing incrementConnectionCount() 22 and decrementConnectionCount() to get called on the AudioNode instead of ref() and 23 deref(). 24 25 I believe this new design is a bit simpler to reason about and less prone to leaks. 26 There is no longer any code explicitly ref'ing or deref'ing the AudioNodes. Instead, 27 RefPtr<> or AudioConnectionRefPtr<> is used to increment/decrement the right internal 28 count. 29 30 No new tests, no Web-facing behavior change. 31 32 * Modules/webaudio/AudioBufferSourceNode.cpp: 33 (WebCore::AudioBufferSourceNode::setPannerNode): 34 (WebCore::AudioBufferSourceNode::clearPannerNode): 35 * Modules/webaudio/AudioBufferSourceNode.h: 36 * Modules/webaudio/AudioNode.cpp: 37 (WebCore::AudioNode::disableOutputsIfNecessary): 38 (WebCore::AudioNode::incrementConnectionCount): 39 (WebCore::AudioNode::decrementConnectionCount): 40 (WebCore::AudioNode::decrementConnectionCountWithLock): 41 (WebCore::AudioNode::markNodeForDeletionIfNecessary): 42 (WebCore::AudioNode::ref): 43 (WebCore::AudioNode::deref): 44 (WebCore::AudioNode::derefWithLock): 45 * Modules/webaudio/AudioNode.h: 46 (WebCore::AudioNodeConnectionRefDerefTraits::refIfNotNull): 47 (WebCore::AudioNodeConnectionRefDerefTraits::derefIfNotNull): 48 * Modules/webaudio/AudioNodeInput.cpp: 49 (WebCore::AudioNodeInput::connect): 50 (WebCore::AudioNodeInput::disconnect): 51 * Modules/webaudio/AudioNodeOutput.cpp: 52 (WebCore::AudioNodeOutput::propagateChannelCount): 53 (WebCore::AudioNodeOutput::addInput): 54 (WebCore::AudioNodeOutput::disconnectAllInputs): 55 (WebCore::AudioNodeOutput::disable): 56 (WebCore::AudioNodeOutput::enable): 57 * Modules/webaudio/AudioNodeOutput.h: 58 * Modules/webaudio/BaseAudioContext.cpp: 59 (WebCore::BaseAudioContext::~BaseAudioContext): 60 (WebCore::BaseAudioContext::refNode): 61 (WebCore::BaseAudioContext::derefNode): 62 (WebCore::BaseAudioContext::derefUnfinishedSourceNodes): 63 (WebCore::BaseAudioContext::addDeferredDecrementConnectionCount): 64 (WebCore::BaseAudioContext::handlePostRenderTasks): 65 (WebCore::BaseAudioContext::handleDeferredDecrementConnectionCounts): 66 * Modules/webaudio/BaseAudioContext.h: 67 * Modules/webaudio/ScriptProcessorNode.cpp: 68 (WebCore::ScriptProcessorNode::process): 69 1 70 2020-09-25 Rob Buis <rbuis@igalia.com> 2 71 -
trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp
r267544 r267591 581 581 void AudioBufferSourceNode::setPannerNode(PannerNodeBase* pannerNode) 582 582 { 583 if (m_pannerNode != pannerNode && !hasFinished()) { 584 if (pannerNode) 585 pannerNode->ref(AudioNode::RefTypeConnection); 586 if (m_pannerNode) 587 m_pannerNode->deref(AudioNode::RefTypeConnection); 588 583 if (m_pannerNode != pannerNode && !hasFinished()) 589 584 m_pannerNode = pannerNode; 590 }591 585 } 592 586 593 587 void AudioBufferSourceNode::clearPannerNode() 594 588 { 595 if (m_pannerNode) { 596 m_pannerNode->deref(AudioNode::RefTypeConnection); 597 m_pannerNode = nullptr; 598 } 589 m_pannerNode = nullptr; 599 590 } 600 591 -
trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.h
r267537 r267591 142 142 143 143 // We optionally keep track of a panner node which has a doppler shift that is incorporated into 144 // the pitch rate. We manually manage ref-counting because we want to use RefTypeConnection.145 PannerNodeBase* m_pannerNode { nullptr };144 // the pitch rate. 145 AudioConnectionRefPtr<PannerNodeBase> m_pannerNode; 146 146 147 147 // This synchronizes process() with setBuffer() which can cause dynamic channel count changes. -
trunk/Source/WebCore/Modules/webaudio/AudioNode.cpp
r267543 r267591 549 549 { 550 550 // Disable outputs if appropriate. We do this if the number of connections is 0 or 1. The case 551 // of 0 is from finishDeref() where there are no connections left. The case of 1 is from551 // of 0 is from decrementConnectionCountWithLock() where there are no connections left. The case of 1 is from 552 552 // AudioNodeInput::disable() where we want to disable outputs when there's only one connection 553 553 // left because we're ready to go away, but can't quite yet. … … 575 575 } 576 576 577 void AudioNode::ref(RefType refType) 578 { 579 switch (refType) { 580 case RefTypeNormal: 581 ++m_normalRefCount; 582 break; 583 case RefTypeConnection: 584 ++m_connectionRefCount; 585 break; 586 default: 587 ASSERT_NOT_REACHED(); 588 } 589 590 #if DEBUG_AUDIONODE_REFERENCES 591 fprintf(stderr, "%p: %d: AudioNode::ref(%d) %d %d\n", this, nodeType(), refType, m_normalRefCount, m_connectionRefCount); 592 #endif 593 594 // See the disabling code in finishDeref() below. This handles the case where a node 577 void AudioNode::incrementConnectionCount() 578 { 579 ++m_connectionRefCount; 580 581 // See the disabling code in decrementConnectionCountWithLock() below. This handles the case where a node 595 582 // is being re-connected after being used at least once and disconnected. 596 583 // In this case, we need to re-enable. 597 if (refType == RefTypeConnection) 598 enableOutputsIfNecessary(); 599 } 600 601 void AudioNode::deref(RefType refType) 584 enableOutputsIfNecessary(); 585 586 #if DEBUG_AUDIONODE_REFERENCES 587 fprintf(stderr, "%p: %d: AudioNode::incrementConnectionCount() %d %d\n", this, nodeType(), m_normalRefCount, m_connectionRefCount); 588 #endif 589 } 590 591 void AudioNode::decrementConnectionCount() 602 592 { 603 593 // The actually work for deref happens completely within the audio context's graph lock. … … 616 606 if (hasLock) { 617 607 // This is where the real deref work happens. 618 finishDeref(refType);608 decrementConnectionCountWithLock(); 619 609 620 610 if (mustReleaseLock) … … 623 613 // We were unable to get the lock, so put this in a list to finish up later. 624 614 ASSERT(context().isAudioThread()); 625 ASSERT(refType == RefTypeConnection); 626 context().addDeferredFinishDeref(this); 615 context().addDeferredDecrementConnectionCount(this); 627 616 } 628 617 … … 634 623 } 635 624 625 void AudioNode::decrementConnectionCountWithLock() 626 { 627 ASSERT(context().isGraphOwner()); 628 629 ASSERT(m_connectionRefCount > 0); 630 --m_connectionRefCount; 631 632 #if DEBUG_AUDIONODE_REFERENCES 633 fprintf(stderr, "%p: %d: AudioNode::decrementConnectionCountWithLock() %d %d\n", this, nodeType(), m_normalRefCount, m_connectionRefCount); 634 #endif 635 636 if (!m_connectionRefCount && m_normalRefCount) 637 disableOutputsIfNecessary(); 638 639 markNodeForDeletionIfNecessary(); 640 } 641 642 void AudioNode::markNodeForDeletionIfNecessary() 643 { 644 ASSERT(context().isGraphOwner()); 645 646 if (m_connectionRefCount || m_normalRefCount || m_isMarkedForDeletion) 647 return; 648 649 // All references are gone - we need to go away. 650 for (auto& output : m_outputs) 651 output->disconnectAll(); // This will deref() nodes we're connected to. 652 653 // Mark for deletion at end of each render quantum or when context shuts down. 654 context().markForDeletion(*this); 655 m_isMarkedForDeletion = true; 656 didBecomeMarkedForDeletion(); 657 } 658 659 void AudioNode::ref() 660 { 661 ++m_normalRefCount; 662 663 #if DEBUG_AUDIONODE_REFERENCES 664 fprintf(stderr, "%p: %d: AudioNode::ref() %d %d\n", this, nodeType(), m_normalRefCount, m_connectionRefCount); 665 #endif 666 } 667 668 void AudioNode::deref() 669 { 670 ASSERT(!context().isAudioThread()); 671 672 { 673 BaseAudioContext::AutoLocker locker(context()); 674 // This is where the real deref work happens. 675 derefWithLock(); 676 } 677 678 // Once AudioContext::uninitialize() is called there's no more chances for deleteMarkedNodes() to get called, so we call here. 679 // We can't call in AudioContext::~AudioContext() since it will never be called as long as any AudioNode is alive 680 // because AudioNodes keep a reference to the context. 681 if (context().isAudioThreadFinished()) 682 context().deleteMarkedNodes(); 683 } 684 636 685 Variant<RefPtr<BaseAudioContext>, RefPtr<WebKitAudioContext>> AudioNode::contextForBindings() const 637 686 { … … 641 690 } 642 691 643 void AudioNode:: finishDeref(RefType refType)692 void AudioNode::derefWithLock() 644 693 { 645 694 ASSERT(context().isGraphOwner()); 646 695 647 switch (refType) { 648 case RefTypeNormal: 649 ASSERT(m_normalRefCount > 0); 650 --m_normalRefCount; 651 break; 652 case RefTypeConnection: 653 ASSERT(m_connectionRefCount > 0); 654 --m_connectionRefCount; 655 break; 656 default: 657 ASSERT_NOT_REACHED(); 658 } 696 ASSERT(m_normalRefCount > 0); 697 --m_normalRefCount; 659 698 660 699 #if DEBUG_AUDIONODE_REFERENCES 661 fprintf(stderr, "%p: %d: AudioNode::deref(%d) %d %d\n", this, nodeType(), refType, m_normalRefCount, m_connectionRefCount); 662 #endif 663 664 if (!m_connectionRefCount) { 665 if (!m_normalRefCount) { 666 if (!m_isMarkedForDeletion) { 667 // All references are gone - we need to go away. 668 for (auto& output : m_outputs) 669 output->disconnectAll(); // This will deref() nodes we're connected to. 670 671 // Mark for deletion at end of each render quantum or when context shuts down. 672 context().markForDeletion(*this); 673 m_isMarkedForDeletion = true; 674 didBecomeMarkedForDeletion(); 675 } 676 } else if (refType == RefTypeConnection) 677 disableOutputsIfNecessary(); 678 } 700 fprintf(stderr, "%p: %d: AudioNode::deref() %d %d\n", this, nodeType(), m_normalRefCount, m_connectionRefCount); 701 #endif 702 703 markNodeForDeletionIfNecessary(); 679 704 } 680 705 -
trunk/Source/WebCore/Modules/webaudio/AudioNode.h
r267543 r267591 97 97 void setNodeType(NodeType); 98 98 99 // We handle our own ref-counting because of the threading issues and subtle nature of100 // how AudioNodes can continue processing (playing one-shot sound) after there are no more101 // JavaScript references to the object.102 enum RefType { RefTypeNormal, RefTypeConnection };103 104 99 // Can be called from main thread or context's audio thread. 105 void ref(RefType refType = RefTypeNormal); 106 void deref(RefType refType = RefTypeNormal); 100 void ref(); 101 void deref(); 102 void incrementConnectionCount(); 103 void decrementConnectionCount(); 107 104 108 105 // Can be called from main thread or context's audio thread. It must be called while the context's graph lock is held. 109 void finishDeref(RefType refType);106 void decrementConnectionCountWithLock(); 110 107 virtual void didBecomeMarkedForDeletion() { } 111 108 … … 203 200 void addOutput(unsigned numberOfChannels); 204 201 202 void markNodeForDeletionIfNecessary(); 203 void derefWithLock(); 204 205 205 struct DefaultAudioNodeOptions { 206 206 unsigned channelCount; … … 271 271 }; 272 272 273 template<typename T> struct AudioNodeConnectionRefDerefTraits { 274 static ALWAYS_INLINE void refIfNotNull(T* ptr) 275 { 276 if (LIKELY(ptr != nullptr)) 277 ptr->incrementConnectionCount(); 278 } 279 280 static ALWAYS_INLINE void derefIfNotNull(T* ptr) 281 { 282 if (LIKELY(ptr != nullptr)) 283 ptr->decrementConnectionCount(); 284 } 285 }; 286 287 template<typename T> 288 using AudioConnectionRefPtr = RefPtr<T, DumbPtrTraits<T>, AudioNodeConnectionRefDerefTraits<T>>; 289 273 290 String convertEnumerationToString(AudioNode::NodeType); 274 291 -
trunk/Source/WebCore/Modules/webaudio/AudioNodeInput.cpp
r267560 r267591 61 61 output->addInput(this); 62 62 changedOutputs(); 63 64 // Sombody has just connected to us, so count it as a reference.65 node()->ref(AudioNode::RefTypeConnection);66 63 } 67 64 … … 77 74 if (m_outputs.remove(output)) { 78 75 changedOutputs(); 79 output->removeInput(this); 80 node()->deref(AudioNode::RefTypeConnection); // Note: it's important to return immediately after all deref() calls since the node may be deleted. 76 output->removeInput(this); // Note: it's important to return immediately after this since the node may be deleted. 81 77 return; 82 78 } … … 84 80 // Otherwise, try to disconnect from disabled connections. 85 81 if (m_disabledOutputs.remove(output)) { 86 output->removeInput(this); 87 node()->deref(AudioNode::RefTypeConnection); // Note: it's important to return immediately after all deref() calls since the node may be deleted. 82 output->removeInput(this); // Note: it's important to return immediately after this since the node may be deleted. 88 83 return; 89 84 } -
trunk/Source/WebCore/Modules/webaudio/AudioNodeOutput.cpp
r267560 r267591 96 96 if (isChannelCountKnown()) { 97 97 // Announce to any nodes we're connected to that we changed our channel count for its input. 98 for (auto& input : m_inputs ) {98 for (auto& input : m_inputs.keys()) { 99 99 AudioNode* connectionNode = input->node(); 100 100 connectionNode->checkNumberOfChannelsForInput(input); … … 158 158 return; 159 159 160 m_inputs.add(input );160 m_inputs.add(input, input->node()); 161 161 } 162 162 … … 178 178 // AudioNodeInput::disconnect() changes m_inputs by calling removeInput(). 179 179 while (!m_inputs.isEmpty()) { 180 AudioNodeInput* input = *m_inputs.begin();180 AudioNodeInput* input = m_inputs.begin()->key; 181 181 input->disconnect(this); 182 182 } … … 227 227 228 228 if (m_isEnabled) { 229 for (auto& input : m_inputs )229 for (auto& input : m_inputs.keys()) 230 230 input->disable(this); 231 231 m_isEnabled = false; … … 238 238 239 239 if (!m_isEnabled) { 240 for (auto& input : m_inputs )240 for (auto& input : m_inputs.keys()) 241 241 input->enable(this); 242 242 m_isEnabled = true; -
trunk/Source/WebCore/Modules/webaudio/AudioNodeOutput.h
r267544 r267591 141 141 bool m_isInPlace { false }; 142 142 143 HashSet<AudioNodeInput*> m_inputs; 144 typedef HashSet<AudioNodeInput*>::iterator InputsIterator; 143 using InputsMap = HashMap<AudioNodeInput*, AudioConnectionRefPtr<AudioNode>>; 144 InputsMap m_inputs; 145 typedef InputsMap::iterator InputsIterator; 145 146 bool m_isEnabled { true }; 146 147 -
trunk/Source/WebCore/Modules/webaudio/BaseAudioContext.cpp
r267505 r267591 198 198 m_renderingAutomaticPullNodes.resize(m_automaticPullNodes.size()); 199 199 ASSERT(m_renderingAutomaticPullNodes.isEmpty()); 200 // FIXME: Can we assert that m_deferred FinishDerefList is empty?200 // FIXME: Can we assert that m_deferredBreakConnectionList is empty? 201 201 202 202 if (!isOfflineContext() && scriptExecutionContext()) { … … 682 682 AutoLocker locker(*this); 683 683 684 node.ref(AudioNode::RefTypeConnection);685 684 m_referencedNodes.append(&node); 686 685 } … … 690 689 ASSERT(isGraphOwner()); 691 690 692 node.deref(AudioNode::RefTypeConnection);693 694 691 ASSERT(m_referencedNodes.contains(&node)); 695 692 m_referencedNodes.removeFirst(&node); … … 699 696 { 700 697 ASSERT(isMainThread() && isAudioThreadFinished()); 701 for (auto& node : m_referencedNodes)702 node->deref(AudioNode::RefTypeConnection);703 704 698 m_referencedNodes.clear(); 705 699 } … … 779 773 } 780 774 781 void BaseAudioContext::addDeferred FinishDeref(AudioNode* node)775 void BaseAudioContext::addDeferredDecrementConnectionCount(AudioNode* node) 782 776 { 783 777 ASSERT(isAudioThread()); 784 m_deferred FinishDerefList.append(node);778 m_deferredBreakConnectionList.append(node); 785 779 } 786 780 … … 822 816 if (tryLock(mustReleaseLock)) { 823 817 // Take care of finishing any derefs where the tryLock() failed previously. 824 handleDeferred FinishDerefs();818 handleDeferredDecrementConnectionCounts(); 825 819 826 820 // Dynamically clean up nodes which are no longer needed. … … 842 836 } 843 837 844 void BaseAudioContext::handleDeferred FinishDerefs()838 void BaseAudioContext::handleDeferredDecrementConnectionCounts() 845 839 { 846 840 ASSERT(isAudioThread() && isGraphOwner()); 847 for (auto& node : m_deferred FinishDerefList)848 node-> finishDeref(AudioNode::RefTypeConnection);849 850 m_deferred FinishDerefList.clear();841 for (auto& node : m_deferredBreakConnectionList) 842 node->decrementConnectionCountWithLock(); 843 844 m_deferredBreakConnectionList.clear(); 851 845 } 852 846 -
trunk/Source/WebCore/Modules/webaudio/BaseAudioContext.h
r267147 r267591 230 230 static unsigned maxNumberOfChannels() { return MaxNumberOfChannels; } 231 231 232 // In AudioNode::de ref() a tryLock() is used for calling finishDeref(), but if it fails keep track here.233 void addDeferred FinishDeref(AudioNode*);234 235 // In the audio thread at the start of each render cycle, we'll call handleDeferred FinishDerefs().236 void handleDeferred FinishDerefs();232 // In AudioNode::decrementConnectionCount() a tryLock() is used for calling decrementConnectionCountWithLock(), but if it fails keep track here. 233 void addDeferredDecrementConnectionCount(AudioNode*); 234 235 // In the audio thread at the start of each render cycle, we'll call handleDeferredDecrementConnectionCounts(). 236 void handleDeferredDecrementConnectionCounts(); 237 237 238 238 // Only accessed when the graph lock is held. … … 398 398 Vector<AudioNode*> m_finishedNodes; 399 399 400 // We don't use RefPtr<AudioNode> here because AudioNode has a more complex ref() / deref() implementation401 // with an optional argument for refType. We need to use the special refType: RefTypeConnection402 400 // Either accessed when the graph lock is held, or on the main thread when the audio thread has finished. 403 Vector<Audio Node*> m_referencedNodes;401 Vector<AudioConnectionRefPtr<AudioNode>> m_referencedNodes; 404 402 405 403 // Accumulate nodes which need to be deleted here. … … 428 426 Vector<AudioNode*> m_renderingAutomaticPullNodes; 429 427 // Only accessed in the audio thread. 430 Vector<AudioNode*> m_deferred FinishDerefList;428 Vector<AudioNode*> m_deferredBreakConnectionList; 431 429 Vector<Vector<DOMPromiseDeferred<void>>> m_stateReactions; 432 430 -
trunk/Source/WebCore/Modules/webaudio/ScriptProcessorNode.cpp
r267544 r267591 184 184 if (!m_bufferReadWriteIndex) { 185 185 // Reference ourself so we don't accidentally get deleted before fireProcessEvent() gets called. 186 auto protector = makeRef(*this);187 188 186 // We only wait for script code execution when the context is an offline one for performance reasons. 189 187 if (context().isOfflineContext()) { 190 188 BinarySemaphore semaphore; 191 callOnMainThread([this, &semaphore, doubleBufferIndex = m_doubleBufferIndex ] {189 callOnMainThread([this, &semaphore, doubleBufferIndex = m_doubleBufferIndex, protector = makeRef(*this)] { 192 190 fireProcessEvent(doubleBufferIndex); 193 191 semaphore.signal(); … … 203 201 } 204 202 205 callOnMainThread([this, doubleBufferIndex = m_doubleBufferIndex, protector = WTFMove(protector)] {203 callOnMainThread([this, doubleBufferIndex = m_doubleBufferIndex, protector = makeRef(*this)] { 206 204 auto locker = holdLock(m_processLock); 207 205 fireProcessEvent(doubleBufferIndex); -
trunk/Source/WebCore/platform/graphics/cairo/RefPtrCairo.cpp
r237847 r267591 26 26 namespace WTF { 27 27 28 template<> voidrefIfNotNull(cairo_t* ptr)28 void DefaultRefDerefTraits<cairo_t>::refIfNotNull(cairo_t* ptr) 29 29 { 30 30 if (LIKELY(ptr)) … … 32 32 } 33 33 34 template<> voidderefIfNotNull(cairo_t* ptr)34 void DefaultRefDerefTraits<cairo_t>::derefIfNotNull(cairo_t* ptr) 35 35 { 36 36 if (LIKELY(ptr)) … … 38 38 } 39 39 40 template<> voidrefIfNotNull(cairo_surface_t* ptr)40 void DefaultRefDerefTraits<cairo_surface_t>::refIfNotNull(cairo_surface_t* ptr) 41 41 { 42 42 if (LIKELY(ptr)) … … 44 44 } 45 45 46 template<> voidderefIfNotNull(cairo_surface_t* ptr)46 void DefaultRefDerefTraits<cairo_surface_t>::derefIfNotNull(cairo_surface_t* ptr) 47 47 { 48 48 if (LIKELY(ptr)) … … 50 50 } 51 51 52 template<> voidrefIfNotNull(cairo_font_face_t* ptr)52 void DefaultRefDerefTraits<cairo_font_face_t>::refIfNotNull(cairo_font_face_t* ptr) 53 53 { 54 54 if (LIKELY(ptr)) … … 56 56 } 57 57 58 template<> voidderefIfNotNull(cairo_font_face_t* ptr)58 void DefaultRefDerefTraits<cairo_font_face_t>::derefIfNotNull(cairo_font_face_t* ptr) 59 59 { 60 60 if (LIKELY(ptr)) … … 62 62 } 63 63 64 template<> voidrefIfNotNull(cairo_scaled_font_t* ptr)64 void DefaultRefDerefTraits<cairo_scaled_font_t>::refIfNotNull(cairo_scaled_font_t* ptr) 65 65 { 66 66 if (LIKELY(ptr)) … … 68 68 } 69 69 70 template<> voidderefIfNotNull(cairo_scaled_font_t* ptr)70 void DefaultRefDerefTraits<cairo_scaled_font_t>::derefIfNotNull(cairo_scaled_font_t* ptr) 71 71 { 72 72 if (LIKELY(ptr)) … … 74 74 } 75 75 76 template<> voidrefIfNotNull(cairo_pattern_t* ptr)76 void DefaultRefDerefTraits<cairo_pattern_t>::refIfNotNull(cairo_pattern_t* ptr) 77 77 { 78 78 if (LIKELY(ptr)) … … 80 80 } 81 81 82 template<> voidderefIfNotNull(cairo_pattern_t* ptr)82 void DefaultRefDerefTraits<cairo_pattern_t>::derefIfNotNull(cairo_pattern_t* ptr) 83 83 { 84 84 if (LIKELY(ptr)) … … 86 86 } 87 87 88 template<> voidrefIfNotNull(cairo_region_t* ptr)88 void DefaultRefDerefTraits<cairo_region_t>::refIfNotNull(cairo_region_t* ptr) 89 89 { 90 90 if (LIKELY(ptr)) … … 92 92 } 93 93 94 template<> voidderefIfNotNull(cairo_region_t* ptr)94 void DefaultRefDerefTraits<cairo_region_t>::derefIfNotNull(cairo_region_t* ptr) 95 95 { 96 96 if (LIKELY(ptr)) -
trunk/Source/WebCore/platform/graphics/cairo/RefPtrCairo.h
r261014 r267591 34 34 namespace WTF { 35 35 36 template<> void refIfNotNull(cairo_t* ptr); 37 template<> WEBCORE_EXPORT void derefIfNotNull(cairo_t* ptr); 36 template<> 37 struct DefaultRefDerefTraits<cairo_t> { 38 static void refIfNotNull(cairo_t* ptr); 39 WEBCORE_EXPORT static void derefIfNotNull(cairo_t* ptr); 40 }; 38 41 39 template<> WEBCORE_EXPORT void refIfNotNull(cairo_surface_t* ptr); 40 template<> WEBCORE_EXPORT void derefIfNotNull(cairo_surface_t* ptr); 42 template<> 43 struct DefaultRefDerefTraits<cairo_surface_t> { 44 WEBCORE_EXPORT static void refIfNotNull(cairo_surface_t* ptr); 45 WEBCORE_EXPORT static void derefIfNotNull(cairo_surface_t* ptr); 46 }; 41 47 42 template<> void refIfNotNull(cairo_font_face_t* ptr); 43 template<> void derefIfNotNull(cairo_font_face_t* ptr); 48 template<> 49 struct DefaultRefDerefTraits<cairo_font_face_t> { 50 static void refIfNotNull(cairo_font_face_t* ptr); 51 static void derefIfNotNull(cairo_font_face_t* ptr); 52 }; 44 53 45 template<> void refIfNotNull(cairo_scaled_font_t* ptr); 46 template<> void derefIfNotNull(cairo_scaled_font_t* ptr); 54 template<> 55 struct DefaultRefDerefTraits<cairo_scaled_font_t> { 56 static void refIfNotNull(cairo_scaled_font_t* ptr); 57 static void derefIfNotNull(cairo_scaled_font_t* ptr); 58 }; 47 59 48 template<> void refIfNotNull(cairo_pattern_t*); 49 template<> void derefIfNotNull(cairo_pattern_t*); 60 template<> 61 struct DefaultRefDerefTraits<cairo_pattern_t> { 62 static void refIfNotNull(cairo_pattern_t*); 63 static void derefIfNotNull(cairo_pattern_t*); 64 }; 50 65 51 template<> void refIfNotNull(cairo_region_t*); 52 template<> void derefIfNotNull(cairo_region_t*); 66 template<> 67 struct DefaultRefDerefTraits<cairo_region_t> { 68 static void refIfNotNull(cairo_region_t*); 69 static void derefIfNotNull(cairo_region_t*); 70 }; 53 71 54 72 } // namespace WTF -
trunk/Source/WebCore/platform/graphics/freetype/RefPtrFontconfig.cpp
r237847 r267591 26 26 namespace WTF { 27 27 28 template<> voidrefIfNotNull(FcPattern* ptr)28 void DefaultRefDerefTraits<FcPattern>::refIfNotNull(FcPattern* ptr) 29 29 { 30 30 if (LIKELY(ptr)) … … 32 32 } 33 33 34 template<> voidderefIfNotNull(FcPattern* ptr)34 void DefaultRefDerefTraits<FcPattern>::derefIfNotNull(FcPattern* ptr) 35 35 { 36 36 if (LIKELY(ptr)) … … 38 38 } 39 39 40 template<> voidrefIfNotNull(FcConfig* ptr)40 void DefaultRefDerefTraits<FcConfig>::refIfNotNull(FcConfig* ptr) 41 41 { 42 42 if (LIKELY(ptr)) … … 44 44 } 45 45 46 template<> voidderefIfNotNull(FcConfig* ptr)46 void DefaultRefDerefTraits<FcConfig>::derefIfNotNull(FcConfig* ptr) 47 47 { 48 48 if (LIKELY(ptr)) -
trunk/Source/WebCore/platform/graphics/freetype/RefPtrFontconfig.h
r237847 r267591 29 29 namespace WTF { 30 30 31 template<> void refIfNotNull(FcPattern* ptr); 32 template<> void derefIfNotNull(FcPattern* ptr); 31 template<> 32 struct DefaultRefDerefTraits<FcPattern> { 33 static void refIfNotNull(FcPattern* ptr); 34 static void derefIfNotNull(FcPattern* ptr); 35 }; 33 36 34 template<> void refIfNotNull(FcConfig* ptr); 35 template<> void derefIfNotNull(FcConfig* ptr); 37 template<> 38 struct DefaultRefDerefTraits<FcConfig> { 39 static void refIfNotNull(FcConfig* ptr); 40 static void derefIfNotNull(FcConfig* ptr); 41 }; 36 42 37 43 } // namespace WTF
Note:
See TracChangeset
for help on using the changeset viewer.