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 14 15 93.3
branch 6 16 37.5
condition n/a
subroutine n/a
pod n/a
total 20 31 64.5


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