File indexing completed on 2024-06-23 05:21:36
0001 /* 0002 * SPDX-FileCopyrightText: 2008 Trevor Pounds 0003 * SPDX-License-Identifier: MIT 0004 */ 0005 0006 #ifndef __MOCKITOPP_POINTERS_PTR__ 0007 #define __MOCKITOPP_POINTERS_PTR__ 0008 0009 namespace mockitopp 0010 { 0011 namespace detail 0012 { 0013 /** 0014 * The default deleter functor used by shared_ptr 0015 * to free the underlying allocated memory. 0016 * 0017 * @author Trevor Pounds 0018 */ 0019 template <typename T> 0020 struct default_ptr_deleter 0021 { 0022 void operator() (T* ptr) 0023 { delete ptr; } 0024 }; 0025 0026 /** 0027 * A reference counting "smart" pointer similar to 0028 * the ones provided by boost, tr1, c++0x, etc. 0029 * 0030 * NOTE: 0031 * 0032 * Concurrent usage is not supported since the 0033 * reference counter is not modified atomically. 0034 * 0035 * @author Trevor Pounds 0036 */ 0037 template <typename T, typename D = default_ptr_deleter<T> > 0038 class shared_ptr 0039 { 0040 public: 0041 0042 shared_ptr() 0043 : _ptr_impl() 0044 {} 0045 0046 shared_ptr(const shared_ptr& rhs) 0047 : _ptr_impl(rhs._ptr_impl) 0048 { __increment(); } 0049 0050 explicit shared_ptr(T* raw_ptr) 0051 : _ptr_impl(new shared_ptr_impl(raw_ptr, 1)) 0052 {} 0053 0054 ~shared_ptr() { __decrement(); } 0055 0056 bool operator==(const shared_ptr& rhs) const { return _ptr_impl == rhs._ptr_impl; } 0057 bool operator!=(const shared_ptr& rhs) const { return _ptr_impl != rhs._ptr_impl; } 0058 bool operator<(const shared_ptr& rhs) const { return _ptr_impl < rhs._ptr_impl; } 0059 bool operator>(const shared_ptr& rhs) const { return _ptr_impl > rhs._ptr_impl; } 0060 bool operator<=(const shared_ptr& rhs) const { return _ptr_impl <= rhs._ptr_impl; } 0061 bool operator>=(const shared_ptr& rhs) const { return _ptr_impl >= rhs._ptr_impl; } 0062 0063 shared_ptr& operator=(const shared_ptr& rhs) 0064 { 0065 if(this != &rhs) 0066 { 0067 __decrement(); 0068 _ptr_impl = rhs._ptr_impl; 0069 __increment(); 0070 } 0071 return *this; 0072 } 0073 0074 T* get() const { return (_ptr_impl) ? _ptr_impl->_raw_ptr : 0; } 0075 T& operator*() const { return *get(); } 0076 T* operator->() const { return get(); } 0077 0078 private: 0079 0080 struct shared_ptr_impl 0081 { 0082 T* _raw_ptr; 0083 size_t _count; 0084 0085 shared_ptr_impl(T* raw_ptr = 0, size_t count = 0) 0086 : _raw_ptr(raw_ptr) 0087 , _count(count) 0088 {} 0089 0090 shared_ptr_impl(const shared_ptr_impl &other) 0091 : _raw_ptr(other._raw_ptr) 0092 , _count(other._count) 0093 {} 0094 0095 ~shared_ptr_impl() 0096 { D()(_raw_ptr); } 0097 0098 shared_ptr_impl &operator=(const shared_ptr_impl &other) 0099 { 0100 shared_ptr_impl tmp(other); 0101 std::swap(*this, other); 0102 return *this; 0103 } 0104 0105 }* _ptr_impl; 0106 0107 void __decrement() 0108 { 0109 if(_ptr_impl && --(_ptr_impl->_count) == 0) 0110 { delete _ptr_impl; } 0111 } 0112 0113 void __increment() 0114 { 0115 if(_ptr_impl) 0116 { (_ptr_impl->_count)++; } 0117 } 0118 }; 0119 0120 /** 0121 * The default deleter functor used by shared_array 0122 * to free the underlying allocated memory. 0123 * 0124 * @author Trevor Pounds 0125 */ 0126 template <typename T> 0127 struct default_array_deleter 0128 { 0129 void operator() (T* array) 0130 { delete[] array; } 0131 }; 0132 0133 /** 0134 * A reference counting "smart" array pointer similar 0135 * to the ones provided by boost, tr1, c++0x, etc. 0136 * 0137 * NOTE: 0138 * 0139 * Concurrent usage is not supported since the 0140 * reference counter is not modified atomically. 0141 * 0142 * @author Trevor Pounds 0143 */ 0144 template <typename T, typename D = default_array_deleter<T> > 0145 class shared_array : public shared_ptr<T, D> 0146 { 0147 public: 0148 0149 shared_array() 0150 : shared_ptr<T, D>() 0151 {} 0152 0153 explicit shared_array(T* raw_ptr) 0154 : shared_ptr<T, D>(raw_ptr) 0155 {} 0156 0157 T& operator[] (size_t i) const { return *(shared_array::get() + i); } 0158 }; 0159 0160 /** 0161 * A pointer that transfers ownership on copies and assignment. 0162 * 0163 * @author Trevor Pounds 0164 */ 0165 template <typename T, typename D = default_ptr_deleter<T> > 0166 class owned_ptr 0167 { 0168 public: 0169 0170 owned_ptr() 0171 : _ptr(0) 0172 {} 0173 0174 owned_ptr(const owned_ptr& rhs) 0175 : _ptr((T*) ((size_t) rhs.release() | OWNER)) 0176 {} 0177 0178 explicit owned_ptr(T* ptr) 0179 : _ptr((T*) ((size_t) ptr | OWNER)) 0180 {} 0181 0182 ~owned_ptr() { __delete(); } 0183 0184 owned_ptr& operator=(const owned_ptr& rhs) 0185 { 0186 if(this != &rhs) 0187 { 0188 if(get() != rhs.get()) 0189 { __delete(); } 0190 _ptr = rhs._ptr; 0191 rhs.release(); 0192 } 0193 return *this; 0194 } 0195 0196 bool is_owner() const { return ((size_t) _ptr & OWNER) == OWNER; } 0197 0198 T* get() const { return (T*) ((size_t) _ptr & POINTER); } 0199 T& operator*() const { return *get(); } 0200 T* operator->() const { return get(); } 0201 T* release() const { return (_ptr = get()); } 0202 0203 private: 0204 0205 static const size_t OWNER = 0x1; 0206 static const size_t POINTER = ~OWNER; 0207 0208 mutable T* _ptr; 0209 0210 void __delete() 0211 { 0212 if(is_owner()) 0213 { 0214 D()(get()); 0215 _ptr = 0; 0216 } 0217 } 0218 }; 0219 0220 /** 0221 * An array pointer that transfers ownership on copies and assignment. 0222 * 0223 * @author Trevor Pounds 0224 */ 0225 template <typename T, typename D = default_array_deleter<T> > 0226 class owned_array : public owned_ptr<T, D> 0227 { 0228 public: 0229 0230 owned_array() 0231 : owned_ptr<T, D>() 0232 {} 0233 0234 explicit owned_array(T* ptr) 0235 : owned_ptr<T, D>(ptr) 0236 {} 0237 0238 T& operator[] (size_t i) const { return *(owned_array::get() + i); } 0239 }; 0240 } // namespace detail 0241 } // namespace mockitopp 0242 0243 #endif //__MOCKITOPP_POINTERS_PTR__