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