// Copyright (C) 2007 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_WEAK_PTr_ #define DLIB_WEAK_PTr_ #include <algorithm> #include <memory> #include "shared_ptr.h" #include "../algs.h" #include "weak_ptr_abstract.h" namespace dlib { template < typename T > class weak_ptr { /*! CONVENTION - if (weak_node != 0) then - data == valid pointer to shared data - weak_node->ref_count == the number of weak_ptrs that reference this->data - else - data == 0 - expired() == ((weak_node == 0) || (weak_node->shared_node == 0)) - if (expired() == false) then - use_count() == weak_node->shared_node->ref_count - else - use_count() == 0 !*/ public: typedef T element_type; weak_ptr( ) : data(0), weak_node(0) { } template<typename Y> weak_ptr( const shared_ptr<Y>& r ) { data = r.data; if (r.shared_node) { if (r.shared_node->weak_node) { weak_node = r.shared_node->weak_node; weak_node->ref_count += 1; } else { weak_node = new weak_ptr_node(r.shared_node); r.shared_node->weak_node = weak_node; } } else { weak_node = 0; } } weak_ptr( const weak_ptr& r ) { data = r.data; weak_node = r.weak_node; if (weak_node) weak_node->ref_count += 1; } template<typename Y> weak_ptr( const weak_ptr<Y>& r ) { data = r.data; weak_node = r.weak_node; if (weak_node) weak_node->ref_count += 1; } ~weak_ptr( ) { if (weak_node) { // make note that this weak_ptr is being destroyed weak_node->ref_count -= 1; // if this is the last weak_ptr then we should clean up our stuff if (weak_node->ref_count == 0) { if (expired() == false) weak_node->shared_node->weak_node = 0; delete weak_node; } } } weak_ptr& operator= ( const weak_ptr& r ) { weak_ptr(r).swap(*this); return *this; } template<typename Y> weak_ptr& operator= ( const weak_ptr<Y>& r ) { weak_ptr(r).swap(*this); return *this; } template<typename Y> weak_ptr& operator=( const shared_ptr<Y>& r ) { weak_ptr(r).swap(*this); return *this; } long use_count( ) const { if (expired()) return 0; else return weak_node->shared_node->ref_count; } bool expired() const { return weak_node == 0 || weak_node->shared_node == 0; } shared_ptr<T> lock( ) const { if (expired()) return shared_ptr<T>(); else return shared_ptr<T>(*this); } void reset( ) { weak_ptr().swap(*this); } void swap( weak_ptr<T>& b ) { std::swap(data, b.data); std::swap(weak_node, b.weak_node); } template <typename Y> bool _private_less ( const weak_ptr<Y>& rhs ) const { if (expired()) { if (rhs.expired()) { return false; } else { return true; } } else { if (rhs.expired()) { return false; } else { // in this case they have both not expired so lets // compare the shared_node pointers return (weak_node->shared_node) < (rhs.weak_node->shared_node); } } } private: template <typename Y> friend class shared_ptr; template <typename Y> friend class weak_ptr; T* data; weak_ptr_node* weak_node; }; template<typename T, typename U> bool operator< ( const weak_ptr<T>& a, const weak_ptr<U>& b ) { return a._private_less(b); } template<typename T> void swap( weak_ptr<T>& a, weak_ptr<T> & b ) { a.swap(b); } } #endif // DLIB_WEAK_PTr_