|
1
|
1 #pragma once
|
|
|
2
|
|
|
3 namespace pfc {
|
|
|
4
|
|
|
5 struct _rcptr_null;
|
|
|
6 typedef _rcptr_null* t_rcptr_null;
|
|
|
7
|
|
|
8 static const t_rcptr_null rcptr_null = NULL;
|
|
|
9
|
|
|
10 class rc_container_base {
|
|
|
11 public:
|
|
|
12 long add_ref() throw() {
|
|
|
13 return ++m_counter;
|
|
|
14 }
|
|
|
15 long release() throw() {
|
|
|
16 long ret = --m_counter;
|
|
|
17 if (ret == 0) PFC_ASSERT_NO_EXCEPTION( delete this );
|
|
|
18 return ret;
|
|
|
19 }
|
|
|
20 protected:
|
|
|
21 virtual ~rc_container_base() {}
|
|
|
22 private:
|
|
|
23 refcounter m_counter;
|
|
|
24 };
|
|
|
25
|
|
|
26 template<typename t_object>
|
|
|
27 class rc_container_t : public rc_container_base {
|
|
|
28 public:
|
|
|
29 template<typename ... arg_t>
|
|
|
30 rc_container_t(arg_t && ... arg) : m_object(std::forward<arg_t>(arg) ...) {}
|
|
|
31
|
|
|
32 t_object m_object;
|
|
|
33 };
|
|
|
34
|
|
|
35 template<typename t_object>
|
|
|
36 class rcptr_t {
|
|
|
37 private:
|
|
|
38 typedef rcptr_t<t_object> t_self;
|
|
|
39 typedef rc_container_base t_container;
|
|
|
40 typedef rc_container_t<t_object> t_container_impl;
|
|
|
41 public:
|
|
|
42 rcptr_t(t_rcptr_null) throw() {_clear();}
|
|
|
43 rcptr_t() throw() {_clear();}
|
|
|
44 rcptr_t(const t_self & p_source) throw() {__init(p_source);}
|
|
|
45 t_self const & operator=(const t_self & p_source) throw() {__copy(p_source); return *this;}
|
|
|
46
|
|
|
47 template<typename t_source>
|
|
|
48 rcptr_t(const rcptr_t<t_source> & p_source) throw() {__init(p_source);}
|
|
|
49 template<typename t_source>
|
|
|
50 const t_self & operator=(const rcptr_t<t_source> & p_source) throw() {__copy(p_source); return *this;}
|
|
|
51
|
|
|
52 rcptr_t(t_self && p_source) throw() {_move(p_source);}
|
|
|
53 const t_self & operator=(t_self && p_source) throw() {release(); _move(p_source); return *this;}
|
|
|
54
|
|
|
55 const t_self & operator=(t_rcptr_null) throw() {release(); return *this;}
|
|
|
56
|
|
|
57 /* template<typename t_object_cast>
|
|
|
58 operator rcptr_t<t_object_cast>() const throw() {
|
|
|
59 rcptr_t<t_object_cast> temp;
|
|
|
60 if (is_valid()) temp.__set_from_cast(this->m_container,this->m_ptr);
|
|
|
61 return temp;
|
|
|
62 }*/
|
|
|
63
|
|
|
64
|
|
|
65 template<typename t_other>
|
|
|
66 bool operator==(const rcptr_t<t_other> & p_other) const throw() {
|
|
|
67 return m_container == p_other.__container();
|
|
|
68 }
|
|
|
69
|
|
|
70 template<typename t_other>
|
|
|
71 bool operator!=(const rcptr_t<t_other> & p_other) const throw() {
|
|
|
72 return m_container != p_other.__container();
|
|
|
73 }
|
|
|
74
|
|
|
75 void __set_from_cast(t_container * p_container,t_object * p_ptr) throw() {
|
|
|
76 //addref first because in rare cases this is the same pointer as the one we currently own
|
|
|
77 if (p_container != NULL) p_container->add_ref();
|
|
|
78 release();
|
|
|
79 m_container = p_container;
|
|
|
80 m_ptr = p_ptr;
|
|
|
81 }
|
|
|
82
|
|
|
83 bool is_valid() const throw() {return m_container != NULL;}
|
|
|
84 bool is_empty() const throw() {return m_container == NULL;}
|
|
|
85
|
|
|
86
|
|
|
87 ~rcptr_t() throw() {release();}
|
|
|
88
|
|
|
89 void release() throw() {
|
|
|
90 t_container * temp = m_container;
|
|
|
91 m_ptr = NULL;
|
|
|
92 m_container = NULL;
|
|
|
93 if (temp != NULL) temp->release();
|
|
|
94 }
|
|
|
95
|
|
|
96
|
|
|
97 template<typename t_object_cast>
|
|
|
98 rcptr_t<t_object_cast> static_cast_t() const throw() {
|
|
|
99 rcptr_t<t_object_cast> temp;
|
|
|
100 if (is_valid()) temp.__set_from_cast(this->m_container,static_cast<t_object_cast*>(this->m_ptr));
|
|
|
101 return temp;
|
|
|
102 }
|
|
|
103
|
|
|
104 void new_t() {
|
|
|
105 on_new(new t_container_impl());
|
|
|
106 }
|
|
|
107
|
|
|
108 template<typename ... arg_t>
|
|
|
109 void new_t(arg_t && ... arg) {
|
|
|
110 on_new(new t_container_impl(std::forward<arg_t>(arg) ...));
|
|
|
111 }
|
|
|
112
|
|
|
113 static t_self g_new_t() {
|
|
|
114 t_self temp;
|
|
|
115 temp.new_t();
|
|
|
116 return temp;
|
|
|
117 }
|
|
|
118
|
|
|
119 template<typename ... arg_t>
|
|
|
120 static t_self g_new_t(arg_t && ... arg) {
|
|
|
121 t_self temp;
|
|
|
122 temp.new_t(std::forward<arg_t>(arg) ...);
|
|
|
123 return temp;
|
|
|
124 }
|
|
|
125
|
|
|
126 t_object & operator*() const throw() {return *this->m_ptr;}
|
|
|
127
|
|
|
128 t_object * operator->() const throw() {return this->m_ptr;}
|
|
|
129
|
|
|
130
|
|
|
131 t_container * __container() const throw() {return m_container;}
|
|
|
132
|
|
|
133 // FOR INTERNAL USE ONLY
|
|
|
134 void _clear() throw() {m_container = NULL; m_ptr = NULL;}
|
|
|
135 private:
|
|
|
136
|
|
|
137 template<typename t_source>
|
|
|
138 void __init(const rcptr_t<t_source> & p_source) throw() {
|
|
|
139 m_container = p_source.__container();
|
|
|
140 m_ptr = &*p_source;
|
|
|
141 if (m_container != NULL) m_container->add_ref();
|
|
|
142 }
|
|
|
143 template<typename t_source>
|
|
|
144 void _move(rcptr_t<t_source> & p_source) throw() {
|
|
|
145 m_container = p_source.__container();
|
|
|
146 m_ptr = &*p_source;
|
|
|
147 p_source._clear();
|
|
|
148 }
|
|
|
149 template<typename t_source>
|
|
|
150 void __copy(const rcptr_t<t_source> & p_source) throw() {
|
|
|
151 __set_from_cast(p_source.__container(),&*p_source);
|
|
|
152 }
|
|
|
153 void on_new(t_container_impl * p_container) throw() {
|
|
|
154 this->release();
|
|
|
155 p_container->add_ref();
|
|
|
156 this->m_ptr = &p_container->m_object;
|
|
|
157 this->m_container = p_container;
|
|
|
158 }
|
|
|
159
|
|
|
160 t_container * m_container;
|
|
|
161 t_object * m_ptr;
|
|
|
162 };
|
|
|
163
|
|
|
164 template<typename t_object, typename ... arg_t>
|
|
|
165 rcptr_t<t_object> rcnew_t(arg_t && ... arg) {
|
|
|
166 rcptr_t<t_object> temp;
|
|
|
167 temp.new_t(std::forward<arg_t>(arg) ...);
|
|
|
168 return temp;
|
|
|
169 }
|
|
|
170
|
|
|
171 class traits_rcptr : public traits_default {
|
|
|
172 public:
|
|
|
173 enum { realloc_safe = true, constructor_may_fail = false };
|
|
|
174 };
|
|
|
175
|
|
|
176 template<typename T> class traits_t<rcptr_t<T> > : public traits_rcptr {};
|
|
|
177 } |