// <tr1/boost_shared_ptr.h> -*- C++ -*-

// Copyright (C) 2005 Free Software Foundation, Inc.
//
// 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.

// As a special exception, you may use this file as part of a free software
// library without restriction.  Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License.  This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.

//  shared_count.hpp
//  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.

//  shared_ptr.hpp
//  Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes.
//  Copyright (C) 2001, 2002, 2003 Peter Dimov

//  weak_ptr.hpp
//  Copyright (C) 2001, 2002, 2003 Peter Dimov

//  enable_shared_from_this.hpp
//  Copyright (C) 2002 Peter Dimov

// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

// GCC Note:  based on version 1.32.0 of the Boost library.

/** @file boost_memory.h
 *  This is an internal header file, included by other library headers.
 *  You should not attempt to use it directly.
 */

#ifndef _BOOST_SHARED_PTR_H
#define _BOOST_SHARED_PTR_H 1

// namespace std::tr1
namespace std
{
namespace tr1
{

class bad_weak_ptr : public std::exception
{
public:

  virtual char const*
  what() const throw()
  { return "tr1::bad_weak_ptr"; }
};

// Helper for exception objects in <tr1/memory>
// TODO this should be defined in a different file.
inline void
__throw_bad_weak_ptr()
{
#if __EXCEPTIONS
  throw bad_weak_ptr();
#else
  std::abort();
#endif
}


template<typename _Tp>
  struct _Sp_deleter
  {
    typedef void result_type;
    typedef _Tp* argument_type;

    void
    operator()(_Tp* p) const
    { delete p; }
  };


class _Sp_counted_base
{
public:

  _Sp_counted_base()
  : _M_use_count(1), _M_weak_count(1)
  {
    // For the case of __GTHREAD_MUTEX_INIT we haven't initialised
    // the mutex yet, so do it now.
#if defined(__GTHREADS) && defined(__GTHREAD_MUTEX_INIT)
    __gthread_mutex_t __tmp = __GTHREAD_MUTEX_INIT;
    _M_mutex = __tmp;
#endif
  }

  virtual
  ~_Sp_counted_base() // nothrow
  { }

  // dispose() is called when _M_use_count drops to zero, to release
  // the resources managed by *this.
  virtual void
  dispose() = 0; // nothrow

  // destroy() is called when _M_weak_count drops to zero.
  virtual void
  destroy() // nothrow
  {
    delete this;
  }

  virtual void*
  get_deleter(const std::type_info&) = 0;

  void
  add_ref_copy()
  {
    __gnu_cxx::__atomic_add(&_M_use_count, 1);
  }

  void
  add_ref_lock()
  {
    __gnu_cxx::lock lock(_M_mutex);
    if (__gnu_cxx::__exchange_and_add(&_M_use_count, 1) == 0)
      {
	_M_use_count = 0;
	__throw_bad_weak_ptr();
      }
  }

  void
  release() // nothrow
  {
    if (__gnu_cxx::__exchange_and_add(&_M_use_count, -1) == 1)
      {
	dispose();
#ifdef __GTHREADS	
	_GLIBCXX_READ_MEM_BARRIER;
	_GLIBCXX_WRITE_MEM_BARRIER;
#endif
	if (__gnu_cxx::__exchange_and_add(&_M_weak_count, -1) == 1)
	  destroy();
      }
  }

  void
  weak_add_ref() // nothrow
  {
    __gnu_cxx::__atomic_add(&_M_weak_count, 1);
  }

  void
  weak_release() // nothrow
  {
    if (__gnu_cxx::__exchange_and_add(&_M_weak_count, -1) == 1)
      {
#ifdef __GTHREADS
	_GLIBCXX_READ_MEM_BARRIER;
	_GLIBCXX_WRITE_MEM_BARRIER;
#endif
	destroy();
      }
  }

  long
  use_count() const // nothrow
  {
    return _M_use_count;  // XXX is this MT safe?
  }

private:

  _Sp_counted_base(_Sp_counted_base const&);
  _Sp_counted_base& operator=(_Sp_counted_base const&);

  _Atomic_word _M_use_count;        // #shared
  _Atomic_word _M_weak_count;       // #weak + (#shared != 0)
  __gnu_cxx::mutex_type _M_mutex;
};

template<typename _Ptr, typename _Deleter>
  class _Sp_counted_base_impl
  : public _Sp_counted_base
  {
  public:

    /**
     *  @brief   
     *  @pre     d(p) must not throw.
     */
    _Sp_counted_base_impl(_Ptr __p, _Deleter __d)
    : _M_ptr(__p), _M_del(__d)
    { }
    
    virtual void
    dispose() // nothrow
    {
      _M_del(_M_ptr);
    }
    
    virtual void*
    get_deleter(const std::type_info& __ti)
    {
      return __ti == typeid(_Deleter) ? &_M_del : 0;
    }
    
  private:
    _Sp_counted_base_impl(const _Sp_counted_base_impl&);
    _Sp_counted_base_impl& operator=(const _Sp_counted_base_impl&);
    
    _Ptr     _M_ptr; // copy constructor must not throw
    _Deleter _M_del; // copy constructor must not throw
  };

class weak_count;

class shared_count
{
private:

  _Sp_counted_base* _M_pi;

  friend class weak_count;

public:

  shared_count()
  : _M_pi(0) // nothrow
  { }

  template<typename _Ptr, typename _Deleter>
    shared_count(_Ptr __p, _Deleter __d)
    : _M_pi(0)
    {
      try
	{
	  _M_pi = new _Sp_counted_base_impl<_Ptr, _Deleter>(__p, __d);
	}
      catch(...)
	{
	  __d(__p); // delete __p
	  __throw_exception_again;
	}
    }

  // auto_ptr<_Tp> is special cased 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> >(__r.get(), _Sp_deleter<_Tp>()))
    { __r.release(); }

  // throws bad_weak_ptr when __r.use_count() == 0
  explicit shared_count(const weak_count& __r);

  ~shared_count() // nothrow
  {
    if (_M_pi != 0)
      _M_pi->release();
  }

  shared_count(const shared_count& __r)
  : _M_pi(__r._M_pi) // nothrow
  {
    if (_M_pi != 0)
      _M_pi->add_ref_copy();
  }

  shared_count&
  operator=(const shared_count& __r) // nothrow
  {
    _Sp_counted_base* __tmp = __r._M_pi;

    if(__tmp != _M_pi)
      {
	if(__tmp != 0)
	  __tmp->add_ref_copy();
	if(_M_pi != 0)
	  _M_pi->release();
	_M_pi = __tmp;
      }
    return *this;
  }

  void swap(shared_count& __r) // nothrow
  {
    _Sp_counted_base* __tmp = __r._M_pi;
    __r._M_pi = _M_pi;
    _M_pi = __tmp;
  }

  long
  use_count() const // nothrow
  { return _M_pi != 0 ? _M_pi->use_count() : 0; }

  bool
  unique() const // nothrow
  { return this->use_count() == 1; }

  friend inline bool
  operator==(const shared_count& __a, const shared_count& __b)
  { return __a._M_pi == __b._M_pi; }

  friend inline bool
  operator<(const shared_count& __a, const shared_count& __b)
  { return std::less<_Sp_counted_base*>()(__a._M_pi, __b._M_pi); }

  void*
  get_deleter(const std::type_info& __ti) const
  { return _M_pi ? _M_pi->get_deleter(__ti) : 0; }
};

class weak_count
{
private:

  _Sp_counted_base* _M_pi;

  friend class shared_count;

public:

  weak_count()
  : _M_pi(0) // nothrow
  { }

  weak_count(const shared_count& __r)
  : _M_pi(__r._M_pi) // nothrow
  {
    if (_M_pi != 0)
      _M_pi->weak_add_ref();
  }

  weak_count(const weak_count& __r)
  : _M_pi(__r._M_pi) // nothrow
  {
    if (_M_pi != 0)
      _M_pi->weak_add_ref();
  }

  ~weak_count() // nothrow
  {
    if (_M_pi != 0)
      _M_pi->weak_release();
  }

  weak_count&
  operator=(const shared_count& __r) // nothrow
  {
    _Sp_counted_base* __tmp = __r._M_pi;
    if (__tmp != 0)
      __tmp->weak_add_ref();
    if (_M_pi != 0)
      _M_pi->weak_release();
    _M_pi = __tmp;

    return *this;
  }

  weak_count&
  operator=(const weak_count& __r) // nothrow
  {
    _Sp_counted_base * __tmp = __r._M_pi;
    if (__tmp != 0)
      __tmp->weak_add_ref();
    if (_M_pi != 0)
      _M_pi->weak_release();
    _M_pi = __tmp;

    return *this;
  }

  void
  swap(weak_count& __r) // nothrow
  {
    _Sp_counted_base * __tmp = __r._M_pi;
    __r._M_pi = _M_pi;
    _M_pi = __tmp;
  }

  long
  use_count() const // nothrow
  { return _M_pi != 0 ? _M_pi->use_count() : 0; }

  friend inline bool
  operator==(const weak_count& __a, const weak_count& __b)
  { return __a._M_pi == __b._M_pi; }

  friend inline bool
  operator<(const weak_count& __a, const weak_count& __b)
  { return std::less<_Sp_counted_base*>()(__a._M_pi, __b._M_pi); }
};

inline
shared_count::shared_count(const weak_count& __r)
: _M_pi(__r._M_pi)
{
  if (_M_pi != 0)
    _M_pi->add_ref_lock();
  else
    __throw_bad_weak_ptr();
}


// fwd decls
template<typename _Tp>
  class shared_ptr;

template<typename _Tp>
  class weak_ptr;

template<typename _Tp>
  class enable_shared_from_this;

struct __static_cast_tag {};
struct __const_cast_tag {};
struct __dynamic_cast_tag {};
struct __polymorphic_cast_tag {};

template<class _Tp>
  struct shared_ptr_traits
  { typedef _Tp& reference; };

template<>
  struct shared_ptr_traits<void>
  { typedef void reference; };

template<>
  struct shared_ptr_traits<void const>
  { typedef void reference; };

template<>
  struct shared_ptr_traits<void volatile>
  { typedef void reference; };

template<>
  struct shared_ptr_traits<void const volatile>
  { typedef void reference; };


// enable_shared_from_this support

// friend of enable_shared_from_this
template<typename _Tp1, typename _Tp2>
  void
  __enable_shared_from_this(const shared_count& __pn,
                            const enable_shared_from_this<_Tp1>* __pe,
                            const _Tp2* __px );

inline void
__enable_shared_from_this(const shared_count&, ...)
{ }


// get_deleter must be declared before friend declaration by shared_ptr.
template<typename _Del, typename _Tp>
  _Del* get_deleter(const shared_ptr<_Tp>&);

/**
 *  @class shared_ptr <tr1/memory>
 *
 *  A smart pointer with reference-counted copy semantics.
 *  The object pointed to is deleted when the last shared_ptr pointing to it
 *  is destroyed or reset.
 */
template<typename _Tp>
  class shared_ptr
  {
    typedef typename shared_ptr_traits<_Tp>::reference _Reference;

  public:

    typedef _Tp   element_type;

    /** @brief  Construct an empty %shared_ptr.
     *  @post   use_count()==0 && get()==0
     */
    shared_ptr()
    : _M_ptr(0), _M_refcount() // never throws
    { }

    /** @brief  Construct a %shared_ptr that owns the pointer @a p.
     *  @param  p  A pointer that is convertible to element_type*.
     *  @post   use_count() == 1 && get() == p
     *  @throw  std::bad_alloc, in which case @c delete @a p is called.
     */
    template<typename _Tp1>
      explicit shared_ptr(_Tp1* __p)
      : _M_ptr(__p), _M_refcount(__p, _Sp_deleter<_Tp1>())
      {
        __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
        // __glibcxx_function_requires(_CompleteConcept<_Tp1*>)

        __enable_shared_from_this( _M_refcount, __p, __p );
      }

    //
    // Requirements: D'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.
     *  @post   use_count() == 1 && get() == p
     *  @throw  std::bad_alloc, in which case @a d(p) is called.
     */
    template<typename _Tp1, typename _Deleter>
      shared_ptr(_Tp1* __p, _Deleter __d)
      : _M_ptr(__p), _M_refcount(__p, __d)
      {
        __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
        // TODO requires D is CopyConstructible and d(p) well-formed

        __enable_shared_from_this( _M_refcount, __p, __p );
      }

    //  generated copy constructor, assignment, destructor are fine.

    /** @brief  If @a r is empty, constructs an empty %shared_ptr; otherwise
     *          construct a %shared_ptr that shares ownership with @a r.
     *  @param  r  A %shared_ptr.
     *  @post   get() == r.get() && use_count() == r.use_count()
     *  @throw  std::bad_alloc, in which case 
     */
    template<typename _Tp1>
      shared_ptr(const shared_ptr<_Tp1>& __r)
      : _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws
      {
        __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
      }

    /** @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.
     *  @post   use_count() == r.use_count()
     *  @throw  bad_weak_ptr when r.expired(),
     *          in which case the constructor has no effect.
     */
    template<typename _Tp1>
      explicit shared_ptr(const weak_ptr<_Tp1>& __r)
      : _M_refcount(__r._M_refcount) // may throw
      {
        __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
        // it is now safe to copy r__._M_ptr, as _M_refcount(__r._M_refcount)
        // did not throw
        _M_ptr = __r._M_ptr;
      }

    /**
     * @post use_count() == 1 and r.get() == 0
     */
    template<typename _Tp1>
      explicit shared_ptr(std::auto_ptr<_Tp1>& __r)
      : _M_ptr(__r.get()), _M_refcount()
      {
        // TODO requires r.release() convertible to _Tp*, Tp1 is complete,
        // delete r.release() well-formed
        _Tp1 * __tmp = __r.get();
        _M_refcount = shared_count(__r);

        __enable_shared_from_this( _M_refcount, __tmp, __tmp );
      }

    template<typename _Tp1>
      shared_ptr(const shared_ptr<_Tp1>& __r, __static_cast_tag)
      : _M_ptr(static_cast<element_type*>(__r._M_ptr)),
	_M_refcount(__r._M_refcount)
      { }

    template<typename _Tp1>
      shared_ptr(const shared_ptr<_Tp1>& __r, __const_cast_tag)
      : _M_ptr(const_cast<element_type*>(__r._M_ptr)),
	_M_refcount(__r._M_refcount)
      { }

    template<typename _Tp1>
      shared_ptr(const shared_ptr<_Tp1>& __r, __dynamic_cast_tag)
      : _M_ptr(dynamic_cast<element_type*>(__r._M_ptr)),
	_M_refcount(__r._M_refcount)
      {
        if (_M_ptr == 0) // need to allocate new counter -- the cast failed
          _M_refcount = shared_count();
      }

    template<typename _Tp1>
      shared_ptr&
      operator=(const shared_ptr<_Tp1>& __r) // never throws
      {
        _M_ptr = __r._M_ptr;
        _M_refcount = __r._M_refcount; // shared_count::op= doesn't throw
        return *this;
      }

    template<typename _Tp1>
      shared_ptr&
      operator=(std::auto_ptr<_Tp1>& __r)
      {
        shared_ptr(__r).swap(*this);
        return *this;
      }

    void
    reset() // never throws
    { shared_ptr().swap(*this); }

    template<typename _Tp1>
      void
      reset(_Tp1* __p) // _Tp1 must be complete
      {
        _GLIBCXX_DEBUG_ASSERT(__p == 0 || __p != _M_ptr); // catch self-reset
	                                                  // errors
        shared_ptr(__p).swap(*this);
      }

    template<typename _Tp1, typename _Deleter>
      void
      reset(_Tp1 * __p, _Deleter __d)
      { shared_ptr(__p, __d).swap(*this); }

    // error to instantiate if _Tp is [cv-qual] void
    _Reference
    operator*() const // never throws
    {
      _GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
      return *_M_ptr;
    }

    _Tp*
    operator->() const // never throws
    {
      _GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
      return _M_ptr;
    }
    
    _Tp*
    get() const // never throws
    { return _M_ptr; }

    // implicit conversion to "bool"
  private:
    typedef _Tp* shared_ptr::*__unspecified_bool_type;

  public:
    operator __unspecified_bool_type() const // never throws
    { return _M_ptr == 0 ? 0 : &shared_ptr::_M_ptr; }

    bool
    unique() const // never throws
    { return _M_refcount.unique(); }

    long
    use_count() const // never throws
    { return _M_refcount.use_count(); }

    void
    swap(shared_ptr<_Tp>& __other) // never throws
    {
      std::swap(_M_ptr, __other._M_ptr);
      _M_refcount.swap(__other._M_refcount);
    }

  private:
    void*
    _M_get_deleter(const std::type_info& __ti) const
    { return _M_refcount.get_deleter(__ti); }

    template<typename _Tp1>
      bool
      _M_less(const shared_ptr<_Tp1>& __rhs) const
      { return _M_refcount < __rhs._M_refcount; }

    template<typename _Tp1> friend class shared_ptr;
    template<typename _Tp1> friend class weak_ptr;

    template<typename _Del, typename _Tp1>
      friend _Del* get_deleter(const shared_ptr<_Tp1>&);

    // friends injected into enclosing namespace and found by ADL:
    template<typename _Tp1>
      friend inline bool
      operator==(const shared_ptr& __a, const shared_ptr<_Tp1>& __b)
      { return __a.get() == __b.get(); }

    template<typename _Tp1>
      friend inline bool
      operator!=(const shared_ptr& __a, const shared_ptr<_Tp1>& __b)
      { return __a.get() != __b.get(); }

    template<typename _Tp1>
      friend inline bool
      operator<(const shared_ptr& __a, const shared_ptr<_Tp1>& __b)
      { return __a._M_less(__b); }

    _Tp*         _M_ptr;         // contained pointer
    shared_count _M_refcount;    // reference counter
  };  // shared_ptr

// 2.2.3.8 shared_ptr specialized algorithms.
template<typename _Tp>
  inline void
  swap(shared_ptr<_Tp>& __a, shared_ptr<_Tp>& __b)
  { __a.swap(__b); }

// 2.2.3.9 shared_ptr casts
/** @warning The seemingly equivalent
 *           <code>shared_ptr<T>(static_cast<T*>(r.get()))</code>
 *           will eventually result in undefined behaviour,
 *           attempting to delete the same object twice.
 */
template<typename _Tp, typename _Tp1>
  shared_ptr<_Tp>
  static_pointer_cast(const shared_ptr<_Tp1>& __r)
  {
    return shared_ptr<_Tp>(__r, __static_cast_tag());
  }

/** @warning The seemingly equivalent
 *           <code>shared_ptr<T>(const_cast<T*>(r.get()))</code>
 *           will eventually result in undefined behaviour,
 *           attempting to delete the same object twice.
 */
template<typename _Tp, typename _Tp1>
  shared_ptr<_Tp>
  const_pointer_cast(const shared_ptr<_Tp1>& __r)
  {
    return shared_ptr<_Tp>(__r, __const_cast_tag());
  }

/** @warning The seemingly equivalent
 *           <code>shared_ptr<T>(dynamic_cast<T*>(r.get()))</code>
 *           will eventually result in undefined behaviour,
 *           attempting to delete the same object twice.
 */
template<typename _Tp, typename _Tp1>
  shared_ptr<_Tp>
  dynamic_pointer_cast(const shared_ptr<_Tp1>& __r)
  {
    return shared_ptr<_Tp>(__r, __dynamic_cast_tag());
  }

// 2.2.3.7 shared_ptr I/O
template<typename _Ch, typename _Tr, typename _Tp>
  std::basic_ostream<_Ch, _Tr>&
  operator<<(std::basic_ostream<_Ch, _Tr>& __os, const shared_ptr<_Tp>& __p)
  {
    __os << __p.get();
    return __os;
  }

// 2.2.3.10 shared_ptr get_deleter (experimental)
template<typename _Del, typename _Tp>
  inline _Del*
  get_deleter(const shared_ptr<_Tp>& __p)
  { return static_cast<_Del*>(__p._M_get_deleter(typeid(_Del))); }


template<typename _Tp>
  class weak_ptr
  {
  public:

    typedef _Tp element_type;

    weak_ptr()
    : _M_ptr(0), _M_refcount() // never throws
    { }

    //  generated copy constructor, assignment, destructor are fine

    //
    //  The "obvious" converting constructor implementation:
    //
    //  template<class Y>
    //    weak_ptr(weak_ptr<Y> const & r)
    //    : _M_ptr(r._M_ptr), _M_refcount(r._M_refcount) // never throws
    //    { }
    //
    //  has a serious problem.
    //
    //  r._M_ptr may already have been invalidated. The _M_ptr(r._M_ptr)
    //  conversion may require access to *r._M_ptr (virtual inheritance).
    //
    //  It is not possible to avoid spurious access violations since
    //  in multithreaded programs r._M_ptr may be invalidated at any point.
    //

    template<typename _Tp1>
      weak_ptr(const weak_ptr<_Tp1>& r)
      : _M_refcount(r._M_refcount) // never throws
      {
        __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
        _M_ptr = r.lock().get();
      }

    template<typename _Tp1>
      weak_ptr(const shared_ptr<_Tp1>& r)
      : _M_ptr(r._M_ptr), _M_refcount(r._M_refcount) // never throws
      {
        __glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
      }

    template<typename _Tp1>
      weak_ptr&
      operator=(const weak_ptr<_Tp1>& r) // never throws
      {
        _M_ptr = r.lock().get();
        _M_refcount = r._M_refcount;
        return *this;
      }

    template<typename _Tp1>
      weak_ptr&
      operator=(const shared_ptr<_Tp1>& r) // never throws
      {
        _M_ptr = r._M_ptr;
        _M_refcount = r._M_refcount;
        return *this;
      }

    shared_ptr<_Tp>
    lock() const // never throws
    {
#ifdef __GTHREADS

      // optimization: avoid throw overhead
      if (expired())
	return shared_ptr<element_type>();
      
      try
	{
	  return shared_ptr<element_type>(*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>();
	}

#else

      // optimization: avoid try/catch overhead when single threaded
      return expired() ? shared_ptr<element_type>()
	               : shared_ptr<element_type>(*this);

#endif
    } // XXX MT

    long
    use_count() const // never throws
    { return _M_refcount.use_count(); }

    bool
    expired() const // never throws
    { return _M_refcount.use_count() == 0; }

    void
    reset() // never throws
    { weak_ptr().swap(*this); }

    void
    swap(weak_ptr& __s) // never throws
    {
      std::swap(_M_ptr, __s._M_ptr);
      _M_refcount.swap(__s._M_refcount);
    }

  private:

    template<typename _Tp1>
      bool
      _M_less(const weak_ptr<_Tp1>& __rhs) const
      { return _M_refcount < __rhs._M_refcount; }

    // used by __enable_shared_from_this
    void
    _M_assign(_Tp* __ptr, const shared_count& __refcount)
    {
      _M_ptr = __ptr;
      _M_refcount = __refcount;
    }

    // friend injected into namespace and found by ADL

    template<typename _Tp1>
      friend inline bool
      operator<(const weak_ptr& __lhs, const weak_ptr<_Tp1>& __rhs)
      { return __lhs._M_less(__rhs); }

    template<typename _Tp1> friend class weak_ptr;
    template<typename _Tp1> friend class shared_ptr;
    friend class enable_shared_from_this<_Tp>;

    _Tp*       _M_ptr;           // contained pointer
    weak_count _M_refcount;      // reference counter

  };  // weak_ptr

// 2.2.4.7 weak_ptr specialized algorithms.
template<typename _Tp>
  void
  swap(weak_ptr<_Tp>& __a, weak_ptr<_Tp>& __b)
  { __a.swap(__b); }


template<typename _Tp>
  class enable_shared_from_this
  {
  protected:

    enable_shared_from_this()
    { }

    enable_shared_from_this(const enable_shared_from_this&)
    { }

    enable_shared_from_this&
    operator=(const enable_shared_from_this&)
    { return *this; }

    ~enable_shared_from_this()
    { }

  public:

    shared_ptr<_Tp>
    shared_from_this()
    {
      shared_ptr<_Tp> __p(this->_M_weak_this);
      return __p;
    }

    shared_ptr<const _Tp>
    shared_from_this() const
    {
      shared_ptr<const _Tp> __p(this->_M_weak_this);
      return __p;
    }

  private:
    template<typename _Tp1>
      void
      _M_weak_assign(_Tp1* __p, const shared_count& __n) const
      { _M_weak_this._M_assign(__p, __n); }

    template<typename _Tp1>
      friend void
      __enable_shared_from_this(const shared_count& __pn,
				const enable_shared_from_this* __pe,
				const _Tp1* __px)
      {
        if(__pe != 0)
          __pe->_M_weak_assign(const_cast<_Tp1*>(__px), __pn);
      }

    mutable weak_ptr<_Tp> _M_weak_this;
  };

} // namespace tr1
} // namespace std

#endif
