summaryrefslogtreecommitdiffstats
path: root/libstdc++-v3
diff options
context:
space:
mode:
authorredi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>2014-01-28 10:23:27 +0000
committerredi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>2014-01-28 10:23:27 +0000
commit1a0a355eb31cedbcac3345e370b5426beff87b4c (patch)
tree2784f59b8c4a0e29330cec40f45e3c91d147a2c8 /libstdc++-v3
parent64eb97fb1c1654613b466628922d61e82a945122 (diff)
downloadppe42-gcc-1a0a355eb31cedbcac3345e370b5426beff87b4c.tar.gz
ppe42-gcc-1a0a355eb31cedbcac3345e370b5426beff87b4c.zip
2014-01-28 Jonathan Wakely <jwakely@redhat.com>
Kyle Lippincott <spectral@google.com> PR libstdc++/59656 * include/bits/shared_ptr.h (shared_ptr): Add new non-throwing constructor and grant friendship to weak_ptr. (weak_ptr::lock()): Use new constructor. * include/bits/shared_ptr_base.h (_Sp_counted_base::_M_add_ref_lock_nothrow()): Declare new function and define specializations. (__shared_count): Add new non-throwing constructor. (__shared_ptr): Add new non-throwing constructor and grant friendship to __weak_ptr. (__weak_ptr::lock()): Use new constructor. * testsuite/20_util/shared_ptr/cons/43820_neg.cc: Adjust dg-error. * testsuite/20_util/shared_ptr/cons/void_neg.cc: Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@207180 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/ChangeLog17
-rw-r--r--libstdc++-v3/include/bits/shared_ptr.h24
-rw-r--r--libstdc++-v3/include/bits/shared_ptr_base.h105
-rw-r--r--libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc2
-rw-r--r--libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc2
5 files changed, 103 insertions, 47 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index da708305497..4674e1f7318 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,20 @@
+2014-01-28 Jonathan Wakely <jwakely@redhat.com>
+ Kyle Lippincott <spectral@google.com>
+
+ PR libstdc++/59656
+ * include/bits/shared_ptr.h (shared_ptr): Add new non-throwing
+ constructor and grant friendship to weak_ptr.
+ (weak_ptr::lock()): Use new constructor.
+ * include/bits/shared_ptr_base.h
+ (_Sp_counted_base::_M_add_ref_lock_nothrow()): Declare new function
+ and define specializations.
+ (__shared_count): Add new non-throwing constructor.
+ (__shared_ptr): Add new non-throwing constructor and grant friendship
+ to __weak_ptr.
+ (__weak_ptr::lock()): Use new constructor.
+ * testsuite/20_util/shared_ptr/cons/43820_neg.cc: Adjust dg-error.
+ * testsuite/20_util/shared_ptr/cons/void_neg.cc: Likewise.
+
2014-01-27 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/59215
diff --git a/libstdc++-v3/include/bits/shared_ptr.h b/libstdc++-v3/include/bits/shared_ptr.h
index 8fcf710b328..081d3bd3748 100644
--- a/libstdc++-v3/include/bits/shared_ptr.h
+++ b/libstdc++-v3/include/bits/shared_ptr.h
@@ -319,6 +319,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Tp1, typename _Alloc, typename... _Args>
friend shared_ptr<_Tp1>
allocate_shared(const _Alloc& __a, _Args&&... __args);
+
+ // This constructor is non-standard, it is used by weak_ptr::lock().
+ shared_ptr(const weak_ptr<_Tp>& __r, std::nothrow_t)
+ : __shared_ptr<_Tp>(__r, std::nothrow) { }
+
+ friend class weak_ptr<_Tp>;
};
// 20.7.2.2.7 shared_ptr comparisons
@@ -492,23 +498,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
shared_ptr<_Tp>
lock() const noexcept
- {
-#ifdef __GTHREADS
- if (this->expired())
- return shared_ptr<_Tp>();
-
- __try
- {
- return shared_ptr<_Tp>(*this);
- }
- __catch(const bad_weak_ptr&)
- {
- return shared_ptr<_Tp>();
- }
-#else
- return this->expired() ? shared_ptr<_Tp>() : shared_ptr<_Tp>(*this);
-#endif
- }
+ { return shared_ptr<_Tp>(*this, std::nothrow); }
};
// 20.7.2.3.6 weak_ptr specialized algorithms.
diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h
index 1c3a47dfb6e..536df017d11 100644
--- a/libstdc++-v3/include/bits/shared_ptr_base.h
+++ b/libstdc++-v3/include/bits/shared_ptr_base.h
@@ -134,7 +134,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void
_M_add_ref_lock();
-
+
+ bool
+ _M_add_ref_lock_nothrow();
+
void
_M_release() noexcept
{
@@ -247,6 +250,51 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
template<>
+ inline bool
+ _Sp_counted_base<_S_single>::
+ _M_add_ref_lock_nothrow()
+ {
+ if (_M_use_count == 0)
+ return false;
+ ++_M_use_count;
+ return true;
+ }
+
+ template<>
+ inline bool
+ _Sp_counted_base<_S_mutex>::
+ _M_add_ref_lock_nothrow()
+ {
+ __gnu_cxx::__scoped_lock sentry(*this);
+ if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
+ {
+ _M_use_count = 0;
+ return false;
+ }
+ return true;
+ }
+
+ template<>
+ inline bool
+ _Sp_counted_base<_S_atomic>::
+ _M_add_ref_lock_nothrow()
+ {
+ // Perform lock-free add-if-not-zero operation.
+ _Atomic_word __count = _M_get_use_count();
+ do
+ {
+ if (__count == 0)
+ return false;
+ // Replace the current counter value with the old value + 1, as
+ // long as it's not changed meanwhile.
+ }
+ while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1,
+ true, __ATOMIC_ACQ_REL,
+ __ATOMIC_RELAXED));
+ return true;
+ }
+
+ template<>
inline void
_Sp_counted_base<_S_single>::_M_add_ref_copy()
{ ++_M_use_count; }
@@ -609,6 +657,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Throw bad_weak_ptr when __r._M_get_use_count() == 0.
explicit __shared_count(const __weak_count<_Lp>& __r);
+ // Does not throw if __r._M_get_use_count() == 0, caller must check.
+ explicit __shared_count(const __weak_count<_Lp>& __r, std::nothrow_t);
+
~__shared_count() noexcept
{
if (_M_pi != nullptr)
@@ -761,15 +812,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Now that __weak_count is defined we can define this constructor:
template<_Lock_policy _Lp>
- inline __shared_count<_Lp>:: __shared_count(const __weak_count<_Lp>& __r)
+ inline
+ __shared_count<_Lp>::__shared_count(const __weak_count<_Lp>& __r)
: _M_pi(__r._M_pi)
{
- if (_M_pi != 0)
+ if (_M_pi != nullptr)
_M_pi->_M_add_ref_lock();
else
__throw_bad_weak_ptr();
}
+ // Now that __weak_count is defined we can define this constructor:
+ template<_Lock_policy _Lp>
+ inline
+ __shared_count<_Lp>::
+ __shared_count(const __weak_count<_Lp>& __r, std::nothrow_t)
+ : _M_pi(__r._M_pi)
+ {
+ if (_M_pi != nullptr)
+ if (!_M_pi->_M_add_ref_lock_nothrow())
+ _M_pi = nullptr;
+ }
// Support for enable_shared_from_this.
@@ -1077,6 +1140,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
friend __shared_ptr<_Tp1, _Lp1>
__allocate_shared(const _Alloc& __a, _Args&&... __args);
+ // This constructor is used by __weak_ptr::lock() and
+ // shared_ptr::shared_ptr(const weak_ptr&, std::nothrow_t).
+ __shared_ptr(const __weak_ptr<_Tp, _Lp>& __r, std::nothrow_t)
+ : _M_refcount(__r._M_refcount, std::nothrow)
+ {
+ _M_ptr = _M_refcount._M_get_use_count() ? __r._M_ptr : nullptr;
+ }
+
+ friend class __weak_ptr<_Tp, _Lp>;
+
private:
void*
_M_get_deleter(const std::type_info& __ti) const noexcept
@@ -1322,31 +1395,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__shared_ptr<_Tp, _Lp>
lock() const noexcept
- {
-#ifdef __GTHREADS
- // Optimization: avoid throw overhead.
- if (expired())
- return __shared_ptr<element_type, _Lp>();
-
- __try
- {
- return __shared_ptr<element_type, _Lp>(*this);
- }
- __catch(const bad_weak_ptr&)
- {
- // Q: How can we get here?
- // A: Another thread may have invalidated r after the
- // use_count test above.
- return __shared_ptr<element_type, _Lp>();
- }
-
-#else
- // Optimization: avoid try/catch overhead when single threaded.
- return expired() ? __shared_ptr<element_type, _Lp>()
- : __shared_ptr<element_type, _Lp>(*this);
-
-#endif
- } // XXX MT
+ { return __shared_ptr<element_type, _Lp>(*this, std::nothrow); }
long
use_count() const noexcept
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc
index 0a986468146..fbd8ccde620 100644
--- a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc
@@ -32,7 +32,7 @@ void test01()
{
X* px = 0;
std::shared_ptr<X> p1(px); // { dg-error "here" }
- // { dg-error "incomplete" "" { target *-*-* } 812 }
+ // { dg-error "incomplete" "" { target *-*-* } 875 }
std::shared_ptr<X> p9(ap()); // { dg-error "here" }
// { dg-error "incomplete" "" { target *-*-* } 307 }
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc
index 492d1db67ea..3f93a5e5249 100644
--- a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc
@@ -25,5 +25,5 @@
void test01()
{
std::shared_ptr<void> p((void*)nullptr); // { dg-error "here" }
- // { dg-error "incomplete" "" { target *-*-* } 811 }
+ // { dg-error "incomplete" "" { target *-*-* } 874 }
}
OpenPOWER on IntegriCloud