IBR-DTNSuite 0.6

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                         ibrcommon::MutexLock l(right.h_->lock);
00074                         ++right.h_->count_;
00075 
00076                         down();
00077 
00078                         h_ = right.h_;
00079 
00080                         return *this;
00081                 }
00082 
00083                 refcnt_ptr<T>& operator= (refcnt_ptr<T>& right)
00084                 {
00085                         ibrcommon::MutexLock l(right.h_->lock);
00086                         ++right.h_->count_;
00087 
00088                         down();
00089 
00090                         h_ = right.h_;
00091 
00092                         return *this;
00093                 }
00094 
00095                 // access to the managed object
00096                 T* operator-> () { return h_->ptr_; }
00097                 T& operator* () { return *h_->ptr_; }
00098                 T* getPointer() { return h_->ptr_; }
00099 
00100                 const T* operator-> () const { return h_->ptr_; }
00101                 const T& operator* () const { return *h_->ptr_; }
00102                 const T* getPointer() const { return h_->ptr_; }
00103 };
00104 #endif