IBR-DTNSuite
0.8
|
00001 /* 00002 * Copyright 2011 Johannes Morgenroth, IBR, TU Braunschweig 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #ifndef IBRCOMMON_refcnt_ptr_h 00018 #define IBRCOMMON_refcnt_ptr_h 1 00019 00020 #include "ibrcommon/thread/Mutex.h" 00021 #include "ibrcommon/thread/MutexLock.h" 00022 00023 template <class T> class refcnt_ptr 00024 { 00025 protected: 00026 // a helper class that holds the pointer to the managed object 00027 // and its reference count 00028 class Holder 00029 { 00030 public: 00031 Holder( T* ptr) : ptr_(ptr), count_(1) {}; 00032 virtual ~Holder() { delete ptr_;}; 00033 00034 T* ptr_; 00035 unsigned count_; 00036 ibrcommon::Mutex lock; 00037 }; 00038 00039 Holder* h_; 00040 00041 private: 00042 void down() 00043 { 00044 try { 00045 ibrcommon::MutexLock l(h_->lock); 00046 if (--h_->count_ == 0) throw true; 00047 } catch (const bool&) { 00048 delete h_; 00049 } 00050 } 00051 00052 public: 00053 // ctor of refcnt_ptr (p must not be NULL) 00054 explicit refcnt_ptr(T* p) : h_(new Holder(p)) 00055 { 00056 } 00057 00058 // dtor of refcnt_ptr 00059 ~refcnt_ptr() 00060 { 00061 down(); 00062 } 00063 00064 // copy and assignment of refcnt_ptr 00065 refcnt_ptr (const refcnt_ptr<T>& right) : h_(right.h_) 00066 { 00067 ibrcommon::MutexLock l(h_->lock); 00068 ++h_->count_; 00069 } 00070 00071 refcnt_ptr<T>& operator= (const refcnt_ptr<T>& right) 00072 { 00073 // ignore assignment to myself 00074 if (h_ == right.h_) return *this; 00075 00076 ibrcommon::MutexLock l(right.h_->lock); 00077 ++right.h_->count_; 00078 00079 down(); 00080 00081 h_ = right.h_; 00082 00083 return *this; 00084 } 00085 00086 refcnt_ptr<T>& operator= (refcnt_ptr<T>& right) 00087 { 00088 // ignore assignment to myself 00089 if (h_ == right.h_) return *this; 00090 00091 ibrcommon::MutexLock l(right.h_->lock); 00092 ++right.h_->count_; 00093 00094 down(); 00095 00096 h_ = right.h_; 00097 00098 return *this; 00099 } 00100 00101 // access to the managed object 00102 T* operator-> () { return h_->ptr_; } 00103 T& operator* () { return *h_->ptr_; } 00104 T* getPointer() { return h_->ptr_; } 00105 00106 const T* operator-> () const { return h_->ptr_; } 00107 const T& operator* () const { return *h_->ptr_; } 00108 const T* getPointer() const { return h_->ptr_; } 00109 }; 00110 #endif