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 "compiler.h"
00024 #include "refcounter_decls.h"
00025 
00026 inline void RefCounter::addWeakRef(WeakRefBase &wr) {
00027         WITHACQUIRED(this->datalock);
00028         this->notifier.insert(&wr);
00029         this->cond.notify();
00030 }
00031 
00032 inline void RefCounter::removeWeakRef(WeakRefBase &wr) {
00033         WITHACQUIRED(this->datalock);
00034         this->notifier.erase(&wr);
00035         this->cond.notify();
00036 }
00037 
00038 inline void RefCounter::notifyall() {
00039         /* datalock is acquired from ~RefCounter() */
00040         while(!this->notifier.empty()) {
00041                 WeakRefBase *const t(*this->notifier.begin());
00042                 if(likely(t->datalock.tryacquire())) {
00043                         this->notifier.erase(this->notifier.begin());
00044                         t->notify();
00045                         t->datalock.release();
00046                 } else
00047                         this->cond.wait();
00048         }
00049 }
00050 
00051 inline RefCounter::~RefCounter() {
00052         /* datalock is acquired in decref. */
00053         this->notifyall();
00054         this->datalock.release();
00055 }
00056 
00057 inline RefCounter::RefCounter() : cond(datalock), refcount(0) {
00058 }
00059 
00060 inline void RefCounter::incref() {
00061         WITHACQUIRED(this->datalock);
00062         ++this->refcount;
00063 }
00064 
00065 inline void RefCounter::decref() {
00066         this->datalock.acquire();
00067         if(!--this->refcount)
00068                 /* The destructor will release the lock. */
00069                 delete this;
00070         else
00071                 this->datalock.release();
00072 }
00073 
00074 template<class RC> inline Reference<RC>::Reference(RC *obj) : object(obj) {
00075         assert(this->object != NULL);
00076         this->object->incref();
00077 }
00078 
00079 template<class RC> inline Reference<RC>::Reference(const Reference &other)
00080                 : object(other.object) {
00081         this->object->incref();
00082 }
00083 
00084 template<class RC> inline Reference<RC> &Reference<RC>::operator=(RC *obj) {
00085         assert(obj != NULL);
00086         obj->incref();
00087         this->object->decref();
00088         this->object = obj;
00089         return *this;
00090 }
00091 
00092 template<class RC> inline Reference<RC> &Reference<RC>::operator=(const
00093                 Reference &other) {
00094         other.object->incref();
00095         this->object->decref();
00096         this->object = other.object;
00097         return *this;
00098 }
00099 
00100 template<class RC> inline bool Reference<RC>::operator==(const Reference
00101                 &other) const {
00102         return this->object == other.object;
00103 }
00104 
00105 template<class RC> inline bool Reference<RC>::operator!=(const Reference
00106                 &other) const {
00107         return this->object != other.object;
00108 }
00109 
00110 template<class RC> inline RC &Reference<RC>::operator*() const {
00111         return *this->object;
00112 }
00113 
00114 template<class RC> inline RC *Reference<RC>::operator->() const {
00115         return this->object;
00116 }
00117 
00118 template<class RC> inline Reference<RC>::~Reference() {
00119         this->object->decref();
00120 }
00121 
00122 inline WeakRefBase::WeakRefBase() {
00123 }
00124 
00125 template<class RC> void WeakReference<RC>::notify() {
00126         /* locked in RefCounter::notifyall */
00127         this->object = NULL;
00128 }
00129 
00130 template<class RC> inline WeakReference<RC>::WeakReference() : object(NULL) {
00131 }
00132 
00133 template<class RC> inline WeakReference<RC>::WeakReference(const WeakReference
00134                 &other) : object(other.object) {
00135         if(this->object)
00136                 this->object->addWeakRef(*this);
00137 }
00138 
00139 template<class RC> inline WeakReference<RC>::WeakReference(const Reference<RC>
00140                 &other) : object(other.object) {
00141         assert(this->object != NULL);
00142         this->object->addWeakRef(*this);
00143 }
00144 
00145 template<class RC> inline WeakReference<RC>::WeakReference(RC *obj)
00146                 : object(obj) {
00147         if(this->object)
00148                 this->object->addWeakRef(*this);
00149 }
00150 
00151 template<class RC> inline WeakReference<RC> &WeakReference<RC>::operator=(const
00152                 WeakReference &other) {
00153         WITHACQUIRED(this->datalock);
00154         if(likely(this->object != other.object)) {
00155                 if(this->object)
00156                         this->object->removeWeakRef(*this);
00157                 this->object = other.object;
00158                 if(this->object)
00159                         this->object->addWeakRef(*this);
00160         }
00161         return *this;
00162 }
00163 
00164 template<class RC> inline WeakReference<RC> &WeakReference<RC>::operator=(const
00165                 Reference<RC> &other) {
00166         WITHACQUIRED(this->datalock);
00167         if(likely(this->object != other.object)) {
00168                 if(this->object)
00169                         this->object->removeWeakRef(*this);
00170                 this->object = other.object;
00171                 assert(this->object != NULL);
00172                 this->object->addWeakRef(*this);
00173         }
00174         return *this;
00175 }
00176 
00177 template<class RC> inline bool WeakReference<RC>::operator==(const WeakReference
00178                 &other) const {
00179         WITHACQUIRED(this->datalock);
00180         return this->object == other.object;
00181 }
00182 
00183 template<class RC> inline bool WeakReference<RC>::operator==(const Reference<RC>
00184                 &other) const {
00185         WITHACQUIRED(this->datalock);
00186         return this->object == other.object;
00187 }
00188 
00189 template<class RC> inline bool WeakReference<RC>::operator!=(const WeakReference
00190                 &other) const {
00191         WITHACQUIRED(this->datalock);
00192         return this->object != other.object;
00193 }
00194 
00195 template<class RC> inline bool WeakReference<RC>::operator!=(const Reference<RC>
00196                 &other) const {
00197         WITHACQUIRED(this->datalock);
00198         return this->object != other.object;
00199 }
00200 
00201 template<class RC> inline Reference<RC> WeakReference<RC>::operator*() const {
00202         WITHACQUIRED(this->datalock);
00203         if(!this->object)
00204                 throw NullPointerException();
00205         return Reference<RC>(this->object);
00206 }
00207 
00208 template<class RC> WeakReference<RC>::~WeakReference() {
00209         WITHACQUIRED(this->datalock);
00210         if(this->object)
00211                 this->object->removeWeakRef(*this);
00212 }
00213 
00214 #endif

Generated on Sat Feb 7 01:26:50 2009 by  doxygen 1.5.1