Page Speed Optimization Libraries
1.4.26.1
|
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_