File: smartpointer.h

package info (click to toggle)
faust 2.81.10%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 431,496 kB
  • sloc: cpp: 283,941; ansic: 116,215; javascript: 18,529; sh: 14,356; vhdl: 14,052; java: 5,900; python: 5,091; objc: 3,852; makefile: 2,725; cs: 1,672; lisp: 1,146; ruby: 954; yacc: 586; xml: 471; lex: 247; awk: 111; tcl: 26
file content (182 lines) | stat: -rw-r--r-- 5,272 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/*

  Copyright (C) 2011 Grame

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

  Grame Research Laboratory, 9 rue du Garet, 69001 Lyon - France
  research@grame.fr

*/

#ifndef __smartpointer__
#define __smartpointer__

#include "exception.hh"

/*!
\brief the base class for smart pointers implementation

    Any object that want to support smart pointers should
    inherit from the smartable class which provides reference counting
    and automatic delete when the reference count drops to zero.
*/
class smartable {
   private:
    unsigned refCount;

   public:
    //! gives the reference count of the object
    unsigned refs() const { return refCount; }
    //! addReference increments the ref count and checks for refCount overflow
    void addReference()
    {
        refCount++;
        faustassert(refCount != 0);
    }
    //! removeReference delete the object when refCount is zero
    void removeReference()
    {
        if (--refCount == 0) {
            delete this;
        }
    }

   protected:
    smartable() : refCount(0) {}
    smartable(const smartable&) : refCount(0) {}
    //! destructor checks for non-zero refCount
    virtual ~smartable()
    {
        // printf(" ~smartable() \n");
        // faustassert(refCount == 0);
    }
    smartable& operator=(const smartable&) { return *this; }
};

/*!
\brief the smart pointer implementation

    A smart pointer is in charge of maintaining the objects reference count
    by the way of pointers operators overloading. It supports class
    inheritance and conversion whenever possible.
\n	Instances of the SMARTP class are supposed to use \e smartable types (or at least
    objects that implements the \e addReference and \e removeReference
    methods in a consistent way).
*/
template <class T>
class SMARTP {
   private:
    //! the actual pointer to the class
    T* fSmartPtr;

   public:
    //! an empty constructor - points to null
    SMARTP() : fSmartPtr(0) {}
    //! build a smart pointer from a class pointer
    SMARTP(T* rawptr) : fSmartPtr(rawptr)
    {
        if (fSmartPtr) {
            fSmartPtr->addReference();
        }
    }
    //! build a smart pointer from an convertible class reference
    template <class T2>
    SMARTP(const SMARTP<T2>& ptr) : fSmartPtr((T*)ptr)
    {
        if (fSmartPtr) {
            fSmartPtr->addReference();
        }
    }
    //! build a smart pointer from another smart pointer reference
    SMARTP(const SMARTP& ptr) : fSmartPtr((T*)ptr)
    {
        if (fSmartPtr) {
            fSmartPtr->addReference();
        }
    }

    //! the smart pointer destructor: simply removes one reference count
    ~SMARTP()
    {
        if (fSmartPtr) {
            fSmartPtr->removeReference();
        }
    }

    //! cast operator to retrieve the actual class pointer
    operator T*() const { return fSmartPtr; }

    //! '*' operator to access the actual class pointer
    T& operator*() const
    {
        // checks for null dereference
        faustassert(fSmartPtr != 0);
        return *fSmartPtr;
    }

    //! operator -> overloading to access the actual class pointer
    T* operator->() const
    {
        // checks for null dereference
        faustassert(fSmartPtr != 0);
        return fSmartPtr;
    }

    //! operator = that moves the actual class pointer
    template <class T2>
    SMARTP& operator=(T2 p1_)
    {
        *this = (T*)p1_;
        return *this;
    }

    //! operator = that moves the actual class pointer
    SMARTP& operator=(T* p_)
    {
        // check first that pointers differ
        if (fSmartPtr != p_) {
            // increments the ref count of the new pointer if not null
            if (p_ != 0) {
                p_->addReference();
            }
            // decrements the ref count of the old pointer if not null
            if (fSmartPtr != 0) {
                fSmartPtr->removeReference();
            }
            // and finally stores the new actual pointer
            fSmartPtr = p_;
        }
        return *this;
    }
    //! operator < to support SMARTP map with Visual C++
    bool operator<(const SMARTP<T>& p_) const { return fSmartPtr < ((T*)p_); }
    //! operator = to support inherited class reference
    SMARTP& operator=(const SMARTP<T>& p_) { return operator=((T*)p_); }
    //! dynamic cast support
    template <class T2>
    SMARTP& cast(T2* p_)
    {
        return operator=(dynamic_cast<T*>(p_));
    }
    //! dynamic cast support
    template <class T2>
    SMARTP& cast(const SMARTP<T2>& p_)
    {
        return operator=(dynamic_cast<T*>(p_));
    }
};

#endif