1/*
2 * This file is part of the KDE libraries.
3 *
4 * Copyright 2005 Frerich Raabe <raabe@kde.org>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27#ifndef KSHAREDPTR_H
28#define KSHAREDPTR_H
29
30#include <QtCore/QExplicitlySharedDataPointer>
31#include <QtCore/QAtomicPointer>
32#include <kdemacros.h>
33
34/**
35 * @deprecated
36 * Use QSharedData instead.
37 */
38typedef QSharedData KShared;
39
40/**
41 * \class KSharedPtr ksharedptr.h <KSharedPtr>
42 *
43 * Can be used to control the lifetime of an object that has derived
44 * QSharedData. As long a someone holds
45 * a KSharedPtr on some QSharedData object it won't become deleted but
46 * is deleted once its reference count is 0.
47 * This struct emulates C++ pointers virtually perfectly.
48 * So just use it like a simple C++ pointer.
49 *
50 * The difference with QSharedPointer is that QSharedPointer does the refcounting
51 * in the pointer, while KSharedPtr does the refcounting in the object.
52 * This allows to convert to a raw pointer temporarily and back to a KSharedPtr
53 * without deleting the object, if another reference exists. But it imposes a
54 * requirement on the object, which must inherit QSharedData.
55 *
56 * The difference with using QSharedDataPointer is that QSharedDataPointer is
57 * a building block for implementing a value class with implicit sharing (like QString),
58 * whereas KSharedPtr provides refcounting to code that uses pointers.
59 *
60 * @author Waldo Bastian <bastian@kde.org>
61 */
62template< class T >
63class KSharedPtr
64{
65public:
66 /**
67 * Creates a null pointer.
68 */
69 inline KSharedPtr()
70 : d(0) { }
71
72 /**
73 * Creates a new pointer.
74 * @param p the pointer
75 */
76 inline explicit KSharedPtr( T* p )
77 : d(p) { if(d) d->ref.ref(); }
78
79 /**
80 * Copies a pointer.
81 * @param o the pointer to copy
82 */
83 inline KSharedPtr( const KSharedPtr& o )
84 : d(o.d) { if(d) d->ref.ref(); }
85
86 /**
87 * Unreferences the object that this pointer points to. If it was
88 * the last reference, the object will be deleted.
89 */
90 inline ~KSharedPtr() { if (d && !d->ref.deref()) delete d; }
91
92 inline KSharedPtr<T>& operator= ( const KSharedPtr& o ) { attach(o.d); return *this; }
93 inline bool operator== ( const KSharedPtr& o ) const { return ( d == o.d ); }
94 inline bool operator!= ( const KSharedPtr& o ) const { return ( d != o.d ); }
95 inline bool operator< ( const KSharedPtr& o ) const { return ( d < o.d ); }
96
97 inline KSharedPtr<T>& operator= ( T* p ) { attach(p); return *this; }
98 inline bool operator== ( const T* p ) const { return ( d == p ); }
99 inline bool operator!= ( const T* p ) const { return ( d != p ); }
100
101 /**
102 * Test if the shared pointer is NOT null.
103 * @return true if the shared pointer is NOT null, false otherwise.
104 * @see isNull
105 */
106 inline operator bool() const { return ( d != 0 ); }
107
108 /**
109 * @return the pointer
110 */
111 inline T* data() { return d; }
112
113 /**
114 * @return the pointer
115 */
116 inline const T* data() const { return d; }
117
118 /**
119 * @return a const pointer to the shared object.
120 */
121 inline const T* constData() const { return d; }
122
123 inline const T& operator*() const { Q_ASSERT(d); return *d; }
124 inline T& operator*() { Q_ASSERT(d); return *d; }
125 inline const T* operator->() const { Q_ASSERT(d); return d; }
126 inline T* operator->() { Q_ASSERT(d); return d; }
127
128 /**
129 * Attach the given pointer to the current KSharedPtr.
130 * If the previous shared pointer is not owned by any KSharedPtr,
131 * it is deleted.
132 */
133 void attach(T* p);
134
135 /**
136 * Clear the pointer, i.e. make it a null pointer.
137 */
138 void clear();
139
140 /**
141 * Returns the number of references.
142 * @return the number of references
143 */
144 inline int count() const { return d ? static_cast<int>(d->ref) : 0; } // for debugging purposes
145
146 /**
147 * Test if the shared pointer is null.
148 * @return true if the pointer is null, false otherwise.
149 * @see opertor (bool)
150 */
151 inline bool isNull() const { return (d == 0); }
152
153 /**
154 * @return Whether this is the only shared pointer pointing to
155 * to the pointee, or whether it's shared among multiple
156 * shared pointers.
157 */
158 inline bool isUnique() const { return count() == 1; }
159
160 template <class U> friend class KSharedPtr;
161
162 /**
163 * Convert KSharedPtr<U> to KSharedPtr<T>, using a static_cast.
164 * This will compile whenever T* and U* are compatible, i.e.
165 * T is a subclass of U or vice-versa.
166 * Example syntax:
167 * <code>
168 * KSharedPtr<T> tPtr;
169 * KSharedPtr<U> uPtr = KSharedPtr<U>::staticCast( tPtr );
170 * </code>
171 */
172 template <class U>
173 static KSharedPtr<T> staticCast( const KSharedPtr<U>& o ) {
174 return KSharedPtr<T>( static_cast<T *>( o.d ) );
175 }
176 /**
177 * Convert KSharedPtr<U> to KSharedPtr<T>, using a dynamic_cast.
178 * This will compile whenever T* and U* are compatible, i.e.
179 * T is a subclass of U or vice-versa.
180 * Example syntax:
181 * <code>
182 * KSharedPtr<T> tPtr;
183 * KSharedPtr<U> uPtr = KSharedPtr<U>::dynamicCast( tPtr );
184 * </code>
185 * Since a dynamic_cast is used, if U derives from T, and tPtr isn't an instance of U, uPtr will be 0.
186 */
187 template <class U>
188 static KSharedPtr<T> dynamicCast( const KSharedPtr<U>& o ) {
189 return KSharedPtr<T>( dynamic_cast<T *>( o.d ) );
190 }
191
192protected:
193 T* d;
194};
195
196template <class T>
197Q_INLINE_TEMPLATE bool operator== (const T* p, const KSharedPtr<T>& o)
198{
199 return ( o == p );
200}
201
202template <class T>
203Q_INLINE_TEMPLATE bool operator!= (const T* p, const KSharedPtr<T>& o)
204{
205 return ( o != p );
206}
207
208template <class T>
209Q_INLINE_TEMPLATE void KSharedPtr<T>::attach(T* p)
210{
211 if (d != p) {
212 if (p) p->ref.ref();
213 if (d && !d->ref.deref())
214 delete d;
215 d = p;
216 }
217}
218
219template <class T>
220Q_INLINE_TEMPLATE void KSharedPtr<T>::clear()
221{
222 attach(static_cast<T*>(0));
223}
224
225#endif
226
227