IBR-DTNSuite  0.8
ibrcommon/ibrcommon/refcnt_ptr.h
Go to the documentation of this file.
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