diff --git a/doc/smart_ptr/shared_ptr.adoc b/doc/smart_ptr/shared_ptr.adoc index f7e5335..52aa1be 100644 --- a/doc/smart_ptr/shared_ptr.adoc +++ b/doc/smart_ptr/shared_ptr.adoc @@ -577,7 +577,7 @@ element_type * get() const noexcept; [none] * {blank} + -Returns:: the stored pointer. +Returns:: The stored pointer. ### unique ``` @@ -595,7 +595,7 @@ long use_count() const noexcept; [none] * {blank} + -Returns:: the number of `shared_ptr` objects, `*this` included, that share ownership with `*this`, or 0 when `*this` is empty. +Returns:: The number of `shared_ptr` objects, `*this` included, that share ownership with `*this`, or 0 when `*this` is empty. ### conversions ``` @@ -682,7 +682,7 @@ template [none] * {blank} + -Returns:: an unspecified value such that +Returns:: An unspecified value such that - `operator<` is a strict weak ordering as described in section [lib.alg.sorting] of the {cpp} standard; - under the equivalence relation defined by `operator<`, `!(a < b) && !(b < a)`, two `shared_ptr` instances are equivalent if and only if they share ownership or are both empty. diff --git a/doc/smart_ptr/weak_ptr.adoc b/doc/smart_ptr/weak_ptr.adoc index c5a740c..b605949 100644 --- a/doc/smart_ptr/weak_ptr.adoc +++ b/doc/smart_ptr/weak_ptr.adoc @@ -1,5 +1,7 @@ //// -Copyright 2017 Peter Dimov +Copyright 1999 Greg Colvin and Beman Dawes +Copyright 2002 Darin Adler +Copyright 2002-2005, 2017 Peter Dimov Distributed under the Boost Software License, Version 1.0. @@ -13,3 +15,287 @@ http://www.boost.org/LICENSE_1_0.txt :toc-title: :idprefix: weak_ptr_ +## Description + +The `weak_ptr` class template stores a "weak reference" to an object that's already managed by a `shared_ptr`. +To access the object, a `weak_ptr` can be converted to a `shared_ptr` using the `shared_ptr` constructor taking +`weak_ptr`, or the `weak_ptr` member function `lock`. When the last `shared_ptr` to the object goes away and the +object is deleted, the attempt to obtain a `shared_ptr` from the `weak_ptr` instances that refer to the deleted +object will fail: the constructor will throw an exception of type `boost::bad_weak_ptr`, and `weak_ptr::lock` will +return an empty `shared_ptr`. + +Every `weak_ptr` meets the `CopyConstructible` and `Assignable` requirements of the {cpp} Standard Library, and so +can be used in standard library containers. Comparison operators are supplied so that `weak_ptr` works with the standard +library's associative containers. + +`weak_ptr` operations never throw exceptions. + +The class template is parameterized on `T`, the type of the object pointed to. + +Compared to `shared_ptr`, `weak_ptr` provides a very limited subset of operations since accessing its stored pointer is +often dangerous in multithreaded programs, and sometimes unsafe even within a single thread (that is, it may invoke undefined +behavior.) Pretend for a moment that `weak_ptr` had a get member function that returned a raw pointer, and consider this innocent +piece of code: + +``` +shared_ptr p(new int(5)); +weak_ptr q(p); + +// some time later + +if(int * r = q.get()) +{ + // use *r +} +``` + +Imagine that after the `if`, but immediately before `r` is used, another thread executes the statement `p.reset()`. Now `r` is a dangling pointer. + +The solution to this problem is to create a temporary `shared_ptr` from `q`: + +``` +shared_ptr p(new int(5)); +weak_ptr q(p); + +// some time later + +if(shared_ptr r = q.lock()) +{ + // use *r +} +``` + +Now `r` holds a reference to the object that was pointed by `q`. Even if `p.reset()` is executed in another thread, the object will stay alive until +`r` goes out of scope or is reset. By obtaining a `shared_ptr` to the object, we have effectively locked it against destruction. + +## Synopsis + +`weak_ptr` is defined in ``. + +``` +namespace boost +{ + +template class weak_ptr +{ +public: + + typedef /*see below*/ element_type; + + weak_ptr() noexcept; + + template weak_ptr(shared_ptr const & r) noexcept; + weak_ptr(weak_ptr const & r) noexcept; + template weak_ptr(weak_ptr const & r) noexcept; + + weak_ptr(weak_ptr && r) noexcept; + + ~weak_ptr() noexcept; + + weak_ptr & operator=(weak_ptr const & r) noexcept; + weak_ptr & operator=(weak_ptr && r) noexcept; + template weak_ptr & operator=(weak_ptr const & r) noexcept; + template weak_ptr & operator=(shared_ptr const & r) noexcept; + + long use_count() const noexcept; + bool expired() const noexcept; + + shared_ptr lock() const noexcept; + + void reset() noexcept; + + void swap(weak_ptr & b) noexcept; + + template bool owner_before( weak_ptr const & r ) const noexcept; + template bool owner_before( shared_ptr const & r ) const noexcept; +}; + +template + bool operator<(weak_ptr const & a, weak_ptr const & b) noexcept; + +template void swap(weak_ptr & a, weak_ptr & b) noexcept; + +} // namespace boost +``` + +## Members + +### element_type +``` +typedef ... element_type; +``` +`element_type` is `T` when `T` is not an array type, and `U` when `T` is `U[]` or `U[N]`. + +### constructors +``` +weak_ptr() noexcept; +``` +[none] +* {blank} ++ +Effects:: Constructs an empty `weak_ptr`. +Postconditions:: `use_count() == 0`. + +``` +template weak_ptr(shared_ptr const & r) noexcept; +``` +``` +weak_ptr(weak_ptr const & r) noexcept; +``` +``` +template weak_ptr(weak_ptr const & r) noexcept; +``` +[none] +* {blank} ++ +Effects:: If `r` is empty, constructs an empty `weak_ptr`; otherwise, constructs a `weak_ptr` that shares ownership with `r` as if by storing a copy of the pointer stored in `r`. +Postconditions:: `use_count() == r.use_count()`. + +``` +weak_ptr(weak_ptr && r) noexcept; +``` +[none] +* {blank} ++ +Effects:: Constructs a `weak_ptr` that has the value `r` held. +Postconditions:: `r` is empty. + +### destructor +``` +~weak_ptr() noexcept; +``` +[none] +* {blank} ++ +Effects:: Destroys this `weak_ptr` but has no effect on the object its stored pointer points to. + +### assignment +``` +weak_ptr & operator=(weak_ptr const & r) noexcept; +``` +``` +weak_ptr & operator=(weak_ptr && r) noexcept; +``` +``` +template weak_ptr & operator=(weak_ptr const & r) noexcept; +``` +``` +template weak_ptr & operator=(shared_ptr const & r) noexcept; +``` +[none] +* {blank} ++ +Effects:: Equivalent to `weak_ptr(r).swap(*this)`. + +NOTE: The implementation is free to meet the effects (and the implied guarantees) via different means, without creating a temporary. + +### use_count +``` +long use_count() const noexcept; +``` +[none] +* {blank} ++ +Returns:: 0 if `*this` is empty; otherwise, the number of `shared_ptr` objects that share ownership with `*this`. + +### expired +``` +bool expired() const noexcept; +``` +[none] +* {blank} ++ +Returns:: `use_count() == 0`. + +### lock +``` +shared_ptr lock() const noexcept; +``` +[none] +* {blank} ++ +Returns:: `expired()? shared_ptr(): shared_ptr(*this)`. + +### reset +``` +void reset() noexcept; +``` +[none] +* {blank} ++ +Effects:: Equivalent to `weak_ptr().swap(*this)`. + +### swap +``` +void swap(weak_ptr & b) noexcept; +``` +[none] +* {blank} ++ +Effects:: Exchanges the contents of the two smart pointers. + +``` +template bool owner_before( weak_ptr const & r ) const noexcept; +``` +``` +template bool owner_before( shared_ptr const & r ) const noexcept; +``` +[none] +* {blank} ++ +Returns:: See the description of `operator<`. + +## Free Functions + +### comparison +``` +template + bool operator<(weak_ptr const & a, weak_ptr const & b) noexcept; +``` +[none] +* {blank} ++ +Returns:: An unspecified value such that +- `operator<` is a strict weak ordering as described in section [lib.alg.sorting] of the {cpp} standard; +- under the equivalence relation defined by `operator<`, `!(a < b) && !(b < a)`, two `weak_ptr` instances + are equivalent if and only if they share ownership or are both empty. + +NOTE: Allows `weak_ptr` objects to be used as keys in associative containers. + +### swap +``` +template void swap(weak_ptr & a, weak_ptr & b) noexcept; +``` +[none] +* {blank} ++ +Effects:: Equivalent to `a.swap(b)`. + +## Frequently Asked Questions + +[qanda] +Can an object create a weak_ptr to itself in its constructor?:: + + No. A `weak_ptr` can only be created from a `shared_ptr`, and at object construction time no + `shared_ptr` to the object exists yet. Even if you could create a temporary `shared_ptr` to `this`, + it would go out of scope at the end of the constructor, and all `weak_ptr` instances would instantly expire. ++ +The solution is to make the constructor private, and supply a factory function that returns a `shared_ptr`: ++ +``` +class X +{ +private: + + X(); + +public: + + static shared_ptr create() + { + shared_ptr px(new X); + // create weak pointers from px here + return px; + } +}; +```