⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 267591 in webkit


Ignore:
Timestamp:
Sep 25, 2020, 1:36:50 PM (6 years ago)
Author:
Chris Dumez
Message:

Get rid of AudioNode::RefType
https://bugs.webkit.org/show_bug.cgi?id=216945

Reviewed by Darin Adler.

Source/JavaScriptCore:

  • runtime/CachedTypes.cpp:

(JSC::CachedRefPtr::decode const):

Source/WebCore:

Previously, the node had ref()/deref() function taking a RefType parameter.
The RefType would be used to determine which counter should be incremented
or decremented: either m_normalRefCount or m_connectionRefCount.

In a previous patch, I have already ported code that was calling ref() / deref()
explicitly with RefTypeNormal to use RefPtr<> instead. This patch goes further by:

  1. Dropping the RefType parameter to ref() / deref(). ref() / deref() now increment or decrement m_normalRefCount only. Clients are expected to use RefPtr to handle ref counting.
  2. Introduce new incrementConnectionCount() / decrementConnectionCount() to increment or decrement m_connectionRefCount. To reduce the chance of leakage, clients should not call these functions directly anymore. Instead, they use use the new AudioConnectionRefPtr<> pointer type to handle the connection ref counting for them. AudioConnectionRefPtr<> is a RefPtr<> which special traits causing incrementConnectionCount() and decrementConnectionCount() to get called on the AudioNode instead of ref() and deref().

I believe this new design is a bit simpler to reason about and less prone to leaks.
There is no longer any code explicitly ref'ing or deref'ing the AudioNodes. Instead,
RefPtr<> or AudioConnectionRefPtr<> is used to increment/decrement the right internal
count.

No new tests, no Web-facing behavior change.

  • Modules/webaudio/AudioBufferSourceNode.cpp:

(WebCore::AudioBufferSourceNode::setPannerNode):
(WebCore::AudioBufferSourceNode::clearPannerNode):

  • Modules/webaudio/AudioBufferSourceNode.h:
  • Modules/webaudio/AudioNode.cpp:

(WebCore::AudioNode::disableOutputsIfNecessary):
(WebCore::AudioNode::incrementConnectionCount):
(WebCore::AudioNode::decrementConnectionCount):
(WebCore::AudioNode::decrementConnectionCountWithLock):
(WebCore::AudioNode::markNodeForDeletionIfNecessary):
(WebCore::AudioNode::ref):
(WebCore::AudioNode::deref):
(WebCore::AudioNode::derefWithLock):

  • Modules/webaudio/AudioNode.h:

(WebCore::AudioNodeConnectionRefDerefTraits::refIfNotNull):
(WebCore::AudioNodeConnectionRefDerefTraits::derefIfNotNull):

  • Modules/webaudio/AudioNodeInput.cpp:

(WebCore::AudioNodeInput::connect):
(WebCore::AudioNodeInput::disconnect):

  • Modules/webaudio/AudioNodeOutput.cpp:

(WebCore::AudioNodeOutput::propagateChannelCount):
(WebCore::AudioNodeOutput::addInput):
(WebCore::AudioNodeOutput::disconnectAllInputs):
(WebCore::AudioNodeOutput::disable):
(WebCore::AudioNodeOutput::enable):

  • Modules/webaudio/AudioNodeOutput.h:
  • Modules/webaudio/BaseAudioContext.cpp:

(WebCore::BaseAudioContext::~BaseAudioContext):
(WebCore::BaseAudioContext::refNode):
(WebCore::BaseAudioContext::derefNode):
(WebCore::BaseAudioContext::derefUnfinishedSourceNodes):
(WebCore::BaseAudioContext::addDeferredDecrementConnectionCount):
(WebCore::BaseAudioContext::handlePostRenderTasks):
(WebCore::BaseAudioContext::handleDeferredDecrementConnectionCounts):

  • Modules/webaudio/BaseAudioContext.h:
  • Modules/webaudio/ScriptProcessorNode.cpp:

(WebCore::ScriptProcessorNode::process):

Source/WTF:

Add third template parameter to RefPtr allowing to define the traits
from incrementing / decrementing the refcount. The default traits
call ref() / deref() but this can now be customized to call other
functions.

  • wtf/CompactRefPtrTuple.h:
  • wtf/Forward.h:
  • wtf/RefPtr.h:

(WTF::DefaultRefDerefTraits::refIfNotNull):
(WTF::DefaultRefDerefTraits::derefIfNotNull):
(WTF::RefPtr::RefPtr):
(WTF::RefPtr::~RefPtr):
(WTF::V>::RefPtr):
(WTF::V>::leakRef):
(WTF::=):
(WTF::V>::swap):
(WTF::swap):
(WTF::operator==):
(WTF::operator!=):
(WTF::static_pointer_cast):
(WTF::adoptRef):
(WTF::is):

Location:
trunk/Source
Files:
21 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r267564 r267591  
     12020-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
    1112020-09-25  Alexey Shvayka  <shvaikalesh@gmail.com>
    212
  • trunk/Source/JavaScriptCore/runtime/CachedTypes.cpp

    r264488 r267591  
    555555        if (isNewAllocation) {
    556556            decoder.addFinalizer([=] {
    557                 derefIfNotNull(decodedPtr);
     557                WTF::DefaultRefDerefTraits<Source>::derefIfNotNull(decodedPtr);
    558558            });
    559559        }
    560         refIfNotNull(decodedPtr);
     560        WTF::DefaultRefDerefTraits<Source>::refIfNotNull(decodedPtr);
    561561        return adoptRef(decodedPtr);
    562562    }
  • trunk/Source/WTF/ChangeLog

    r267562 r267591  
     12020-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
    1312020-09-25  Antti Koivisto  <antti@apple.com>
    232
  • trunk/Source/WTF/wtf/CompactRefPtrTuple.h

    r257295 r267591  
    4040    ~CompactRefPtrTuple()
    4141    {
    42         derefIfNotNull(m_data.pointer());
     42        WTF::DefaultRefDerefTraits<T>::derefIfNotNull(m_data.pointer());
    4343    }
    4444
     
    5050    void setPointer(T* pointer)
    5151    {
    52         refIfNotNull(pointer);
     52        WTF::DefaultRefDerefTraits<T>::refIfNotNull(pointer);
    5353        auto* old = m_data.pointer();
    5454        m_data.setPointer(pointer);
    55         derefIfNotNull(old);
     55        WTF::DefaultRefDerefTraits<T>::derefIfNotNull(old);
    5656    }
    5757
  • trunk/Source/WTF/wtf/Forward.h

    r264533 r267591  
    6060
    6161template<typename> struct DumbPtrTraits;
     62template<typename> struct DefaultRefDerefTraits;
    6263
    6364template<typename> class CompletionHandler;
     
    7071template<typename T, size_t = alignof(T)> class PackedAlignedPtr;
    7172template<typename T, typename = DumbPtrTraits<T>> class Ref;
    72 template<typename T, typename = DumbPtrTraits<T>> class RefPtr;
     73template<typename T, typename = DumbPtrTraits<T>, typename = DefaultRefDerefTraits<T>> class RefPtr;
    7374template<typename> class StringBuffer;
    7475template<typename> class StringParsingBuffer;
  • trunk/Source/WTF/wtf/RefPtr.h

    r254881 r267591  
    3030namespace WTF {
    3131
    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>
     32template<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
     46template<typename T, typename PtrTraits, typename RefDerefTraits> class RefPtr;
     47template<typename T, typename PtrTraits = DumbPtrTraits<T>, typename RefDerefTraits = DefaultRefDerefTraits<T>> RefPtr<T, PtrTraits, RefDerefTraits> adoptRef(T*);
     48
     49template<typename T, typename _PtrTraits, typename _RefDerefTraits>
    4850class RefPtr {
    4951    WTF_MAKE_FAST_ALLOCATED;
    5052public:
    51     using PtrTraits = Traits;
     53    using PtrTraits = _PtrTraits;
     54    using RefDerefTraits = _RefDerefTraits;
    5255    typedef T ValueType;
    5356    typedef ValueType* PtrType;
     
    5659
    5760    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)); }
    6164
    6265    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()) { }
    6467    template<typename X, typename Y> RefPtr(Ref<X, Y>&&);
    6568
     
    6871    bool isHashTableDeletedValue() const { return PtrTraits::isHashTableDeletedValue(m_ptr); }
    6972
    70     ALWAYS_INLINE ~RefPtr() { derefIfNotNull(PtrTraits::exchange(m_ptr, nullptr)); }
     73    ALWAYS_INLINE ~RefPtr() { RefDerefTraits::derefIfNotNull(PtrTraits::exchange(m_ptr, nullptr)); }
    7174
    7275    T* get() const { return PtrTraits::unwrap(m_ptr); }
     
    9194    RefPtr& operator=(T*);
    9295    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>&);
    9497    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>&&);
    9699    template<typename X> RefPtr& operator=(Ref<X>&&);
    97100
    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>&);
    99102
    100103    RefPtr copyRef() && = delete;
     
    104107    void unspecifiedBoolTypeInstance() const { }
    105108
    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;
    108111
    109112    enum AdoptTag { Adopt };
     
    113116};
    114117
    115 template<typename T, typename U>
     118template<typename T, typename U, typename V>
    116119template<typename X, typename Y>
    117 inline RefPtr<T, U>::RefPtr(Ref<X, Y>&& reference)
     120inline RefPtr<T, U, V>::RefPtr(Ref<X, Y>&& reference)
    118121    : m_ptr(&reference.leakRef())
    119122{
    120123}
    121124
    122 template<typename T, typename U>
    123 inline T* RefPtr<T, U>::leakRef()
     125template<typename T, typename U, typename V>
     126inline T* RefPtr<T, U, V>::leakRef()
    124127{
    125128    return U::exchange(m_ptr, nullptr);
    126129}
    127130
    128 template<typename T, typename U>
    129 inline RefPtr<T, U>& RefPtr<T, U>::operator=(const RefPtr& o)
     131template<typename T, typename U, typename V>
     132inline RefPtr<T, U, V>& RefPtr<T, U, V>::operator=(const RefPtr& o)
    130133{
    131134    RefPtr ptr = o;
     
    134137}
    135138
    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)
     139template<typename T, typename U, typename V>
     140template<typename X, typename Y, typename Z>
     141inline RefPtr<T, U, V>& RefPtr<T, U, V>::operator=(const RefPtr<X, Y, Z>& o)
    139142{
    140143    RefPtr ptr = o;
     
    143146}
    144147
    145 template<typename T, typename U>
    146 inline RefPtr<T, U>& RefPtr<T, U>::operator=(T* optr)
     148template<typename T, typename U, typename V>
     149inline RefPtr<T, U, V>& RefPtr<T, U, V>::operator=(T* optr)
    147150{
    148151    RefPtr ptr = optr;
     
    151154}
    152155
    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)
     156template<typename T, typename U, typename V>
     157inline 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
     163template<typename T, typename U, typename V>
     164inline RefPtr<T, U, V>& RefPtr<T, U, V>::operator=(RefPtr&& o)
    162165{
    163166    RefPtr ptr = WTFMove(o);
     
    166169}
    167170
    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)
     171template<typename T, typename U, typename V>
     172template<typename X, typename Y, typename Z>
     173inline RefPtr<T, U, V>& RefPtr<T, U, V>::operator=(RefPtr<X, Y, Z>&& o)
    171174{
    172175    RefPtr ptr = WTFMove(o);
     
    175178}
    176179
    177 template<typename T, typename V>
     180template<typename T, typename V, typename W>
    178181template<typename U>
    179 inline RefPtr<T, V>& RefPtr<T, V>::operator=(Ref<U>&& reference)
     182inline RefPtr<T, V, W>& RefPtr<T, V, W>::operator=(Ref<U>&& reference)
    180183{
    181184    RefPtr ptr = WTFMove(reference);
     
    184187}
    185188
    186 template<class T, typename U>
    187 template<typename X, typename Y>
    188 inline void RefPtr<T, U>::swap(RefPtr<X, Y>& o)
     189template<class T, typename U, typename V>
     190template<typename X, typename Y, typename Z>
     191inline void RefPtr<T, U, V>::swap(RefPtr<X, Y, Z>& o)
    189192{
    190193    U::swap(m_ptr, o.m_ptr);
    191194}
    192195
    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)
     196template<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>>
     197inline void swap(RefPtr<T, U, V>& a, RefPtr<X, Y, Z>& b)
    195198{
    196199    a.swap(b);
    197200}
    198201
    199 template<typename T, typename U, typename X, typename Y>
    200 inline bool operator==(const RefPtr<T, U>& a, const RefPtr<X, Y>& b)
     202template<typename T, typename U, typename V, typename X, typename Y, typename Z>
     203inline bool operator==(const RefPtr<T, U, V>& a, const RefPtr<X, Y, Z>& b)
    201204{
    202205    return a.get() == b.get();
    203206}
    204207
    205 template<typename T, typename U, typename X>
    206 inline bool operator==(const RefPtr<T, U>& a, X* b)
     208template<typename T, typename U, typename V, typename X>
     209inline bool operator==(const RefPtr<T, U, V>& a, X* b)
    207210{
    208211    return a.get() == b;
    209212}
    210213
    211 template<typename T, typename X, typename Y>
    212 inline bool operator==(T* a, const RefPtr<X, Y>& b)
     214template<typename T, typename X, typename Y, typename Z>
     215inline bool operator==(T* a, const RefPtr<X, Y, Z>& b)
    213216{
    214217    return a == b.get();
    215218}
    216219
    217 template<typename T, typename U, typename X, typename Y>
    218 inline bool operator!=(const RefPtr<T, U>& a, const RefPtr<X, Y>& b)
     220template<typename T, typename U, typename V, typename X, typename Y, typename Z>
     221inline bool operator!=(const RefPtr<T, U, V>& a, const RefPtr<X, Y, Z>& b)
    219222{
    220223    return a.get() != b.get();
    221224}
    222225
    223 template<typename T, typename U, typename X>
    224 inline bool operator!=(const RefPtr<T, U>& a, X* b)
     226template<typename T, typename U, typename V, typename X>
     227inline bool operator!=(const RefPtr<T, U, V>& a, X* b)
    225228{
    226229    return a.get() != b;
    227230}
    228231
    229 template<typename T, typename X, typename Y>
    230 inline bool operator!=(T* a, const RefPtr<X, Y>& b)
     232template<typename T, typename X, typename Y, typename Z>
     233inline bool operator!=(T* a, const RefPtr<X, Y, Z>& b)
    231234{
    232235    return a != b.get();
    233236}
    234237
    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>> {
     238template<typename T, typename U = DumbPtrTraits<T>, typename V = DefaultRefDerefTraits<T>, typename X, typename Y, typename Z>
     239inline 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
     244template <typename T, typename U, typename V>
     245struct IsSmartPtr<RefPtr<T, U, V>> {
    243246    static constexpr bool value = true;
    244247};
    245248
    246 template<typename T, typename U>
    247 inline RefPtr<T, U> adoptRef(T* p)
     249template<typename T, typename U, typename V>
     250inline RefPtr<T, U, V> adoptRef(T* p)
    248251{
    249252    adopted(p);
    250     return RefPtr<T, U>(p, RefPtr<T, U>::Adopt);
     253    return RefPtr<T, U, V>(p, RefPtr<T, U, V>::Adopt);
    251254}
    252255
     
    261264}
    262265
    263 template<typename ExpectedType, typename ArgType, typename PtrTraits>
    264 inline bool is(RefPtr<ArgType, PtrTraits>& source)
     266template<typename ExpectedType, typename ArgType, typename PtrTraits, typename RefDerefTraits>
     267inline bool is(RefPtr<ArgType, PtrTraits, RefDerefTraits>& source)
    265268{
    266269    return is<ExpectedType>(source.get());
    267270}
    268271
    269 template<typename ExpectedType, typename ArgType, typename PtrTraits>
    270 inline bool is(const RefPtr<ArgType, PtrTraits>& source)
     272template<typename ExpectedType, typename ArgType, typename PtrTraits, typename RefDerefTraits>
     273inline bool is(const RefPtr<ArgType, PtrTraits, RefDerefTraits>& source)
    271274{
    272275    return is<ExpectedType>(source.get());
  • trunk/Source/WebCore/ChangeLog

    r267590 r267591  
     12020-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
    1702020-09-25  Rob Buis  <rbuis@igalia.com>
    271
  • trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp

    r267544 r267591  
    581581void AudioBufferSourceNode::setPannerNode(PannerNodeBase* pannerNode)
    582582{
    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())
    589584        m_pannerNode = pannerNode;
    590     }
    591585}
    592586
    593587void AudioBufferSourceNode::clearPannerNode()
    594588{
    595     if (m_pannerNode) {
    596         m_pannerNode->deref(AudioNode::RefTypeConnection);
    597         m_pannerNode = nullptr;
    598     }
     589    m_pannerNode = nullptr;
    599590}
    600591
  • trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.h

    r267537 r267591  
    142142
    143143    // 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;
    146146
    147147    // This synchronizes process() with setBuffer() which can cause dynamic channel count changes.
  • trunk/Source/WebCore/Modules/webaudio/AudioNode.cpp

    r267543 r267591  
    549549{
    550550    // 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 from
     551    // of 0 is from decrementConnectionCountWithLock() where there are no connections left. The case of 1 is from
    552552    // AudioNodeInput::disable() where we want to disable outputs when there's only one connection
    553553    // left because we're ready to go away, but can't quite yet.
     
    575575}
    576576
    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
     577void AudioNode::incrementConnectionCount()
     578{
     579    ++m_connectionRefCount;
     580
     581    // See the disabling code in decrementConnectionCountWithLock() below. This handles the case where a node
    595582    // is being re-connected after being used at least once and disconnected.
    596583    // 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
     591void AudioNode::decrementConnectionCount()
    602592{
    603593    // The actually work for deref happens completely within the audio context's graph lock.
     
    616606    if (hasLock) {
    617607        // This is where the real deref work happens.
    618         finishDeref(refType);
     608        decrementConnectionCountWithLock();
    619609
    620610        if (mustReleaseLock)
     
    623613        // We were unable to get the lock, so put this in a list to finish up later.
    624614        ASSERT(context().isAudioThread());
    625         ASSERT(refType == RefTypeConnection);
    626         context().addDeferredFinishDeref(this);
     615        context().addDeferredDecrementConnectionCount(this);
    627616    }
    628617
     
    634623}
    635624
     625void 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
     642void 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
     659void 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
     668void 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
    636685Variant<RefPtr<BaseAudioContext>, RefPtr<WebKitAudioContext>> AudioNode::contextForBindings() const
    637686{
     
    641690}
    642691
    643 void AudioNode::finishDeref(RefType refType)
     692void AudioNode::derefWithLock()
    644693{
    645694    ASSERT(context().isGraphOwner());
    646695   
    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;
    659698   
    660699#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();
    679704}
    680705
  • trunk/Source/WebCore/Modules/webaudio/AudioNode.h

    r267543 r267591  
    9797    void setNodeType(NodeType);
    9898
    99     // We handle our own ref-counting because of the threading issues and subtle nature of
    100     // how AudioNodes can continue processing (playing one-shot sound) after there are no more
    101     // JavaScript references to the object.
    102     enum RefType { RefTypeNormal, RefTypeConnection };
    103 
    10499    // 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();
    107104
    108105    // 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();
    110107    virtual void didBecomeMarkedForDeletion() { }
    111108
     
    203200    void addOutput(unsigned numberOfChannels);
    204201
     202    void markNodeForDeletionIfNecessary();
     203    void derefWithLock();
     204
    205205    struct DefaultAudioNodeOptions {
    206206        unsigned channelCount;
     
    271271};
    272272
     273template<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
     287template<typename T>
     288using AudioConnectionRefPtr = RefPtr<T, DumbPtrTraits<T>, AudioNodeConnectionRefDerefTraits<T>>;
     289
    273290String convertEnumerationToString(AudioNode::NodeType);
    274291
  • trunk/Source/WebCore/Modules/webaudio/AudioNodeInput.cpp

    r267560 r267591  
    6161    output->addInput(this);
    6262    changedOutputs();
    63 
    64     // Sombody has just connected to us, so count it as a reference.
    65     node()->ref(AudioNode::RefTypeConnection);
    6663}
    6764
     
    7774    if (m_outputs.remove(output)) {
    7875        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.
    8177        return;
    8278    }
     
    8480    // Otherwise, try to disconnect from disabled connections.
    8581    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.
    8883        return;
    8984    }
  • trunk/Source/WebCore/Modules/webaudio/AudioNodeOutput.cpp

    r267560 r267591  
    9696    if (isChannelCountKnown()) {
    9797        // 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()) {
    9999            AudioNode* connectionNode = input->node();
    100100            connectionNode->checkNumberOfChannelsForInput(input);
     
    158158        return;
    159159
    160     m_inputs.add(input);
     160    m_inputs.add(input, input->node());
    161161}
    162162
     
    178178    // AudioNodeInput::disconnect() changes m_inputs by calling removeInput().
    179179    while (!m_inputs.isEmpty()) {
    180         AudioNodeInput* input = *m_inputs.begin();
     180        AudioNodeInput* input = m_inputs.begin()->key;
    181181        input->disconnect(this);
    182182    }
     
    227227
    228228    if (m_isEnabled) {
    229         for (auto& input : m_inputs)
     229        for (auto& input : m_inputs.keys())
    230230            input->disable(this);
    231231        m_isEnabled = false;
     
    238238
    239239    if (!m_isEnabled) {
    240         for (auto& input : m_inputs)
     240        for (auto& input : m_inputs.keys())
    241241            input->enable(this);
    242242        m_isEnabled = true;
  • trunk/Source/WebCore/Modules/webaudio/AudioNodeOutput.h

    r267544 r267591  
    141141    bool m_isInPlace { false };
    142142
    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;
    145146    bool m_isEnabled { true };
    146147
  • trunk/Source/WebCore/Modules/webaudio/BaseAudioContext.cpp

    r267505 r267591  
    198198        m_renderingAutomaticPullNodes.resize(m_automaticPullNodes.size());
    199199    ASSERT(m_renderingAutomaticPullNodes.isEmpty());
    200     // FIXME: Can we assert that m_deferredFinishDerefList is empty?
     200    // FIXME: Can we assert that m_deferredBreakConnectionList is empty?
    201201
    202202    if (!isOfflineContext() && scriptExecutionContext()) {
     
    682682    AutoLocker locker(*this);
    683683   
    684     node.ref(AudioNode::RefTypeConnection);
    685684    m_referencedNodes.append(&node);
    686685}
     
    690689    ASSERT(isGraphOwner());
    691690   
    692     node.deref(AudioNode::RefTypeConnection);
    693 
    694691    ASSERT(m_referencedNodes.contains(&node));
    695692    m_referencedNodes.removeFirst(&node);
     
    699696{
    700697    ASSERT(isMainThread() && isAudioThreadFinished());
    701     for (auto& node : m_referencedNodes)
    702         node->deref(AudioNode::RefTypeConnection);
    703 
    704698    m_referencedNodes.clear();
    705699}
     
    779773}
    780774
    781 void BaseAudioContext::addDeferredFinishDeref(AudioNode* node)
     775void BaseAudioContext::addDeferredDecrementConnectionCount(AudioNode* node)
    782776{
    783777    ASSERT(isAudioThread());
    784     m_deferredFinishDerefList.append(node);
     778    m_deferredBreakConnectionList.append(node);
    785779}
    786780
     
    822816    if (tryLock(mustReleaseLock)) {
    823817        // Take care of finishing any derefs where the tryLock() failed previously.
    824         handleDeferredFinishDerefs();
     818        handleDeferredDecrementConnectionCounts();
    825819
    826820        // Dynamically clean up nodes which are no longer needed.
     
    842836}
    843837
    844 void BaseAudioContext::handleDeferredFinishDerefs()
     838void BaseAudioContext::handleDeferredDecrementConnectionCounts()
    845839{
    846840    ASSERT(isAudioThread() && isGraphOwner());
    847     for (auto& node : m_deferredFinishDerefList)
    848         node->finishDeref(AudioNode::RefTypeConnection);
    849    
    850     m_deferredFinishDerefList.clear();
     841    for (auto& node : m_deferredBreakConnectionList)
     842        node->decrementConnectionCountWithLock();
     843   
     844    m_deferredBreakConnectionList.clear();
    851845}
    852846
  • trunk/Source/WebCore/Modules/webaudio/BaseAudioContext.h

    r267147 r267591  
    230230    static unsigned maxNumberOfChannels() { return MaxNumberOfChannels; }
    231231   
    232     // In AudioNode::deref() a tryLock() is used for calling finishDeref(), but if it fails keep track here.
    233     void addDeferredFinishDeref(AudioNode*);
    234 
    235     // In the audio thread at the start of each render cycle, we'll call handleDeferredFinishDerefs().
    236     void handleDeferredFinishDerefs();
     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();
    237237
    238238    // Only accessed when the graph lock is held.
     
    398398    Vector<AudioNode*> m_finishedNodes;
    399399
    400     // We don't use RefPtr<AudioNode> here because AudioNode has a more complex ref() / deref() implementation
    401     // with an optional argument for refType.  We need to use the special refType: RefTypeConnection
    402400    // Either accessed when the graph lock is held, or on the main thread when the audio thread has finished.
    403     Vector<AudioNode*> m_referencedNodes;
     401    Vector<AudioConnectionRefPtr<AudioNode>> m_referencedNodes;
    404402
    405403    // Accumulate nodes which need to be deleted here.
     
    428426    Vector<AudioNode*> m_renderingAutomaticPullNodes;
    429427    // Only accessed in the audio thread.
    430     Vector<AudioNode*> m_deferredFinishDerefList;
     428    Vector<AudioNode*> m_deferredBreakConnectionList;
    431429    Vector<Vector<DOMPromiseDeferred<void>>> m_stateReactions;
    432430
  • trunk/Source/WebCore/Modules/webaudio/ScriptProcessorNode.cpp

    r267544 r267591  
    184184    if (!m_bufferReadWriteIndex) {
    185185        // Reference ourself so we don't accidentally get deleted before fireProcessEvent() gets called.
    186         auto protector = makeRef(*this);
    187 
    188186        // We only wait for script code execution when the context is an offline one for performance reasons.
    189187        if (context().isOfflineContext()) {
    190188            BinarySemaphore semaphore;
    191             callOnMainThread([this, &semaphore, doubleBufferIndex = m_doubleBufferIndex] {
     189            callOnMainThread([this, &semaphore, doubleBufferIndex = m_doubleBufferIndex, protector = makeRef(*this)] {
    192190                fireProcessEvent(doubleBufferIndex);
    193191                semaphore.signal();
     
    203201            }
    204202
    205             callOnMainThread([this, doubleBufferIndex = m_doubleBufferIndex, protector = WTFMove(protector)] {
     203            callOnMainThread([this, doubleBufferIndex = m_doubleBufferIndex, protector = makeRef(*this)] {
    206204                auto locker = holdLock(m_processLock);
    207205                fireProcessEvent(doubleBufferIndex);
  • trunk/Source/WebCore/platform/graphics/cairo/RefPtrCairo.cpp

    r237847 r267591  
    2626namespace WTF {
    2727
    28 template<> void refIfNotNull(cairo_t* ptr)
     28void DefaultRefDerefTraits<cairo_t>::refIfNotNull(cairo_t* ptr)
    2929{
    3030    if (LIKELY(ptr))
     
    3232}
    3333
    34 template<> void derefIfNotNull(cairo_t* ptr)
     34void DefaultRefDerefTraits<cairo_t>::derefIfNotNull(cairo_t* ptr)
    3535{
    3636    if (LIKELY(ptr))
     
    3838}
    3939
    40 template<> void refIfNotNull(cairo_surface_t* ptr)
     40void DefaultRefDerefTraits<cairo_surface_t>::refIfNotNull(cairo_surface_t* ptr)
    4141{
    4242    if (LIKELY(ptr))
     
    4444}
    4545
    46 template<> void derefIfNotNull(cairo_surface_t* ptr)
     46void DefaultRefDerefTraits<cairo_surface_t>::derefIfNotNull(cairo_surface_t* ptr)
    4747{
    4848    if (LIKELY(ptr))
     
    5050}
    5151
    52 template<> void refIfNotNull(cairo_font_face_t* ptr)
     52void DefaultRefDerefTraits<cairo_font_face_t>::refIfNotNull(cairo_font_face_t* ptr)
    5353{
    5454    if (LIKELY(ptr))
     
    5656}
    5757
    58 template<> void derefIfNotNull(cairo_font_face_t* ptr)
     58void DefaultRefDerefTraits<cairo_font_face_t>::derefIfNotNull(cairo_font_face_t* ptr)
    5959{
    6060    if (LIKELY(ptr))
     
    6262}
    6363
    64 template<> void refIfNotNull(cairo_scaled_font_t* ptr)
     64void DefaultRefDerefTraits<cairo_scaled_font_t>::refIfNotNull(cairo_scaled_font_t* ptr)
    6565{
    6666    if (LIKELY(ptr))
     
    6868}
    6969
    70 template<> void derefIfNotNull(cairo_scaled_font_t* ptr)
     70void DefaultRefDerefTraits<cairo_scaled_font_t>::derefIfNotNull(cairo_scaled_font_t* ptr)
    7171{
    7272    if (LIKELY(ptr))
     
    7474}
    7575
    76 template<> void refIfNotNull(cairo_pattern_t* ptr)
     76void DefaultRefDerefTraits<cairo_pattern_t>::refIfNotNull(cairo_pattern_t* ptr)
    7777{
    7878    if (LIKELY(ptr))
     
    8080}
    8181
    82 template<> void derefIfNotNull(cairo_pattern_t* ptr)
     82void DefaultRefDerefTraits<cairo_pattern_t>::derefIfNotNull(cairo_pattern_t* ptr)
    8383{
    8484    if (LIKELY(ptr))
     
    8686}
    8787
    88 template<> void refIfNotNull(cairo_region_t* ptr)
     88void DefaultRefDerefTraits<cairo_region_t>::refIfNotNull(cairo_region_t* ptr)
    8989{
    9090    if (LIKELY(ptr))
     
    9292}
    9393
    94 template<> void derefIfNotNull(cairo_region_t* ptr)
     94void DefaultRefDerefTraits<cairo_region_t>::derefIfNotNull(cairo_region_t* ptr)
    9595{
    9696    if (LIKELY(ptr))
  • trunk/Source/WebCore/platform/graphics/cairo/RefPtrCairo.h

    r261014 r267591  
    3434namespace WTF {
    3535
    36 template<> void refIfNotNull(cairo_t* ptr);
    37 template<> WEBCORE_EXPORT void derefIfNotNull(cairo_t* ptr);
     36template<>
     37struct DefaultRefDerefTraits<cairo_t> {
     38    static void refIfNotNull(cairo_t* ptr);
     39    WEBCORE_EXPORT static void derefIfNotNull(cairo_t* ptr);
     40};
    3841
    39 template<> WEBCORE_EXPORT void refIfNotNull(cairo_surface_t* ptr);
    40 template<> WEBCORE_EXPORT void derefIfNotNull(cairo_surface_t* ptr);
     42template<>
     43struct 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};
    4147
    42 template<> void refIfNotNull(cairo_font_face_t* ptr);
    43 template<> void derefIfNotNull(cairo_font_face_t* ptr);
     48template<>
     49struct DefaultRefDerefTraits<cairo_font_face_t> {
     50    static void refIfNotNull(cairo_font_face_t* ptr);
     51    static void derefIfNotNull(cairo_font_face_t* ptr);
     52};
    4453
    45 template<> void refIfNotNull(cairo_scaled_font_t* ptr);
    46 template<> void derefIfNotNull(cairo_scaled_font_t* ptr);
     54template<>
     55struct DefaultRefDerefTraits<cairo_scaled_font_t> {
     56    static void refIfNotNull(cairo_scaled_font_t* ptr);
     57    static void derefIfNotNull(cairo_scaled_font_t* ptr);
     58};
    4759
    48 template<> void refIfNotNull(cairo_pattern_t*);
    49 template<> void derefIfNotNull(cairo_pattern_t*);
     60template<>
     61struct DefaultRefDerefTraits<cairo_pattern_t> {
     62    static void refIfNotNull(cairo_pattern_t*);
     63    static void derefIfNotNull(cairo_pattern_t*);
     64};
    5065
    51 template<> void refIfNotNull(cairo_region_t*);
    52 template<> void derefIfNotNull(cairo_region_t*);
     66template<>
     67struct DefaultRefDerefTraits<cairo_region_t> {
     68    static void refIfNotNull(cairo_region_t*);
     69    static void derefIfNotNull(cairo_region_t*);
     70};
    5371
    5472} // namespace WTF
  • trunk/Source/WebCore/platform/graphics/freetype/RefPtrFontconfig.cpp

    r237847 r267591  
    2626namespace WTF {
    2727
    28 template<> void refIfNotNull(FcPattern* ptr)
     28void DefaultRefDerefTraits<FcPattern>::refIfNotNull(FcPattern* ptr)
    2929{
    3030    if (LIKELY(ptr))
     
    3232}
    3333
    34 template<> void derefIfNotNull(FcPattern* ptr)
     34void DefaultRefDerefTraits<FcPattern>::derefIfNotNull(FcPattern* ptr)
    3535{
    3636    if (LIKELY(ptr))
     
    3838}
    3939
    40 template<> void refIfNotNull(FcConfig* ptr)
     40void DefaultRefDerefTraits<FcConfig>::refIfNotNull(FcConfig* ptr)
    4141{
    4242    if (LIKELY(ptr))
     
    4444}
    4545
    46 template<> void derefIfNotNull(FcConfig* ptr)
     46void DefaultRefDerefTraits<FcConfig>::derefIfNotNull(FcConfig* ptr)
    4747{
    4848    if (LIKELY(ptr))
  • trunk/Source/WebCore/platform/graphics/freetype/RefPtrFontconfig.h

    r237847 r267591  
    2929namespace WTF {
    3030
    31 template<> void refIfNotNull(FcPattern* ptr);
    32 template<> void derefIfNotNull(FcPattern* ptr);
     31template<>
     32struct DefaultRefDerefTraits<FcPattern> {
     33    static void refIfNotNull(FcPattern* ptr);
     34    static void derefIfNotNull(FcPattern* ptr);
     35};
    3336
    34 template<> void refIfNotNull(FcConfig* ptr);
    35 template<> void derefIfNotNull(FcConfig* ptr);
     37template<>
     38struct DefaultRefDerefTraits<FcConfig> {
     39    static void refIfNotNull(FcConfig* ptr);
     40    static void derefIfNotNull(FcConfig* ptr);
     41};
    3642
    3743} // namespace WTF
Note: See TracChangeset for help on using the changeset viewer.