SharedPointer.h

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