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
1.5.1