SharedData.h

Go to the documentation of this file.
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