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

Changeset 280952 in webkit


Ignore:
Timestamp:
Aug 11, 2021, 7:08:08 PM (5 years ago)
Author:
Darin Adler
Message:

Add deduction guide to RetainPtr, use constexpr a bit more, and streamline the implementation
https://bugs.webkit.org/show_bug.cgi?id=228852

Reviewed by Sam Weinig.

Source/WebKit:

  • UIProcess/mac/WKTextFinderClient.mm:

(-[WKTextFinderClient findMatchesForString:relativeToMatch:findOptions:maxResults:resultCollector:]):
Test the deduction guide by writing RetainPtr instead of RetainPtr<NSProgress>.

Source/WTF:

  • wtf/RetainPtr.h: Sort includes. Made many functions constexpr including the move

constructors and adoptCF. Use using instead of typedef in most places. Use
remove_pointer_t, conditional_t, is_convertible_v, is_same_v, and other such templates
to simplify expressions. Initialize the m_ptr data member and use the default constructor.
Removed unneeded StorageType synonym for CFTypeRef. Move some inline function bodies out
of the class template definition. Use if constexpr to get rid of the need for the overloaded
autoreleaseHelper function. Added a deduction guide so we can use expressions with the
type RetainPtr on the left side, and an Objective-C pointer or CFTypeRef on the right side,
and have the appropriate RetainPtr type deduced.

Location:
trunk/Source
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WTF/ChangeLog

    r280934 r280952  
     12021-08-11  Darin Adler  <darin@apple.com>
     2
     3        Add deduction guide to RetainPtr, use constexpr a bit more, and streamline the implementation
     4        https://bugs.webkit.org/show_bug.cgi?id=228852
     5
     6        Reviewed by Sam Weinig.
     7
     8        * wtf/RetainPtr.h: Sort includes. Made many functions constexpr including the move
     9        constructors and adoptCF. Use using instead of typedef in most places. Use
     10        remove_pointer_t, conditional_t, is_convertible_v, is_same_v, and other such templates
     11        to simplify expressions. Initialize the m_ptr data member and use the default constructor.
     12        Removed unneeded StorageType synonym for CFTypeRef. Move some inline function bodies out
     13        of the class template definition. Use if constexpr to get rid of the need for the overloaded
     14        autoreleaseHelper function. Added a deduction guide so we can use expressions with the
     15        type RetainPtr on the left side, and an Objective-C pointer or CFTypeRef on the right side,
     16        and have the appropriate RetainPtr type deduced.
     17
    1182021-08-11  Sihui Liu  <sihui_liu@apple.com>
    219
  • trunk/Source/WTF/wtf/RetainPtr.h

    r275650 r280952  
    11/*
    2  *  Copyright (C) 2005-2019 Apple Inc. All rights reserved.
     2 *  Copyright (C) 2005-2021 Apple Inc. All rights reserved.
    33 *
    44 *  This library is free software; you can redistribute it and/or
     
    2525#if USE(CF) || defined(__OBJC__)
    2626
    27 #include <wtf/HashTraits.h>
    2827#include <algorithm>
    2928#include <cstddef>
     29#include <wtf/HashTraits.h>
     30#include <wtf/NeverDestroyed.h>
    3031
    3132#if USE(CF)
     
    6667template<typename T> class RetainPtr;
    6768
    68 template<typename T> RetainPtr<T> adoptCF(T CF_RELEASES_ARGUMENT) WARN_UNUSED_RETURN;
     69template<typename T> constexpr RetainPtr<T> adoptCF(T CF_RELEASES_ARGUMENT) WARN_UNUSED_RETURN;
     70
    6971#ifdef __OBJC__
    7072template<typename T> RetainPtr<typename RetainPtr<T>::HelperPtrType> adoptNS(T NS_RELEASES_ARGUMENT) WARN_UNUSED_RETURN;
     
    7375template<typename T> class RetainPtr {
    7476public:
    75     typedef typename std::remove_pointer<T>::type ValueType;
    76     typedef ValueType* PtrType;
    77     typedef CFTypeRef StorageType;
    78 
    79 #ifdef __OBJC__
    80     typedef typename std::conditional<std::is_convertible<T, id>::value && !std::is_same<T, id>::value, typename std::remove_pointer<T>::type, T>::type HelperPtrType;
     77    using ValueType = std::remove_pointer_t<T>;
     78    using PtrType = ValueType*;
     79
     80#ifdef __OBJC__
     81    using HelperPtrType = typename std::conditional_t<std::is_convertible_v<T, id> && !std::is_same_v<T, id>, std::remove_pointer_t<T>, T>;
    8182#else
    82     typedef T HelperPtrType;
    83 #endif
    84 
    85     RetainPtr() : m_ptr(nullptr) { }
    86     RetainPtr(PtrType ptr) : m_ptr(toStorageType(ptr)) { if (m_ptr) CFRetain(m_ptr); }
    87 
    88     RetainPtr(const RetainPtr& o) : m_ptr(o.m_ptr) { if (StorageType ptr = m_ptr) CFRetain(ptr); }
    89 
    90     RetainPtr(RetainPtr&& o) : m_ptr(toStorageType(o.leakRef())) { }
    91     template<typename U> RetainPtr(RetainPtr<U>&& o) : m_ptr(toStorageType(o.leakRef())) { }
     83    using HelperPtrType = PtrType;
     84#endif
     85
     86    RetainPtr() = default;
     87    RetainPtr(PtrType);
     88
     89    RetainPtr(const RetainPtr&);
     90    template<typename U> RetainPtr(const RetainPtr<U>&);
     91
     92    constexpr RetainPtr(RetainPtr&& o) : m_ptr(toStorageType(o.leakRef())) { }
     93    template<typename U> constexpr RetainPtr(RetainPtr<U>&& o) : m_ptr(toStorageType(o.leakRef())) { }
    9294
    9395    // Hash table deleted values, which are only constructed and never copied or destroyed.
    94     RetainPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { }
    95     bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); }
    96    
     96    constexpr RetainPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { }
     97    constexpr bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); }
     98
    9799    ~RetainPtr();
    98    
    99     template<typename U> RetainPtr(const RetainPtr<U>&);
    100100
    101101    void clear();
    102102    PtrType leakRef() WARN_UNUSED_RETURN;
    103103    PtrType autorelease();
     104
    104105#ifdef __OBJC__
    105106    id bridgingAutorelease();
    106107#endif
    107108
    108     PtrType get() const { return fromStorageType(m_ptr); }
    109     PtrType operator->() const { return fromStorageType(m_ptr); }
    110     explicit operator PtrType() const { return fromStorageType(m_ptr); }
    111     explicit operator bool() const { return m_ptr; }
    112 
    113     bool operator!() const { return !m_ptr; }
     109    constexpr PtrType get() const { return fromStorageType(m_ptr); }
     110    constexpr PtrType operator->() const { return fromStorageType(m_ptr); }
     111    constexpr explicit operator PtrType() const { return fromStorageType(m_ptr); }
     112    constexpr explicit operator bool() const { return m_ptr; }
     113
     114    constexpr bool operator!() const { return !m_ptr; }
    114115
    115116    // This conversion operator allows implicit conversion to bool but not to other integer types.
    116     typedef StorageType RetainPtr::*UnspecifiedBoolType;
     117    // FIXME: Eventually we should remove this; it's an outdated technique and less needed since we have explicit operator bool.
     118    typedef CFTypeRef RetainPtr::*UnspecifiedBoolType;
    117119    operator UnspecifiedBoolType() const { return m_ptr ? &RetainPtr::m_ptr : nullptr; }
    118    
     120
    119121    RetainPtr& operator=(const RetainPtr&);
    120122    template<typename U> RetainPtr& operator=(const RetainPtr<U>&);
     
    127129    void swap(RetainPtr&);
    128130
    129     template<typename U> friend RetainPtr<U> adoptCF(U CF_RELEASES_ARGUMENT) WARN_UNUSED_RETURN;
     131    template<typename U> friend constexpr RetainPtr<U> adoptCF(U CF_RELEASES_ARGUMENT) WARN_UNUSED_RETURN;
     132
    130133#ifdef __OBJC__
    131134    template<typename U> friend RetainPtr<typename RetainPtr<U>::HelperPtrType> adoptNS(U NS_RELEASES_ARGUMENT) WARN_UNUSED_RETURN;
     
    134137private:
    135138    enum AdoptTag { Adopt };
    136     RetainPtr(PtrType ptr, AdoptTag) : m_ptr(toStorageType(ptr)) { }
    137 
    138     static PtrType hashTableDeletedValue() { return reinterpret_cast<PtrType>(-1); }
    139 
    140 #ifdef __OBJC__
    141     template<typename U>
    142     typename std::enable_if<std::is_convertible<U, id>::value, PtrType>::type
    143     fromStorageTypeHelper(StorageType ptr) const
     139    constexpr RetainPtr(PtrType ptr, AdoptTag) : m_ptr(toStorageType(ptr)) { }
     140
     141    static constexpr PtrType hashTableDeletedValue() { return reinterpret_cast<PtrType>(-1); }
     142
     143#ifdef __OBJC__
     144    template<typename U> constexpr std::enable_if_t<std::is_convertible_v<U, id>, PtrType> fromStorageTypeHelper(CFTypeRef ptr) const
    144145    {
    145146        return (__bridge PtrType)const_cast<CF_BRIDGED_TYPE(id) void*>(ptr);
    146147    }
    147 
    148     template<typename U>
    149     typename std::enable_if<!std::is_convertible<U, id>::value, PtrType>::type
    150     fromStorageTypeHelper(StorageType ptr) const
     148    template<typename U> constexpr std::enable_if_t<!std::is_convertible_v<U, id>, PtrType> fromStorageTypeHelper(CFTypeRef ptr) const
    151149    {
    152150        return (PtrType)const_cast<CF_BRIDGED_TYPE(id) void*>(ptr);
    153151    }
    154 
    155     PtrType fromStorageType(StorageType ptr) const { return fromStorageTypeHelper<PtrType>(ptr); }
    156     StorageType toStorageType(id ptr) const { return (__bridge StorageType)ptr; }
    157     StorageType toStorageType(CFTypeRef ptr) const { return (StorageType)ptr; }
     152    constexpr PtrType fromStorageType(CFTypeRef ptr) const { return fromStorageTypeHelper<PtrType>(ptr); }
     153    constexpr CFTypeRef toStorageType(id ptr) const { return (__bridge CFTypeRef)ptr; }
     154    constexpr CFTypeRef toStorageType(CFTypeRef ptr) const { return (CFTypeRef)ptr; }
    158155#else
    159     PtrType fromStorageType(StorageType ptr) const
     156    constexpr PtrType fromStorageType(CFTypeRef ptr) const
    160157    {
    161158        return (PtrType)const_cast<CF_BRIDGED_TYPE(id) void*>(ptr);
    162159    }
    163     StorageType toStorageType(PtrType ptr) const { return (StorageType)ptr; }
    164 #endif
    165 
    166 #ifdef __OBJC__
    167     template<typename U> std::enable_if_t<std::is_convertible<U, id>::value, PtrType> autoreleaseHelper();
    168     template<typename U> std::enable_if_t<!std::is_convertible<U, id>::value, PtrType> autoreleaseHelper();
    169 #endif
    170 
    171     StorageType m_ptr;
     160    constexpr CFTypeRef toStorageType(PtrType ptr) const { return (CFTypeRef)ptr; }
     161#endif
     162
     163    CFTypeRef m_ptr { nullptr };
    172164};
     165
     166template<typename T> RetainPtr(T) -> RetainPtr<std::remove_pointer_t<T>>;
    173167
    174168// Helper function for creating a RetainPtr using template argument deduction.
     
    177171template<typename T> inline RetainPtr<T>::~RetainPtr()
    178172{
    179     if (StorageType ptr = std::exchange(m_ptr, nullptr))
     173    if (auto ptr = std::exchange(m_ptr, nullptr))
    180174        CFRelease(ptr);
    181175}
    182176
     177template<typename T> inline RetainPtr<T>::RetainPtr(PtrType ptr)
     178    : m_ptr(toStorageType(ptr))
     179{
     180    if (m_ptr)
     181        CFRetain(m_ptr);
     182}
     183
     184template<typename T> inline RetainPtr<T>::RetainPtr(const RetainPtr& o)
     185    : RetainPtr(o.get())
     186{
     187}
     188
    183189template<typename T> template<typename U> inline RetainPtr<T>::RetainPtr(const RetainPtr<U>& o)
    184     : m_ptr(toStorageType(o.get()))
    185 {
    186     if (StorageType ptr = m_ptr)
    187         CFRetain(ptr);
     190    : RetainPtr(o.get())
     191{
    188192}
    189193
    190194template<typename T> inline void RetainPtr<T>::clear()
    191195{
    192     if (StorageType ptr = std::exchange(m_ptr, nullptr))
     196    if (auto ptr = std::exchange(m_ptr, nullptr))
    193197        CFRelease(ptr);
    194198}
     
    199203}
    200204
    201 #ifndef __OBJC__
    202 
    203205template<typename T> inline auto RetainPtr<T>::autorelease() -> PtrType
    204206{
     207#ifdef __OBJC__
     208    if constexpr (std::is_convertible_v<PtrType, id>)
     209        return CFBridgingRelease(std::exchange(m_ptr, nullptr));
     210#endif
    205211    if (m_ptr)
    206212        CFAutorelease(m_ptr);
     
    208214}
    209215
    210 #else
    211 
    212 template<typename T> template<typename U> inline auto RetainPtr<T>::autoreleaseHelper() -> std::enable_if_t<std::is_convertible<U, id>::value, PtrType>
    213 {
    214     return CFBridgingRelease(std::exchange(m_ptr, nullptr));
    215 }
    216 
    217 template<typename T> template<typename U> inline auto RetainPtr<T>::autoreleaseHelper() -> std::enable_if_t<!std::is_convertible<U, id>::value, PtrType>
    218 {
    219     if (m_ptr)
    220         CFAutorelease(m_ptr);
    221     return leakRef();
    222 }
    223 
    224 template<typename T> inline auto RetainPtr<T>::autorelease() -> PtrType
    225 {
    226     return autoreleaseHelper<PtrType>();
    227 }
    228 
    229 // FIXME: It would be nice if we could base the return type on the type that is toll-free bridged with T rather than using id.
     216#ifdef __OBJC__
     217
     218// FIXME: It would be better if we could base the return type on the type that is toll-free bridged with T rather than using id.
    230219template<typename T> inline id RetainPtr<T>::bridgingAutorelease()
    231220{
     
    288277}
    289278
    290 template<typename T, typename U> inline bool operator==(const RetainPtr<T>& a, const RetainPtr<U>& b)
     279template<typename T, typename U> constexpr bool operator==(const RetainPtr<T>& a, const RetainPtr<U>& b)
    291280{
    292281    return a.get() == b.get();
    293282}
    294283
    295 template<typename T, typename U> inline bool operator==(const RetainPtr<T>& a, U* b)
     284template<typename T, typename U> constexpr bool operator==(const RetainPtr<T>& a, U* b)
    296285{
    297286    return a.get() == b;
    298287}
    299288
    300 template<typename T, typename U> inline bool operator==(T* a, const RetainPtr<U>& b)
     289template<typename T, typename U> constexpr bool operator==(T* a, const RetainPtr<U>& b)
    301290{
    302291    return a == b.get();
    303292}
    304293
    305 template<typename T, typename U> inline bool operator!=(const RetainPtr<T>& a, const RetainPtr<U>& b)
     294template<typename T, typename U> constexpr bool operator!=(const RetainPtr<T>& a, const RetainPtr<U>& b)
    306295{
    307296    return a.get() != b.get();
    308297}
    309298
    310 template<typename T, typename U> inline bool operator!=(const RetainPtr<T>& a, U* b)
     299template<typename T, typename U> constexpr bool operator!=(const RetainPtr<T>& a, U* b)
    311300{
    312301    return a.get() != b;
    313302}
    314303
    315 template<typename T, typename U> inline bool operator!=(T* a, const RetainPtr<U>& b)
     304template<typename T, typename U> constexpr bool operator!=(T* a, const RetainPtr<U>& b)
    316305{
    317306    return a != b.get();
    318307}
    319308
    320 template<typename T> inline RetainPtr<T> adoptCF(T CF_RELEASES_ARGUMENT ptr)
     309template<typename T> constexpr RetainPtr<T> adoptCF(T CF_RELEASES_ARGUMENT ptr)
    321310{
    322311#ifdef __OBJC__
     
    332321    return ptr;
    333322#elif defined(OBJC_NO_GC)
    334     return RetainPtr<typename RetainPtr<T>::HelperPtrType>(ptr, RetainPtr<typename RetainPtr<T>::HelperPtrType>::Adopt);
     323    using ReturnType = RetainPtr<typename RetainPtr<T>::HelperPtrType>;
     324    return ReturnType { ptr, ReturnType::Adopt };
    335325#else
    336326    RetainPtr<typename RetainPtr<T>::HelperPtrType> result = ptr;
     
    346336}
    347337
    348 template <typename T> struct IsSmartPtr<RetainPtr<T>> {
     338template<typename T> struct IsSmartPtr<RetainPtr<T>> {
    349339    static constexpr bool value = true;
    350340};
     
    355345template<typename P> struct DefaultHash<RetainPtr<P>> : PtrHash<RetainPtr<P>> { };
    356346
    357 template <typename P>
    358 struct RetainPtrObjectHashTraits : SimpleClassHashTraits<RetainPtr<P>> {
     347template<typename P> struct RetainPtrObjectHashTraits : SimpleClassHashTraits<RetainPtr<P>> {
    359348    static const RetainPtr<P>& emptyValue()
    360349    {
    361         static RetainPtr<P>& null = *(new RetainPtr<P>);
     350        static NeverDestroyed<RetainPtr<P>> null;
    362351        return null;
    363352    }
    364353};
    365354
    366 template <typename P>
    367 struct RetainPtrObjectHash {
     355template<typename P> struct RetainPtrObjectHash {
    368356    static unsigned hash(const RetainPtr<P>& o)
    369357    {
  • trunk/Source/WebKit/ChangeLog

    r280951 r280952  
     12021-08-11  Darin Adler  <darin@apple.com>
     2
     3        Add deduction guide to RetainPtr, use constexpr a bit more, and streamline the implementation
     4        https://bugs.webkit.org/show_bug.cgi?id=228852
     5
     6        Reviewed by Sam Weinig.
     7
     8        * UIProcess/mac/WKTextFinderClient.mm:
     9        (-[WKTextFinderClient findMatchesForString:relativeToMatch:findOptions:maxResults:resultCollector:]):
     10        Test the deduction guide by writing RetainPtr instead of RetainPtr<NSProgress>.
     11
    1122021-08-11  Peng Liu  <peng.liu6@apple.com>
    213
  • trunk/Source/WebKit/UIProcess/mac/WKTextFinderClient.mm

    r272784 r280952  
    226226    }
    227227
    228     RetainPtr<NSProgress> progress = [NSProgress progressWithTotalUnitCount:1];
     228    RetainPtr progress = [NSProgress progressWithTotalUnitCount:1];
    229229    auto copiedResultCollector = Block_copy(resultCollector);
    230230    _findReplyCallbacks.append([progress, copiedResultCollector] (NSArray *matches, bool didWrap) {
Note: See TracChangeset for help on using the changeset viewer.