Ignore:
Timestamp:
2019-06-27T11:15:35Z (5 years ago)
Author:
Jaroslav Jindrak <dzejrou@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
04c0fc5
Parents:
bc73be3
Message:

cpp: move reference counting logic from the shared payload so that it can be reused elsewhere

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/cpp/include/__bits/memory/shared_payload.hpp

    rbc73be3 r8add15e0  
    3030#define LIBCPP_BITS_MEMORY_SHARED_PAYLOAD
    3131
     32#include <__bits/refcount_obj.hpp>
    3233#include <cinttypes>
    3334#include <utility>
     
    4344namespace std::aux
    4445{
    45     /**
    46      * At the moment we do not have atomics, change this
    47      * to std::atomic<long> once we do.
    48      */
    49     using refcount_t = long;
    50 
    5146    /**
    5247     * This allows us to construct shared_ptr from
     
    6661
    6762    template<class T>
    68     class shared_payload_base
     63    class shared_payload_base: public aux::refcount_obj
    6964    {
    7065        public:
    71             virtual void destroy() = 0;
    7266            virtual T* get() const noexcept = 0;
    7367
    7468            virtual uint8_t* deleter() const noexcept = 0;
    7569
    76             virtual void increment() noexcept = 0;
    77             virtual void increment_weak() noexcept = 0;
    78             virtual bool decrement() noexcept = 0;
    79             virtual bool decrement_weak() noexcept = 0;
    80             virtual refcount_t refs() const noexcept = 0;
    81             virtual refcount_t weak_refs() const noexcept = 0;
    82             virtual bool expired() const noexcept = 0;
    8370            virtual shared_payload_base* lock() noexcept = 0;
    8471
     
    9178        public:
    9279            shared_payload(T* ptr, D deleter = D{})
    93                 : data_{ptr}, deleter_{deleter},
    94                   refcount_{1}, weak_refcount_{1}
     80                : data_{ptr}, deleter_{deleter}
    9581            { /* DUMMY BODY */ }
    9682
     
    9884            shared_payload(Args&&... args)
    9985                : data_{new T{forward<Args>(args)...}},
    100                   deleter_{}, refcount_{1}, weak_refcount_{1}
     86                  deleter_{}
    10187            { /* DUMMY BODY */ }
    10288
     
    10490            shared_payload(allocator_arg_t, Alloc alloc, Args&&... args)
    10591                : data_{alloc.allocate(1)},
    106                   deleter_{}, refcount_{1}, weak_refcount_{1}
     92                  deleter_{}
    10793            {
    10894                alloc.construct(data_, forward<Args>(args)...);
     
    11298            shared_payload(D deleter, Alloc alloc, Args&&... args)
    11399                : data_{alloc.allocate(1)},
    114                   deleter_{deleter}, refcount_{1}, weak_refcount_{1}
     100                  deleter_{deleter}
    115101            {
    116102                alloc.construct(data_, forward<Args>(args)...);
     
    119105            void destroy() override
    120106            {
    121                 if (refs() == 0)
     107                if (this->refs() == 0)
    122108                {
    123109                    if (data_)
     
    127113                    }
    128114
    129                     if (weak_refs() == 0)
     115                    if (this->weak_refs() == 0)
    130116                        delete this;
    131117                }
     
    142128            }
    143129
    144             void increment() noexcept override
    145             {
    146                 __atomic_add_fetch(&refcount_, 1, __ATOMIC_ACQ_REL);
    147             }
    148 
    149             void increment_weak() noexcept override
    150             {
    151                 __atomic_add_fetch(&weak_refcount_, 1, __ATOMIC_ACQ_REL);
    152             }
    153 
    154             bool decrement() noexcept override
    155             {
    156                 if (__atomic_sub_fetch(&refcount_, 1, __ATOMIC_ACQ_REL) == 0)
    157                 {
    158                     /**
    159                      * First call to destroy() will delete the held object,
    160                      * so it doesn't matter what the weak_refcount_ is,
    161                      * but we added one and we need to remove it now.
    162                      */
    163                     decrement_weak();
    164 
    165                     return true;
    166                 }
    167                 else
    168                     return false;
    169             }
    170 
    171             bool decrement_weak() noexcept override
    172             {
    173                 return __atomic_sub_fetch(&weak_refcount_, 1, __ATOMIC_ACQ_REL) == 0 && refs() == 0;
    174             }
    175 
    176             refcount_t refs() const noexcept override
    177             {
    178                 return __atomic_load_n(&refcount_, __ATOMIC_RELAXED);
    179             }
    180 
    181             refcount_t weak_refs() const noexcept override
    182             {
    183                 return __atomic_load_n(&weak_refcount_, __ATOMIC_RELAXED);
    184             }
    185 
    186             bool expired() const noexcept override
    187             {
    188                 return refs() == 0;
    189             }
    190 
    191130            shared_payload_base<T>* lock() noexcept override
    192131            {
    193                 refcount_t rfs = refs();
     132                refcount_t rfs = this->refs();
    194133                while (rfs != 0L)
    195134                {
    196                     if (__atomic_compare_exchange_n(&refcount_, &rfs, rfs + 1,
     135                    if (__atomic_compare_exchange_n(&this->refcount_, &rfs, rfs + 1,
    197136                                                    true, __ATOMIC_RELAXED,
    198137                                                    __ATOMIC_RELAXED))
     
    208147            T* data_;
    209148            D deleter_;
    210 
    211             /**
    212              * We're using a trick where refcount_ > 0
    213              * means weak_refcount_ has 1 added to it,
    214              * this makes it easier for weak_ptrs that
    215              * can't decrement the weak_refcount_ to
    216              * zero with shared_ptrs using this object.
    217              */
    218             refcount_t refcount_;
    219             refcount_t weak_refcount_;
    220149    };
    221150}
Note: See TracChangeset for help on using the changeset viewer.