The Pedigree Project  0.1
SharedPointer.h
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #ifndef SHAREDPOINTER_H
21 #define SHAREDPOINTER_H
22 
23 #include "pedigree/kernel/processor/types.h"
24 #include "pedigree/kernel/utilities/utility.h"
25 
30 template <class T>
32 {
33  public:
37  SharedPointer();
38 
42  SharedPointer(T *ptr);
43 
50 
54  virtual ~SharedPointer();
55 
60 
64  void reset();
69  void reset(T *ptr);
70 
74  T *get() const;
75 
79  T *operator->() const;
80 
84  T &operator*() const;
85 
91 
96 
100  explicit operator bool() const;
101 
105  bool unique() const;
106 
110  size_t refcount() const;
111 
115  template <class... Args>
116  static SharedPointer<T> allocate(Args...);
117 
122  bool operator==(const SharedPointer &p) const;
123  bool operator!=(const SharedPointer &p) const;
124  bool operator<(const SharedPointer &p) const;
125  bool operator<=(const SharedPointer &p) const;
126  bool operator>(const SharedPointer &p) const;
127  bool operator>=(const SharedPointer &p) const;
128 
129  private:
133  void release();
134 
139  struct Control
140  {
141  T *ptr;
142  size_t refcount;
143  } * m_Control;
144 };
145 
146 template <class T>
148 {
149 }
150 
151 template <class T>
152 SharedPointer<T>::SharedPointer(T *ptr) : m_Control(0)
153 {
154  reset(ptr);
155 }
156 
157 template <class T>
159 {
160  m_Control = pedigree_std::move(other.m_Control);
161 
162  other.m_Control = nullptr;
163 }
164 
165 template <class T>
167 {
168  release();
169 }
170 
171 template <class T>
173 {
174  if (p.m_Control)
175  {
176  __atomic_add_fetch(&p.m_Control->refcount, 1, __ATOMIC_SEQ_CST);
177  }
178 
179  release();
180 
181  m_Control = p.m_Control;
182 }
183 
184 template <class T>
186 {
187  release();
188 }
189 
190 template <class T>
192 {
193  release();
194 
195  m_Control = new Control;
196  m_Control->refcount = 1;
197  m_Control->ptr = ptr;
198 }
199 
200 template <class T>
202 {
203  if (!m_Control)
204  return 0;
205 
206  return m_Control->ptr;
207 }
208 
209 template <class T>
211 {
212  return get();
213 }
214 
215 template <class T>
217 {
218  return *(get());
219 }
220 
221 template <class T>
223 {
224  // If the other is assigned, boost its refcount before we release. If it
225  // happens that the other is in fact pointing to the same place, the counts
226  // will not potentially drop to zero then back to one this way (causing a
227  // bad pointer).
228  if (p.m_Control)
229  {
230  __atomic_add_fetch(&p.m_Control->refcount, 1, __ATOMIC_SEQ_CST);
231  }
232 
233  release();
234 
235  m_Control = p.m_Control;
236 
237  return *this;
238 }
239 
240 template <class T>
242 {
243  release();
244  m_Control = pedigree_std::move(p.m_Control);
245  p.m_Control = nullptr;
246 
247  return *this;
248 }
249 
250 template <class T>
252 {
253  return get() != 0;
254 }
255 
256 template <class T>
258 {
259  return refcount() == 1;
260 }
261 
262 template <class T>
264 {
265  if (!m_Control)
266  return 0;
267 
268  return __atomic_load_n(&m_Control->refcount, __ATOMIC_SEQ_CST);
269 }
270 
271 template <class T>
272 template <class... Args>
274 {
275  SharedPointer<T> result;
276  result.reset(new T(args...));
277  return pedigree_std::move(result);
278 }
279 
280 template <class T>
282 {
283  if (!m_Control)
284  return;
285 
286  size_t rc = __atomic_sub_fetch(&m_Control->refcount, 1, __ATOMIC_SEQ_CST);
287  if (!rc)
288  {
290  delete m_Control->ptr;
291  m_Control->ptr = 0;
292 
293  delete m_Control;
294  }
295 
296  // We don't care about the control structure anymore. Someone else will
297  // free it if we did not.
298  m_Control = 0;
299 }
300 
301 template <class T>
303 {
304  return get() == p.get();
305 }
306 
307 template <class T>
308 bool SharedPointer<T>::operator!=(const SharedPointer &p) const
309 {
310  return get() != p.get();
311 }
312 
313 template <class T>
314 bool SharedPointer<T>::operator<(const SharedPointer &p) const
315 {
316  return get() < p.get();
317 }
318 
319 template <class T>
320 bool SharedPointer<T>::operator<=(const SharedPointer &p) const
321 {
322  return get() <= p.get();
323 }
324 
325 template <class T>
326 bool SharedPointer<T>::operator>(const SharedPointer &p) const
327 {
328  return get() > p.get();
329 }
330 
331 template <class T>
332 bool SharedPointer<T>::operator>=(const SharedPointer &p) const
333 {
334  return get() >= p.get();
335 }
336 
337 #endif
T * get() const
bool unique() const
bool operator==(const SharedPointer &p) const
T & operator*() const
T * operator->() const
size_t refcount() const
virtual ~SharedPointer()
SharedPointer< T > & operator=(const SharedPointer< T > &p)
static SharedPointer< T > allocate(Args...)