1 // Copyright (C) 2007 Davis E. King (davis@dlib.net) 2 // License: Boost Software License See LICENSE.txt for the full license. 3 #ifndef DLIB_WEAK_PTr_ 4 #define DLIB_WEAK_PTr_ 5 6 #include <algorithm> 7 #include <memory> 8 #include "shared_ptr.h" 9 #include "../algs.h" 10 #include "weak_ptr_abstract.h" 11 12 namespace dlib { 13 14 template < 15 typename T 16 > 17 class weak_ptr 18 { 19 20 /*! 21 CONVENTION 22 - if (weak_node != 0) then 23 - data == valid pointer to shared data 24 - weak_node->ref_count == the number of weak_ptrs that reference this->data 25 - else 26 - data == 0 27 28 - expired() == ((weak_node == 0) || (weak_node->shared_node == 0)) 29 - if (expired() == false) then 30 - use_count() == weak_node->shared_node->ref_count 31 - else 32 - use_count() == 0 33 !*/ 34 35 public: 36 typedef T element_type; 37 weak_ptr()38 weak_ptr( 39 ) : data(0), weak_node(0) 40 { 41 } 42 43 template<typename Y> weak_ptr(const shared_ptr<Y> & r)44 weak_ptr( 45 const shared_ptr<Y>& r 46 ) 47 { 48 data = r.data; 49 if (r.shared_node) 50 { 51 if (r.shared_node->weak_node) 52 { 53 weak_node = r.shared_node->weak_node; 54 weak_node->ref_count += 1; 55 } 56 else 57 { 58 weak_node = new weak_ptr_node(r.shared_node); 59 r.shared_node->weak_node = weak_node; 60 } 61 } 62 else 63 { 64 weak_node = 0; 65 } 66 } 67 weak_ptr(const weak_ptr & r)68 weak_ptr( 69 const weak_ptr& r 70 ) 71 { 72 data = r.data; 73 weak_node = r.weak_node; 74 if (weak_node) 75 weak_node->ref_count += 1; 76 } 77 78 template<typename Y> weak_ptr(const weak_ptr<Y> & r)79 weak_ptr( 80 const weak_ptr<Y>& r 81 ) 82 { 83 data = r.data; 84 weak_node = r.weak_node; 85 if (weak_node) 86 weak_node->ref_count += 1; 87 } 88 ~weak_ptr()89 ~weak_ptr( 90 ) 91 { 92 if (weak_node) 93 { 94 // make note that this weak_ptr is being destroyed 95 weak_node->ref_count -= 1; 96 97 // if this is the last weak_ptr then we should clean up our stuff 98 if (weak_node->ref_count == 0) 99 { 100 if (expired() == false) 101 weak_node->shared_node->weak_node = 0; 102 delete weak_node; 103 } 104 } 105 } 106 107 weak_ptr& operator= ( 108 const weak_ptr& r 109 ) 110 { 111 weak_ptr(r).swap(*this); 112 return *this; 113 } 114 115 template<typename Y> 116 weak_ptr& operator= ( 117 const weak_ptr<Y>& r 118 ) 119 { 120 weak_ptr(r).swap(*this); 121 return *this; 122 } 123 124 template<typename Y> 125 weak_ptr& operator=( 126 const shared_ptr<Y>& r 127 ) 128 { 129 weak_ptr(r).swap(*this); 130 return *this; 131 } 132 use_count()133 long use_count( 134 ) const 135 { 136 if (expired()) 137 return 0; 138 else 139 return weak_node->shared_node->ref_count; 140 } 141 expired()142 bool expired() const { return weak_node == 0 || weak_node->shared_node == 0; } 143 lock()144 shared_ptr<T> lock( 145 ) const 146 { 147 if (expired()) 148 return shared_ptr<T>(); 149 else 150 return shared_ptr<T>(*this); 151 } 152 reset()153 void reset( 154 ) 155 { 156 weak_ptr().swap(*this); 157 } 158 swap(weak_ptr<T> & b)159 void swap( 160 weak_ptr<T>& b 161 ) 162 { 163 std::swap(data, b.data); 164 std::swap(weak_node, b.weak_node); 165 } 166 167 template <typename Y> _private_less(const weak_ptr<Y> & rhs)168 bool _private_less ( 169 const weak_ptr<Y>& rhs 170 ) const 171 { 172 if (expired()) 173 { 174 if (rhs.expired()) 175 { 176 return false; 177 } 178 else 179 { 180 return true; 181 } 182 } 183 else 184 { 185 if (rhs.expired()) 186 { 187 return false; 188 } 189 else 190 { 191 // in this case they have both not expired so lets 192 // compare the shared_node pointers 193 return (weak_node->shared_node) < (rhs.weak_node->shared_node); 194 } 195 } 196 } 197 198 private: 199 200 template <typename Y> friend class shared_ptr; 201 template <typename Y> friend class weak_ptr; 202 203 T* data; 204 weak_ptr_node* weak_node; 205 }; 206 207 template<typename T, typename U> 208 bool operator< ( 209 const weak_ptr<T>& a, 210 const weak_ptr<U>& b 211 ) 212 { 213 return a._private_less(b); 214 } 215 216 template<typename T> swap(weak_ptr<T> & a,weak_ptr<T> & b)217 void swap( 218 weak_ptr<T>& a, 219 weak_ptr<T> & b 220 ) { a.swap(b); } 221 } 222 223 #endif // DLIB_WEAK_PTr_ 224 225 226