Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 1
//
2
// Copyright 2013 Francisco Jerez
3
//
4
// Permission is hereby granted, free of charge, to any person obtaining a
5
// copy of this software and associated documentation files (the "Software"),
6
// to deal in the Software without restriction, including without limitation
7
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
// and/or sell copies of the Software, and to permit persons to whom the
9
// Software is furnished to do so, subject to the following conditions:
10
//
11
// The above copyright notice and this permission notice shall be included in
12
// all copies or substantial portions of the Software.
13
//
14
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20
// OTHER DEALINGS IN THE SOFTWARE.
21
//
22
 
23
#ifndef CLOVER_UTIL_POINTER_HPP
24
#define CLOVER_UTIL_POINTER_HPP
25
 
26
#include 
27
 
28
namespace clover {
29
   ///
30
   /// Base class for objects that support reference counting.
31
   ///
32
   class ref_counter {
33
   public:
34
      ref_counter(unsigned value = 1) : _ref_count(value) {}
35
 
36
      unsigned
37
      ref_count() const {
38
         return _ref_count;
39
      }
40
 
41
      void
42
      retain() {
43
         _ref_count++;
44
      }
45
 
46
      bool
47
      release() {
48
         return (--_ref_count) == 0;
49
      }
50
 
51
   private:
52
      std::atomic _ref_count;
53
   };
54
 
55
   ///
56
   /// Simple reference to a clover::ref_counter object.  Unlike
57
   /// clover::intrusive_ptr and clover::intrusive_ref, it does nothing
58
   /// special when the reference count drops to zero.
59
   ///
60
   class ref_holder {
61
   public:
62
      ref_holder(ref_counter &o) : p(&o) {
63
         p->retain();
64
      }
65
 
66
      ref_holder(const ref_holder &ref) :
67
         ref_holder(*ref.p) {
68
      }
69
 
70
      ref_holder(ref_holder &&ref) :
71
         p(ref.p) {
72
         ref.p = NULL;
73
      }
74
 
75
      ~ref_holder() {
76
         if (p)
77
            p->release();
78
      }
79
 
80
      ref_holder &
81
      operator=(ref_holder ref) {
82
         std::swap(ref.p, p);
83
         return *this;
84
      }
85
 
86
      bool
87
      operator==(const ref_holder &ref) const {
88
         return p == ref.p;
89
      }
90
 
91
      bool
92
      operator!=(const ref_holder &ref) const {
93
         return p != ref.p;
94
      }
95
 
96
   private:
97
      ref_counter *p;
98
   };
99
 
100
   ///
101
   /// Intrusive smart pointer for objects that implement the
102
   /// clover::ref_counter interface.
103
   ///
104
   template
105
   class intrusive_ptr {
106
   public:
107
      intrusive_ptr(T *q = NULL) : p(q) {
108
         if (p)
109
            p->retain();
110
      }
111
 
112
      intrusive_ptr(const intrusive_ptr &ptr) :
113
         intrusive_ptr(ptr.p) {
114
      }
115
 
116
      intrusive_ptr(intrusive_ptr &&ptr) :
117
         p(ptr.p) {
118
         ptr.p = NULL;
119
      }
120
 
121
      ~intrusive_ptr() {
122
         if (p && p->release())
123
            delete p;
124
      }
125
 
126
      intrusive_ptr &
127
      operator=(intrusive_ptr ptr) {
128
         std::swap(ptr.p, p);
129
         return *this;
130
      }
131
 
132
      bool
133
      operator==(const intrusive_ptr &ref) const {
134
         return p == ref.p;
135
      }
136
 
137
      bool
138
      operator!=(const intrusive_ptr &ref) const {
139
         return p != ref.p;
140
      }
141
 
142
      T &
143
      operator*() const {
144
         return *p;
145
      }
146
 
147
      T *
148
      operator->() const {
149
         return p;
150
      }
151
 
152
      T *
153
      operator()() const {
154
         return p;
155
      }
156
 
157
      explicit operator bool() const {
158
         return p;
159
      }
160
 
161
      explicit operator T *() const {
162
         return p;
163
      }
164
 
165
   private:
166
      T *p;
167
   };
168
 
169
   ///
170
   /// Intrusive smart reference for objects that implement the
171
   /// clover::ref_counter interface.
172
   ///
173
   template
174
   class intrusive_ref {
175
   public:
176
      intrusive_ref(T &o) : p(&o) {
177
         p->retain();
178
      }
179
 
180
      intrusive_ref(const intrusive_ref &ref) :
181
         intrusive_ref(*ref.p) {
182
      }
183
 
184
      intrusive_ref(intrusive_ref &&ref) :
185
         p(ref.p) {
186
         ref.p = NULL;
187
      }
188
 
189
      ~intrusive_ref() {
190
         if (p && p->release())
191
            delete p;
192
      }
193
 
194
      intrusive_ref &
195
      operator=(intrusive_ref ref) {
196
         std::swap(ref.p, p);
197
         return *this;
198
      }
199
 
200
      bool
201
      operator==(const intrusive_ref &ref) const {
202
         return p == ref.p;
203
      }
204
 
205
      bool
206
      operator!=(const intrusive_ref &ref) const {
207
         return p != ref.p;
208
      }
209
 
210
      T &
211
      operator()() const {
212
         return *p;
213
      }
214
 
215
      operator T &() const {
216
         return *p;
217
      }
218
 
219
   private:
220
      T *p;
221
   };
222
 
223
   ///
224
   /// Initialize a clover::intrusive_ref from a newly created object
225
   /// using the specified constructor arguments.
226
   ///
227
   template
228
   intrusive_ref
229
   create(As &&... as) {
230
      intrusive_ref ref { *new T(std::forward(as)...) };
231
      ref().release();
232
      return ref;
233
   }
234
 
235
   ///
236
   /// Class that implements the usual pointer interface but in fact
237
   /// contains the object it seems to be pointing to.
238
   ///
239
   template
240
   class pseudo_ptr {
241
   public:
242
      pseudo_ptr(T x) : x(x) {
243
      }
244
 
245
      pseudo_ptr(const pseudo_ptr &p) : x(p.x) {
246
      }
247
 
248
      pseudo_ptr &
249
      operator=(const pseudo_ptr &p) {
250
         x = p.x;
251
         return *this;
252
      }
253
 
254
      T &
255
      operator*() {
256
         return x;
257
      }
258
 
259
      T *
260
      operator->() {
261
         return &x;
262
      }
263
 
264
      explicit operator bool() const {
265
         return true;
266
      }
267
 
268
   private:
269
      T x;
270
   };
271
}
272
 
273
#endif