Page Speed Optimization Libraries  1.3.25.1
net/instaweb/util/public/ref_counted_ptr.h
Go to the documentation of this file.
00001 /*
00002  * Copyright 2010 Google Inc.
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 
00030 
00031 #ifndef NET_INSTAWEB_UTIL_PUBLIC_REF_COUNTED_PTR_H_
00032 #define NET_INSTAWEB_UTIL_PUBLIC_REF_COUNTED_PTR_H_
00033 
00034 #include "base/logging.h"
00035 #include "net/instaweb/util/public/atomic_int32.h"
00036 #include "net/instaweb/util/public/basictypes.h"
00037 
00038 namespace net_instaweb {
00039 
00040 template<class T>
00041 class RefCounted {
00042  public:
00043   RefCounted() : ref_count_(0) {}
00044   ~RefCounted() { DCHECK(ref_count_.value() == 0); }
00045 
00046   void Release() {
00047     if (ref_count_.BarrierIncrement(-1) == 0) {
00048       delete static_cast<T*>(this);
00049     }
00050   }
00051 
00052   void AddRef() {
00053     ref_count_.NoBarrierIncrement(1);
00054   }
00055 
00056   bool HasOneRef() {
00057     return (ref_count_.value() == 1);
00058   }
00059 
00060  private:
00061   AtomicInt32 ref_count_;
00062   DISALLOW_COPY_AND_ASSIGN(RefCounted<T>);
00063 };
00064 
00068 template<class T>
00069 class RefCountedPtr {
00070  public:
00071   RefCountedPtr() : ptr_(NULL) {}
00072   explicit RefCountedPtr(T* t) : ptr_(t) {
00073     if (t != NULL) {
00074       t->AddRef();
00075     }
00076   }
00077 
00078   RefCountedPtr(const RefCountedPtr<T>& src)
00079       : ptr_(src.ptr_) {
00080     if (ptr_ != NULL) {
00081       ptr_->AddRef();
00082     }
00083   }
00084 
00085   template<class U>
00086   explicit RefCountedPtr(const RefCountedPtr<U>& src)
00087       : ptr_(static_cast<T*>(src.ptr_)) {
00088     if (ptr_ != NULL) {
00089       ptr_->AddRef();
00090     }
00091   }
00092 
00093   ~RefCountedPtr() {
00094     if (ptr_ != NULL) {
00095       ptr_->Release();
00096     }
00097   }
00098 
00099   RefCountedPtr<T>& operator=(const RefCountedPtr<T>& other) {
00101     if (other.ptr_ != NULL) {
00102       other.ptr_->AddRef();
00103     }
00104     if (ptr_ != NULL) {
00105       ptr_->Release();
00106     }
00107     ptr_ = other.ptr_;
00108     return *this;
00109   }
00110 
00111   template<class U>
00112   RefCountedPtr<T>& operator=(const RefCountedPtr<U>& other) {
00113     if (other.ptr_ != NULL) {
00114       other.ptr_->AddRef();
00115     }
00116     if (ptr_ != NULL) {
00117       ptr_->Release();
00118     }
00119     ptr_ = static_cast<T*>(other.ptr_);
00120     return *this;
00121   }
00122 
00123   T* operator->() const { return ptr_; }
00124   T* get() const { return ptr_; }
00125 
00129   bool unique() const { return !this->ptr_ || this->ptr_->HasOneRef(); }
00130 
00131   template<typename U>
00132   RefCountedPtr<U> StaticCast() const {
00133     return RefCountedPtr<U>(static_cast<U*>(this->get()));
00134   }
00135 
00136   void clear() {
00137     *this = RefCountedPtr();
00138   }
00139   void reset(T* ptr) {
00140     *this = RefCountedPtr(ptr);
00141   }
00142   void reset(const RefCountedPtr& src) {
00143     *this = src;
00144   }
00145 
00146  private:
00147   template <class U> friend class RefCountedPtr;
00148   operator void*() const; 
00149   operator T*() const; 
00150 
00153   T* ptr_;
00154 };
00155 
00161 template<class T>
00162 class RefCountedObj {
00163  public:
00164   RefCountedObj() : data_ptr_(new Data()) {}
00165   explicit RefCountedObj(const T& val) : data_ptr_(new Data(val)) {}
00166 
00170   bool unique() const { return data_ptr_.unique(); }
00171 
00172   T* get() { return &data_ptr_->value; }
00173   const T* get() const { return &data_ptr_->value; }
00174   T* operator->() { return &data_ptr_->value; }
00175   const T* operator->() const { return &data_ptr_->value; }
00176   T& operator*() { return data_ptr_->value; }
00177   const T& operator*() const { return data_ptr_->value; }
00178 
00179  protected:
00180   struct Data : public RefCounted<Data> {
00181     Data() {}
00182     explicit Data(const T& val) : value(val) {}
00183     T value;
00184   };
00185 
00186   RefCountedPtr<Data> data_ptr_;
00187 
00188  private:
00189   operator void*() const; 
00190   operator T*() const; 
00191 
00193 };
00194 
00204 #define REFCOUNT_FRIEND_DECLARATION(class_name) \
00205   friend class net_instaweb::RefCounted<class_name>
00206 
00207 }  
00208 
00209 #endif  ///< NET_INSTAWEB_UTIL_PUBLIC_REF_COUNTED_PTR_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines