00001 /* 00002 00003 Copyright (C) 2006-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_DATA_H 00046 #define UTILS__MEMORY__SHARED_DATA_H 00047 00048 namespace Utils { 00049 namespace Memory { 00050 00052 00071 class SharedData 00072 { 00073 public: 00074 QAtomic ref; 00075 00076 inline SharedData() : ref(0) { } 00077 inline SharedData(const SharedData &) : ref(0) { } 00078 virtual SharedData * copy() const = 0; 00079 virtual ~SharedData() {} 00080 00081 private: 00082 // using the operator= would lead to corruption in the ref-counting 00083 SharedData &operator= (const SharedData &); 00084 }; 00085 00086 00088 00100 class SharedDataPointer 00101 { 00102 public: 00103 inline void detach() { if (d && d->ref != 1) detach_helper(); } 00104 inline SharedData &operator*() { detach(); return *d; } 00105 inline const SharedData &operator*() const { return *d; } 00106 inline SharedData *operator->() { detach(); return d; } 00107 inline const SharedData *operator->() const { return d; } 00108 inline operator SharedData *() { detach(); return d; } 00109 inline operator const SharedData *() const { return d; } 00110 inline SharedData *data() { detach(); return d; } 00111 inline const SharedData *data() const { return d; } 00112 inline const SharedData *constData() const { return d; } 00113 00114 inline bool operator==(const SharedDataPointer &other) const { return d == other.d; } 00115 inline bool operator!=(const SharedDataPointer &other) const { return d != other.d; } 00116 00117 inline SharedDataPointer() : d (0) {} 00118 inline ~SharedDataPointer() { if (d && !d->ref.deref()) delete d; } 00119 00120 explicit SharedDataPointer(SharedData *data); 00121 inline SharedDataPointer(const SharedDataPointer &o) : d(o.d) { if (d) d->ref.ref(); } 00122 inline SharedDataPointer & operator= (const SharedDataPointer &o) { 00123 if (o.d != d) { 00124 SharedData *x = o.d; 00125 if (x) x->ref.ref(); 00126 x = qAtomicSetPtr(&d, x); 00127 if (x && !x->ref.deref()) 00128 delete x; 00129 } 00130 return *this; 00131 } 00132 inline SharedDataPointer & operator= (SharedData *o) { 00133 if (o != d) { 00134 SharedData *x = o; 00135 if (x) x->ref.ref(); 00136 x = qAtomicSetPtr(&d, x); 00137 if (x && !x->ref.deref()) 00138 delete x; 00139 } 00140 return *this; 00141 } 00142 00143 inline bool operator!() const { return !d; } 00144 00145 private: 00146 void detach_helper(); 00147 00148 SharedData *d; 00149 }; 00150 00151 inline SharedDataPointer::SharedDataPointer (SharedData *adata) : d(adata) 00152 { if (d) d->ref.ref(); } 00153 00154 inline void SharedDataPointer::detach_helper() 00155 { 00156 SharedData *x = d->copy(); 00157 x->ref.ref(); 00158 x = qAtomicSetPtr(&d, x); 00159 if (!x->ref.deref()) 00160 delete x; 00161 } 00162 00163 // This macros facilitate implicit sharing of private data: 00164 #define Q_SHARED_DATA_COPY(Class) \ 00165 Class * copy() const { return new Class (*this); } 00166 00167 #define Q_DECLARE_SHARED_DATA(Class) \ 00168 inline Class* d_func() \ 00169 { return static_cast <Class *> (d_ptr.data()); } \ 00170 inline const Class* d_func() const \ 00171 { return static_cast <const Class *> (d_ptr.data()); } 00172 00173 #define Q_SD(Class) Class * const d = d_func() 00174 00175 } // namespace Memory 00176 } // namespace Utils 00177 00178 #endif // UTILS__MEMORY__SHARED_DATA_H