get_shared_ptr renamed to weak_ptr::lock.

[SVN r17307]
This commit is contained in:
Peter Dimov
2003-02-10 15:56:36 +00:00
parent 34f423f811
commit 851d87a1bb
7 changed files with 69 additions and 73 deletions

View File

@@ -24,8 +24,6 @@
namespace boost namespace boost
{ {
template<class T> shared_ptr<T> get_shared_ptr(weak_ptr<T> const & r); // never throws
template<class T> class weak_ptr template<class T> class weak_ptr
{ {
private: private:
@@ -64,7 +62,7 @@ public:
template<class Y> template<class Y>
weak_ptr(weak_ptr<Y> const & r): pn(r.pn) // never throws weak_ptr(weak_ptr<Y> const & r): pn(r.pn) // never throws
{ {
px = boost::get_shared_ptr(r).get(); px = r.lock().get();
} }
template<class Y> template<class Y>
@@ -77,7 +75,7 @@ public:
template<class Y> template<class Y>
weak_ptr & operator=(weak_ptr<Y> const & r) // never throws weak_ptr & operator=(weak_ptr<Y> const & r) // never throws
{ {
px = boost::get_shared_ptr(r).get(); px = r.lock().get();
pn = r.pn; pn = r.pn;
return *this; return *this;
} }
@@ -92,9 +90,33 @@ public:
#endif #endif
void reset() // never throws in 1.30+ shared_ptr<T> lock() const // never throws
{ {
this_type().swap(*this); #if defined(BOOST_HAS_THREADS)
// optimization: avoid throw overhead
if(expired())
{
return shared_ptr<element_type>();
}
try
{
return shared_ptr<element_type>(*this);
}
catch(bad_weak_ptr const &)
{
// Q: how can we get here?
// A: another thread may have invalidated r after the use_count test above.
return shared_ptr<element_type>();
}
#else
// optimization: avoid try/catch overhead when single threaded
return expired()? shared_ptr<element_type>(): shared_ptr<element_type>(*this);
#endif
} }
long use_count() const // never throws long use_count() const // never throws
@@ -107,6 +129,11 @@ public:
return pn.use_count() == 0; return pn.use_count() == 0;
} }
void reset() // never throws in 1.30+
{
this_type().swap(*this);
}
void swap(this_type & other) // never throws void swap(this_type & other) // never throws
{ {
std::swap(px, other.px); std::swap(px, other.px);
@@ -151,39 +178,10 @@ template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b)
a.swap(b); a.swap(b);
} }
template<class T> shared_ptr<T> get_shared_ptr(weak_ptr<T> const & r) // never throws
{
#if defined(BOOST_HAS_THREADS)
// optimization: avoid throw overhead
if(r.use_count() == 0)
{
return shared_ptr<T>();
}
try
{
return shared_ptr<T>(r);
}
catch(bad_weak_ptr const &)
{
// Q: how can we get here?
// A: another thread may have invalidated r after the use_count test above.
return shared_ptr<T>();
}
#else
// optimization: avoid try/catch overhead when single threaded
return r.use_count() == 0? shared_ptr<T>(): shared_ptr<T>(r);
#endif
}
// deprecated, provided for backward compatibility // deprecated, provided for backward compatibility
template<class T> shared_ptr<T> make_shared(weak_ptr<T> const & r) template<class T> shared_ptr<T> make_shared(weak_ptr<T> const & r)
{ {
return boost::get_shared_ptr(r); return r.lock();
} }
} // namespace boost } // namespace boost

View File

@@ -390,8 +390,8 @@ q = p;
many of the implicit conversion pitfalls.</P> many of the implicit conversion pitfalls.</P>
</blockquote> </blockquote>
<P><EM>[The conversion to bool is not merely syntactic sugar. It allows <STRONG>shared_ptr</STRONG>s <P><EM>[The conversion to bool is not merely syntactic sugar. It allows <STRONG>shared_ptr</STRONG>s
to be declared in conditions when using <STRONG>dynamic_pointer_cast </STRONG>or to be declared in conditions when using <A href="#dynamic_pointer_cast">dynamic_pointer_cast</A> or
<STRONG>get_shared_ptr</STRONG>.]</EM></P> <A href="weak_ptr.htm#lock">weak_ptr::lock</A>.]</EM></P>
<h3><a name="swap">swap</a></h3> <h3><a name="swap">swap</a></h3>
<pre>void swap(shared_ptr &amp; b); // never throws</pre> <pre>void swap(shared_ptr &amp; b); // never throws</pre>
<blockquote> <blockquote>

View File

@@ -413,7 +413,7 @@ public:
virtual shared_ptr&lt;X&gt; getX() virtual shared_ptr&lt;X&gt; getX()
{ {
shared_ptr&lt;X&gt; px = get_shared_ptr(weak_this); shared_ptr&lt;X&gt; px = weak_this.lock();
return px; return px;
} }
}; };

View File

@@ -94,7 +94,7 @@ template<class T> void test_is_Y(boost::shared_ptr<T> const & p)
template<class T> void test_is_Y(boost::weak_ptr<T> const & p) template<class T> void test_is_Y(boost::weak_ptr<T> const & p)
{ {
boost::shared_ptr<T> q = boost::get_shared_ptr(p); boost::shared_ptr<T> q = p.lock();
BOOST_TEST(q.get() != 0); BOOST_TEST(q.get() != 0);
BOOST_TEST(q->id() == 2); BOOST_TEST(q->id() == 2);
} }
@@ -221,7 +221,7 @@ int main()
{ {
} }
test_is_zero(boost::get_shared_ptr(wp1)); test_is_zero(wp1.lock());
weak_ptr<X> wp2 = static_pointer_cast<X>(p5); weak_ptr<X> wp2 = static_pointer_cast<X>(p5);
@@ -232,10 +232,10 @@ int main()
// Scoped to not affect the subsequent use_count() tests. // Scoped to not affect the subsequent use_count() tests.
{ {
shared_ptr<X> sp2(wp2); shared_ptr<X> sp2(wp2);
test_is_nonzero(boost::get_shared_ptr(wp2)); test_is_nonzero(wp2.lock());
} }
weak_ptr<Y> wp3 = dynamic_pointer_cast<Y>(boost::get_shared_ptr(wp2)); weak_ptr<Y> wp3 = dynamic_pointer_cast<Y>(wp2.lock());
BOOST_TEST(wp3.use_count() == 1); BOOST_TEST(wp3.use_count() == 1);
test_shared(wp2, wp3); test_shared(wp2, wp3);
@@ -246,7 +246,7 @@ int main()
test_shared(wp2, wp4); test_shared(wp2, wp4);
wp1 = p2; wp1 = p2;
test_is_zero(boost::get_shared_ptr(wp1)); test_is_zero(wp1.lock());
wp1 = p4; wp1 = p4;
wp1 = wp3; wp1 = wp3;

View File

@@ -3094,7 +3094,7 @@ public:
virtual boost::shared_ptr<X> getX() virtual boost::shared_ptr<X> getX()
{ {
boost::shared_ptr<X> px = boost::get_shared_ptr(weak_this); boost::shared_ptr<X> px = weak_this.lock();
return px; return px;
} }
}; };

View File

@@ -1183,14 +1183,14 @@ void test()
} // namespace n_comparison } // namespace n_comparison
namespace n_get_shared_ptr namespace n_lock
{ {
void test() void test()
{ {
} }
} // namespace n_get_shared_ptr } // namespace n_lock
namespace n_map namespace n_map
{ {
@@ -1272,7 +1272,7 @@ int main()
n_use_count::test(); n_use_count::test();
n_swap::test(); n_swap::test();
n_comparison::test(); n_comparison::test();
n_get_shared_ptr::test(); n_lock::test();
n_map::test(); n_map::test();

View File

@@ -17,12 +17,12 @@
<p>The <b>weak_ptr</b> class template stores a "weak reference" to an object that's <p>The <b>weak_ptr</b> class template stores a "weak reference" to an object that's
already managed by a <b>shared_ptr</b>. To access the object, a <STRONG>weak_ptr</STRONG> already managed by a <b>shared_ptr</b>. To access the object, a <STRONG>weak_ptr</STRONG>
can be converted to a <STRONG>shared_ptr</STRONG> using <A href="shared_ptr.htm#constructors"> can be converted to a <STRONG>shared_ptr</STRONG> using <A href="shared_ptr.htm#constructors">
the <STRONG>shared_ptr</STRONG> constructor</A> or the function <STRONG><A href="#get_shared_ptr"> the <STRONG>shared_ptr</STRONG> constructor</A> or the member function <STRONG><A href="#lock">
get_shared_ptr</A></STRONG>. When the last <b>shared_ptr</b> to the lock</A></STRONG>. When the last <b>shared_ptr</b> to the object goes
object goes away and the object is deleted, the attempt to obtain a <STRONG>shared_ptr</STRONG> away and the object is deleted, the attempt to obtain a <STRONG>shared_ptr</STRONG>
from the <b>weak_ptr</b> instances that refer to the deleted object will fail: from the <b>weak_ptr</b> instances that refer to the deleted object will fail:
the constructor will throw an exception of type <STRONG>boost::bad_weak_ptr</STRONG>, the constructor will throw an exception of type <STRONG>boost::bad_weak_ptr</STRONG>,
and <STRONG>get_shared_ptr</STRONG> will return an <EM>empty</EM> <STRONG>shared_ptr</STRONG>.</p> and <STRONG>weak_ptr::lock</STRONG> will return an <EM>empty</EM> <STRONG>shared_ptr</STRONG>.</p>
<p>Every <b>weak_ptr</b> meets the <b>CopyConstructible</b> and <b>Assignable</b> requirements <p>Every <b>weak_ptr</b> meets the <b>CopyConstructible</b> and <b>Assignable</b> requirements
of the C++ Standard Library, and so can be used in standard library containers. of the C++ Standard Library, and so can be used in standard library containers.
Comparison operators are supplied so that <b>weak_ptr</b> works with the Comparison operators are supplied so that <b>weak_ptr</b> works with the
@@ -33,7 +33,8 @@
<P>Compared to <STRONG>shared_ptr</STRONG>, <STRONG>weak_ptr</STRONG> provides a <P>Compared to <STRONG>shared_ptr</STRONG>, <STRONG>weak_ptr</STRONG> provides a
very limited subset of operations since accessing its stored pointer is often very limited subset of operations since accessing its stored pointer is often
dangerous in multithreaded programs, and sometimes unsafe even within a single dangerous in multithreaded programs, and sometimes unsafe even within a single
thread (that is, it may invoke undefined behavior.) Consider, for example, this thread (that is, it may invoke undefined behavior.) Pretend for a moment that <b>weak_ptr</b>
has a <b>get</b> member function that returns a raw pointer, and consider this
innocent piece of code:</P> innocent piece of code:</P>
<pre>shared_ptr&lt;int&gt; p(new int(5)); <pre>shared_ptr&lt;int&gt; p(new int(5));
weak_ptr&lt;int&gt; q(p); weak_ptr&lt;int&gt; q(p);
@@ -55,14 +56,16 @@ weak_ptr&lt;int&gt; q(p);
// some time later // some time later
if(shared_ptr&lt;int&gt; r = <A href="#get_shared_ptr" >get_shared_ptr</A>(q)) if(shared_ptr&lt;int&gt; r = q.<A href="#lock" >lock</A>())
{ {
// use *r // use *r
} }
</pre> </pre>
<p>Now <STRONG>r</STRONG> holds a reference to the object that was pointed by <STRONG>q</STRONG>. <p>Now <STRONG>r</STRONG> holds a reference to the object that was pointed by <STRONG>q</STRONG>.
Even if <code>p.reset()</code> is executed in another thread, the object will Even if <code>p.reset()</code> is executed in another thread, the object will
stay alive until <STRONG>r</STRONG> goes out of scope (or is reset.)</p> stay alive until <STRONG>r</STRONG> goes out of scope or is reset. By obtaining
a <STRONG>shared_ptr</STRONG> to the object, we have effectively locked it
against destruction.</p>
<h2><a name="Synopsis">Synopsis</a></h2> <h2><a name="Synopsis">Synopsis</a></h2>
<pre>namespace boost { <pre>namespace boost {
@@ -83,11 +86,11 @@ if(shared_ptr&lt;int&gt; r = <A href="#get_shared_ptr" >get_shared_ptr</A>(q))
template&lt;class Y&gt; weak_ptr &amp; <A href="#assignment" >operator=</A>(weak_ptr&lt;Y&gt; const &amp; r); template&lt;class Y&gt; weak_ptr &amp; <A href="#assignment" >operator=</A>(weak_ptr&lt;Y&gt; const &amp; r);
template&lt;class Y&gt; weak_ptr &amp; <A href="#assignment" >operator=</A>(shared_ptr&lt;Y&gt; const &amp; r); template&lt;class Y&gt; weak_ptr &amp; <A href="#assignment" >operator=</A>(shared_ptr&lt;Y&gt; const &amp; r);
void <A href="#reset" >reset</A>();
long <A href="#use_count" >use_count</A>() const; long <A href="#use_count" >use_count</A>() const;
bool <A href="#expired" >expired</A>() const; bool <A href="#expired" >expired</A>() const;
shared_ptr&lt;T&gt; <A href="#lock" >lock</A>() const;
void <A href="#reset" >reset</A>();
void <A href="#swap" >swap</A>(weak_ptr&lt;T&gt; &amp; b); void <A href="#swap" >swap</A>(weak_ptr&lt;T&gt; &amp; b);
}; };
@@ -96,10 +99,6 @@ if(shared_ptr&lt;int&gt; r = <A href="#get_shared_ptr" >get_shared_ptr</A>(q))
template&lt;class T&gt; template&lt;class T&gt;
void <A href="#free-swap" >swap</A>(weak_ptr&lt;T&gt; &amp; a, weak_ptr&lt;T&gt; &amp; b); void <A href="#free-swap" >swap</A>(weak_ptr&lt;T&gt; &amp; a, weak_ptr&lt;T&gt; &amp; b);
template&lt;class T&gt;
shared_ptr&lt;T&gt; <A href="#get_shared_ptr" >get_shared_ptr</A>(weak_ptr&lt;T&gt; const &amp; r);
} }
</pre> </pre>
<h2><a name="Members">Members</a></h2> <h2><a name="Members">Members</a></h2>
@@ -143,11 +142,6 @@ template&lt;class Y&gt; weak_ptr &amp; operator=(shared_ptr&lt;Y&gt; const &amp;
<P><B>Notes:</B> The implementation is free to meet the effects (and the implied <P><B>Notes:</B> The implementation is free to meet the effects (and the implied
guarantees) via different means, without creating a temporary.</P> guarantees) via different means, without creating a temporary.</P>
</BLOCKQUOTE> </BLOCKQUOTE>
<h3><a name="reset">reset</a></h3>
<pre>void reset();</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>weak_ptr().swap(*this)</code>.</P>
</BLOCKQUOTE>
<h3><a name="use_count">use_count</a></h3> <h3><a name="use_count">use_count</a></h3>
<pre>long use_count() const;</pre> <pre>long use_count() const;</pre>
<blockquote> <blockquote>
@@ -165,6 +159,17 @@ template&lt;class Y&gt; weak_ptr &amp; operator=(shared_ptr&lt;Y&gt; const &amp;
<p><b>Throws:</b> nothing.</p> <p><b>Throws:</b> nothing.</p>
<P><B>Notes:</B> <code>expired()</code> may be faster than <code>use_count()</code>.</P> <P><B>Notes:</B> <code>expired()</code> may be faster than <code>use_count()</code>.</P>
</blockquote> </blockquote>
<h3><a name="lock">lock</a></h3>
<pre>shared_ptr&lt;T&gt; lock() const;</pre>
<BLOCKQUOTE>
<P><B>Returns:</B> <code>expired()? shared_ptr&lt;T&gt;(): shared_ptr&lt;T&gt;(*this)</code>.</P>
<P><B>Throws:</B> nothing.</P>
</BLOCKQUOTE>
<h3><a name="reset">reset</a></h3>
<pre>void reset();</pre>
<BLOCKQUOTE>
<P><B>Effects:</B> Equivalent to <code>weak_ptr().swap(*this)</code>.</P>
</BLOCKQUOTE>
<h3><a name="swap">swap</a></h3> <h3><a name="swap">swap</a></h3>
<pre>void swap(weak_ptr &amp; b);</pre> <pre>void swap(weak_ptr &amp; b);</pre>
<blockquote> <blockquote>
@@ -198,13 +203,6 @@ template&lt;class Y&gt; weak_ptr &amp; operator=(shared_ptr&lt;Y&gt; const &amp;
<P><B>Notes:</B> Matches the interface of <B>std::swap</B>. Provided as an aid to <P><B>Notes:</B> Matches the interface of <B>std::swap</B>. Provided as an aid to
generic programming.</P> generic programming.</P>
</BLOCKQUOTE> </BLOCKQUOTE>
<h3><a name="get_shared_ptr">get_shared_ptr</a></h3>
<pre>template&lt;class T&gt;
shared_ptr&lt;T&gt; get_shared_ptr(weak_ptr&lt;T&gt; &amp; const r)</pre>
<BLOCKQUOTE>
<P><B>Returns:</B> <code>r.expired()? shared_ptr&lt;T&gt;(): shared_ptr&lt;T&gt;(r)</code>.</P>
<P><B>Throws:</B> nothing.</P>
</BLOCKQUOTE>
<h2><a name="FAQ">Frequently Asked Questions</a></h2> <h2><a name="FAQ">Frequently Asked Questions</a></h2>
<P><B>Q.</B> Can an object create a <STRONG>weak_ptr</STRONG> to itself in its <P><B>Q.</B> Can an object create a <STRONG>weak_ptr</STRONG> to itself in its
constructor?</P> constructor?</P>