Changeset 5735b111 in mainline for uspace/lib/cpp/include/internal/memory/shared_payload.hpp
- Timestamp:
- 2018-07-05T21:41:23Z (6 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 5df0491
- Parents:
- e13c378
- git-author:
- Dzejrou <dzejrou@…> (2018-05-09 20:16:49)
- git-committer:
- Dzejrou <dzejrou@…> (2018-07-05 21:41:23)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/cpp/include/internal/memory/shared_payload.hpp
re13c378 r5735b111 30 30 #define LIBCPP_INTERNAL_MEMORY_SHARED_PAYLOAD 31 31 32 #include <internal/list.hpp> 32 #include <cinttypes> 33 #include <utility> 34 35 namespace std 36 { 37 template<class> 38 struct default_delete; 39 40 struct allocator_arg_t; 41 } 33 42 34 43 namespace std::aux … … 40 49 using refcount_t = long; 41 50 51 template<class D, class T> 52 void use_payload_deleter(D* deleter, T* data) 53 { 54 if (deleter) 55 (*deleter)(data); 56 } 57 42 58 template<class T> 43 class shared_payload 59 class shared_payload_base 44 60 { 45 61 public: 62 virtual void destroy() = 0; 63 virtual T* get() const noexcept = 0; 64 65 virtual uint8_t* deleter() const noexcept = 0; 66 67 virtual void increment() noexcept = 0; 68 virtual void increment_weak() noexcept = 0; 69 virtual bool decrement() noexcept = 0; 70 virtual bool decrement_weak() noexcept = 0; 71 virtual refcount_t refs() const noexcept = 0; 72 virtual refcount_t weak_refs() const noexcept = 0; 73 virtual bool expired() const noexcept = 0; 74 75 virtual ~shared_payload_base() = default; 76 }; 77 78 template<class T, class D = default_delete<T>> 79 class shared_payload: public shared_payload_base<T> 80 { 81 public: 82 shared_payload(T* ptr, D deleter = D{}) 83 : data_{ptr}, deleter_{deleter}, 84 refcount_{1}, weak_refcount_{1} 85 { /* DUMMY BODY */ } 46 86 47 87 template<class... Args> 48 88 shared_payload(Args&&... args) 89 : data_{new T{forward<Args>(args)...}}, 90 deleter_{}, refcount_{1}, weak_refcount_{1} 49 91 { /* DUMMY BODY */ } 50 92 51 93 template<class Alloc, class... Args> 52 shared_payloda(Alloc alloc, Args&&... args) 53 { /* DUMMY BODY */ } 94 shared_payload(allocator_arg_t, Alloc alloc, Args&&... args) 95 : data_{alloc.allocate(1)}, 96 deleter_{}, refcount_{1}, weak_refcount_{1} 97 { 98 alloc.construct(data_, forward<Args>(args)...); 99 } 54 100 55 T* get() const 101 template<class Alloc, class... Args> 102 shared_payload(D deleter, Alloc alloc, Args&&... args) 103 : data_{alloc.allocate(1)}, 104 deleter_{deleter}, refcount_{1}, weak_refcount_{1} 105 { 106 alloc.construct(data_, forward<Args>(args)...); 107 } 108 109 void destroy() override 110 { 111 if (refs() == 0) 112 { 113 if (data_) 114 { 115 deleter_(data_); 116 data_ = nullptr; 117 } 118 119 if (weak_refs() == 0) 120 delete this; 121 } 122 } 123 124 T* get() const noexcept override 56 125 { 57 126 return data_; 58 127 } 59 128 60 void increment_refcount()129 uint8_t* deleter() const noexcept override 61 130 { 62 ++refcount_;131 return (uint8_t*)&deleter_; 63 132 } 64 133 65 void increment _weak_refcount()134 void increment() noexcept override 66 135 { 67 ++weak_refcount_;136 __atomic_add_fetch(&refcount_, 1, __ATOMIC_ACQ_REL); 68 137 } 69 138 70 bool decrement_refcount()139 void increment_weak() noexcept override 71 140 { 72 return --refcount_ == 0;141 __atomic_add_fetch(&weak_refcount_, 1, __ATOMIC_ACQ_REL); 73 142 } 74 143 75 bool decrement _weak_refcount()144 bool decrement() noexcept override 76 145 { 77 return --weak_refcount_ == 0; 146 if (__atomic_sub_fetch(&refcount_, 1, __ATOMIC_ACQ_REL) == 0) 147 return decrement_weak(); 148 else 149 return false; 78 150 } 79 151 80 refcount_t refs() const152 bool decrement_weak() noexcept override 81 153 { 82 return refcount_;154 return __atomic_sub_fetch(&weak_refcount_, 1, __ATOMIC_ACQ_REL) == 0 && refs() == 0; 83 155 } 84 156 85 refcount_t weak_refs() const157 refcount_t refs() const noexcept override 86 158 { 87 return weak_refcount_; 159 return __atomic_load_n(&refcount_, __ATOMIC_RELAXED); 160 } 161 162 refcount_t weak_refs() const noexcept override 163 { 164 return __atomic_load_n(&weak_refcount_, __ATOMIC_RELAXED); 165 } 166 167 bool expired() const noexcept override 168 { 169 return refs() == 0; 88 170 } 89 171 90 172 private: 91 173 T* data_; 174 D deleter_; 175 176 /** 177 * We're using a trick where refcount_ > 0 178 * means weak_refcount_ has 1 added to it, 179 * this makes it easier for weak_ptrs that 180 * can't decrement the weak_refcount_ to 181 * zero with shared_ptrs using this object. 182 */ 92 183 refcount_t refcount_; 93 184 refcount_t weak_refcount_;
Note:
See TracChangeset
for help on using the changeset viewer.