refcounter.h

00001 /*
00002  *  Copyright (C) 2006  Helmut Grohne
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017  */
00018 
00019 #ifndef LIBMUTH_REFCOUNTER_H
00020 #define LIBMUTH_REFCOUNTER_H
00021 
00022 #include <assert.h>
00023 #include "refcounter_decls.h"
00024 
00025 inline void RefCounter::addWeakRef(WeakRefBase &wr) {
00026         WITHACQUIRED(this->datalock);
00027         this->notifier.insert(&wr);
00028         this->cond.notify();
00029 }
00030 
00031 inline void RefCounter::removeWeakRef(WeakRefBase &wr) {
00032         WITHACQUIRED(this->datalock);
00033         this->notifier.erase(&wr);
00034         this->cond.notify();
00035 }
00036 
00037 inline void RefCounter::notifyall() {
00038         /* datalock is acquired from ~RefCounter() */
00039         while(!this->notifier.empty()) {
00040                 WeakRefBase *const t(*this->notifier.begin());
00041                 if(t->datalock.tryacquire()) {
00042                         this->notifier.erase(this->notifier.begin());
00043                         t->notify();
00044                         t->datalock.release();
00045                 } else
00046                         this->cond.wait();
00047         }
00048 }
00049 
00050 inline RefCounter::~RefCounter() {
00051         /* datalock is acquired in decref. */
00052         this->notifyall();
00053         this->datalock.release();
00054 }
00055 
00056 inline RefCounter::RefCounter() : cond(datalock), refcount(0) {
00057 }
00058 
00059 inline void RefCounter::incref() {
00060         WITHACQUIRED(this->datalock);
00061         ++this->refcount;
00062 }
00063 
00064 inline void RefCounter::decref() {
00065         this->datalock.acquire();
00066         if(!--this->refcount)
00067                 /* The destructor will release the lock. */
00068                 delete this;
00069         else
00070                 this->datalock.release();
00071 }
00072 
00073 template<class RC> inline Reference<RC>::Reference(RC *obj) : object(obj) {
00074         assert(this->object != NULL);
00075         this->object->incref();
00076 }
00077 
00078 template<class RC> inline Reference<RC>::Reference(const Reference &other)
00079                 : object(other.object) {
00080         this->object->incref();
00081 }
00082 
00083 template<class RC> inline Reference<RC> &Reference<RC>::operator=(RC *obj) {
00084         assert(obj != NULL);
00085         obj->incref();
00086         this->object->decref();
00087         this->object = obj;
00088         return *this;
00089 }
00090 
00091 template<class RC> inline Reference<RC> &Reference<RC>::operator=(const
00092                 Reference &other) {
00093         other.object->incref();
00094         this->object->decref();
00095         this->object = other.object;
00096         return *this;
00097 }
00098 
00099 template<class RC> inline bool Reference<RC>::operator==(const Reference
00100                 &other) const {
00101         return this->object == other.object;
00102 }
00103 
00104 template<class RC> inline bool Reference<RC>::operator!=(const Reference
00105                 &other) const {
00106         return this->object != other.object;
00107 }
00108 
00109 template<class RC> inline RC &Reference<RC>::operator*() const {
00110         return *this->object;
00111 }
00112 
00113 template<class RC> inline RC *Reference<RC>::operator->() const {
00114         return this->object;
00115 }
00116 
00117 template<class RC> inline Reference<RC>::~Reference() {
00118         this->object->decref();
00119 }
00120 
00121 inline WeakRefBase::WeakRefBase() {
00122 }
00123 
00124 template<class RC> void WeakReference<RC>::notify() {
00125         /* locked in RefCounter::notifyall */
00126         this->object = NULL;
00127 }
00128 
00129 template<class RC> inline WeakReference<RC>::WeakReference() : object(NULL) {
00130 }
00131 
00132 template<class RC> inline WeakReference<RC>::WeakReference(const WeakReference
00133                 &other) : object(other.object) {
00134         if(this->object)
00135                 this->object->addWeakRef(*this);
00136 }
00137 
00138 template<class RC> inline WeakReference<RC>::WeakReference(const Reference<RC>
00139                 &other) : object(other.object) {
00140         assert(this->object != NULL);
00141         this->object->addWeakRef(*this);
00142 }
00143 
00144 template<class RC> inline WeakReference<RC>::WeakReference(RC *obj)
00145                 : object(obj) {
00146         if(this->object)
00147                 this->object->addWeakRef(*this);
00148 }
00149 
00150 template<class RC> inline WeakReference<RC> &WeakReference<RC>::operator=(const
00151                 WeakReference &other) {
00152         WITHACQUIRED(this->datalock);
00153         if(this->object != other.object) {
00154                 if(this->object)
00155                         this->object->removeWeakRef(*this);
00156                 this->object = other.object;
00157                 if(this->object)
00158                         this->object->addWeakRef(*this);
00159         }
00160         return *this;
00161 }
00162 
00163 template<class RC> inline WeakReference<RC> &WeakReference<RC>::operator=(const
00164                 Reference<RC> &other) {
00165         WITHACQUIRED(this->datalock);
00166         if(this->object != other.object) {
00167                 if(this->object)
00168                         this->object->removeWeakRef(*this);
00169                 this->object = other.object;
00170                 assert(this->object != NULL);
00171                 this->object->addWeakRef(*this);
00172         }
00173         return *this;
00174 }
00175 
00176 template<class RC> inline bool WeakReference<RC>::operator==(const WeakReference
00177                 &other) const {
00178         WITHACQUIRED(this->datalock);
00179         return this->object == other.object;
00180 }
00181 
00182 template<class RC> inline bool WeakReference<RC>::operator==(const Reference<RC>
00183                 &other) const {
00184         WITHACQUIRED(this->datalock);
00185         return this->object == other.object;
00186 }
00187 
00188 template<class RC> inline bool WeakReference<RC>::operator!=(const WeakReference
00189                 &other) const {
00190         WITHACQUIRED(this->datalock);
00191         return this->object != other.object;
00192 }
00193 
00194 template<class RC> inline bool WeakReference<RC>::operator!=(const Reference<RC>
00195                 &other) const {
00196         WITHACQUIRED(this->datalock);
00197         return this->object != other.object;
00198 }
00199 
00200 template<class RC> inline Reference<RC> WeakReference<RC>::operator*() const {
00201         WITHACQUIRED(this->datalock);
00202         if(!this->object)
00203                 throw NullPointerException();
00204         return Reference<RC>(this->object);
00205 }
00206 
00207 template<class RC> WeakReference<RC>::~WeakReference() {
00208         WITHACQUIRED(this->datalock);
00209         if(this->object)
00210                 this->object->removeWeakRef(*this);
00211 }
00212 
00213 #endif

Generated on Thu Feb 14 13:30:30 2008 by  doxygen 1.5.1