sp_counted_impl.hpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. #ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED
  2. #define BOOST_INTERPROCESS_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED
  3. #ifndef BOOST_CONFIG_HPP
  4. # include <boost/config.hpp>
  5. #endif
  6. #
  7. #if defined(BOOST_HAS_PRAGMA_ONCE)
  8. # pragma once
  9. #endif
  10. //
  11. // This file is the adaptation for shared memory memory mapped
  12. // files of boost/detail/sp_counted_impl.hpp
  13. //
  14. // Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
  15. // Copyright 2004-2005 Peter Dimov
  16. // Copyright 2006 Ion Gaztanaga
  17. //
  18. // Distributed under the Boost Software License, Version 1.0. (See
  19. // accompanying file LICENSE_1_0.txt or copy at
  20. // http://www.boost.org/LICENSE_1_0.txt)
  21. //
  22. #include <boost/interprocess/detail/config_begin.hpp>
  23. #include <boost/interprocess/detail/workaround.hpp>
  24. #include <boost/interprocess/containers/version_type.hpp>
  25. #include <boost/interprocess/smart_ptr/detail/sp_counted_base.hpp>
  26. #include <boost/interprocess/smart_ptr/scoped_ptr.hpp>
  27. #include <boost/interprocess/detail/utilities.hpp>
  28. #include <boost/container/allocator_traits.hpp>
  29. #include <boost/intrusive/pointer_traits.hpp>
  30. namespace boost {
  31. namespace interprocess {
  32. namespace ipcdetail {
  33. //!A deleter for scoped_ptr that deallocates the memory
  34. //!allocated for an object using a STL allocator.
  35. template <class Allocator>
  36. struct scoped_ptr_dealloc_functor
  37. {
  38. typedef typename Allocator::pointer pointer;
  39. typedef ipcdetail::integral_constant<unsigned,
  40. boost::interprocess::version<Allocator>::value> alloc_version;
  41. typedef ipcdetail::integral_constant<unsigned, 1> allocator_v1;
  42. typedef ipcdetail::integral_constant<unsigned, 2> allocator_v2;
  43. private:
  44. void priv_deallocate(const typename Allocator::pointer &p, allocator_v1)
  45. { m_alloc.deallocate(p, 1); }
  46. void priv_deallocate(const typename Allocator::pointer &p, allocator_v2)
  47. { m_alloc.deallocate_one(p); }
  48. public:
  49. Allocator& m_alloc;
  50. scoped_ptr_dealloc_functor(Allocator& a)
  51. : m_alloc(a) {}
  52. void operator()(pointer ptr)
  53. { if (ptr) priv_deallocate(ptr, alloc_version()); }
  54. };
  55. template<class A, class D>
  56. class sp_counted_impl_pd
  57. : public sp_counted_base
  58. , boost::container::allocator_traits<A>::template
  59. portable_rebind_alloc< sp_counted_impl_pd<A, D> >::type
  60. , D // copy constructor must not throw
  61. {
  62. private:
  63. typedef sp_counted_impl_pd<A, D> this_type;
  64. typedef typename boost::container::
  65. allocator_traits<A>::template
  66. portable_rebind_alloc
  67. < this_type >::type this_allocator;
  68. typedef typename boost::container::
  69. allocator_traits<A>::template
  70. portable_rebind_alloc
  71. < const this_type >::type const_this_allocator;
  72. typedef typename this_allocator::pointer this_pointer;
  73. typedef typename boost::intrusive::
  74. pointer_traits<this_pointer> this_pointer_traits;
  75. sp_counted_impl_pd( sp_counted_impl_pd const & );
  76. sp_counted_impl_pd & operator= ( sp_counted_impl_pd const & );
  77. typedef typename boost::intrusive::
  78. pointer_traits<typename A::pointer>::template
  79. rebind_pointer<const D>::type const_deleter_pointer;
  80. typedef typename boost::intrusive::
  81. pointer_traits<typename A::pointer>::template
  82. rebind_pointer<const A>::type const_allocator_pointer;
  83. typedef typename D::pointer pointer;
  84. pointer m_ptr;
  85. public:
  86. // pre: d(p) must not throw
  87. template<class Ptr>
  88. sp_counted_impl_pd(const Ptr & p, const A &a, const D &d )
  89. : this_allocator(a), D(d), m_ptr(p)
  90. {}
  91. const_deleter_pointer get_deleter() const
  92. { return const_deleter_pointer(&static_cast<const D&>(*this)); }
  93. const_allocator_pointer get_allocator() const
  94. { return const_allocator_pointer(&static_cast<const A&>(*this)); }
  95. void dispose() // nothrow
  96. { static_cast<D&>(*this)(m_ptr); }
  97. void destroy() // nothrow
  98. {
  99. //Self destruction, so move the allocator
  100. this_allocator a_copy(::boost::move(static_cast<this_allocator&>(*this)));
  101. BOOST_ASSERT(a_copy == *this);
  102. this_pointer this_ptr(this_pointer_traits::pointer_to(*this));
  103. //Do it now!
  104. scoped_ptr< this_type, scoped_ptr_dealloc_functor<this_allocator> >
  105. deleter_ptr(this_ptr, a_copy);
  106. typedef typename this_allocator::value_type value_type;
  107. ipcdetail::to_raw_pointer(this_ptr)->~value_type();
  108. }
  109. void release() // nothrow
  110. {
  111. if(this->ref_release()){
  112. this->dispose();
  113. this->weak_release();
  114. }
  115. }
  116. void weak_release() // nothrow
  117. {
  118. if(sp_counted_base::weak_release()){
  119. this->destroy();
  120. }
  121. }
  122. };
  123. } // namespace ipcdetail
  124. } // namespace interprocess
  125. } // namespace boost
  126. #include <boost/interprocess/detail/config_end.hpp>
  127. #endif // #ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED