Re: [Boost-bugs] [Boost C++ Libraries] #1109: intrusive_ptr needs a helper base class

Subject: Re: [Boost-bugs] [Boost C++ Libraries] #1109: intrusive_ptr needs a helper base class
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2013-11-07 09:03:47


#1109: intrusive_ptr needs a helper base class
-------------------------------+-----------------------
  Reporter: pdimov | Owner: pdimov
      Type: Feature Requests | Status: new
 Milestone: To Be Determined | Component: smart_ptr
   Version: | Severity: Problem
Resolution: | Keywords:
-------------------------------+-----------------------

Comment (by Jiří Havel <JSH@…>):

 I use this base class. It is inspired by boost.intrusive and uses the
 example reference counter from boost.atomic.

 If you want, I can improve this a bit. I think, it should be possible to
 select atomic/nonatomic internal counter and some checking policy (again
 inspired by boost.atomic).

 {{{
 #ifndef INTRUSIVE_PTR_BASE_HOOK_H_INCLUDED
 #define INTRUSIVE_PTR_BASE_HOOK_H_INCLUDED

 #include <memory>
 #include <utility>

 #include <boost/assert.hpp>
 #include <boost/atomic.hpp>
 #include <boost/intrusive_ptr.hpp>
 #include <boost/parameter/binding.hpp>
 #include <boost/parameter/name.hpp>
 #include <boost/parameter/parameters.hpp>

 namespace utils {

 BOOST_PARAMETER_TEMPLATE_KEYWORD(deleter)
 BOOST_PARAMETER_TEMPLATE_KEYWORD(count_type)

 typedef boost::parameter::parameters<
     boost::parameter::optional<tag::deleter>,
     boost::parameter::optional<tag::count_type>
> intrusive_ptr_base_hook_signature;

 template<typename Derived, typename ... Params>
 class intrusive_ptr_base_hook
 {
     typedef typename
 intrusive_ptr_base_hook_signature::bind<Params...>::type args;

 protected :
     typedef Derived derived_type;

     typedef typename boost::parameter::binding<
             args, tag::deleter, std::default_delete<derived_type>
>::type deleter_type;

     typedef typename boost::parameter::binding<
             args, tag::count_type, unsigned
>::type count_type;

 private:
     struct Data
         : public deleter_type
     {
         boost::atomic<count_type> count;

         constexpr Data(count_type c, deleter_type const & d)
             : deleter_type(d)
             , count(c)
         {}
     } m_data;

 protected :
     constexpr intrusive_ptr_base_hook()
         : m_data(0, deleter_type())
     {}

     intrusive_ptr_base_hook(intrusive_ptr_base_hook const &) = delete;
     intrusive_ptr_base_hook & operator=(intrusive_ptr_base_hook const &) =
 delete;

     ~intrusive_ptr_base_hook() noexcept
     {
 BOOST_ASSERT(m_count.load(boost::memory_order::memory_order_relaxed) ==
 0);
     }

 public :
     friend void intrusive_ptr_add_ref(
             intrusive_ptr_base_hook const * p)
     {
         const_cast<intrusive_ptr_base_hook*>(p)
             ->m_data.count.fetch_add(1, boost::memory_order_relaxed);
     }

     friend void intrusive_ptr_release(
             intrusive_ptr_base_hook const * pc)
     {
         intrusive_ptr_base_hook * p =
 const_cast<intrusive_ptr_base_hook*>(pc);
         if(p->m_data.count.fetch_sub(1, boost::memory_order_release) == 1)
         {
             boost::atomic_thread_fence(boost::memory_order_acquire);
             // call deleter hidden in m_data
             p->m_data(static_cast<derived_type*>(p));
         }
     }
 };

 template<typename T, typename ... Args>
 inline boost::intrusive_ptr<T> make_intrusive(Args && ... args)
 {
     return boost::intrusive_ptr<T>(new T(std::forward<Args>(args)...));
 }

 }//namespace utils

 #endif//INTRUSIVE_PTR_BASE_HOOK_H_INCLUDED
 }}}

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/1109#comment:9>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:14 UTC