00001 /* 00002 00003 Copyright (C) 2005-2007 by Peter Dimov. 00004 00005 This file is part of Calitko (http://www.calitko.org). 00006 00007 Calitko is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 2 of the License, or 00010 (at your option) any later version. 00011 00012 Calitko is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with Calitko; if not, write to the Free Software 00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00020 00021 */ 00022 /**************************************************************************** 00023 ** 00024 ** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved. 00025 ** 00026 ** This file is part of the QtCore module of the Qt Toolkit. 00027 ** 00028 ** This file may be used under the terms of the GNU General Public 00029 ** License version 2.0 as published by the Free Software Foundation 00030 ** and appearing in the file LICENSE.GPL included in the packaging of 00031 ** this file. Please review the following information to ensure GNU 00032 ** General Public Licensing requirements will be met: 00033 ** http://www.trolltech.com/products/qt/opensource.html 00034 ** 00035 ** If you are unsure which license is appropriate for your use, please 00036 ** review the following information: 00037 ** http://www.trolltech.com/products/qt/licensing.html or contact the 00038 ** sales department at sales@trolltech.com. 00039 ** 00040 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00041 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00042 ** 00043 ****************************************************************************/ 00044 00045 #ifndef UTILS__MEMORY__SHARED_POINTER_H 00046 #define UTILS__MEMORY__SHARED_POINTER_H 00047 00048 namespace Utils { 00049 namespace Memory { 00050 00052 00059 template <typename T> 00060 class SharedPointer 00061 { 00062 public: 00063 inline void detach() { if (d && d->ref != 1) detach_helper(); } 00064 inline T &operator*() { detach(); return *(d->data); } 00065 inline const T &operator*() const { return *(d->data); } 00066 inline T *operator->() { detach(); return d->data; } 00067 inline const T *operator->() const { return d->data; } 00068 inline operator T *() { detach(); return d->data; } 00069 inline operator const T *() const { return d->data; } 00070 inline T *data() { detach(); return d->data; } 00071 inline const T *data() const { return d->data; } 00072 inline const T *constData() const { return d->data; } 00073 00074 inline bool operator==(const SharedPointer &other) const { return d == other.d; } 00075 inline bool operator!=(const SharedPointer &other) const { return d != other.d; } 00076 00077 inline SharedPointer() { d = 0; } 00078 explicit SharedPointer(T *data); 00079 inline ~SharedPointer() { if (d && !d->ref.deref()) delete d; } 00080 00081 inline SharedPointer(const SharedPointer &o) : d(o.d) { if (d) d->ref.ref(); } 00082 inline SharedPointer & operator= (const SharedPointer &o) { 00083 if (o.d != d) { 00084 SharedData *x = o.d; 00085 if (x) x->ref.ref(); 00086 x = qAtomicSetPtr(&d, x); 00087 if (x && !x->ref.deref()) 00088 delete x; 00089 } 00090 return *this; 00091 } 00092 00093 inline bool operator!() const { return !d; } 00094 00095 private: 00096 void detach_helper(); 00097 00098 class SharedData 00099 { 00100 public: 00101 QAtomic ref; 00102 T *data; 00103 00104 inline SharedData (T *adata) : ref(0) { data = adata; } 00105 inline SharedData(const SharedData &other) 00106 : ref(0) { data = other.data->copy(); } 00107 ~SharedData() { delete data; } 00108 00109 private: 00110 // using the operator= would lead to corruption in the ref-counting 00111 SharedData &operator= (const SharedData &); 00112 }; 00113 00114 SharedData *d; 00115 }; 00116 00117 template <typename T> 00118 inline SharedPointer <T>::SharedPointer (T *adata) : d(0) 00119 { d = new SharedData (adata); d->ref.ref(); } 00120 00121 template <typename T> 00122 inline void SharedPointer <T>::detach_helper() 00123 { 00124 SharedData *x = new SharedData (d); 00125 x->ref.ref(); 00126 x = qAtomicSetPtr(&d, x); 00127 if (!x->ref.deref()) 00128 delete x; 00129 } 00130 00131 } // namespace Memory 00132 } // namespace Utils 00133 00134 #endif // UTILS__MEMORY__SHARED_POINTER_H