Simple Application Framework
1
|
00001 /* 00002 This file is part of Simple Application Framework (Saf) library. 00003 Copyright (C) 2010 - 2012 Ondrej Danek <ondrej.danek@gmail.com> 00004 00005 This library is free software: you can redistribute it and/or modify 00006 it under the terms of the GNU General Public License as published 00007 by the Free Software Foundation, either version 3 of the License, or 00008 (at your option) any later version. 00009 00010 Saf is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with Simple Application Framework library. If not, 00017 see <http://www.gnu.org/licenses/>. 00018 */ 00019 00028 #ifndef SAF_MEM_SHAREDPTR_H 00029 #define SAF_MEM_SHAREDPTR_H 00030 00031 #include <typeinfo> 00032 #include "../Type.h" 00033 #include "../OverflowException.h" 00034 #include "../InvalidOperationException.h" 00035 #include "../InvalidCastException.h" 00036 #include "../ArgumentNullException.h" 00037 #include "../Type/Limits.h" 00038 00039 namespace Saf 00040 { 00041 namespace Mem 00042 { 00079 template <class T> 00080 class SharedPtr 00081 { 00082 private: 00084 Size *m_refCounter; 00086 T *m_ptr; 00087 00088 public: 00090 SharedPtr() 00091 : m_refCounter(nullptr), m_ptr(nullptr) 00092 {} 00093 00099 explicit SharedPtr(T *ptr) 00100 : m_refCounter(nullptr), m_ptr(nullptr) 00101 { 00102 Bind(ptr); 00103 } 00104 00106 SharedPtr(const SharedPtr<T> &p) 00107 : m_refCounter(nullptr), m_ptr(nullptr) 00108 { 00109 *this = p; 00110 } 00111 00113 ~SharedPtr() 00114 { 00115 Free(); 00116 } 00117 00119 SharedPtr<T>& operator=(const SharedPtr<T>& p) 00120 { 00121 if (&p != this) 00122 { 00123 Free(); 00124 00125 if (p.m_refCounter != nullptr) 00126 { 00127 if (*p.m_refCounter == Type::Limits<Size>::Max()) 00128 { 00129 throw OverflowException(SAF_SOURCE_LOCATION, 00130 "Reference counter overflow."); 00131 } 00132 00133 m_ptr = p.m_ptr; 00134 m_refCounter = p.m_refCounter; 00135 (*m_refCounter)++; 00136 } 00137 } 00138 00139 return *this; 00140 } 00141 00143 void Swap(SharedPtr<T>& p) 00144 { 00145 if (this != &p) 00146 { 00147 Algo::Swap(m_ptr, p.m_ptr); 00148 Algo::Swap(m_refCounter, p.m_refCounter); 00149 } 00150 } 00151 00166 SharedPtr<T>& Bind(T *ptr) 00167 { 00168 if (ptr == nullptr) 00169 { 00170 throw ArgumentNullException(SAF_SOURCE_LOCATION, "Binding a null pointer."); 00171 } 00172 00173 if (m_ptr == ptr) 00174 { 00175 throw InvalidOperationException(SAF_SOURCE_LOCATION, 00176 "Binding a pointer that has been already binded."); 00177 } 00178 00179 Free(); 00180 00181 m_refCounter = SAF_NEW Size(1); 00182 m_ptr = ptr; 00183 00184 return *this; 00185 } 00186 00193 SharedPtr<T>& BindWithCounter(T *ptr, Size *counter) 00194 { 00195 if (ptr == nullptr) 00196 { 00197 throw ArgumentNullException(SAF_SOURCE_LOCATION, "Binding a null pointer."); 00198 } 00199 00200 if (m_ptr == ptr) 00201 { 00202 throw InvalidOperationException(SAF_SOURCE_LOCATION, 00203 "Binding a pointer that has been already binded."); 00204 } 00205 00206 if (counter == nullptr) 00207 { 00208 throw ArgumentNullException(SAF_SOURCE_LOCATION, "Counter is a null pointer."); 00209 } 00210 00211 if (*counter == Type::Limits<Size>::Max()) 00212 { 00213 throw OverflowException(SAF_SOURCE_LOCATION, "Reference counter overflow."); 00214 } 00215 00216 Free(); 00217 00218 m_ptr = ptr; 00219 m_refCounter = counter; 00220 (*m_refCounter)++; 00221 00222 return *this; 00223 } 00224 00230 void Free() 00231 { 00232 if (m_refCounter != nullptr) 00233 { 00234 if (*m_refCounter > 1) 00235 { 00236 (*m_refCounter)--; 00237 m_refCounter = nullptr; 00238 m_ptr = nullptr; 00239 } 00240 else 00241 { 00242 Mem::Delete(m_refCounter); 00243 Mem::Delete(m_ptr); 00244 } 00245 } 00246 } 00247 00254 template <class C> 00255 SharedPtr<C> Cast() 00256 { 00257 Ptr<C> p; 00258 00259 if (m_refCounter != nullptr) 00260 { 00261 C *np = dynamic_cast<C *>(m_ptr); 00262 00263 if (np == nullptr) 00264 { 00265 throw InvalidCastException(SAF_SOURCE_LOCATION); 00266 } 00267 00268 p.BindWithCounter(np, m_refCounter); 00269 } 00270 00271 return p; 00272 } 00273 00275 bool IsNull() const 00276 { 00277 return m_ptr == nullptr; 00278 } 00279 00281 T* Get() 00282 { 00283 return m_ptr; 00284 } 00285 00287 const T* Get() const 00288 { 00289 return m_ptr; 00290 } 00291 00293 T *operator->() 00294 { 00295 return m_ptr; 00296 } 00297 00299 const T *operator->() const 00300 { 00301 return m_ptr; 00302 } 00303 00305 T& operator*() 00306 { 00307 return *m_ptr; 00308 } 00309 00311 const T& operator*() const 00312 { 00313 return *m_ptr; 00314 } 00315 }; 00316 } 00317 00319 namespace Algo 00320 { 00321 // Swap specialization for pointer container. 00322 template <class T> 00323 struct SwapFunc< Ptr<T> > 00324 { 00325 void operator()(Ptr<T>& x, Ptr<T>& y) 00326 { 00327 x.Swap(y); 00328 } 00329 }; 00330 } 00332 } 00333 00334 #endif