public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [patch] Improving shared_ptr for C++0x
@ 2007-11-14  1:25 Jonathan Wakely
  2007-11-14  1:37 ` Benjamin Kosnik
  0 siblings, 1 reply; 4+ messages in thread
From: Jonathan Wakely @ 2007-11-14  1:25 UTC (permalink / raw)
  To: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1413 bytes --]

This patch adds move semantics and the features from N2351.  I believe
this brings GCC's shared_ptr in line with the latest C++ working
paper.

New tests and docs on the implementation choices are included. There
are a few places where further work could be done, see the new HTML
file for details. That doc is also available at
http://www.kayari.org/doc/c++/shared_ptr.html to save you reading the
HTML. I haven't linked to the new doc from any existing pages yet as
the C++0x status is still experimental and I don't know where these
sort of implementation notes will fit in Benjamin's new doc plan.

2007-11-13  Jonathan Wakely  <...>

        * include/tr1_impl/boost_shared_ptr.h: Add support for allocators,
        aliasing, make_shared and rvalue-references.
        * docs/html/20_util/shared_ptr.html: New.
        * testsuite/tr1/2_general_utilities/shared_ptr/cons/alias.cc: New.
        * testsuite/tr1/2_general_utilities/shared_ptr/cons/alloc.cc: New.
        * testsuite/tr1/2_general_utilities/shared_ptr/cons/move.cc: New.
        * testsuite/tr1/2_general_utilities/shared_ptr/assign/move.cc: New.
        * testsuite/tr1/2_general_utilities/shared_ptr/creation/alloc.cc: New.
        * testsuite/tr1/2_general_utilities/shared_ptr/creation/make.cc: New.
        * testsuite/tr1/2_general_utilities/shared_ptr/modifiers/
        reset_alloc.cc: New.

Tested x86_64/linux, OK for mainline?

Jon

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: shared_ptr_cxx0x.diff --]
[-- Type: text/x-patch; name=shared_ptr_cxx0x.diff, Size: 58765 bytes --]

Index: include/tr1_impl/boost_shared_ptr.h
===================================================================
--- include/tr1_impl/boost_shared_ptr.h	(revision 130155)
+++ include/tr1_impl/boost_shared_ptr.h	(working copy)
@@ -51,6 +51,11 @@
  *  You should not attempt to use it directly.
  */
 
+#include <ext/new_allocator.h>
+#ifdef _GLIBCXX_INCLUDE_AS_CXX0X
+# include <bits/stl_move.h>
+#endif
+
 namespace std
 {
 _GLIBCXX_BEGIN_NAMESPACE_TR1
@@ -60,7 +65,11 @@
   public:
     virtual char const*
     what() const throw()
+#ifdef _GLIBCXX_INCLUDE_AS_CXX0X
+    { return "std::bad_weak_ptr"; }
+#else
     { return "tr1::bad_weak_ptr"; }
+#endif
   };
 
   // Substitute for bad_weak_ptr object in the case of -fno-exceptions.
@@ -80,17 +89,6 @@
   using __gnu_cxx::_S_mutex;
   using __gnu_cxx::_S_atomic;
 
-  template<typename _Tp>
-    struct _Sp_deleter
-    {
-      typedef void result_type;
-      typedef _Tp* argument_type;
-
-      void
-      operator()(_Tp* __p) const
-      { delete __p; }
-    };
-
   // Empty helper class except when the template argument is _S_mutex.
   template<_Lock_policy _Lp>
     class _Mutex_base
@@ -130,8 +128,7 @@
       
       // Called when _M_weak_count drops to zero.
       virtual void
-      _M_destroy() // nothrow
-      { delete this; }
+      _M_destroy() = 0; // nothrow
       
       virtual void*
       _M_get_deleter(const std::type_info&) = 0;
@@ -246,34 +243,163 @@
 					   __count + 1));
     }
 
-  template<typename _Ptr, typename _Deleter, _Lock_policy _Lp>
-    class _Sp_counted_base_impl
+  // counted ptr with no deleter or allocator support
+  template<typename _Ptr, _Lock_policy _Lp>
+    class _Sp_counted_ptr
     : public _Sp_counted_base<_Lp>
     {
     public:
       /**
        *  @brief   
+       */
+      _Sp_counted_ptr(_Ptr __p)
+      : _M_ptr(__p) { }
+    
+      virtual void
+      _M_dispose() // nothrow
+      { delete _M_ptr; }
+      
+      virtual void
+      _M_destroy() // nothrow
+      { delete this; }
+      
+      virtual void*
+      _M_get_deleter(const std::type_info& __ti)
+      { return 0; }
+      
+    private:
+      _Sp_counted_ptr(const _Sp_counted_ptr&);
+      _Sp_counted_ptr& operator=(const _Sp_counted_ptr&);
+      
+    protected:
+      _Ptr             _M_ptr;  // copy constructor must not throw
+    };
+
+  // support for custom deleter and/or allocator
+  template<typename _Ptr, typename _Deleter, typename _Alloc, _Lock_policy _Lp>
+    class _Sp_counted_deleter
+    : public _Sp_counted_ptr<_Ptr, _Lp>
+    {
+      typedef typename _Alloc::template
+          rebind<_Sp_counted_deleter>::other _My_alloc_type;
+
+      // Helper class that stores the Deleter and also acts as an allocator.
+      // Used to dispose of the owned pointer and the internal refcount
+      // Requires that copies of _Alloc can free each other's memory.
+      struct _My_Deleter
+      : public _My_alloc_type    // copy constructor must not throw
+      {
+	_Deleter _M_del;         // copy constructor must not throw
+	_My_Deleter(_Deleter __d, const _Alloc& __a)
+	  : _My_alloc_type(__a), _M_del(__d) { }
+      };
+
+    protected:
+      typedef _Sp_counted_ptr<_Ptr, _Lp> _Base_type;
+
+    public:
+      /**
+       *  @brief   
        *  @pre     __d(__p) must not throw.
        */
-      _Sp_counted_base_impl(_Ptr __p, _Deleter __d)
-      : _M_ptr(__p), _M_del(__d) { }
+      _Sp_counted_deleter(_Ptr __p, _Deleter __d)
+      : _Base_type(__p), _M_del(__d, _Alloc()) { }
     
+      /**
+       *  @brief   
+       *  @pre     __d(__p) must not throw.
+       */
+      _Sp_counted_deleter(_Ptr __p, _Deleter __d, const _Alloc& __a)
+      : _Base_type(__p), _M_del(__d, __a) { }
+    
       virtual void
       _M_dispose() // nothrow
-      { _M_del(_M_ptr); }
+      { _M_del._M_del(_Base_type::_M_ptr); }
       
+      virtual void
+      _M_destroy() // nothrow
+      {
+        _My_alloc_type __a(_M_del);
+        this->~_Sp_counted_deleter();
+        __a.deallocate(this, 1);
+      }
+      
       virtual void*
       _M_get_deleter(const std::type_info& __ti)
-      { return __ti == typeid(_Deleter) ? &_M_del : 0; }
+      { return __ti == typeid(_Deleter) ? &_M_del._M_del : 0; }
       
     private:
-      _Sp_counted_base_impl(const _Sp_counted_base_impl&);
-      _Sp_counted_base_impl& operator=(const _Sp_counted_base_impl&);
+      _Sp_counted_deleter(const _Sp_counted_deleter&);
+      _Sp_counted_deleter& operator=(const _Sp_counted_deleter&);
       
-      _Ptr      _M_ptr;  // copy constructor must not throw
-      _Deleter  _M_del;  // copy constructor must not throw
+    protected:
+      _My_Deleter      _M_del;  // copy constructor must not throw
     };
 
+#ifdef _GLIBCXX_INCLUDE_AS_CXX0X
+  // helpers for make_shared / allocate_shared
+
+  template<typename _Tp>
+    struct _Sp_destroy_inplace
+    {
+      void operator()(_Tp* __p) const { if (__p) __p->~_Tp(); }
+    };
+
+  struct _Sp_make_shared_tag { };
+
+  template<typename _Tp, typename _Alloc, _Lock_policy _Lp>
+    class _Sp_counted_ptr_inplace
+    : public _Sp_counted_deleter<_Tp*, _Sp_destroy_inplace<_Tp>, _Alloc, _Lp>
+    {
+      typedef _Sp_counted_deleter<_Tp*, _Sp_destroy_inplace<_Tp>, _Alloc, _Lp>
+        _Base_type;
+
+    public:
+      _Sp_counted_ptr_inplace(_Alloc __a)
+      : _Base_type(static_cast<_Tp*>(0), _Sp_destroy_inplace<_Tp>(), __a)
+      , _M_storage()
+      {
+        void* __p = &_M_storage;
+        new (__p) _Tp();  // might throw
+        _Base_type::_Base_type::_M_ptr = static_cast<_Tp*>(__p);
+      }
+
+      template<typename... _Args>
+        _Sp_counted_ptr_inplace(_Alloc __a, _Args&&... __args)
+        : _Base_type(static_cast<_Tp*>(0), _Sp_destroy_inplace<_Tp>(), __a)
+        , _M_storage()
+        {
+          void* __p = &_M_storage;
+          new (__p) _Tp(std::forward<_Args>(__args)...);  // might throw
+          _Base_type::_Base_type::_M_ptr = static_cast<_Tp*>(__p);
+        }
+
+      // override because the allocator needs to know the dynamic type
+      virtual void
+      _M_destroy() // nothrow
+      {
+        typedef typename _Alloc::template
+            rebind<_Sp_counted_ptr_inplace>::other _My_alloc_type;
+        _My_alloc_type __a(_Base_type::_M_del);
+        this->~_Sp_counted_ptr_inplace();
+        __a.deallocate(this, 1);
+      }
+
+      // sneaky trick so __shared_ptr can get the managed pointer
+      virtual void*
+      _M_get_deleter(const std::type_info& __ti)
+      {
+        return __ti == typeid(_Sp_make_shared_tag)
+               ? static_cast<void*>(&_M_storage)
+               : _Base_type::_M_get_deleter(__ti);
+      }
+      
+    private:
+      typename aligned_storage<sizeof(_Tp), alignment_of<_Tp>::value>::type
+        _M_storage;
+    };
+#endif  // _GLIBCXX_INCLUDE_AS_CXX0X
+
   template<_Lock_policy _Lp = __default_lock_policy>
     class __weak_count;
 
@@ -285,12 +411,29 @@
       : _M_pi(0) // nothrow
       { }
   
+      template<typename _Ptr>
+        __shared_count(_Ptr __p) : _M_pi(0)
+        {
+          try
+            {
+	      _M_pi = new _Sp_counted_ptr<_Ptr, _Lp>(__p);
+	    }
+	  catch(...)
+	    {
+	      delete __p;
+	      __throw_exception_again;
+	    }
+	}
+
       template<typename _Ptr, typename _Deleter>
         __shared_count(_Ptr __p, _Deleter __d) : _M_pi(0)
         {
 	  try
 	    {
-	      _M_pi = new _Sp_counted_base_impl<_Ptr, _Deleter, _Lp>(__p, __d);
+              // allocator's value_type doesn't matter, will rebind it anyway
+              typedef __gnu_cxx::new_allocator<int> _New_allocator;
+	      _M_pi = new _Sp_counted_deleter<_Ptr, _Deleter,
+                                              _New_allocator, _Lp>(__p, __d);
 	    }
 	  catch(...)
 	    {
@@ -299,16 +442,58 @@
 	    }
 	}
 
+      template<typename _Ptr, typename _Deleter, typename _Alloc>
+        __shared_count(_Ptr __p, _Deleter __d, _Alloc __a) : _M_pi(0)
+        {
+	  typedef _Sp_counted_deleter<_Ptr, _Deleter, _Alloc, _Lp> _Sp_cd_type;
+	  typedef typename _Alloc::template rebind<_Sp_cd_type>::other _Alloc2;
+          _Alloc2 __a2(__a);
+	  try
+	    {
+	      _M_pi = __a2.allocate(1);
+	      new(static_cast<void*>(_M_pi)) _Sp_cd_type(__p, __d, __a);
+	    }
+	  catch(...)
+	    {
+	      __d(__p); // Call _Deleter on __p.
+              if (_M_pi)
+                __a2.deallocate(static_cast<_Sp_cd_type*>(_M_pi), 1);
+	      __throw_exception_again;
+	    }
+	}
+
+#ifdef _GLIBCXX_INCLUDE_AS_CXX0X
+      template<typename _Tp, typename _Alloc, typename... _Args>
+        __shared_count(_Sp_make_shared_tag, _Tp*, _Alloc __a, _Args&&... __args)
+        : _M_pi(0)
+        {
+	  typedef _Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp> _Sp_cp_type;
+	  typedef typename _Alloc::template rebind<_Sp_cp_type>::other _Alloc2;
+          _Alloc2 __a2(__a);
+	  try
+	    {
+	      _M_pi = __a2.allocate(1);
+	      new(static_cast<void*>(_M_pi)) _Sp_cp_type(__a,
+                  std::forward<_Args>(__args)...);
+	    }
+	  catch(...)
+	    {
+	      if (_M_pi)
+		__a2.deallocate(static_cast<_Sp_cp_type*>(_M_pi), 1);
+	      __throw_exception_again;
+	    }
+	}
+#endif
+
 #if !defined(__GXX_EXPERIMENTAL_CXX0X__) || _GLIBCXX_DEPRECATED
       // Special case for auto_ptr<_Tp> to provide the strong guarantee.
       template<typename _Tp>
         explicit
         __shared_count(std::auto_ptr<_Tp>& __r)
-	: _M_pi(new _Sp_counted_base_impl<_Tp*,
-		_Sp_deleter<_Tp>, _Lp >(__r.get(), _Sp_deleter<_Tp>()))
+	: _M_pi(new _Sp_counted_ptr<_Tp*, _Lp>(__r.get()))
         { __r.release(); }
 #endif
-
+  
       // Throw bad_weak_ptr when __r._M_get_use_count() == 0.
       explicit
       __shared_count(const __weak_count<_Lp>& __r);
@@ -318,7 +503,7 @@
 	if (_M_pi != 0)
 	  _M_pi->_M_release();
       }
-      
+
       __shared_count(const __shared_count& __r)
       : _M_pi(__r._M_pi) // nothrow
       {
@@ -356,7 +541,7 @@
       bool
       _M_unique() const // nothrow
       { return this->_M_get_use_count() == 1; }
-      
+
       friend inline bool
       operator==(const __shared_count& __a, const __shared_count& __b)
       { return __a._M_pi == __b._M_pi; }
@@ -539,7 +724,7 @@
       template<typename _Tp1>
         explicit
         __shared_ptr(_Tp1* __p)
-	: _M_ptr(__p), _M_refcount(__p, _Sp_deleter<_Tp1>())
+	: _M_ptr(__p), _M_refcount(__p)
         {
 	  __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
 	  // __glibcxx_function_requires(_CompleteConcept<_Tp1*>)
@@ -560,13 +745,58 @@
        */
       template<typename _Tp1, typename _Deleter>
         __shared_ptr(_Tp1* __p, _Deleter __d)
-	: _M_ptr(__p), _M_refcount(__p, __d)
+        : _M_ptr(__p), _M_refcount(__p, __d)
         {
 	  __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
 	  // TODO requires _Deleter CopyConstructible and __d(__p) well-formed
 	  __enable_shared_from_this_helper(_M_refcount, __p, __p);
 	}
       
+#ifdef _GLIBCXX_INCLUDE_AS_CXX0X
+      //
+      // Requirements: _Deleter's copy constructor and destructor must not throw
+      // _Alloc's copy constructor and destructor must not throw.
+      //
+      // __shared_ptr will release __p by calling __d(__p)
+      //
+      /** @brief  Construct a %__shared_ptr that owns the pointer @a __p
+       *          and the deleter @a __d.
+       *  @param  __p  A pointer.
+       *  @param  __d  A deleter.
+       *  @param  __a  An allocator.
+       *  @post   use_count() == 1 && get() == __p
+       *  @throw  std::bad_alloc, in which case @a __d(__p) is called.
+       */
+      template<typename _Tp1, typename _Deleter, typename _Alloc>
+        __shared_ptr(_Tp1* __p, _Deleter __d, const _Alloc& __a)
+	: _M_ptr(__p), _M_refcount(__p, __d, __a)
+        {
+	  __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
+	  // TODO requires _Deleter CopyConstructible and __d(__p) well-formed
+	  __enable_shared_from_this_helper(_M_refcount, __p, __p);
+	}
+
+      /** @brief  Constructs a %__shared_ptr instance that stores @a __p
+       *          and shares ownership with @a __r.
+       *  @param  __r  A %__shared_ptr.
+       *  @param  __p  A pointer that will remain valid while @a *__r is valid.
+       *  @post   get() == __p && use_count() == __r.use_count()
+       *
+       *  This can be used to construct a @c shared_ptr to a sub-object
+       *  of an object managed by an existing @c shared_ptr.
+       *
+       * @code
+       * shared_ptr< pair<int,int> > pii(new pair<int,int>());
+       * shared_ptr<int> pi(pii, &pii->first);
+       * assert(pii.use_count() == 2);
+       * @endcode
+       */
+      template<typename _Tp1>
+        __shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r, _Tp* __p)
+	: _M_ptr(__p), _M_refcount(__r._M_refcount) // never throws
+        { }
+#endif
+
       //  generated copy constructor, assignment, destructor are fine.
       
       /** @brief  If @a __r is empty, constructs an empty %__shared_ptr;
@@ -580,6 +810,32 @@
 	: _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws
         { __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>) }
 
+#ifdef _GLIBCXX_INCLUDE_AS_CXX0X
+      /** @brief  Move-constructs a %__shared_ptr instance from @a __r.
+       *  @param  __r  A %__shared_ptr rvalue.
+       *  @post   *this contains the old value of @a __r, @a __r is empty.
+       */
+      __shared_ptr(__shared_ptr&& __r)
+      : _M_ptr(__r._M_ptr), _M_refcount() // never throws
+      {
+        _M_refcount._M_swap(__r._M_refcount);
+        __r._M_ptr = 0;
+      }
+
+      /** @brief  Move-constructs a %__shared_ptr instance from @a __r.
+       *  @param  __r  A %__shared_ptr rvalue.
+       *  @post   *this contains the old value of @a __r, @a __r is empty.
+       */
+      template<typename _Tp1>
+        __shared_ptr(__shared_ptr<_Tp1, _Lp>&& __r)
+	: _M_ptr(__r._M_ptr), _M_refcount() // never throws
+        {
+          __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
+          _M_refcount._M_swap(__r._M_refcount);
+          __r._M_ptr = 0;
+        }
+#endif
+
       /** @brief  Constructs a %__shared_ptr that shares ownership with @a __r
        *          and stores a copy of the pointer stored in @a __r.
        *  @param  __r  A weak_ptr.
@@ -655,6 +911,23 @@
 	}
 #endif
 
+#ifdef _GLIBCXX_INCLUDE_AS_CXX0X
+      __shared_ptr&
+      operator=(__shared_ptr&& __r)
+      {
+        __shared_ptr(std::move(__r)).swap(*this);
+        return *this;
+      }
+     
+      template<class _Tp1>
+        __shared_ptr&
+        operator=(__shared_ptr<_Tp1, _Lp>&& __r)
+        {
+          __shared_ptr(std::move(__r)).swap(*this);
+          return *this;
+        }
+#endif
+
       void
       reset() // never throws
       { __shared_ptr().swap(*this); }
@@ -673,10 +946,16 @@
         reset(_Tp1* __p, _Deleter __d)
         { __shared_ptr(__p, __d).swap(*this); }
 
+#ifdef _GLIBCXX_INCLUDE_AS_CXX0X
+      template<typename _Tp1, typename _Deleter, typename _Alloc>
+        void
+        reset(_Tp1* __p, _Deleter __d, const _Alloc& __a)
+        { __shared_ptr(__p, __d, __a).swap(*this); }
+
       // Allow class instantiation when _Tp is [cv-qual] void.
-#ifdef _GLIBCXX_INCLUDE_AS_CXX0X
       typename std::add_lvalue_reference<_Tp>::type
 #else
+      // Allow class instantiation when _Tp is [cv-qual] void.
       typename std::tr1::add_reference<_Tp>::type
 #endif
       operator*() const // never throws
@@ -719,6 +998,26 @@
 	_M_refcount._M_swap(__other._M_refcount);
       }
 
+#ifdef _GLIBCXX_INCLUDE_AS_CXX0X
+    protected:
+      // This constructor is non-standard, it is used by allocate_shared.
+      template<typename _Alloc, typename... _Args>
+        __shared_ptr(_Sp_make_shared_tag __tag, _Alloc __a, _Args&&... __args)
+        : _M_ptr()
+        , _M_refcount(__tag, (_Tp*)0, __a, std::forward<_Args>(__args)...)
+        {
+          // _M_ptr needs to point to the newly constructed object.
+          // This relies on _Sp_counted_ptr_inplace::_M_get_deleter.
+          void * __p = _M_refcount._M_get_deleter(typeid(__tag));
+          _M_ptr = static_cast<_Tp*>(__p);
+        }
+
+      template<typename _Tp1, _Lock_policy _Lp1, typename _Alloc,
+               typename... _Args>
+        friend __shared_ptr<_Tp1, _Lp1>
+        __allocate_shared(_Alloc __a, _Args&&... __args);
+#endif
+
     private:
       void*
       _M_get_deleter(const std::type_info& __ti) const
@@ -1011,11 +1310,31 @@
         shared_ptr(_Tp1* __p, _Deleter __d)
 	: __shared_ptr<_Tp>(__p, __d) { }
 
+#ifdef _GLIBCXX_INCLUDE_AS_CXX0X
+      template<typename _Tp1, typename _Deleter, typename _Alloc>
+        shared_ptr(_Tp1* __p, _Deleter __d, const _Alloc& __a)
+	: __shared_ptr<_Tp>(__p, __d, __a) { }
+
+      // Aliasing constructor
       template<typename _Tp1>
+        shared_ptr(const shared_ptr<_Tp1>& __r, _Tp* __p)
+	: __shared_ptr<_Tp>(__r, __p) { }
+#endif
+
+      template<typename _Tp1>
         shared_ptr(const shared_ptr<_Tp1>& __r)
 	: __shared_ptr<_Tp>(__r) { }
 
+#ifdef _GLIBCXX_INCLUDE_AS_CXX0X
+      shared_ptr(shared_ptr&& __r)
+      : __shared_ptr<_Tp>(std::move(__r)) { }
+
       template<typename _Tp1>
+        shared_ptr(shared_ptr<_Tp1>&& __r)
+        : __shared_ptr<_Tp>(std::move(__r)) { }
+#endif
+
+      template<typename _Tp1>
         explicit
         shared_ptr(const weak_ptr<_Tp1>& __r)
 	: __shared_ptr<_Tp>(__r) { }
@@ -1056,6 +1375,36 @@
 	  return *this;
 	}
 #endif
+
+#ifdef _GLIBCXX_INCLUDE_AS_CXX0X
+      shared_ptr&
+      operator=(shared_ptr&& __r)
+      {
+        this->__shared_ptr<_Tp>::operator=(std::move(__r));
+        return *this;
+      }
+     
+      template<class _Tp1>
+        shared_ptr&
+        operator=(shared_ptr<_Tp1>&& __r)
+        {
+          this->__shared_ptr<_Tp>::operator=(std::move(__r));
+          return *this;
+        }
+#endif
+
+#ifdef _GLIBCXX_INCLUDE_AS_CXX0X
+    private:
+      // This constructor is non-standard, it is used by allocate_shared.
+      template<typename _Alloc, typename... _Args>
+        shared_ptr(_Sp_make_shared_tag __tag, _Alloc __a, _Args&&... __args)
+        : __shared_ptr<_Tp>(__tag, __a, std::forward<_Args>(__args)...)
+        { }
+
+      template<typename _Tp1, typename _Alloc, typename... _Args>
+        friend shared_ptr<_Tp1>
+        allocate_shared(_Alloc __a, _Args&&... __args);
+#endif
     };
 
   template<typename _Tp, typename _Tp1>
@@ -1173,5 +1522,57 @@
       mutable weak_ptr<_Tp>  _M_weak_this;
     };
 
+#ifdef _GLIBCXX_INCLUDE_AS_CXX0X
+  template<typename _Tp, _Lock_policy _Lp, typename _Alloc, typename... _Args>
+    inline __shared_ptr<_Tp, _Lp>
+    __allocate_shared(_Alloc __a, _Args&&... __args)
+    {
+      return __shared_ptr<_Tp, _Lp>(_Sp_make_shared_tag(),
+          std::forward<_Alloc>(__a), std::forward<_Args>(__args)...);
+    }
+
+  template<typename _Tp, _Lock_policy _Lp, typename... _Args>
+    inline __shared_ptr<_Tp, _Lp>
+    __make_shared(_Args&&... __args)
+    {
+      typedef typename std::remove_const<_Tp>::type _Tp_nc;
+      return __allocate_shared<_Tp, _Lp>(std::allocator<_Tp_nc>(),
+              std::forward<_Args>(__args)...);
+    }
+
+  /** @brief  Create an object that is owned by a shared_ptr. 
+   *  @param  __a     An allocator.
+   *  @param  __args  Arguments for the @a _Tp object's constructor.
+   *  @return A shared_ptr that owns the newly created object.
+   *  @throw  An exception thrown from @a _Alloc::allocate or from the
+   *          constructor of @A _Tp.
+   *
+   *  A copy of @a __a will be used to allocate memory for the shared_ptr
+   *  and the new object.
+   */
+  template<typename _Tp, typename _Alloc, typename... _Args>
+    inline shared_ptr<_Tp>
+    allocate_shared(_Alloc __a, _Args&&... __args)
+    {
+      return shared_ptr<_Tp>(_Sp_make_shared_tag(), std::forward<_Alloc>(__a),
+              std::forward<_Args>(__args)...);
+    }
+
+  /** @brief  Create an object that is owned by a shared_ptr. 
+   *  @param  __args  Arguments for the @a _Tp object's constructor.
+   *  @return A shared_ptr that owns the newly created object.
+   *  @throw  std::bad_alloc, or an exception thrown from the
+   *          constructor of @A _Tp.
+   */
+  template<typename _Tp, typename... _Args>
+    inline shared_ptr<_Tp>
+    make_shared(_Args&&... __args)
+    {
+      typedef typename std::remove_const<_Tp>::type _Tp_nc;
+      return allocate_shared<_Tp>(std::allocator<_Tp_nc>(),
+              std::forward<_Args>(__args)...);
+    }
+#endif
+
 _GLIBCXX_END_NAMESPACE_TR1
 }
Index: docs/html/20_util/shared_ptr.html
===================================================================
--- docs/html/20_util/shared_ptr.html	(revision 0)
+++ docs/html/20_util/shared_ptr.html	(revision 0)
@@ -0,0 +1,384 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE html
+          PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+   <meta name="KEYWORDS" content="HOWTO, libstdc++, GCC, g++, STL" />
+   <meta name="DESCRIPTION" content="Notes on the shared_ptr implementation." />
+   <title>Notes on the shared_ptr implementation.</title>
+<link rel="StyleSheet" href="../lib3styles.css" type="text/css" />
+<link rel="Start" href="../documentation.html" type="text/html"
+  title="GNU C++ Standard Library" />
+<link rel="Bookmark" href="howto.html" type="text/html" title="General Utilities" />
+<link rel="Copyright" href="../17_intro/license.html" type="text/html" />
+<link rel="Help" href="../faq/index.html" type="text/html" title="F.A.Q." />
+</head>
+<body>
+<h1>
+Notes on the <code>shared_ptr</code> implementation.
+</h1>
+<em>
+prepared by Jonathan Wakely on November 11, 2007
+</em>
+
+<h2>
+1. Abstract
+</h2>
+<p>
+The shared_ptr class template stores a pointer, usually obtained via new,
+and implements shared ownership semantics.
+</p>
+
+<h2>
+2. What the standard says
+</h2>
+
+<blockquote>
+20.6.6.2 - Class template shared_ptr [util.smartptr.shared]
+</blockquote>
+
+<p>
+The standard deliberately doesn't require a reference-counted implementation,
+allowing other techniques such as a circular-linked-list.
+</p>
+
+<p>
+At the time of writing the C++0x working paper doesn't mention how threads
+affect shared_ptr, but it is likely to follow the existing practice set by
+<code>boost::shared_ptr</code>.  The shared_ptr in libstdc++ is derived
+from Boost's, so the same rules apply.
+</p>
+
+<h2>
+3. Problems with shared_ptr: TR1 vs C++0x, thread safety.
+</h2>
+
+<p>
+The interface of <code>tr1::shared_ptr</code> was extended for C++0x with
+support for rvalue-references and the additional features from N2351. As
+with other libstdc++ headers shared by TR1 and C++0x, boost_shared_ptr.h
+uses conditional compilation, based on the macros _GLIBCXX_INCLUDE_AS_CXX0X
+and _GLIBCXX_INCLUDE_AS_TR1, to enable and disable features.
+</p>
+
+<p>
+C++0x-only features are: rvalue-ref/move support, allocator support,
+aliasing constructor, make_shared &amp; allocate_shared. Additionally, the
+constructors taking auto_ptr parameters are deprecated in C++0x mode.
+</p>
+
+<p>
+The 
+<a href="http://boost.org/libs/smart_ptr/shared_ptr.htm#ThreadSafety">Thread
+Safety</a> section of the Boost shared_ptr documentation says "shared_ptr
+objects offer the same level of thread safety as built-in types."
+The implementation must ensure that concurrent updates to separate shared_ptr
+instances are correct even when those instances share a reference count e.g.
+</p>
+<pre>
+shared_ptr&lt;A&gt; a(new A);
+shared_ptr&lt;A&gt; b(a);
+
+// Thread 1     // Thread 2
+   a.reset();      b.reset();
+</pre>
+<p>
+The dynamically-allocated object must be destroyed by exactly one of the
+threads. Weak references make things even more interesting.
+The shared state used to implement shared_ptr must be transparent to the
+user and invariants must be preserved at all times.
+The key pieces of shared state are the strong and weak reference counts.
+Updates to these need to be atomic and visible to all threads to ensure
+correct cleanup of the managed resource (which is, after all, shared_ptr's
+job!)
+On multi-processor systems memory synchronisation may be needed so that
+reference-count updates and the destruction of the managed resource are
+race-free.
+</p>
+
+<p>
+The function <code>_Sp_counted_base::_M_add_ref_lock()</code>, called when
+obtaining a shared_ptr from a weak_ptr, has to test if the managed
+resource still exists and either increment the reference count or throw
+<code>std::bad_weak_ptr</code>.
+In a multi-threaded program there is a potential race condition if the last
+reference is dropped (and the managed resource destroyed) between testing
+the reference count and incrementing it, which could result in a shared_ptr
+pointing to invalid memory.
+</p>
+<p>
+The Boost shared_ptr (as used in GCC) features a clever lock-free algorithm
+to avoid the race condition, but this relies on the processor supporting
+an atomic <em>Compare-And-Swap</em> instruction. For other platforms there
+are fall-backs using mutex locks.  Boost (as of version 1.35) includes
+several different implementations and the preprocessor selects one based
+on the compiler, standard library, platform etc. For the version of
+shared_ptr in libstdc++ the compiler and library are fixed, which makes
+things much simpler: we have an atomic CAS or we don't, see Lock Policy
+below for details.
+</p>
+
+<h2>
+4. Design and Implementation Details
+</h2>
+
+<p>
+The shared_ptr code in libstdc++ was kindly donated to GCC by the Boost
+project and the original authors of the code. The basic design and
+algorithms are from Boost, the notes below describe details specific to
+the GCC implementation. Names have been uglified in this implementation,
+but the design should be recognisable to anyone familiar with the Boost
+1.32 shared_ptr.
+</p>
+
+<p>
+Basic design is an abstract base class, <code>_Sp_counted_base</code> that
+does the reference-counting and calls virtual functions when the count
+drops to zero.
+Derived classes override those functions to destroy resources in a context
+where the correct dynamic type is known. This is an application of the
+technique known as type erasure.
+</p>
+
+<h3>
+Lock Policy
+</h3>
+
+<p>
+Libstdc++ has a single _Sp_counted_base class, which is a template
+parameterized on the enum <code>__gnu_cxx::_Lock_policy</code>.
+The entire family of classes is parameterized on the lock policy, right up
+to <code>__shared_ptr</code>, <code>__weak_ptr</code> and
+<code>__enable_shared_from_this</code>. The actual
+<code>std::shared_ptr</code> class inherits from <code>__shared_ptr</code>
+with the lock policy parameter selected automatically based on the thread
+model and platform that libstdc++ is configured for, so that the best
+available template specialization will be used. This design is necessary
+because it would not be conforming for <code>std::shared_ptr</code> to have
+an extra template parameter, even if it had a default value.
+The available policies are:
+</p>
+
+<dl>
+<dt><code>_S_Atomic</code></dt>
+<dd>
+Selected when GCC supports a builtin atomic compare-and-swap
+operation on the target processor (see
+<a href="http://gcc.gnu.org/onlinedocs/gcc/Atomic-Builtins.html">Atomic
+Builtins</a>.)
+The reference counts are maintained using a lock-free algorithm and GCC's
+atomic builtins, which provide the required memory synchronisation.
+</dd>
+<dt><code>_S_Mutex</code></dt>
+<dd>
+The _Sp_counted_base specialization for this policy contains a mutex,
+which is locked in add_ref_lock(). This policy is used when GCC's atomic
+builtins aren't available so explicit memory barriers are needed in places.
+</dd>
+<dt><code>_S_Single</code></dt>
+<dd>
+This policy uses a non-reentrant add_ref_lock() with no locking. It is
+used when libstdc++ is built without <em>--enable-threads</em>.
+</dd>
+</dl>
+
+<p>
+For all three policies, reference count increments and decrements are done
+via the functions in <tt>&lt;ext/atomicity.h&gt;</tt>, which detect if the
+program is multi-threaded.
+If only one thread of execution exists in the program then less expensive
+non-atomic operations are used.
+</p>
+
+<h3>
+Class Hierarchy
+</h3>
+
+<p>
+A <code>shared_ptr&lt;T&gt;</code> contains a pointer of type <code>T*</code>
+and an object of type <code>__shared_count</code>. The shared_count contains
+a pointer of type <code>_Sp_counted_base*</code> which points to the object
+that maintains the reference-counts and destroys the managed resource.
+</p>
+
+<dl>
+<dt><code>_Sp_counted_base&lt;Lp&gt;</code></dt>
+<dd>
+The base of the hierarchy is parameterized on the lock policy alone.
+_Sp_counted_base doesn't depend on the type of pointer being managed,
+it only maintains the reference counts and calls virtual functions when
+the counts drop to zero. The managed object is destroyed when the last
+strong reference is dropped, but the _Sp_counted_base itself must exist
+until the last weak reference is dropped.
+</dd>
+<dt><code>_Sp_counted_ptr&lt;Ptr, Lp&gt;</code></dt>
+<dd>
+Inherits from _Sp_counted_base and stores a pointer of type <code>Ptr</code>,
+which is passed to <code>delete</code> when the last reference is dropped.
+This is the simplest form and is used when there is no custom deleter or
+allocator.
+</dd>
+<dt><code>_Sp_counted_deleter&lt;Ptr, Deleter, Alloc&gt;</code></dt>
+<dd>
+Inherits from _Sp_counted_ptr and adds support for custom deleter and
+allocator. Empty Base Optimization is used for the allocator. This class
+is used even when the user only provides a custom deleter, in which case
+<code>__gnu_cxx::new_allocator</code> is used as the allocator.
+</dd>
+<dt><code>_Sp_counted_ptr_inplace&lt;Tp, Alloc, Lp&gt;</code></dt>
+<dd>
+Used by <code>allocate_shared</code> and <code>make_shared</code>.
+Contains aligned storage to hold an object of type <code>Tp</code>,
+which is constructed in-place with placement <code>new</code>.
+Has a variadic template constructor allowing any number of arguments to
+be forwarded to <code>Tp</code>'s constructor.
+Unlike the other _Sp_counted_* classes, this one is parameterized on the
+type of object, not the type of pointer; this is purely a convenience
+that simplifies the implementation slightly.
+</dd>
+</dl>
+
+<h3>
+Related functions and classes
+</h3>
+
+<dl>
+<dt><code>dynamic_pointer_cast</code>, <code>static_pointer_cast</code>,
+<code>const_pointer_cast</code></dt>
+<dd>
+As noted in N2351, these functions can be implemented non-intrusively using
+the alias constructor.  This would allow the removal of three non-standard
+constructors from shared_ptr and __shared_ptr, however the aliasing
+constructor is only available in C++0x mode, so these casts rely on access
+to the implementation in order to work in TR1 mode.
+</dd>
+<dt><code>enable_shared_from_this</code></dt>
+<dd>
+The clever overload to detect a base class of type
+<code>enable_shared_from_this</code> comes straight from Boost.
+There is an extra overload for <code>__enable_shared_from_this</code> to 
+work smoothly with <code>__shared_ptr&lt;Tp, Lp&gt;</code> using any lock
+policy.
+</dd>
+<dt><code>make_shared</code>, <code>allocate_shared</code></dt>
+<dd>
+<code>make_shared</code> simply forwards to <code>allocate_shared</code>
+with <code>__gnu_cxx::new_allocator</code> as the allocator.
+Although these functions can be implemented non-intrusively using the
+alias constructor, if they have access to the implementation then it is
+possible to save storage and reduce the number of heap allocations. The
+newly constructed object and the _Sp_counted_* can be allocated in a single
+block and the standard says implementations are "encouraged, but not required,"
+to do so. This implementation provides additional non-standard constructors
+(selected with the type <code>_Sp_make_shared_tag</code>) which create an
+object of type <code>_Sp_counted_ptr_inplace</code> to hold the new object.
+The returned <code>shared_ptr&lt;A&gt;</code> needs to know the address of the
+new <code>A</code> object embedded in the <code>_Sp_counted_ptr_inplace</code>,
+but it has no way to access it.
+This implementation uses a "covert channel" to return the address of the
+embedded object when <code>get_deleter&lt;_Sp_make_shared_tag&gt;()</code>
+is called.  Users should not try to use this.
+As well as the extra constructors, this implementation also needs some
+members of _Sp_counted_deleter to be protected where they could otherwise
+be private.
+</dd>
+</dl>
+
+<h2>
+5. Examples
+</h2>
+
+<p>
+Examples of use can be found in the testsuite, under
+<tt>testsuite/tr1/2_general_utilities/shared_ptr</tt>.
+</p>
+
+<h2>
+6. Unresolved Issues
+</h2>
+
+<p>
+The resolution to C++ Standard Library issue <a
+href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#674">674</a>,
+"shared_ptr interface changes for consistency with N1856" will need to be
+implemented after it is accepted into the working paper. Issue <a 
+href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#743">743</a>
+might also require changes.
+</p>
+
+<p>
+The _S_single policy uses atomics when used in MT code, because it uses
+the same dispatcher functions that check __gthread_active_p(). This could be
+addressed by providing template specialisations for some members of
+_Sp_counted_base&lt;_S_single&gt;.
+</p>
+
+<p>
+Unlike Boost, this implementation does not use separate classes for the
+pointer+deleter and pointer+deleter+allocator cases, combining both into
+_Sp_counted_deleter and using new_allocator when the user doesn't specify
+an allocator (which is always the case in TR1 mode.)
+If it was found to be beneficial an additional class could easily be added.
+With the current implementation, the _Sp_counted_deleter and __shared_count
+constructors taking a custom deleter but no allocator are technically
+redundant and could be removed, changing callers to always specify an
+allocator. If a separate pointer+deleter class was added the __shared_count
+constructor would be needed, so it has been kept for now.
+</p>
+
+<p>
+Exposing the alias constructor in TR1 mode could simplify the *_pointer_cast
+functions.
+Constructor could be private in TR1 mode, with the cast functions as friends.
+</p>
+
+<p>
+The hack used to get the address of the managed object from
+_Sp_counted_ptr_inplace::_M_get_deleter() is accessible to users. This
+could be prevented if get_deleter&lt;_Sp_make_shared_tag&gt; always
+returned NULL, since the hack only needs to work at a lower level, not
+in the public API. This wouldn't be difficult, but hasn't been done since
+there is no danger of accidental misuse: users already know they are
+relying on unsupported features if they refer to implementation details
+such as _Sp_make_shared_tag.
+</p>
+
+<h2>
+7. Acknowledgments
+</h2>
+<p>
+The original authors of the Boost shared_ptr, which is really nice code
+to work with, Peter Dimov in particular for his help and invaluable advice
+on thread safety.
+Phillip Jordan and Paolo Carlini for the lock policy implementation.
+</p>
+
+
+<h2>
+8. Bibliography / Referenced Documents
+</h2>
+
+<p>
+N2351 Improving shared_ptr for C++0x, Revision 2
+<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2351.htm">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2351.htm</a>
+</p>
+
+<p>
+N2456 C++ Standard Library Active Issues List (Revision R52)
+<a href="http://open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2456.html">http://open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2456.html</a></p>
+<p>
+N2461 Working Draft, Standard for Programming Language C++
+<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2461.pdf">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2461.pdf</a>
+</p>
+
+<p>
+Boost C++ Libraries documentation - shared_ptr class template
+<a href="http://boost.org/libs/smart_ptr/shared_ptr.htm">http://boost.org/libs/smart_ptr/shared_ptr.htm</a>
+</p>
+
+</body>
+</html>
+
Index: testsuite/tr1/2_general_utilities/shared_ptr/modifiers/reset_alloc.cc
===================================================================
--- testsuite/tr1/2_general_utilities/shared_ptr/modifiers/reset_alloc.cc	(revision 0)
+++ testsuite/tr1/2_general_utilities/shared_ptr/modifiers/reset_alloc.cc	(revision 0)
@@ -0,0 +1,64 @@
+// { dg-options "-std=gnu++0x" }
+
+// Copyright (C) 2007 Free Software Foundation
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// 20.6.6.2 Template class shared_ptr [util.smartptr.shared]
+
+#include <tr1/memory>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+using __gnu_test::tracker_allocator_counter;
+using __gnu_test::tracker_allocator;
+
+struct A { };
+struct B : A { };
+struct D
+{
+  void operator()(B* p) { delete p; ++delete_count; }
+  static long delete_count;
+};
+long D::delete_count = 0;
+
+// 20.6.6.2.4 shared_ptr modifiers [util.smartptr.shared.mod]
+
+// Reset with allocator
+int
+test01()
+{
+  bool test __attribute__((unused)) = true;
+  tracker_allocator_counter::reset();
+
+  {
+    std::shared_ptr<A> p1;
+    p1.reset(new B, D(), tracker_allocator<B>());
+    VERIFY( tracker_allocator_counter::get_allocation_count() > 0 );
+  }
+  VERIFY( D::delete_count == 1 );
+  VERIFY( tracker_allocator_counter::get_allocation_count() == tracker_allocator_counter::get_deallocation_count() );
+
+  return 0;
+}   
+
+int
+main()
+{
+  test01();
+  return 0;
+}
Index: testsuite/tr1/2_general_utilities/shared_ptr/cons/alias.cc
===================================================================
--- testsuite/tr1/2_general_utilities/shared_ptr/cons/alias.cc	(revision 0)
+++ testsuite/tr1/2_general_utilities/shared_ptr/cons/alias.cc	(revision 0)
@@ -0,0 +1,108 @@
+// { dg-options "-std=gnu++0x" }
+
+// Copyright (C) 2007 Free Software Foundation
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// 20.6.6.2 Template class shared_ptr [util.smartptr.shared]
+
+#include <memory>
+#include <testsuite_hooks.h>
+
+struct A
+{
+  A() : i() { }
+  virtual ~A() { }
+  int i;
+};
+
+struct B : A
+{
+  B() : A(), a() { }
+  virtual ~B() { }
+  A a;
+};
+
+void deletefunc(A* p) { delete p; }
+
+// 20.6.6.2.1 shared_ptr constructors [util.smartptr.shared.const]
+
+// Aliasing constructors
+
+int test01()
+{
+  bool test __attribute__((unused)) = true;
+
+  std::shared_ptr<A> a;
+  std::shared_ptr<bool> b1(a, &test);
+  VERIFY( b1.use_count() == 0 );
+  VERIFY( a.get() == 0 );
+  VERIFY( b1.get() == &test );
+
+  std::shared_ptr<bool> b2(b1);
+  VERIFY( b2.use_count() == 0 );
+  VERIFY( b1.get() == b2.get() );
+
+  return 0;
+}
+
+int
+test02()
+{
+  bool test __attribute__((unused)) = true;
+
+  std::shared_ptr<A> a(new A);
+  std::shared_ptr<int> i1(a, &a->i);
+  VERIFY( i1.use_count() == 2 );
+
+  std::shared_ptr<int> i2(i1);
+  VERIFY( i2.use_count() == 3 );
+  VERIFY( i2.get() == &a->i );
+
+  return 0;
+}
+
+int
+test03()
+{
+  bool test __attribute__((unused)) = true;
+
+  std::shared_ptr<B> b(new B);
+  std::shared_ptr<A> a1(b, b.get());
+  std::shared_ptr<A> a2(b, &b->a);
+  VERIFY( a2.use_count() == 3 );
+  VERIFY( a1 == b );
+  VERIFY( a2 != b );
+  VERIFY( a1.get() != a2.get() );
+
+  std::shared_ptr<A> a3(a1);
+  VERIFY( a3 == b );
+
+  a3 = a2;
+  VERIFY( a3.get() == &b->a );
+
+  return 0;
+}
+
+int
+main()
+{
+  test01();
+  test02();
+  test03();
+  return 0;
+}
Index: testsuite/tr1/2_general_utilities/shared_ptr/cons/alloc.cc
===================================================================
--- testsuite/tr1/2_general_utilities/shared_ptr/cons/alloc.cc	(revision 0)
+++ testsuite/tr1/2_general_utilities/shared_ptr/cons/alloc.cc	(revision 0)
@@ -0,0 +1,104 @@
+// { dg-options "-std=gnu++0x" }
+
+// Copyright (C) 2007 Free Software Foundation
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// 20.6.6.2 Template class shared_ptr [util.smartptr.shared]
+
+#include <memory>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+using __gnu_test::tracker_allocator_counter;
+using __gnu_test::tracker_allocator;
+
+struct A { };
+void deletefunc(A* p) { delete p; }
+struct D
+{
+  void operator()(A* p) { delete p; ++delete_count; }
+  static long delete_count;
+};
+long D::delete_count = 0;
+
+// 20.6.6.2.1 shared_ptr constructors [util.smartptr.shared.const]
+
+// Construction with allocator
+int
+test01()
+{
+  bool test __attribute__((unused)) = true;
+  tracker_allocator_counter::reset();
+
+  std::shared_ptr<A> p1(new A, deletefunc, tracker_allocator<A>());
+  std::size_t const sz = tracker_allocator_counter::get_allocation_count();
+  VERIFY( sz > 0 );
+  {
+    std::shared_ptr<A> p2(p1);
+    VERIFY( p2.use_count() == 2 );
+    VERIFY( tracker_allocator_counter::get_allocation_count() == sz );
+    VERIFY( tracker_allocator_counter::get_deallocation_count() == 0 );
+  }
+  VERIFY( p1.use_count() == 1 );
+  VERIFY( tracker_allocator_counter::get_allocation_count() == sz );
+  VERIFY( tracker_allocator_counter::get_deallocation_count() == 0 );
+  p1.reset();
+  VERIFY( p1.use_count() == 0 );
+  VERIFY( tracker_allocator_counter::get_allocation_count() == sz );
+  VERIFY( tracker_allocator_counter::get_deallocation_count() == sz );
+
+  return 0;
+}
+
+// Construction with allocator
+int
+test02()
+{
+  bool test __attribute__((unused)) = true;
+  tracker_allocator_counter::reset();
+
+  std::shared_ptr<A> p1(new A, deletefunc, tracker_allocator<A>());
+  std::size_t const sz1 = tracker_allocator_counter::get_allocation_count();
+  VERIFY( sz1 > 0 );
+  std::shared_ptr<A> p2(new A, D(), tracker_allocator<A>());
+  std::size_t const sz2 = tracker_allocator_counter::get_allocation_count();
+  VERIFY( sz2 > sz1 );
+  VERIFY( tracker_allocator_counter::get_deallocation_count() == 0 );
+  p1 = p2;
+  VERIFY( p2.use_count() == 2 );
+  VERIFY( tracker_allocator_counter::get_allocation_count() == sz2 );
+  VERIFY( tracker_allocator_counter::get_deallocation_count() == sz1 );
+  p1.reset();
+  VERIFY( p2.use_count() == 1 );
+  VERIFY( tracker_allocator_counter::get_allocation_count() == sz2 );
+  VERIFY( tracker_allocator_counter::get_deallocation_count() == sz1 );
+  p2.reset();
+  VERIFY( tracker_allocator_counter::get_allocation_count() == sz2 );
+  VERIFY( tracker_allocator_counter::get_deallocation_count() == sz2 );
+  VERIFY( D::delete_count == 1 );
+
+  return 0;
+}
+
+int
+main()
+{
+  test01();
+  test02();
+  return 0;
+}
Index: testsuite/tr1/2_general_utilities/shared_ptr/creation/make.cc
===================================================================
--- testsuite/tr1/2_general_utilities/shared_ptr/creation/make.cc	(revision 0)
+++ testsuite/tr1/2_general_utilities/shared_ptr/creation/make.cc	(revision 0)
@@ -0,0 +1,100 @@
+// { dg-options "-std=gnu++0x" }
+
+// Copyright (C) 2007 Free Software Foundation
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// 20.6.6.2 Template class shared_ptr [util.smartptr.shared]
+
+#include <memory>
+#include <testsuite_hooks.h>
+
+struct A
+{
+  A(int i, double d, char c = '\0') : i(i), d(d), c(c) { ++ctor_count; }
+  explicit A(int i) : i(i), d(), c() { ++ctor_count; }
+  A() : i(), d(), c() { ++ctor_count; }
+  ~A() { ++dtor_count; }
+  int i;
+  double d;
+  char c;
+  static int ctor_count;
+  static int dtor_count;
+};
+int A::ctor_count = 0;
+int A::dtor_count = 0;
+
+struct reset_count_struct
+{
+  ~reset_count_struct()
+  {
+    A::ctor_count = 0;
+    A::dtor_count = 0;
+  }
+};
+
+// 20.6.6.2.6 shared_ptr creation [util.smartptr.shared.create]
+
+int
+test01()
+{
+  bool test __attribute__((unused)) = true;
+  reset_count_struct __attribute__((unused)) reset;
+
+  {
+    std::shared_ptr<A> p1 = std::make_shared<A>();
+    VERIFY( p1.get() != 0 );
+    VERIFY( p1.use_count() == 1 );
+    VERIFY( A::ctor_count == 1 );
+  }
+  VERIFY( A::ctor_count == A::dtor_count );
+}
+
+int
+test02()
+{
+  bool test __attribute__((unused)) = true;
+  reset_count_struct __attribute__((unused)) reset;
+
+  std::shared_ptr<A> p1;
+  
+  p1 = std::make_shared<A>(1);
+  VERIFY( A::ctor_count == 1 );
+
+  p1 = std::make_shared<A>(1, 2.0);
+  VERIFY( A::ctor_count == 2 );
+  VERIFY( A::dtor_count == 1 );
+
+  p1 = std::make_shared<A>(1, 2.0, '3');
+  VERIFY( A::ctor_count == 3 );
+  VERIFY( A::dtor_count == 2 );
+  VERIFY( p1->i == 1 );
+  VERIFY( p1->d == 2.0 );
+  VERIFY( p1->c == '3' );
+
+  p1 = std::shared_ptr<A>();
+  VERIFY( A::ctor_count == A::dtor_count );
+
+  return 0;
+}
+
+int
+main()
+{
+  test01();
+  test02();
+}
Index: testsuite/tr1/2_general_utilities/shared_ptr/creation/alloc.cc
===================================================================
--- testsuite/tr1/2_general_utilities/shared_ptr/creation/alloc.cc	(revision 0)
+++ testsuite/tr1/2_general_utilities/shared_ptr/creation/alloc.cc	(revision 0)
@@ -0,0 +1,110 @@
+// { dg-options "-std=gnu++0x" }
+
+// Copyright (C) 2007 Free Software Foundation
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// 20.6.6.2 Template class shared_ptr [util.smartptr.shared]
+
+#include <memory>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+using __gnu_test::tracker_allocator_counter;
+using __gnu_test::tracker_allocator;
+
+struct A
+{
+  A(int i, double d, char c = '\0') : i(i), d(d), c(c) { ++ctor_count; }
+  explicit A(int i) : i(i), d(), c() { ++ctor_count; }
+  A() : i(), d(), c() { ++ctor_count; }
+  ~A() { ++dtor_count; }
+  int i;
+  double d;
+  char c;
+  static int ctor_count;
+  static int dtor_count;
+};
+int A::ctor_count = 0;
+int A::dtor_count = 0;
+
+struct reset_count_struct
+{
+  ~reset_count_struct()
+  {
+    A::ctor_count = 0;
+    A::dtor_count = 0;
+    tracker_allocator_counter::reset();
+  }
+};
+
+// 20.6.6.2.6 shared_ptr creation [util.smartptr.shared.create]
+
+int
+test01()
+{
+  bool test __attribute__((unused)) = true;
+  reset_count_struct __attribute__((unused)) reset;
+
+  {
+    std::shared_ptr<A> p1 = std::allocate_shared<A>(tracker_allocator<A>());
+    VERIFY( p1.get() != 0 );
+    VERIFY( p1.use_count() == 1 );
+    VERIFY( A::ctor_count == 1 );
+    VERIFY( tracker_allocator_counter::get_allocation_count() > 0 );
+  }
+  VERIFY( A::ctor_count == A::dtor_count );
+  VERIFY( tracker_allocator_counter::get_allocation_count() == tracker_allocator_counter::get_deallocation_count() );
+}
+
+int
+test02()
+{
+  bool test __attribute__((unused)) = true;
+  reset_count_struct __attribute__((unused)) reset;
+
+  std::shared_ptr<A> p1;
+  
+  p1 = std::allocate_shared<A>(tracker_allocator<A>(), 1);
+  VERIFY( A::ctor_count == 1 );
+  VERIFY( tracker_allocator_counter::get_allocation_count() > 0 );
+
+  p1 = std::allocate_shared<A>(tracker_allocator<A>(), 1, 2.0);
+  VERIFY( A::ctor_count == 2 );
+  VERIFY( A::dtor_count == 1 );
+  VERIFY( tracker_allocator_counter::get_deallocation_count() > 0 );
+
+  p1 = std::allocate_shared<A>(tracker_allocator<A>(), 1, 2.0, '3');
+  VERIFY( A::ctor_count == 3 );
+  VERIFY( A::dtor_count == 2 );
+  VERIFY( p1->i == 1 );
+  VERIFY( p1->d == 2.0 );
+  VERIFY( p1->c == '3' );
+
+  p1 = std::shared_ptr<A>();
+  VERIFY( A::ctor_count == A::dtor_count );
+  VERIFY( tracker_allocator_counter::get_allocation_count() == tracker_allocator_counter::get_deallocation_count() );
+
+  return 0;
+}
+
+int
+main()
+{
+  test01();
+  test02();
+}
Index: testsuite/tr1/2_general_utilities/shared_ptr/assign/move.cc
===================================================================
--- testsuite/tr1/2_general_utilities/shared_ptr/assign/move.cc	(revision 0)
+++ testsuite/tr1/2_general_utilities/shared_ptr/assign/move.cc	(revision 0)
@@ -0,0 +1,119 @@
+// { dg-options "-std=gnu++0x" }
+
+// Copyright (C) 2007 Free Software Foundation
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// TR1 20.6.6.2 Template class shared_ptr [util.smartptr.shared]
+
+#include <memory>
+#include <utility>
+#include <testsuite_hooks.h>
+
+struct A
+{
+  A() { ++ctor_count; }
+  virtual ~A() { ++dtor_count; }
+  static long ctor_count;
+  static long dtor_count;
+};
+long A::ctor_count = 0;
+long A::dtor_count = 0;
+
+struct B : A
+{
+  B() { ++ctor_count; }
+  virtual ~B() { ++dtor_count; }
+  static long ctor_count;
+  static long dtor_count;
+};
+long B::ctor_count = 0;
+long B::dtor_count = 0;
+
+struct reset_count_struct
+{
+  ~reset_count_struct()
+  {
+    A::ctor_count = 0;
+    A::dtor_count = 0;
+    B::ctor_count = 0;
+    B::dtor_count = 0;
+  }
+};
+
+
+// 20.6.6.2.1 shared_ptr constructors [util.smartptr.shared.const]
+
+// Rvalue assignment from shared_ptr
+void
+test01()
+{
+  reset_count_struct __attribute__((unused)) reset;
+  bool test __attribute__((unused)) = true;
+
+  std::shared_ptr<A> a1;
+  std::shared_ptr<A> a2(new A);
+
+  a1 = std::move(a2);
+  VERIFY( a1.get() != 0 );
+  VERIFY( a2.get() == 0 );
+  VERIFY( a1.use_count() == 1 );
+  VERIFY( a2.use_count() == 0 );
+  VERIFY( A::ctor_count == 1 );
+  VERIFY( A::dtor_count == 0 );
+
+  a1 = std::move(std::shared_ptr<A>());
+  VERIFY( a1.get() == 0 );
+  VERIFY( A::ctor_count == 1 );
+  VERIFY( A::dtor_count == 1 );
+}
+
+// Rvalue assignment from shared_ptr<Y>
+void
+test02()
+{
+  reset_count_struct __attribute__((unused)) reset;
+  bool test __attribute__((unused)) = true;
+
+  std::shared_ptr<A> a;
+  std::shared_ptr<B> b(new B);
+
+  a = std::move(b);
+  VERIFY( a.get() != 0 );
+  VERIFY( b.get() == 0 );
+  VERIFY( a.use_count() == 1 );
+  VERIFY( b.use_count() == 0 );
+  VERIFY( A::ctor_count == 1 );
+  VERIFY( A::dtor_count == 0 );
+  VERIFY( B::ctor_count == 1 );
+  VERIFY( B::dtor_count == 0 );
+
+  a = std::move(std::shared_ptr<A>());
+  VERIFY( a.get() == 0 );
+  VERIFY( A::ctor_count == 1 );
+  VERIFY( A::dtor_count == 1 );
+  VERIFY( B::ctor_count == 1 );
+  VERIFY( B::dtor_count == 1 );
+}
+
+int 
+main()
+{
+  test01();
+  test02();
+  return 0;
+}
Index: testsuite/tr1/2_general_utilities/shared_ptr/cons/move.cc
===================================================================
--- testsuite/tr1/2_general_utilities/shared_ptr/cons/move.cc	(revision 0)
+++ testsuite/tr1/2_general_utilities/shared_ptr/cons/move.cc	(revision 0)
@@ -0,0 +1,165 @@
+// { dg-options "-std=gnu++0x" }
+
+// Copyright (C) 2007 Free Software Foundation
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// TR1 20.6.6.2 Template class shared_ptr [util.smartptr.shared]
+
+#include <memory>
+#include <utility>
+#include <testsuite_hooks.h>
+
+struct A
+{
+  A() { ++ctor_count; }
+  virtual ~A() { ++dtor_count; }
+  static long ctor_count;
+  static long dtor_count;
+};
+long A::ctor_count = 0;
+long A::dtor_count = 0;
+
+struct B : A
+{
+  B() { ++ctor_count; }
+  virtual ~B() { ++dtor_count; }
+  static long ctor_count;
+  static long dtor_count;
+};
+long B::ctor_count = 0;
+long B::dtor_count = 0;
+
+struct D
+{
+  void operator()(B* p) const { delete p; ++delete_count; }
+  static long delete_count;
+};
+long D::delete_count = 0;
+
+struct reset_count_struct
+{
+  ~reset_count_struct()
+  {
+    A::ctor_count = 0;
+    A::dtor_count = 0;
+    B::ctor_count = 0;
+    B::dtor_count = 0;
+    D::delete_count = 0;
+  }
+};
+
+// 20.6.6.2.1 shared_ptr constructors [util.smartptr.shared.const]
+
+// Rvalue construction
+int test01()
+{
+  reset_count_struct __attribute__((unused)) reset;
+  bool test __attribute__((unused)) = true;
+
+  std::shared_ptr<A> a1;
+  std::shared_ptr<A> a2(std::move(a1));
+  VERIFY( a1.use_count() == 0 );
+  VERIFY( a2.use_count() == 0 );
+  VERIFY( A::ctor_count == 0 );
+  VERIFY( A::dtor_count == 0 );
+  VERIFY( B::ctor_count == 0 );
+  VERIFY( B::dtor_count == 0 );
+
+  return 0;
+}
+
+int
+test02()
+{
+  reset_count_struct __attribute__((unused)) reset;
+  bool test __attribute__((unused)) = true;
+
+  std::shared_ptr<A> a1(new A);
+  std::shared_ptr<A> a2(std::move(a1));
+  VERIFY( a1.use_count() == 0 );
+  VERIFY( a2.use_count() == 1 );
+  VERIFY( A::ctor_count == 1 );
+  VERIFY( A::dtor_count == 0 );
+
+  return 0;
+}
+
+int
+test03()
+{
+  reset_count_struct __attribute__((unused)) reset;
+  bool test __attribute__((unused)) = true;
+
+  std::shared_ptr<B> b(new B);
+  std::shared_ptr<A> a(std::move(b));
+  VERIFY( b.use_count() == 0 );
+  VERIFY( a.use_count() == 1 );
+  VERIFY( A::ctor_count == 1 );
+  VERIFY( A::dtor_count == 0 );
+  VERIFY( B::ctor_count == 1 );
+  VERIFY( B::dtor_count == 0 );
+
+  return 0;
+}
+
+int
+test04()
+{
+  reset_count_struct __attribute__((unused)) reset;
+  bool test __attribute__((unused)) = true;
+
+  std::shared_ptr<B> b(new B, D());
+  std::shared_ptr<A> a(std::move(b));
+  VERIFY( b.use_count() == 0 );
+  VERIFY( a.use_count() == 1 );
+  VERIFY( A::ctor_count == 1 );
+  VERIFY( A::dtor_count == 0 );
+  VERIFY( B::ctor_count == 1 );
+  VERIFY( B::dtor_count == 0 );
+
+  a = std::move(std::shared_ptr<A>());
+  VERIFY( D::delete_count == 1 );
+  VERIFY( B::dtor_count == 1 );
+
+  return 0;
+}
+
+int
+test05()
+{
+  reset_count_struct __attribute__((unused)) reset;
+  bool test __attribute__((unused)) = true;
+
+  std::shared_ptr<A> a(std::move(std::shared_ptr<A>(new A)));
+  VERIFY( a.use_count() == 1 );
+  VERIFY( A::ctor_count == 1 );
+  VERIFY( A::dtor_count == 0 );
+
+  return 0;
+}
+
+int
+main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+  test05();
+  return 0;
+}

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [patch] Improving shared_ptr for C++0x
  2007-11-14  1:25 [patch] Improving shared_ptr for C++0x Jonathan Wakely
@ 2007-11-14  1:37 ` Benjamin Kosnik
  2007-11-14 19:07   ` Benjamin Kosnik
  0 siblings, 1 reply; 4+ messages in thread
From: Benjamin Kosnik @ 2007-11-14  1:37 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: libstdc++, gcc-patches


> New tests and docs on the implementation choices are included. There
> are a few places where further work could be done, see the new HTML
> file for details. That doc is also available at
> http://www.kayari.org/doc/c++/shared_ptr.html to save you reading the
> HTML. I haven't linked to the new doc from any existing pages yet as
> the C++0x status is still experimental and I don't know where these
> sort of implementation notes will fit in Benjamin's new doc plan.

Just to answer this last part.

Status for C++0x stuff should go in
docs/html/17_intro/c++0x_status.html. You can put the paper numbers as
links in the notes sections if you'd like. It would be great if you
could correct this document WRT shared_ptr and related items.

FYI, this document is not complete currently. Instead,
it's the tr1_status.html document "ported" to the C++0x draft. I believe
appendix C to be wrong, for instance, but most of the other bits are
fine.

It doesn't actually track (at the moment) anything after tr1, ie
variadic templates, move semantics, or anything here:
http://gcc.gnu.org/projects/cxx0x.html

This needs to be fixed, obviously, but I figure it can be done
incrementally. To be quite honest, I'm not quite sure of the state of
the move semantics work myself, so I didn't want to attempt it.

;)

-benjamin 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [patch] Improving shared_ptr for C++0x
  2007-11-14  1:37 ` Benjamin Kosnik
@ 2007-11-14 19:07   ` Benjamin Kosnik
  2007-11-15 10:11     ` Jonathan Wakely
  0 siblings, 1 reply; 4+ messages in thread
From: Benjamin Kosnik @ 2007-11-14 19:07 UTC (permalink / raw)
  To: Benjamin Kosnik; +Cc: Jonathan Wakely, libstdc++, gcc-patches


> Just to answer this last part.

Now to answer it after actually reading your page....

I see your concern now. This doesn't really fit into a status checklist.

I suppose this could either fit in chapter 20, in a new shared_ptr
section, or in a implementation-defined behavior link after C++0x, a la
what was done for C++98.

-benjamin

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [patch] Improving shared_ptr for C++0x
  2007-11-14 19:07   ` Benjamin Kosnik
@ 2007-11-15 10:11     ` Jonathan Wakely
  0 siblings, 0 replies; 4+ messages in thread
From: Jonathan Wakely @ 2007-11-15 10:11 UTC (permalink / raw)
  To: Benjamin Kosnik; +Cc: Benjamin Kosnik, libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1386 bytes --]

On 14/11/2007, Benjamin Kosnik <bkoz@redhat.com> wrote:
>
> > Just to answer this last part.
>
> Now to answer it after actually reading your page....
>
> I see your concern now. This doesn't really fit into a status checklist.

Right, but attached anyway is an update for the shared_ptr section of
the status page to make the section names and numbers match the
working paper.
This assumes my patch is going in, since I've marked everything done :-)
I'll apply this if the other patch goes in, if not I'll adjust it first.

> I suppose this could either fit in chapter 20, in a new shared_ptr
> section, or in a implementation-defined behavior link after C++0x, a la
> what was done for C++98.

Apart from confirming that libstdc++ only does one allocation in
make_shared none of the behaviour is implementation-defined, and even
that isn't what the standard refers to as ID, since the allocations
done by make_shared are only mentioned in a note.

I modelled the doc on your locale, ctype and messages implementation
notes, so we have a few files like this that are not really user-level
docs, but definitely worth having.  Hmm, then again, the messages and
locale docs are sort of user docs, since they describe libstdc++
extensions to the standard behaviour. My shared_ptr notes are pretty
useless to anyone except maintainers (but should allow me to close
PR24347 at least :)

Jon

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: status.diff --]
[-- Type: text/x-patch; name=status.diff, Size: 1653 bytes --]

Index: docs/html/17_intro/c++0x_status.html
===================================================================
--- docs/html/17_intro/c++0x_status.html	(revision 130159)
+++ docs/html/17_intro/c++0x_status.html	(working copy)
@@ -567,7 +567,7 @@
       <td>done</td>
       <td></td>
       <td></td>
-      <td><a href="tr1.html#1">1</a></td>
+      <td><a href="#1">1</a></td>
     </tr>
     <tr>
       <td>20.6.6.2.1</td>
@@ -611,6 +611,16 @@
     </tr>
     <tr>
       <td>20.6.6.2.6</td>
+      <td><code>shared_ptr</code> creation</td>
+      <td>done</td>
+      <td></td>
+      <td></td>
+      <td>
+      <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2351.htm">N2351</a>
+      </td>
+    </tr>
+    <tr>
+      <td>20.6.6.2.7</td>
       <td><code>shared_ptr</code> comparison</td>
       <td>done</td>
       <td></td>
@@ -618,7 +628,7 @@
       <td></td>
     </tr>
     <tr>
-      <td>20.6.6.2.7</td>
+      <td>20.6.6.2.8</td>
       <td><code>shared_ptr</code> I/O</td>
       <td>done</td>
       <td></td>
@@ -626,7 +636,7 @@
       <td></td>
     </tr>
     <tr>
-      <td>20.6.6.2.8</td>
+      <td>20.6.6.2.9</td>
       <td><code>shared_ptr</code> specialized algorithms</td>
       <td>done</td>
       <td></td>
@@ -634,7 +644,7 @@
       <td></td>
     </tr>
     <tr>
-      <td>20.6.6.2.9</td>
+      <td>20.6.6.2.10</td>
       <td><code>shared_ptr</code> casts</td>
       <td>done</td>
       <td></td>
@@ -642,7 +652,7 @@
       <td></td>
     </tr>
     <tr>
-      <td>20.6.6.2.10</td>
+      <td>20.6.6.2.11</td>
       <td><code>get_deleter</code></td>
       <td>done</td>
       <td></td>

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2007-11-14 23:09 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-11-14  1:25 [patch] Improving shared_ptr for C++0x Jonathan Wakely
2007-11-14  1:37 ` Benjamin Kosnik
2007-11-14 19:07   ` Benjamin Kosnik
2007-11-15 10:11     ` Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).