Gaia
counted_ptr.h
1 /*
2  * Copyright (C) 2006-2013 Music Technology Group - Universitat Pompeu Fabra
3  *
4  * This file is part of Gaia
5  *
6  * Gaia is free software: you can redistribute it and/or modify it under
7  * the terms of the GNU Affero General Public License as published by the Free
8  * Software Foundation (FSF), either version 3 of the License, or (at your
9  * option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14  * details.
15  *
16  * You should have received a copy of the Affero GNU General Public License
17  * version 3 along with this program. If not, see http://www.gnu.org/licenses/
18  */
19 
20 /*
21  * counted_ptr - simple reference counted pointer.
22  *
23  * The is a non-intrusive implementation that allocates an additional
24  * int and pointer for every counted object.
25  */
26 
27 #ifndef COUNTED_PTR_H
28 #define COUNTED_PTR_H
29 
30 /* For ANSI-challenged compilers, you may want to #define
31  * NO_MEMBER_TEMPLATES or explicit */
32 
33 #define NO_MEMBER_TEMPLATES
34 
35 template <class X> class counted_ptr
36 {
37 public:
38  typedef X element_type;
39 
40  explicit counted_ptr(X* p = 0) // allocate a new counter
41  : itsCounter(0) {if (p) itsCounter = new counter(p);}
42  ~counted_ptr()
43  {release();}
44  counted_ptr(const counted_ptr& r) throw()
45  {acquire(r.itsCounter);}
46  counted_ptr& operator=(const counted_ptr& r)
47  {
48  if (this != &r) {
49  release();
50  acquire(r.itsCounter);
51  }
52  return *this;
53  }
54 
55 #ifndef NO_MEMBER_TEMPLATES
56  template <class Y> friend class counted_ptr<Y>;
57  template <class Y> counted_ptr(const counted_ptr<Y>& r) throw()
58  {acquire(r.itsCounter);}
59  template <class Y> counted_ptr& operator=(const counted_ptr<Y>& r)
60  {
61  if (this != &r) {
62  release();
63  acquire(r.itsCounter);
64  }
65  return *this;
66  }
67 #endif // NO_MEMBER_TEMPLATES
68 
69  X& operator*() const throw() {return *itsCounter->ptr;}
70  X* operator->() const throw() {return itsCounter->ptr;}
71  X* get() const throw() {return itsCounter ? itsCounter->ptr : 0;}
72  bool unique() const throw()
73  {return (itsCounter ? itsCounter->count == 1 : true);}
74 
75  operator X*() const throw() { return get(); }
76 
77 private:
78 
79  struct counter {
80  counter(X* p = 0, unsigned c = 1) : ptr(p), count(c) {}
81  X* ptr;
82  unsigned count;
83  }* itsCounter;
84 
85  void acquire(counter* c) throw()
86  { // increment the count
87  itsCounter = c;
88  if (c) ++c->count;
89  }
90 
91  void release()
92  { // decrement the count, delete if it is 0
93  if (itsCounter) {
94  if (--itsCounter->count == 0) {
95  delete itsCounter->ptr;
96  delete itsCounter;
97  }
98  itsCounter = 0;
99  }
100  }
101 };
102 
103 #endif // COUNTED_PTR_H
Definition: counted_ptr.h:35