00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef REFERENCE_COUNTING_HPP
00021 #define REFERENCE_COUNTING_HPP
00022
00031 #include <map>
00032 #include <iomanip>
00033
00034 #include <StreamCenter.hpp>
00035
00036 #ifndef NDEBUG
00037 #include <typeinfo>
00038 #include <string>
00040 #endif // NDEBUG
00041
00042 #include <ThreadStaticBase.hpp>
00043
00044 template <typename T>
00045 class ReferenceCounting;
00046
00047 class ReferenceCountingCenter
00048 : public ThreadStaticBase<ReferenceCountingCenter>
00049 {
00050 private:
00051 template <typename T>
00052 friend class ReferenceCounting;
00053
00054 template <typename T>
00055 friend class ConstReferenceCounting;
00056
00058 std::map <const void*,size_t> __counter;
00059
00060 #ifndef NDEBUG
00062 std::map <const void*,std::string> __typeName;
00063 #endif // NDEBUG
00064
00066 template <typename ReferenceCounterType>
00067 const size_t& numberOfReferences(const ReferenceCounterType& rc)
00068 {
00069 return __counter[rc.__ref];
00070 }
00071
00073 template <typename ReferenceCounterType>
00074 void addReference(ReferenceCounterType& rc)
00075 {
00076 __counter[rc.__ref]++;
00077 #ifndef NDEBUG
00078 __typeName[rc.__ref] = rc.typeName();
00079 #endif //NDEBUG
00080 }
00081
00083 template <typename ReferenceCounterType>
00084 size_t removeReference(ReferenceCounterType& rc)
00085 {
00086 const void* address = rc.__ref;
00087 std::map<const void*,size_t>::iterator i = __counter.find(address);
00088 if ((i->second == 1)&&(address != 0)) {
00089 rc.eraseData();
00090 __counter.erase(i);
00091 #ifndef NDEBUG
00092 __typeName.erase(address);
00093 #endif // NDEBUG
00094 return 0;
00095 }
00096 return (--(i->second));
00097 }
00098
00099
00101 public:
00103 ReferenceCountingCenter()
00104 {
00105 ;
00106 }
00107
00109 ~ReferenceCountingCenter()
00110 {
00111 #ifndef NDEBUG
00112 fflog(0) << "\n###### REFERENCE COUNTING STATE ######\n";
00113 fflog(0) << "Number of referenced addresses: "
00114 << std::setw(5) << __counter.size() << '\n';
00115 size_t n = 0;
00116 for (std::map<const void*,size_t>::iterator i= __counter.begin();
00117 i != __counter.end(); ++i) {
00118 n += (i->second != 0);
00119 }
00120 fflog(0) << "Number of unallocaded addresses: "
00121 << std::setw(5) << n << '\n';
00122 fflog(0) << "--------------------------------------\n";
00123 for (std::map<const void*,size_t>::iterator i= __counter.begin();
00124 i != __counter.end(); ++i) {
00125 if (i->second != 0) {
00126 fflog(0) << i->first << ": " << __typeName[i->first]
00127 << ':' << std::setw(5) << i->second << '\n';
00128 }
00129 }
00130 fflog(0) << "######################################\n";
00131 #endif // NDEBUG
00132 }
00133 };
00134
00143 template <typename ReferencedClass>
00144 class ReferenceCounting;
00145
00146 template <typename ReferencedClass>
00147 class ConstReferenceCounting
00148 {
00149 friend class ReferenceCountingCenter;
00150
00151 friend class ReferenceCounting<ReferencedClass>;
00152
00153 private:
00155 ReferenceCountingCenter& RCC;
00156
00158 const ReferencedClass* __ref;
00159
00161 void eraseData()
00162 {
00163 delete __ref;
00164 }
00165
00166 public:
00167
00168 #ifndef NDEBUG
00169 std::string typeName() const
00170 {
00171 return typeid(__ref).name();
00172 }
00173 #endif // NDEBUG
00174
00175 bool operator == (const ReferencedClass* ref) const
00176 {
00177 return (__ref == ref);
00178 }
00179
00180 bool operator != (const ReferencedClass* ref) const
00181 {
00182 return (__ref != ref);
00183 }
00184
00185 bool operator == (const ReferenceCounting<ReferencedClass> & rc) const
00186 {
00187 return (__ref == rc.__ref);
00188 }
00189
00190 bool operator != (const ReferenceCounting<ReferencedClass> & rc) const
00191 {
00192 return (__ref != rc.__ref);
00193 }
00194
00195 bool operator == (const ConstReferenceCounting<ReferencedClass> & rc) const
00196 {
00197 return (__ref == rc.__ref);
00198 }
00199
00200 bool operator != (const ConstReferenceCounting<ReferencedClass> & rc) const
00201 {
00202 return (__ref != rc.__ref);
00203 }
00204
00206 const size_t& numberOfReferences() const
00207 {
00208 return RCC.numberOfReferences(*this);
00209 }
00210
00212 operator const ReferencedClass*() const
00213 {
00214 return __ref;
00215 }
00216
00223 const ReferencedClass* operator->() const
00224 {
00225 ASSERT(__ref != 0);
00226 return __ref;
00227 }
00228
00235 const ReferencedClass& operator *() const
00236 {
00237 ASSERT(__ref != 0);
00238 return *__ref;
00239 }
00240
00242 const ConstReferenceCounting<ReferencedClass>&
00243 operator = (const ConstReferenceCounting<ReferencedClass>& O)
00244 {
00245 #ifndef NDEBUG
00246 fflog(4)
00247 << __ref << ':' << this->numberOfReferences()
00248 << ": remove operator=(ConstReferenceCounting<T>&) ConstReferenceCounting on "
00249 << typeid(__ref).name() << '\n';
00250 #endif // NDEBUG
00251 RCC.removeReference(*this);
00252
00253 __ref = O.__ref;
00254
00255 #ifndef NDEBUG
00256 fflog(4)
00257 << __ref << ':' << numberOfReferences()
00258 << ": create operator=(ConstReferenceCounting<T>&) ConstReferenceCounting on "
00259 << typeid(__ref).name() << '\n';
00260 #endif // NDEBUG
00261 RCC.addReference(*this);
00262
00263 return *this;
00264 }
00265
00267 ConstReferenceCounting(const ConstReferenceCounting<ReferencedClass>& O)
00268 : RCC(ReferenceCountingCenter::instance()),
00269 __ref(O.__ref)
00270 {
00271 #ifndef NDEBUG
00272 fflog(4) << __ref << ':' << numberOfReferences()
00273 << ": create ConstReferenceCounting on "
00274 << typeid(__ref).name() << '\n';
00275 #endif // NDEBUG
00276 RCC.addReference(*this);
00277 }
00278
00280 ConstReferenceCounting(const ReferenceCounting<ReferencedClass>& O)
00281 : RCC(ReferenceCountingCenter::instance()),
00282 __ref(O.__ref)
00283 {
00284 #ifndef NDEBUG
00285 fflog(4) << __ref << ':' << numberOfReferences()
00286 << ": create ~copy ConstReferenceCounting on "
00287 << typeid(__ref).name() << '\n';
00288 #endif // NDEBUG
00289 RCC.addReference(*this);
00290 }
00291
00293 ConstReferenceCounting(const ReferencedClass* ref)
00294 : RCC(ReferenceCountingCenter::instance()),
00295 __ref(ref)
00296 {
00297 #ifndef NDEBUG
00298 fflog(4) << __ref << ':' << numberOfReferences()
00299 << ": create ConstReferenceCounting on "
00300 << typeid(__ref).name() << '\n';
00301 #endif // NDEBUG
00302 RCC.addReference(*this);
00303 }
00304
00306 ConstReferenceCounting()
00307 : RCC(ReferenceCountingCenter::instance()),
00308 __ref(0)
00309 {
00310 #ifndef NDEBUG
00311 fflog(4) << __ref << ':' << numberOfReferences()
00312 << ": create ConstReferenceCounting on "
00313 << typeid(__ref).name() << '\n';
00314 #endif // NDEBUG
00315 RCC.addReference(*this);
00316 }
00317
00319 ~ConstReferenceCounting()
00320 {
00321 #ifndef NDEBUG
00322 fflog(4) << __ref << ':' << numberOfReferences()
00323 << ": remove ConstReferenceCounting on "
00324 << typeid(__ref).name() << '\n';
00325 #endif // NDEBUG
00326 RCC.removeReference(*this);
00327 }
00328 };
00329
00338 template <typename ReferencedClass>
00339 class ReferenceCounting
00340 {
00341 public:
00343 friend class ConstReferenceCounting<ReferencedClass>;
00344
00345 friend class ReferenceCountingCenter;
00346 private:
00348 ReferenceCountingCenter& RCC;
00349
00351 ReferencedClass* __ref;
00352
00354 void eraseData()
00355 {
00356 delete __ref;
00357 }
00358
00359 public:
00360
00362 const size_t& numberOfReferences() const
00363 {
00364 return RCC.numberOfReferences(*this);
00365 }
00366
00373 const ReferencedClass* operator ->() const
00374 {
00375 ASSERT(__ref != 0);
00376 return __ref;
00377 }
00378
00385 const ReferencedClass& operator *() const
00386 {
00387 ASSERT(__ref != 0);
00388 return *__ref;
00389 }
00390
00397 ReferencedClass* operator ->()
00398 {
00399 ASSERT(__ref != 0);
00400 return __ref;
00401 }
00402
00409 ReferencedClass& operator *()
00410 {
00411 ASSERT(__ref != 0);
00412 return *__ref;
00413 }
00414
00416 operator ReferencedClass*()
00417 {
00418 return __ref;
00419 }
00420
00422 operator const ReferencedClass*() const
00423 {
00424 return __ref;
00425 }
00426
00427 #ifndef NDEBUG
00428 std::string typeName() const
00429 {
00430 return typeid(__ref).name();
00431 }
00432 #endif // NDEBUG
00433
00434 bool operator == (const ReferencedClass * ref) const
00435 {
00436 return (__ref == ref);
00437 }
00438
00439 bool operator != (const ReferencedClass * ref) const
00440 {
00441 return (__ref != ref);
00442 }
00443
00444 bool operator == (const ReferenceCounting<ReferencedClass> & rc) const
00445 {
00446 return (__ref == rc.__ref);
00447 }
00448
00449 bool operator != (const ReferenceCounting<ReferencedClass> & rc) const
00450 {
00451 return (__ref != rc.__ref);
00452 }
00453
00454 bool operator == (const ConstReferenceCounting<ReferencedClass> & rc) const
00455 {
00456 return (__ref == rc.__ref);
00457 }
00458
00459 bool operator != (const ConstReferenceCounting<ReferencedClass> & rc) const
00460 {
00461 return (__ref != rc.__ref);
00462 }
00463
00465 const ReferenceCounting& operator = (ReferencedClass* ref)
00466 {
00467 #ifndef NDEBUG
00468 fflog(4) << __ref << ':' << numberOfReferences()
00469 << ": remove operator=(ReferencedClass*) ReferenceCounting on "
00470 << typeid(__ref).name() << '\n';
00471 #endif // NDEBUG
00472 RCC.removeReference(*this);
00473
00474 __ref = ref;
00475
00476 #ifndef NDEBUG
00477 fflog(4) << __ref << ':' << numberOfReferences()
00478 << ": create operator=(ReferencedClass*) ReferenceCounting on "
00479 << typeid(__ref).name() << '\n';
00480 #endif // NDEBUG
00481 RCC.addReference(*this);
00482
00483 return *this;
00484 }
00485
00487 const ReferenceCounting&
00488 operator = (const ReferenceCounting<ReferencedClass>& O)
00489 {
00490 #ifndef NDEBUG
00491 fflog(4)
00492 << __ref << ':' << numberOfReferences()
00493 << ": remove operator=(ReferenceCounting<T>&) ReferenceCounting on "
00494 << typeid(__ref).name() << '\n';
00495 #endif // NDEBUG
00496 RCC.removeReference(*this);
00497
00498 __ref = O.__ref;
00499
00500 #ifndef NDEBUG
00501 fflog(4)
00502 << __ref << ':' << numberOfReferences()
00503 << ": create operator=(ReferenceCounting<T>&) ReferenceCounting on "
00504 << typeid(__ref).name() << '\n';
00505 #endif // NDEBUG
00506 RCC.addReference(*this);
00507
00508 return *this;
00509 }
00510
00512 ReferenceCounting(const ReferenceCounting<ReferencedClass>& O)
00513 : RCC(ReferenceCountingCenter::instance()),
00514 __ref(O.__ref)
00515 {
00516 #ifndef NDEBUG
00517 fflog(4) << __ref << ':' << numberOfReferences()
00518 << ": create copy ReferenceCounting on "
00519 << typeid(__ref).name() << '\n';
00520 #endif // NDEBUG
00521 RCC.addReference(*this);
00522 }
00523
00525 ReferenceCounting(ReferencedClass* ref)
00526 : RCC(ReferenceCountingCenter::instance()),
00527 __ref(ref)
00528 {
00529 #ifndef NDEBUG
00530 fflog(4) << __ref << ':' << numberOfReferences() << ": create ReferenceCounting on "
00531 << typeid(__ref).name() << '\n';
00532 #endif // NDEBUG
00533 RCC.addReference(*this);
00534 }
00535
00537 ReferenceCounting()
00538 : RCC(ReferenceCountingCenter::instance()),
00539 __ref(0)
00540 {
00541 #ifndef NDEBUG
00542 fflog(4) << __ref << ':' << numberOfReferences() << ": create ReferenceCounting on "
00543 << typeid(__ref).name() << '\n';
00544 #endif // NDEBUG
00545 RCC.addReference(*this);
00546 }
00547
00549 ~ReferenceCounting()
00550 {
00551 #ifndef NDEBUG
00552 fflog(4)
00553 << __ref << ':' << numberOfReferences() << ": remove ReferenceCounting on "
00554 << typeid(__ref).name() << '\n';
00555 #endif // NDEBUG
00556 RCC.removeReference(*this);
00557 }
00558 };
00559
00560 #endif // REFERENCE_COUNTING_HPP