00001 #ifndef UNIQUE_PTR_H_18C6F30C 00002 #define UNIQUE_PTR_H_18C6F30C 00003 00004 #if !defined (ACE_LACKS_PRAGMA_ONCE) 00005 # pragma once 00006 #endif /* ACE_LACKS_PRAGMA_ONCE */ 00007 00008 00009 #include "dds/Versioned_Namespace.h" 00010 00011 #include "ace/config-lite.h" 00012 00013 #ifdef ACE_HAS_CPP11 00014 #define HAS_STD_UNIQUE_PTR 00015 #endif 00016 00017 #ifdef HAS_STD_UNIQUE_PTR 00018 #include <memory> 00019 #else 00020 #include "ace/Atomic_Op.h" 00021 #include "ace/Synch_Traits.h" 00022 #include <cassert> 00023 # ifdef ACE_HAS_CPP11 00024 # include <utility> 00025 # else 00026 # include <algorithm> 00027 # endif 00028 #endif 00029 00030 OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL 00031 00032 namespace OpenDDS { 00033 namespace DCPS { 00034 00035 #ifdef HAS_STD_UNIQUE_PTR 00036 00037 using std::move; 00038 using std::unique_ptr; 00039 00040 template <typename T> 00041 using container_supported_unique_ptr = std::unique_ptr<T>; 00042 00043 template <typename T> 00044 struct EnableContainerSupportedUniquePtr {}; 00045 00046 #else //HAS_STD_UNIQUE_PTR 00047 00048 template <typename T> 00049 class rv : public T { 00050 rv(); 00051 ~rv(); 00052 rv(const rv &); 00053 void operator=(const rv&); 00054 }; 00055 00056 template <typename T> 00057 struct default_deleter 00058 { 00059 void operator()(T* ptr) const 00060 { 00061 delete ptr; 00062 } 00063 }; 00064 00065 template <typename T, typename Deleter = default_deleter<T> > 00066 class unique_ptr { 00067 public: 00068 typedef T element_type; 00069 typedef Deleter deleter_type; 00070 00071 explicit unique_ptr(T* p = 0) // never throws 00072 : ptr_(p) 00073 {} 00074 00075 #ifndef __SUNPRO_CC 00076 typedef rv<unique_ptr>& rv_reference; 00077 #else 00078 typedef unique_ptr& rv_reference; 00079 #endif 00080 00081 unique_ptr(rv_reference other) 00082 : ptr_(other.release()) 00083 {} 00084 00085 ~unique_ptr() // never throws 00086 { 00087 Deleter()(ptr_); 00088 } 00089 00090 unique_ptr& operator=(rv<unique_ptr>& other) 00091 { 00092 reset(other.release()); 00093 return *this; 00094 } 00095 00096 void reset(T* p = 0) // never throws 00097 { 00098 Deleter()(ptr_); 00099 ptr_ = p; 00100 } 00101 00102 T* release() 00103 { 00104 T* p = ptr_; 00105 ptr_ = 0; 00106 return p; 00107 } 00108 00109 T& operator*() const // never throws 00110 { 00111 return *get(); 00112 } 00113 00114 T* operator->() const // never throws 00115 { 00116 return get(); 00117 } 00118 00119 T* get() const // never throws 00120 { 00121 return ptr_; 00122 } 00123 00124 operator bool() const // never throws 00125 { 00126 return get() != 0; 00127 } 00128 00129 void swap(unique_ptr& b) // never throws 00130 { 00131 std::swap(ptr_, b.ptr_); 00132 } 00133 00134 private: 00135 unique_ptr(const unique_ptr&); 00136 unique_ptr& operator=(const unique_ptr&); 00137 00138 T* ptr_; 00139 }; 00140 00141 template <typename T> 00142 typename T::rv_reference move(T& p) 00143 { 00144 return static_cast<typename T::rv_reference>(p); 00145 } 00146 00147 00148 template <typename T, typename Deleter> 00149 void swap(unique_ptr<T, Deleter>& a, unique_ptr<T, Deleter>& b) // never throws 00150 { 00151 return a.swap(b); 00152 } 00153 00154 template <typename T> 00155 class container_supported_unique_ptr 00156 { 00157 public: 00158 00159 container_supported_unique_ptr() 00160 : ptr_(0) 00161 {} 00162 00163 explicit container_supported_unique_ptr(T* p) 00164 : ptr_(p) 00165 { 00166 } 00167 00168 template <typename U> 00169 container_supported_unique_ptr(unique_ptr<U> p) 00170 : ptr_(p.release()) 00171 { 00172 } 00173 00174 template <typename U> 00175 container_supported_unique_ptr(const container_supported_unique_ptr<U>& other) 00176 : ptr_(other.get()) 00177 { 00178 this->bump_up(); 00179 } 00180 00181 container_supported_unique_ptr(const container_supported_unique_ptr& b) 00182 : ptr_(b.ptr_) 00183 { 00184 this->bump_up(); 00185 } 00186 00187 ~container_supported_unique_ptr() 00188 { 00189 this->bump_down(); 00190 } 00191 00192 template <typename U> 00193 void reset(U* p) 00194 { 00195 container_supported_unique_ptr tmp(p); 00196 swap(tmp); 00197 } 00198 00199 void reset(T* p=0) 00200 { 00201 container_supported_unique_ptr tmp(p); 00202 swap(tmp); 00203 } 00204 00205 container_supported_unique_ptr& operator=(const container_supported_unique_ptr& b) 00206 { 00207 container_supported_unique_ptr tmp(b); 00208 swap(tmp); 00209 return *this; 00210 } 00211 00212 template <class U> 00213 container_supported_unique_ptr& operator=(const container_supported_unique_ptr<U>& b) 00214 { 00215 container_supported_unique_ptr<T> tmp(b); 00216 swap(tmp); 00217 return *this; 00218 } 00219 00220 template <typename U> 00221 container_supported_unique_ptr& operator=(unique_ptr<U> b) 00222 { 00223 container_supported_unique_ptr<T> tmp(b.release()); 00224 swap(tmp); 00225 return *this; 00226 } 00227 00228 void swap(container_supported_unique_ptr& rhs) 00229 { 00230 T* t = this->ptr_; 00231 this->ptr_ = rhs.ptr_; 00232 rhs.ptr_ = t; 00233 } 00234 00235 T* operator->() const 00236 { 00237 return this->ptr_; 00238 } 00239 00240 T& operator*() const 00241 { 00242 return *this->ptr_; 00243 } 00244 00245 T* get() const 00246 { 00247 return this->ptr_; 00248 } 00249 00250 T* release() 00251 { 00252 T* retval = this->ptr_; 00253 this->ptr_ = 0; 00254 return retval; 00255 } 00256 00257 operator bool() const 00258 { 00259 return get() != 0; 00260 } 00261 00262 bool operator==(const container_supported_unique_ptr& rhs) const 00263 { 00264 return get() == rhs.get(); 00265 } 00266 00267 bool operator!=(const container_supported_unique_ptr& rhs) const 00268 { 00269 return get() != rhs.get(); 00270 } 00271 00272 bool operator < (const container_supported_unique_ptr& rhs) const 00273 { 00274 return get() < rhs.get(); 00275 } 00276 00277 private: 00278 00279 void bump_up() 00280 { 00281 if (this->ptr_ != 0) { 00282 this->ptr_->_add_ref(); 00283 } 00284 } 00285 00286 void bump_down() 00287 { 00288 if (this->ptr_ != 0) { 00289 this->ptr_->_remove_ref(); 00290 this->ptr_ = 0; 00291 } 00292 } 00293 00294 /// The actual "unsmart" pointer to the T object. 00295 T* ptr_; 00296 }; 00297 00298 template <typename T> 00299 void swap(container_supported_unique_ptr<T>& lhs, container_supported_unique_ptr<T>& rhs) 00300 { 00301 lhs.swap(rhs); 00302 } 00303 00304 template <typename T> 00305 class EnableContainerSupportedUniquePtr { 00306 protected: 00307 EnableContainerSupportedUniquePtr() 00308 : ref_count_(1) 00309 { 00310 } 00311 private: 00312 template <typename U> 00313 friend class container_supported_unique_ptr; 00314 00315 template <typename U> 00316 friend typename unique_ptr<U>::rv_reference move(container_supported_unique_ptr<U>& ptr); 00317 00318 void _add_ref() { 00319 ++this->ref_count_; 00320 } 00321 00322 void _remove_ref(){ 00323 const long new_count = --this->ref_count_; 00324 00325 if (new_count == 0) { 00326 delete static_cast<T*>(this); 00327 } 00328 } 00329 long ref_count() const { return ref_count_.value(); } 00330 ACE_Atomic_Op<ACE_SYNCH_MUTEX, long> ref_count_; 00331 }; 00332 00333 template <typename T> 00334 typename unique_ptr<T>::rv_reference move(container_supported_unique_ptr<T>& ptr) 00335 { 00336 # ifndef OPENDDS_SAFETY_PROFILE 00337 assert(ptr->ref_count() == 1); 00338 # endif 00339 return reinterpret_cast<typename unique_ptr<T>::rv_reference>(ptr); 00340 } 00341 00342 #endif 00343 } // namespace DCPS 00344 } // namespace OpenDDS 00345 00346 OPENDDS_END_VERSIONED_NAMESPACE_DECL 00347 #endif /* end of include guard: UNIQUE_PTR_H_18C6F30C */