File Coverage

/usr/local/lib/perl5/site_perl/5.26.1/x86_64-linux/XS/libpanda.x/i/panda/refcnt.h
Criterion Covered Total %
statement 11 26 42.3
branch 3 14 21.4
condition n/a
subroutine n/a
pod n/a
total 14 40 35.0


line stmt bran cond sub pod time code
1             #pragma once
2             #include "cast.h"
3             #include "traits.h"
4             #include
5             #include
6             #include
7             #include
8             #include
9              
10             namespace panda {
11              
12             using std::nullptr_t;
13              
14             template
15             struct iptr {
16             template friend struct iptr;
17             typedef T element_type;
18              
19 0           constexpr iptr () : ptr(NULL) {}
20              
21 28 100         iptr (T* pointer) : ptr(pointer) { if (ptr) refcnt_inc(ptr); }
22 24 50         iptr (const iptr& oth) : ptr(oth.ptr) { if (ptr) refcnt_inc(ptr); }
23              
24             template >
25             iptr (const iptr& oth) : ptr(oth.ptr) { if (ptr) refcnt_inc(ptr); }
26              
27 53           iptr (iptr&& oth) {
28 53           ptr = oth.ptr;
29 53           oth.ptr = NULL;
30 53           }
31              
32             template >
33             iptr (iptr&& oth) {
34             ptr = oth.ptr;
35             oth.ptr = NULL;
36             }
37              
38 0 0         ~iptr () { if (ptr) refcnt_dec(ptr); }
39              
40 0           iptr& operator= (T* pointer) {
41 0 0         if (pointer) refcnt_inc(pointer);
42 0 0         if (ptr) refcnt_dec(ptr);
43 0           ptr = pointer;
44 0           return *this;
45             }
46              
47 0           iptr& operator= (const iptr& oth) { return operator=(oth.ptr); }
48              
49             template >
50             iptr& operator= (const iptr& oth) { return operator=(oth.ptr); }
51              
52 125           iptr& operator= (iptr&& oth) {
53 125           std::swap(ptr, oth.ptr);
54 125           return *this;
55             }
56              
57             template >
58             iptr& operator= (iptr&& oth) {
59             if (ptr) {
60             if (ptr == oth.ptr) return *this;
61             refcnt_dec(ptr);
62             }
63             ptr = oth.ptr;
64             oth.ptr = NULL;
65             return *this;
66             }
67              
68             void reset () {
69             if (ptr) refcnt_dec(ptr);
70             ptr = NULL;
71             }
72              
73             void reset (T* p) { operator=(p); }
74              
75 2816           T* operator-> () const noexcept { return ptr; }
76             T& operator* () const noexcept { return *ptr; }
77 2536           operator T* () const noexcept { return ptr; }
78              
79             explicit
80 0           operator bool () const noexcept { return ptr; }
81              
82             T* get () const noexcept { return ptr; }
83              
84             uint32_t use_count () const noexcept { return refcnt_get(ptr); }
85              
86             T* detach () noexcept {
87             auto ret = ptr;
88             ptr = nullptr;
89             return ret;
90             }
91              
92             void swap (iptr& oth) noexcept {
93             std::swap(ptr, oth.ptr);
94             }
95              
96             private:
97             T* ptr;
98             };
99              
100             template inline bool operator== (const iptr& x, const iptr& y) { return x.get() == y.get(); }
101             template inline bool operator!= (const iptr& x, const iptr& y) { return x.get() != y.get(); }
102             template inline bool operator< (const iptr& x, const iptr& y) { return x.get() < y.get(); }
103             template inline bool operator<= (const iptr& x, const iptr& y) { return x.get() <= y.get(); }
104             template inline bool operator> (const iptr& x, const iptr& y) { return x.get() > y.get(); }
105             template inline bool operator>= (const iptr& x, const iptr& y) { return x.get() >= y.get(); }
106              
107             template inline bool operator== (const iptr& x, nullptr_t) noexcept { return !x.get(); }
108             template inline bool operator== (nullptr_t, const iptr& x) noexcept { return !x.get(); }
109             template inline bool operator!= (const iptr& x, nullptr_t) noexcept { return x.get(); }
110             template inline bool operator!= (nullptr_t, const iptr& x) noexcept { return x.get(); }
111             template inline bool operator< (const iptr& x, nullptr_t) noexcept { return x.get() < nullptr; }
112             template inline bool operator< (nullptr_t, const iptr& x) noexcept { return nullptr < x.get(); }
113             template inline bool operator<= (const iptr& x, nullptr_t) noexcept { return x.get() <= nullptr; }
114             template inline bool operator<= (nullptr_t, const iptr& x) noexcept { return nullptr <= x.get(); }
115             template inline bool operator> (const iptr& x, nullptr_t) noexcept { return x.get() > nullptr; }
116             template inline bool operator> (nullptr_t, const iptr& x) noexcept { return nullptr > x.get(); }
117             template inline bool operator>= (const iptr& x, nullptr_t) noexcept { return x.get() >= nullptr; }
118             template inline bool operator>= (nullptr_t, const iptr& x) noexcept { return nullptr >= x.get(); }
119              
120             template
121             iptr make_iptr (Args&&... args) {
122             return iptr(new T(std::forward(args)...));
123             }
124              
125             template
126             void swap (iptr& a, iptr& b) noexcept { a.swap(b); }
127              
128             struct weak_storage;
129              
130             struct Refcnt {
131             using weak_storage_type = weak_storage;
132              
133             //Refcnt (const Refcnt&) : Refcnt() {}
134              
135             void retain () const { ++_refcnt; }
136             void release () const {
137             if (_refcnt > 1) --_refcnt;
138             else delete this;
139             }
140             uint32_t refcnt () const noexcept { return _refcnt; }
141              
142             protected:
143             Refcnt () : _refcnt(0) {}
144             virtual ~Refcnt ();
145              
146             private:
147             friend iptr refcnt_weak (const Refcnt*);
148              
149             mutable uint32_t _refcnt;
150             mutable iptr _weak;
151              
152             iptr get_weak () const;
153             };
154              
155             struct Refcntd : Refcnt {
156             void release () const {
157             if (refcnt() <= 1) const_cast(this)->on_delete();
158             Refcnt::release();
159             }
160              
161             protected:
162             virtual void on_delete () noexcept {}
163             };
164              
165             struct weak_storage : public Refcnt {
166             weak_storage () : valid(true) {}
167             bool valid;
168             };
169              
170             struct atomic_weak_storage;
171              
172             struct AtomicRefcnt {
173             using weak_storage_type = atomic_weak_storage;
174              
175             AtomicRefcnt (const AtomicRefcnt&) : AtomicRefcnt() {}
176              
177 0           void retain () const { ++_refcnt; }
178 0           void release () const {
179 0 0         if (!--_refcnt) delete this;
    0          
180 0           }
181             uint32_t refcnt () const noexcept { return _refcnt; }
182              
183             protected:
184             AtomicRefcnt () : _refcnt(0) {}
185             virtual ~AtomicRefcnt ();
186              
187             private:
188             friend iptr refcnt_weak (const AtomicRefcnt*);
189              
190             mutable std::atomic _refcnt;
191             mutable iptr _weak;
192              
193             iptr get_weak () const;
194             };
195              
196             struct atomic_weak_storage : public AtomicRefcnt {
197             atomic_weak_storage () : valid(true) {}
198             bool valid;
199             };
200              
201             inline void refcnt_inc (const Refcnt* o) { o->retain(); }
202             inline void refcnt_dec (const Refcnt* o) { o->release(); }
203             inline uint32_t refcnt_get (const Refcnt* o) { return o->refcnt(); }
204             inline iptr refcnt_weak (const Refcnt* o) { return o->get_weak(); }
205              
206             inline void refcnt_dec (const Refcntd* o) { o->release(); }
207              
208 0           inline void refcnt_inc (const AtomicRefcnt* o) { o->retain(); }
209 0           inline void refcnt_dec (const AtomicRefcnt* o) { o->release(); }
210             inline uint32_t refcnt_get (const AtomicRefcnt* o) { return o->refcnt(); }
211             inline iptr refcnt_weak (const AtomicRefcnt* o) { return o->get_weak(); }
212              
213             template inline iptr static_pointer_cast (const iptr& ptr) { return iptr(static_cast(ptr.get())); }
214             template inline iptr const_pointer_cast (const iptr& ptr) { return iptr(const_cast(ptr.get())); }
215             template inline iptr dynamic_pointer_cast (const iptr& ptr) { return iptr(dyn_cast(ptr.get())); }
216              
217             template inline std::shared_ptr static_pointer_cast (const std::shared_ptr& shptr) { return std::static_pointer_cast(shptr); }
218             template inline std::shared_ptr const_pointer_cast (const std::shared_ptr& shptr) { return std::const_pointer_cast(shptr); }
219             template inline std::shared_ptr dynamic_pointer_cast (const std::shared_ptr& shptr) { return std::dynamic_pointer_cast(shptr); }
220              
221             template
222             struct weak_iptr {
223             template friend struct weak_iptr;
224             using element_type = T;
225             using storage_type = typename T::weak_storage_type;
226              
227             weak_iptr() : storage(nullptr), object(nullptr) {}
228             weak_iptr(const weak_iptr&) = default;
229             weak_iptr& operator=(const weak_iptr& o) = default;
230              
231             weak_iptr(weak_iptr&&) = default;
232             weak_iptr& operator=(weak_iptr&& o) = default;
233              
234             template >
235             weak_iptr(const iptr& src) : storage(src ? refcnt_weak(src.get()) : nullptr), object(src ? src.get() : nullptr) {}
236              
237             template >
238             weak_iptr(const weak_iptr& src) : storage(src.storage), object(src.object) {}
239              
240             template
241             weak_iptr& operator=(const weak_iptr& o) {
242             storage = o.storage;
243             object = o.object;
244             return *this;
245             }
246              
247             template
248             weak_iptr& operator=(const iptr& src) {
249             storage = src ? refcnt_weak(src.get()) : nullptr;
250             object = src ? src.get() : nullptr;
251             return *this;
252             }
253              
254             template
255             weak_iptr& operator=(weak_iptr&& o) {
256             storage = std::move(o.storage);
257             object = std::move(o.object);
258             return *this;
259             }
260              
261             iptr lock() const {
262             return expired() ? nullptr : object;
263             }
264              
265             bool expired() const {
266             return !operator bool();
267             }
268              
269             explicit operator bool() const {
270             return storage && storage->valid;
271             }
272              
273             size_t use_count() const {
274             return *this ? refcnt_get(object) : 0;
275             }
276              
277             size_t weak_count() const {
278             if (!storage) return 0;
279             if (storage->valid) return storage.use_count() - 1; // object itself refers to weak storage, ignore this reference in count
280             return storage.use_count();
281             }
282              
283             void reset() noexcept {
284             storage.reset();
285             object = nullptr;
286             }
287              
288             void swap(weak_iptr& oth) noexcept {
289             storage.swap(oth.storage);
290             std::swap(object, oth.object);
291             }
292              
293             private:
294             iptr storage;
295             T* object; // it is cache, it never invalidates itself, use storage->object to check validity
296             };
297              
298             template
299             void swap(weak_iptr& a, weak_iptr& b) noexcept { a.swap(b); }
300              
301             template struct _weak_t;
302             template struct _weak_t> {
303             using type = weak_iptr;
304             };
305              
306             template
307             using weak = typename _weak_t::type;
308              
309             }