text: //////////////////////////////////////////////////////////////////////////////
  //
  // This file is the adaptation for Interprocess of boost/detail/shared_count.hpp
  //
  // (C) Copyright Peter Dimov and Multi Media Ltd. 2001, 2002, 2003
  // (C) Copyright Peter Dimov 2004-2005
  // (C) Copyright Ion Gaztanaga 2006-2009. 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)
  //
  // See http://www.boost.org/libs/interprocess for documentation.
  //
  //////////////////////////////////////////////////////////////////////////////
  #ifndef BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED
  #define BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED
  
  // MS compatible compilers support #pragma once
  
  #if defined(_MSC_VER) && (_MSC_VER >= 1020)
  # pragma once
  #endif
  
  #include <boost/interprocess/detail/config_begin.hpp>
  #include <boost/interprocess/detail/workaround.hpp>
  
  #include <boost/checked_delete.hpp>
  #include <boost/pointer_to_other.hpp>
  #include <boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp>
  #include <boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp>
  #include <boost/interprocess/detail/utilities.hpp>
  #include <boost/detail/no_exceptions_support.hpp>
  #include <functional>       // std::less
  
  namespace boost {
  namespace interprocess {
  namespace ipcdetail{
  
  template<class T, class VoidAllocator, class Deleter>
  class weak_count;
  
  template<class T, class VoidAllocator, class Deleter>
  class shared_count
  {
     public:
     typedef typename boost::pointer_to_other
        <typename VoidAllocator::pointer, T>::type               pointer;
  
     private:
     typedef sp_counted_impl_pd<VoidAllocator, Deleter>       counted_impl;
     typedef typename boost::pointer_to_other
        <typename VoidAllocator::pointer, counted_impl>::type    counted_impl_ptr;
     typedef typename boost::pointer_to_other
        <typename VoidAllocator::pointer, sp_counted_base>::type counted_base_ptr;
     typedef typename VoidAllocator::template rebind
        <counted_impl>::other                        counted_impl_allocator;
     typedef typename boost::pointer_to_other
              <typename VoidAllocator::pointer, const Deleter>::type   const_deleter_pointer;
     typedef typename boost::pointer_to_other
              <typename VoidAllocator::pointer, const VoidAllocator>::type   const_allocator_pointer;
  
     pointer           m_px;
     counted_impl_ptr  m_pi;
  
     template <class T2, class VoidAllocator2, class Deleter2>
     friend class weak_count;
  
     template <class T2, class VoidAllocator2, class Deleter2>
     friend class shared_count;
  
     public:
  
     shared_count()
        :  m_px(0), m_pi(0) // nothrow
     {}
  
     template <class Ptr>
     shared_count(const shared_count &other_shared_count, const Ptr &p)
        :  m_px(p), m_pi(other_shared_count.m_pi)
     {}
  
     template <class Ptr>
     shared_count(const Ptr &p, const VoidAllocator &a, Deleter d)
        :  m_px(p), m_pi(0)
     {
        BOOST_TRY{
           if(p){
              counted_impl_allocator alloc(a);
              m_pi = alloc.allocate(1);
              //Anti-exception deallocator
              scoped_ptr<counted_impl, 
                       scoped_ptr_dealloc_functor<counted_impl_allocator> >
                          deallocator(m_pi, alloc);
              //It's more correct to use VoidAllocator::construct but
              //this needs copy constructor and we don't like it
              new(ipcdetail::get_pointer(m_pi))counted_impl(p, a, d);
              deallocator.release();
           }
        }
        BOOST_CATCH (...){
           d(p); // delete p
           BOOST_RETHROW
        }
        BOOST_CATCH_END
     }
  
     ~shared_count() // nothrow
     {  
        if( m_pi != 0 ) 
           m_pi->release();
     }
  
     shared_count(shared_count const & r)
        :  m_px(r.m_px), m_pi(r.m_pi) // nothrow
     { if( m_pi != 0 ) m_pi->add_ref_copy(); }
  
     //this is a test
     template<class Y>
     explicit shared_count(shared_count<Y, VoidAllocator, Deleter> const & r)
        :  m_px(r.m_px), m_pi(r.m_pi) // nothrow
     {  if( m_pi != 0 ) m_pi->add_ref_copy();  }
  
     //this is a test
     template<class Y>
     explicit shared_count(const pointer & ptr, shared_count<Y, VoidAllocator, Deleter> const & r)
        :  m_px(ptr), m_pi(r.m_pi) // nothrow
     {  if( m_pi != 0 ) m_pi->add_ref_copy();  }
  
  /*
     explicit shared_count(weak_count<Y, VoidAllocator, Deleter> const & r)
        // throws bad_weak_ptr when r.use_count() == 0
        : m_pi( r.m_pi )
     {
        if( m_pi == 0 || !m_pi->add_ref_lock() ){
           boost::throw_exception( boost::interprocess::bad_weak_ptr() );
        }
     }
  */
     template<class Y>
     explicit shared_count(weak_count<Y, VoidAllocator, Deleter> const & r)
        // throws bad_weak_ptr when r.use_count() == 0
        : m_px(r.m_px), m_pi( r.m_pi )
     {
        if( m_pi == 0 || !m_pi->add_ref_lock() ){
           throw( boost::interprocess::bad_weak_ptr() );
        }
     }
  
     const pointer &get_pointer() const
     {  return m_px;   }
  
     pointer &get_pointer()
     {  return m_px;   }
  
     shared_count & operator= (shared_count const & r) // nothrow
     {
        m_px = r.m_px;
        counted_impl_ptr 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;
     }
  
     template<class Y>
     shared_count & operator= (shared_count<Y, VoidAllocator, Deleter> const & r) // nothrow
     {
        m_px = r.m_px;
        counted_impl_ptr 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
     {  ipcdetail::do_swap(m_px, r.m_px);   ipcdetail::do_swap(m_pi, r.m_pi);   }
  
     long use_count() const // nothrow
     {  return m_pi != 0? m_pi->use_count(): 0;  }
  
     bool unique() const // nothrow
     {  return use_count() == 1;   }
  
     const_deleter_pointer get_deleter() const
     {  return m_pi ? m_pi->get_deleter() : 0; }
  
  //   const_allocator_pointer get_allocator() const
  //   {  return m_pi ? m_pi->get_allocator() : 0; }
  
     template<class T2, class VoidAllocator2, class Deleter2>
     bool internal_equal (shared_count<T2, VoidAllocator2, Deleter2> const & other) const
     {  return this->m_pi == other.m_pi;   }
  
     template<class T2, class VoidAllocator2, class Deleter2>
     bool internal_less  (shared_count<T2, VoidAllocator2, Deleter2> const & other) const
     {  return std::less<counted_base_ptr>()(this->m_pi, other.m_pi);  }
  };
  
  template<class T, class VoidAllocator, class Deleter, class T2, class VoidAllocator2, class Deleter2> inline
  bool operator==(shared_count<T, VoidAllocator, Deleter> const & a, shared_count<T2, VoidAllocator2, Deleter2> const & b)
  {  return a.internal_equal(b);  }
  
  template<class T, class VoidAllocator, class Deleter, class T2, class VoidAllocator2, class Deleter2> inline
  bool operator<(shared_count<T, VoidAllocator, Deleter> const & a, shared_count<T2, VoidAllocator2, Deleter2> const & b)
  {  return a.internal_less(b);   }
  
  
  template<class T, class VoidAllocator, class Deleter>
  class weak_count
  {
     public:
     typedef typename boost::pointer_to_other
        <typename VoidAllocator::pointer, T>::type            pointer;
  
     private:
     typedef sp_counted_impl_pd<VoidAllocator, Deleter>    counted_impl;
     typedef typename boost::pointer_to_other
        <typename VoidAllocator::pointer, counted_impl>::type    counted_impl_ptr;
     typedef typename boost::pointer_to_other
        <typename VoidAllocator::pointer, sp_counted_base>::type counted_base_ptr;
  
     pointer           m_px;
     counted_impl_ptr  m_pi;
  
     template <class T2, class VoidAllocator2, class Deleter2>
     friend class weak_count;
  
     template <class T2, class VoidAllocator2, class Deleter2>
     friend class shared_count;
  
     public:
  
     weak_count(): m_px(0), m_pi(0) // nothrow
     {}
  
     template <class Y>
     explicit weak_count(shared_count<Y, VoidAllocator, Deleter> const & r)
        :  m_px(r.m_px), m_pi(r.m_pi) // nothrow
     {  if(m_pi != 0) m_pi->weak_add_ref(); }
  
     weak_count(weak_count const & r)
        :  m_px(r.m_px), m_pi(r.m_pi) // nothrow
     {  if(m_pi != 0) m_pi->weak_add_ref(); }
  
     template<class Y>
     weak_count(weak_count<Y, VoidAllocator, Deleter> const & r)
        : m_px(r.m_px), 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(); }
  
     template<class Y>
     weak_count & operator= (shared_count<Y, VoidAllocator, Deleter> const & r) // nothrow
     {
        m_px = r.m_px;
        counted_impl_ptr 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= (weak_count const & r) // nothrow
     {
        counted_impl_ptr 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 set_pointer(const pointer &ptr)
     {  m_px = ptr; }
  
     template<class Y>
     weak_count & operator= (weak_count<Y, VoidAllocator, Deleter> const& r) // nothrow
     {
        counted_impl_ptr 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
     {  ipcdetail::do_swap(m_px, r.m_px);  ipcdetail::do_swap(m_pi, r.m_pi);   }
  
     long use_count() const // nothrow
     {  return m_pi != 0? m_pi->use_count() : 0;   }
  
     template<class T2, class VoidAllocator2, class Deleter2>
     bool internal_equal (weak_count<T2, VoidAllocator2, Deleter2> const & other) const
     {  return this->m_pi == other.m_pi;   }
  
     template<class T2, class VoidAllocator2, class Deleter2>
     bool internal_less (weak_count<T2, VoidAllocator2, Deleter2> const & other) const
     {  return std::less<counted_base_ptr>()(this->m_pi, other.m_pi);  }
  };
  
  template<class T, class VoidAllocator, class Deleter, class T2, class VoidAllocator2, class Deleter2> inline
  bool operator==(weak_count<T, VoidAllocator, Deleter> const & a, weak_count<T2, VoidAllocator2, Deleter2> const & b)
  {  return a.internal_equal(b);  }
  
  template<class T, class VoidAllocator, class Deleter, class T2, class VoidAllocator2, class Deleter2> inline
  bool operator<(weak_count<T, VoidAllocator, Deleter> const & a, weak_count<T2, VoidAllocator2, Deleter2> const & b)
  {  return a.internal_less(b);   }
  
  } // namespace ipcdetail
  } // namespace interprocess
  } // namespace boost
  
  
  #include <boost/interprocess/detail/config_end.hpp>
  
  
  #endif  // #ifndef BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED
  