File Coverage

/usr/local/lib/perl5/site_perl/5.26.1/x86_64-linux/CPP/panda/lib.x/i/panda/refcnt.h
Criterion Covered Total %
statement 32 32 100.0
branch 39 58 67.2
condition n/a
subroutine n/a
pod n/a
total 71 90 78.8


line stmt bran cond sub pod time code
1             #pragma once
2             #include
3             #include
4             #include
5             #include
6              
7             namespace panda {
8              
9             static long int void_refcnt = 1;
10              
11             namespace {
12             template
13             struct HasRetain {
14             typedef char yes;
15             typedef char no[2];
16              
17             struct fallback { int retain; };
18             struct mixed_type: T, fallback {};
19             template < typename U, U > struct type_check {};
20              
21             template < typename U > static no& test( type_check< int (fallback::*), &U::retain >* = 0 );
22             template < typename U > static yes& test( ... );
23              
24             static const bool value = sizeof( yes ) == sizeof( test< mixed_type >( NULL ) );
25             };
26              
27             template
28             struct HasRelease {
29             typedef char yes;
30             typedef char no[2];
31              
32             struct fallback { int release; };
33             struct mixed_type: T, fallback {};
34             template < typename U, U > struct type_check {};
35              
36             template < typename U > static no& test( type_check< int (fallback::*), &U::release >* = 0 );
37             template < typename U > static yes& test( ... );
38              
39             static const bool value = sizeof( yes ) == sizeof( test< mixed_type >( NULL ) );
40             };
41              
42             template
43             struct IsRefCounted {
44             static const bool value = HasRelease::value && HasRetain::value;
45             };
46             }
47              
48             class Refcnt {
49             public:
50             void retain () const { ++_refcnt; }
51             void release () const { if (--_refcnt <= 0) delete this; }
52             int32_t refcnt () const { return _refcnt; }
53             protected:
54             Refcnt () : _refcnt(0) {}
55             virtual ~Refcnt () {}
56             private:
57             mutable int32_t _refcnt;
58             };
59              
60             template
61             class iptr {
62             public:
63             template friend class iptr;
64             typedef T element_type;
65              
66             iptr () : ptr(NULL) {}
67             iptr (T* pointer) : ptr(pointer) { if (ptr) ptr->retain(); }
68             iptr (const iptr& oth) : ptr(oth.ptr) { if (ptr) ptr->retain(); }
69             template
70             iptr (const iptr& oth) : ptr(oth.ptr) { if (ptr) ptr->retain(); }
71              
72             iptr (iptr&& oth) {
73             ptr = oth.ptr;
74             oth.ptr = NULL;
75             }
76              
77             template
78             iptr (iptr&& oth) {
79             ptr = oth.ptr;
80             oth.ptr = NULL;
81             }
82              
83             ~iptr () { if (ptr) ptr->release(); }
84              
85             iptr& operator= (T* pointer) {
86             if (ptr) ptr->release();
87             ptr = pointer;
88             if (pointer) pointer->retain();
89             return *this;
90             }
91              
92             iptr& operator= (const iptr& oth) { return iptr::operator=(oth.ptr); }
93             template
94             iptr& operator= (const iptr& oth) { return iptr::operator=(oth.ptr); }
95              
96             iptr& operator= (iptr&& oth) {
97             std::swap(ptr, oth.ptr);
98             return *this;
99             }
100              
101             template
102             iptr& operator= (iptr&& oth) {
103             if (ptr) ptr->release();
104             ptr = oth.ptr;
105             oth.ptr = NULL;
106             return *this;
107             }
108              
109             void reset () {
110             if (ptr) ptr->release();
111             ptr = NULL;
112             }
113              
114             void reset (T* p) { operator=(p); }
115              
116             T* operator-> () const { return ptr; }
117             T& operator* () const { return *ptr; }
118             operator T* () const { return ptr; }
119             explicit
120             operator bool () const { return ptr; }
121              
122             T* get () const { return ptr; }
123              
124             private:
125             T* ptr;
126             };
127              
128             template
129             inline iptr static_pointer_cast (const iptr& ptr) {
130             return iptr(static_cast(ptr.get()));
131             }
132              
133             template
134             inline iptr const_pointer_cast (const iptr& ptr) {
135             return iptr(const_cast(ptr.get()));
136             }
137              
138             template
139             inline iptr dynamic_pointer_cast (const iptr& ptr) {
140             return iptr(dyn_cast(ptr.get()));
141             }
142              
143             class RefCounted {
144             public:
145 130           void retain () const { ++_refcnt; on_retain(); }
146 130 100         void release () const { bool delete_me = --_refcnt <= 0; on_release(); if (delete_me && _refcnt <= 0) delete this; }
    50          
    50          
147             int32_t refcnt () const { return _refcnt; }
148             protected:
149 13           RefCounted () : _refcnt(0) {}
150 65           virtual void on_retain () const {}
151 65           virtual void on_release () const {}
152 26 50         virtual ~RefCounted () {}
153             private:
154             mutable int32_t _refcnt;
155             };
156              
157             template ::value>
158             class shared_ptr {};
159              
160             template
161             class shared_ptr {
162             public:
163             typedef T element_type;
164              
165 3           shared_ptr () : ptr(NULL) {}
166              
167 37           shared_ptr (T* pointer) : ptr(pointer) {
168 37 50         if (ptr) ptr->retain();
    50          
    50          
    50          
    100          
169 37           }
170              
171 65           shared_ptr (const shared_ptr& oth) : ptr(oth.ptr) {
172 65 100         if (ptr) ptr->retain();
    100          
    100          
173 65           }
174              
175             template
176 12           shared_ptr (const shared_ptr& oth) : ptr(oth.get()) {
177 6 50         if (ptr) ptr->retain();
    50          
    50          
    50          
178 6           }
179              
180 111           ~shared_ptr () {
181 111 50         if (ptr) ptr->release();
    50          
    50          
    50          
    100          
    100          
    100          
182 111           }
183              
184 21           shared_ptr& operator= (T* pointer) {
185 21 100         if (ptr) ptr->release();
186 21           ptr = pointer;
187 21 100         if (ptr) ptr->retain();
188 21           return *this;
189             }
190              
191 16           shared_ptr& operator= (const shared_ptr& oth) {
192 16           return shared_ptr::operator=(oth.ptr);
193             }
194              
195             void reset () {
196             if (ptr) ptr->release();
197             ptr = NULL;
198             }
199              
200             template
201             void reset (U* p) {
202             operator=(p);
203             }
204              
205 118           T* operator-> () const { return ptr; }
206             T& operator* () const { return *ptr; }
207 114           operator T* () const { return ptr; }
208 44           explicit operator bool () const { return ptr; }
209              
210 12           T* get () const { return ptr; }
211             long int use_count () const { return ptr->refcnt(); }
212             bool unique () const { return ptr->refcnt() == 1; }
213              
214             private:
215             T* ptr;
216             };
217              
218             template
219             class shared_ptr {
220             public:
221             typedef T element_type;
222              
223             shared_ptr () : ptr(NULL), refcnt(&void_refcnt) {
224             refcnt_inc();
225             }
226             shared_ptr (std::nullptr_t) : shared_ptr() {}
227              
228             explicit shared_ptr (T* pointer) {
229             ptr = pointer;
230             if (ptr) {
231             refcnt = new long int;
232             *refcnt = 1;
233             } else {
234             refcnt = &void_refcnt;
235             refcnt_inc();
236             }
237             }
238              
239             shared_ptr (const shared_ptr& oth) : ptr(oth.ptr), refcnt(oth.refcnt) {
240             refcnt_inc();
241             }
242              
243             template
244             shared_ptr (const shared_ptr& oth) : ptr(oth.ptr), refcnt(oth.refcnt) {
245             refcnt_inc();
246             }
247              
248             template
249             shared_ptr (const shared_ptr& oth, T* pointer) : ptr(pointer), refcnt(oth.refcnt) {
250             refcnt_inc();
251             }
252              
253             ~shared_ptr () {
254             refcnt_dec();
255             }
256              
257             shared_ptr& operator= (const shared_ptr& oth) {
258             refcnt_dec();
259             ptr = oth.ptr;
260             refcnt = oth.refcnt;
261             refcnt_inc();
262             return *this;
263             }
264              
265             void reset () {
266             refcnt_dec();
267             ptr = NULL;
268             refcnt = &void_refcnt;
269             refcnt_inc();
270             }
271              
272             template
273             void reset (U* p) {
274             operator=(p);
275             }
276              
277             T* operator-> () const { return ptr; }
278             T& operator* () const { return *ptr; }
279             operator T* () const { return ptr; }
280             explicit operator bool () const { return ptr; }
281              
282             T* get () const { return ptr; }
283             long int use_count () const { return *refcnt; }
284             bool unique () const { return *refcnt == 1; }
285              
286             template friend class shared_ptr;
287              
288             private:
289             T* ptr;
290             long int* refcnt;
291              
292             void refcnt_inc () {
293             ++*refcnt;
294             }
295              
296             void refcnt_dec () {
297             if (--*refcnt <= 0) {
298             delete ptr;
299             delete refcnt;
300             }
301             }
302             };
303              
304             template
305             inline shared_ptr static_pointer_cast (const shared_ptr& shptr) {
306             return shared_ptr(shptr, static_cast(shptr.get()));
307             }
308              
309             template
310             inline shared_ptr static_pointer_cast (const shared_ptr& shptr) {
311             return shared_ptr(static_cast(shptr.get()));
312             }
313              
314             template
315             inline shared_ptr const_pointer_cast (const shared_ptr& shptr) {
316             return shared_ptr(shptr, const_cast(shptr.get()));
317             }
318              
319             template
320             inline shared_ptr const_pointer_cast (const shared_ptr& shptr) {
321             return shared_ptr(const_cast(shptr.get()));
322             }
323              
324             template
325             inline shared_ptr dynamic_pointer_cast (const shared_ptr& shptr) {
326             if (T1* p = dyn_cast(shptr.get())) return shared_ptr(shptr, p);
327             return shared_ptr();
328             }
329              
330             template
331             inline shared_ptr dynamic_pointer_cast (const shared_ptr& shptr) {
332             if (T1* p = dyn_cast(shptr.get())) return shared_ptr(p);
333             return shared_ptr();
334             }
335              
336             template
337             inline std::shared_ptr static_pointer_cast (const std::shared_ptr& shptr) {
338             return std::static_pointer_cast(shptr);
339             }
340             template
341             inline std::shared_ptr const_pointer_cast (const std::shared_ptr& shptr) {
342             return std::const_pointer_cast(shptr);
343             }
344             template
345             inline std::shared_ptr dynamic_pointer_cast (const std::shared_ptr& shptr) {
346             return std::dynamic_pointer_cast(shptr);
347             }
348              
349             namespace {
350             template ::value>
351             struct make_shared_impl;
352              
353             template
354             struct make_shared_impl {
355             template
356             static shared_ptr make_shared(Args&&... args) {
357             return new T(std::forward(args)...);
358             }
359             };
360              
361             template
362             struct make_shared_impl {
363             template
364             static shared_ptr make_shared(Args&&... args) {
365             struct tmp : public T, public virtual RefCounted {
366             using T::T;
367             };
368              
369             return new tmp(std::forward(args)...);
370             }
371             };
372             }
373              
374             template
375 9           shared_ptr make_shared(Args&&... args) {
376             //return make_shared_impl::make_shared(std::forward(args)...);
377 9 50         return shared_ptr(new T(std::forward(args)...));
    50          
    50          
    50          
378             }
379              
380             }