// Copyright (C) 2007 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #undef DLIB_SHARED_PTr_THREAD_SAFE_ABSTRACT_ #ifdef DLIB_SHARED_PTr_THREAD_SAFE_ABSTRACT_ #include namespace dlib { // ---------------------------------------------------------------------------------------- template < typename T > class shared_ptr_thread_safe { /*! INITIAL VALUE defined by constructors WHAT THIS OBJECT REPRESENTS This object represents a reference counted smart pointer. Each shared_ptr_thread_safe contains a pointer to some object and when the last shared_ptr_thread_safe that points to the object is destructed or reset() then the object is guaranteed to be deleted. This is an implementation of the std::tr1::shared_ptr template from the document ISO/IEC PDTR 19768, Proposed Draft Technical Report on C++ Library Extensions. The only deviation from that document is that this shared_ptr_thread_safe is declared inside the dlib namespace rather than std::tr1, this one is explicitly thread safe, and there isn't a corresponding weak_ptr. THREAD SAFETY This is a version of the shared_ptr object that can be used to share pointers across more than one thread. Note however, that individual instances of this object must still have access to them serialized by a mutex lock if they are to be modified by more than one thread. But if you have two different shared_ptr_thread_safe objects that both point to the same thing from different threads then you are safe. !*/ public: typedef T element_type; shared_ptr_thread_safe( ); /*! ensures - #get() == 0 - #use_count() == 0 !*/ template explicit shared_ptr_thread_safe( Y* p ); /*! requires - p is convertible to a T* type pointer - p can be deleted by calling "delete p;" and doing so will not throw exceptions - p != 0 ensures - #get() == p - #use_count() == 1 - #*this object owns the pointer p throws - std::bad_alloc if this exception is thrown then "delete p;" is called !*/ template shared_ptr_thread_safe( Y* p, const D& d ); /*! requires - p is convertible to a T* type pointer - D is copy constructable (and the copy constructor of D doesn't throw) - p can be deleted by calling "d(p);" and doing so will not throw exceptions - p != 0 ensures - #get() == p - #use_count() == 1 - #*this object owns the pointer p throws - std::bad_alloc if this exception is thrown then "d(p);" is called !*/ shared_ptr_thread_safe( const shared_ptr_thread_safe& r ); /*! ensures - #get() == #r.get() - #use_count() == #r.use_count() - If r is empty, constructs an empty shared_ptr_thread_safe object; otherwise, constructs a shared_ptr_thread_safe object that shares ownership with r. !*/ template shared_ptr_thread_safe( const shared_ptr_thread_safe& r ); /*! requires - Y* is convertible to T* ensures - #get() == #r.get() - #use_count() == #r.use_count() - If r is empty, constructs an empty shared_ptr_thread_safe object; otherwise, constructs a shared_ptr_thread_safe object that shares ownership with r. !*/ ~shared_ptr_thread_safe( ); /*! ensures - if (use_count() > 1) - this object destroys itself but otherwise has no effect (i.e. the pointer get() is still valid and shared between the remaining shared_ptr_thread_safe objects) - else if (use_count() == 1) - deletes the pointer get() by calling delete (or using the deleter passed to the constructor if one was passed in) - else - in this case get() == 0 so there is nothing to do so nothing occurs !*/ shared_ptr_thread_safe& operator= ( const shared_ptr_thread_safe& r ); /*! ensures - equivalent to shared_ptr_thread_safe(r).swap(*this). - returns #*this !*/ template shared_ptr_thread_safe& operator= ( const shared_ptr_thread_safe& r ); /*! requires - Y* is convertible to T* ensures - equivalent to shared_ptr_thread_safe(r).swap(*this). - returns #*this !*/ void reset( ); /*! ensures - equivalent to shared_ptr_thread_safe().swap(*this) !*/ template void reset( Y* p ); /*! requires - p is convertible to a T* type pointer - p can be deleted by calling "delete p;" and doing so will not throw exceptions - p != 0 ensures - equivalent to shared_ptr_thread_safe(p).swap(*this) !*/ template void reset( Y* p, const D& d ); /*! requires - p is convertible to a T* type pointer - D is copy constructable (and the copy constructor of D doesn't throw) - p can be deleted by calling "d(p);" and doing so will not throw exceptions - p != 0 ensures - equivalent to shared_ptr_thread_safe(p,d).swap(*this) !*/ T* get( ) const; /*! ensures - returns the stored pointer !*/ T& operator*( ) const; /*! requires - get() != 0 ensures - returns a reference to *get() !*/ T* operator->( ) const; /*! requires - get() != 0 ensures - returns get() !*/ bool unique( ) const; /*! ensures - returns (use_count() == 1) !*/ long use_count( ) const; /*! ensures - The number of shared_ptr_thread_safe objects, *this included, that share ownership with *this, or 0 when *this is empty. !*/ operator bool( ) const; /*! ensures - returns (get() != 0) !*/ void swap( shared_ptr_thread_safe& b ); /*! ensures - swaps *this and item !*/ }; // ---------------------------------------------------------------------------------------- template bool operator== ( const shared_ptr_thread_safe& a, const shared_ptr_thread_safe& b ); /*! ensures - returns a.get() == b.get() !*/ template bool operator!= ( const shared_ptr_thread_safe& a, const shared_ptr_thread_safe& b ) { return a.get() != b.get(); } /*! ensures - returns a.get() != b.get() !*/ template bool operator< ( const shared_ptr_thread_safe& a, const shared_ptr_thread_safe& b ); /*! ensures - Defines an operator< on shared_ptr_thread_safe types appropriate for use in the associative containers. !*/ template void swap( shared_ptr_thread_safe& a, shared_ptr_thread_safe& b ) { a.swap(b); } /*! provides a global swap function !*/ template shared_ptr_thread_safe static_pointer_cast( const shared_ptr_thread_safe& r ); /*! - if (r.get() == 0) then - returns shared_ptr_thread_safe() - else - returns a shared_ptr_thread_safe object that stores static_cast(r.get()) and shares ownership with r. !*/ template shared_ptr_thread_safe const_pointer_cast( const shared_ptr_thread_safe& r ); /*! - if (r.get() == 0) then - returns shared_ptr_thread_safe() - else - returns a shared_ptr_thread_safe object that stores const_cast(r.get()) and shares ownership with r. !*/ template shared_ptr_thread_safe dynamic_pointer_cast( const shared_ptr_thread_safe& r ); /*! ensures - if (dynamic_cast(r.get()) returns a nonzero value) then - returns a shared_ptr_thread_safe object that stores a copy of dynamic_cast(r.get()) and shares ownership with r - else - returns an empty shared_ptr_thread_safe object. !*/ template std::basic_ostream & operator<< ( std::basic_ostream & os, const shared_ptr_thread_safe& p ); /*! ensures - performs os << p.get() - returns os !*/ template D* get_deleter( const shared_ptr_thread_safe& p ); /*! ensures - if (*this owns a deleter d of type cv-unqualified D) then - returns &d - else - returns 0 !*/ // ---------------------------------------------------------------------------------------- } #endif // DLIB_SHARED_PTr_THREAD_SAFE_ABSTRACT_