Tamer
C++ language extensions for event-driven programming
Loading...
Searching...
No Matches
ref.hh
1#ifndef TAMER_REF_HH
2#define TAMER_REF_HH 1
3/* Copyright (c) 2007-2015, Eddie Kohler
4 * Copyright (c) 2007, Regents of the University of California
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, subject to the conditions
9 * listed in the Tamer LICENSE file. These conditions include: you must
10 * preserve this copyright notice, and you cannot mention the copyright
11 * holders in advertising related to the Software without their permission.
12 * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
13 * notice is a summary of the Tamer LICENSE file; the license in that file is
14 * legally binding.
15 */
16namespace tamer {
17
18class ref;
19
20class ref_monitor {
21 public:
22 explicit inline ref_monitor(ref& m);
23 inline ~ref_monitor() {
24 if (pprev_)
25 *pprev_ = next_;
26 if (next_)
27 next_->pprev_ = pprev_;
28 }
29
30 bool empty() const {
31 return !pprev_;
32 }
33 explicit operator bool() const {
34 return pprev_;
35 }
36
37 private:
38 ref_monitor** pprev_;
39 ref_monitor* next_;
40
41 ref_monitor(const ref_monitor&);
42 ref_monitor& operator=(const ref_monitor&);
43 friend class ref;
44};
45
46class ref {
47 public:
48 ref()
49 : first_(0) {
50 }
51 ~ref() {
52 while (ref_monitor* w = first_) {
53 first_ = w->next_;
54 w->pprev_ = 0;
55 w->next_ = 0;
56 }
57 }
58
59 private:
60 ref_monitor* first_;
61
62 ref(const ref&);
63 ref& operator=(const ref&);
64 friend class ref_monitor;
65};
66
67inline ref_monitor::ref_monitor(ref& m)
68 : pprev_(&m.first_), next_(m.first_) {
69 if (next_)
70 next_->pprev_ = &next_;
71 m.first_ = this;
72}
73
74
75template <typename T> class enable_ref_ptr_with_full_release;
76template <typename T> class ref_ptr;
77template <typename T> class passive_ref_ptr;
78
79class enable_ref_ptr { public:
80
81 enable_ref_ptr()
82 : _use_count(1), _weak_count(0) {
83 }
84
85 ~enable_ref_ptr() {
86 assert(!_use_count && !_weak_count);
87 }
88
89 private:
90
91 uint32_t _use_count;
92 uint32_t _weak_count;
93
94 enable_ref_ptr(const enable_ref_ptr &);
95 enable_ref_ptr &operator=(const enable_ref_ptr &);
96
97 template <typename T> friend class enable_ref_ptr_with_full_release;
98 template <typename T> friend class ref_ptr;
99 template <typename T> friend class passive_ref_ptr;
100
101 void add_ref_copy() {
102 ++_use_count;
103 }
104
105 bool release() {
106 assert(_use_count);
107 return --_use_count == 0 && _weak_count == 0;
108 }
109
110 void weak_add_ref() {
111 ++_weak_count;
112 }
113
114 bool weak_release() {
115 assert(_weak_count);
116 return --_weak_count == 0 && _use_count == 0;
117 }
118
119 uint32_t use_count() const {
120 return _use_count;
121 }
122
123};
124
125
126template <typename T> class enable_ref_ptr_with_full_release : public enable_ref_ptr { public:
127
128 enable_ref_ptr_with_full_release() {
129 }
130
131 ~enable_ref_ptr_with_full_release() {
132 }
133
134 private:
135
136 template <typename U> friend class ref_ptr;
137 template <typename U> friend class passive_ref_ptr;
138
139 bool release() {
140 assert(_use_count);
141 if (_use_count == 1)
142 static_cast<T *>(this)->full_release();
143 return --_use_count == 0 && _weak_count == 0;
144 }
145
146};
147
148
149template <typename T> class ref_ptr { public:
150
151 ref_ptr()
152 : _t(0) {
153 }
154
155 template <typename U> explicit ref_ptr(U* ptr)
156 : _t(ptr) {
157 assert(!_t || _t->use_count() == 1);
158 }
159
160 ref_ptr(const ref_ptr<T>& x)
161 : _t(x._t) {
162 if (_t)
163 _t->add_ref_copy();
164 }
165
166 ref_ptr(ref_ptr<T>&& x)
167 : _t(x._t) {
168 x._t = 0;
169 }
170
171 template <typename U> ref_ptr(const ref_ptr<U>& x)
172 : _t(x._t) {
173 if (_t)
174 _t->add_ref_copy();
175 }
176
177 ~ref_ptr() {
178 if (_t && _t->release())
179 delete _t;
180 }
181
182 ref_ptr<T>& operator=(const ref_ptr<T>& x) {
183 if (x._t)
184 x._t->add_ref_copy();
185 if (_t && _t->release())
186 delete _t;
187 _t = x._t;
188 return *this;
189 }
190
191 ref_ptr<T>& operator=(ref_ptr<T>&& x) {
192 std::swap(_t, x._t);
193 return *this;
194 }
195
196 template <typename U> ref_ptr<T>& operator=(const ref_ptr<U>& x) {
197 if (x._t)
198 x._t->add_ref_copy();
199 if (_t && _t->release())
200 delete _t;
201 _t = x._t;
202 return *this;
203 }
204
205 T& operator*() const {
206 return *_t;
207 }
208
209 T* operator->() const {
210 return _t;
211 }
212
213 T* get() const {
214 return _t;
215 }
216
217 explicit operator bool() const {
218 return _t;
219 }
220
221 private:
222 T* _t;
223};
224
225
226template <typename T> class passive_ref_ptr { public:
227
228 passive_ref_ptr()
229 : _t(0) {
230 }
231
232 template <typename U> explicit passive_ref_ptr(U* ptr)
233 : _t(ptr) {
234 if (_t)
235 _t->weak_add_ref();
236 }
237
238 template <typename U> explicit passive_ref_ptr(const ref_ptr<U>& x)
239 : _t(x.operator->()) {
240 if (_t)
241 _t->weak_add_ref();
242 }
243
244 passive_ref_ptr(const passive_ref_ptr<T>& x)
245 : _t(x._t) {
246 if (_t)
247 _t->weak_add_ref();
248 }
249
250 passive_ref_ptr(passive_ref_ptr<T>&& x)
251 : _t(x._t) {
252 x._t = 0;
253 }
254
255 template <typename U> passive_ref_ptr(const passive_ref_ptr<U>& x)
256 : _t(x._t) {
257 if (_t)
258 _t->weak_add_ref();
259 }
260
261 ~passive_ref_ptr() {
262 if (_t && _t->weak_release())
263 delete _t;
264 }
265
266 passive_ref_ptr<T>& operator=(const passive_ref_ptr<T>& x) {
267 if (x._t)
268 x._t->weak_add_ref();
269 if (_t && _t->weak_release())
270 delete _t;
271 _t = x._t;
272 return *this;
273 }
274
275 passive_ref_ptr<T>& operator=(passive_ref_ptr<T>&& x) {
276 std::swap(_t, x._t);
277 return *this;
278 }
279
280 template <typename U> passive_ref_ptr<T>& operator=(const passive_ref_ptr<U>& x) {
281 if (x._t)
282 x._t->weak_add_ref();
283 if (_t && _t->weak_release())
284 delete _t;
285 _t = x._t;
286 return *this;
287 }
288
289 T& operator*() const {
290 return *_t;
291 }
292
293 T* operator->() const {
294 return _t;
295 }
296
297 T* get() const {
298 return _t;
299 }
300
301 explicit operator bool() const {
302 return _t;
303 }
304
305 private:
306 T* _t;
307};
308
309
310template <typename T, typename U>
311inline bool operator==(const ref_ptr<T> &a, const ref_ptr<T> &b)
312{
313 return a.get() == b.get();
314}
315
316template <typename T, typename U>
317inline bool operator!=(const ref_ptr<T> &a, const ref_ptr<T> &b)
318{
319 return a.get() != b.get();
320}
321
322template <typename T, typename U>
323inline bool operator==(const passive_ref_ptr<T> &a, const passive_ref_ptr<T> &b)
324{
325 return a.get() == b.get();
326}
327
328template <typename T, typename U>
329inline bool operator!=(const passive_ref_ptr<T> &a, const passive_ref_ptr<T> &b)
330{
331 return a.get() != b.get();
332}
333
334}
335#endif /* TAMER_REF_HH */
Namespace containing public Tamer classes and functions for the Tamer core.
Definition adapter.hh:17
bool operator!=(const fd &a, const fd &b)
Test whether two file descriptors refer to the same object.
Definition fd.hh:698
bool operator==(const fd &a, const fd &b)
Test whether two file descriptors refer to the same object.
Definition fd.hh:689