sp_counted_impl.hpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  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 boost::container::
  39. allocator_traits<Allocator>::pointer pointer;
  40. typedef ipcdetail::integral_constant<unsigned,
  41. boost::interprocess::version<Allocator>::value> alloc_version;
  42. typedef ipcdetail::integral_constant<unsigned, 1> allocator_v1;
  43. typedef ipcdetail::integral_constant<unsigned, 2> allocator_v2;
  44. private:
  45. void priv_deallocate(const pointer &p, allocator_v1)
  46. { m_alloc.deallocate(p, 1); }
  47. void priv_deallocate(const pointer &p, allocator_v2)
  48. { m_alloc.deallocate_one(p); }
  49. public:
  50. Allocator& m_alloc;
  51. scoped_ptr_dealloc_functor(Allocator& a)
  52. : m_alloc(a) {}
  53. void operator()(pointer ptr)
  54. { if (ptr) priv_deallocate(ptr, alloc_version()); }
  55. };
  56. template<class A, class D>
  57. class sp_counted_impl_pd
  58. : public sp_counted_base
  59. , boost::container::allocator_traits<A>::template
  60. portable_rebind_alloc< sp_counted_impl_pd<A, D> >::type
  61. , D // copy constructor must not throw
  62. {
  63. private:
  64. typedef sp_counted_impl_pd<A, D> this_type;
  65. typedef typename boost::container::
  66. allocator_traits<A>::template
  67. portable_rebind_alloc
  68. < this_type >::type this_allocator;
  69. typedef typename boost::container::
  70. allocator_traits<A>::template
  71. portable_rebind_alloc
  72. < const this_type >::type const_this_allocator;
  73. typedef typename boost::container::
  74. allocator_traits<this_allocator>
  75. ::pointer this_pointer;
  76. typedef typename boost::container::
  77. allocator_traits<A>::pointer a_pointer;
  78. typedef typename boost::intrusive::
  79. pointer_traits<this_pointer> this_pointer_traits;
  80. sp_counted_impl_pd( sp_counted_impl_pd const & );
  81. sp_counted_impl_pd & operator= ( sp_counted_impl_pd const & );
  82. typedef typename boost::intrusive::
  83. pointer_traits<a_pointer>::template
  84. rebind_pointer<const D>::type const_deleter_pointer;
  85. typedef typename boost::intrusive::
  86. pointer_traits<a_pointer>::template
  87. rebind_pointer<const A>::type const_allocator_pointer;
  88. typedef typename D::pointer pointer;
  89. pointer m_ptr;
  90. public:
  91. // pre: d(p) must not throw
  92. template<class Ptr>
  93. sp_counted_impl_pd(const Ptr & p, const A &a, const D &d )
  94. : this_allocator(a), D(d), m_ptr(p)
  95. {}
  96. const_deleter_pointer get_deleter() const
  97. { return const_deleter_pointer(&static_cast<const D&>(*this)); }
  98. const_allocator_pointer get_allocator() const
  99. { return const_allocator_pointer(&static_cast<const A&>(*this)); }
  100. void dispose() // nothrow
  101. { static_cast<D&>(*this)(m_ptr); }
  102. void destroy() // nothrow
  103. {
  104. //Self destruction, so move the allocator
  105. this_allocator a_copy(::boost::move(static_cast<this_allocator&>(*this)));
  106. BOOST_ASSERT(a_copy == *this);
  107. this_pointer this_ptr(this_pointer_traits::pointer_to(*this));
  108. //Do it now!
  109. scoped_ptr< this_type, scoped_ptr_dealloc_functor<this_allocator> >
  110. deleter_ptr(this_ptr, a_copy);
  111. ipcdetail::to_raw_pointer(this_ptr)->~this_type();
  112. }
  113. void release() // nothrow
  114. {
  115. if(this->ref_release()){
  116. this->dispose();
  117. this->weak_release();
  118. }
  119. }
  120. void weak_release() // nothrow
  121. {
  122. if(sp_counted_base::weak_release()){
  123. this->destroy();
  124. }
  125. }
  126. };
  127. } // namespace ipcdetail
  128. } // namespace interprocess
  129. } // namespace boost
  130. #include <boost/interprocess/detail/config_end.hpp>
  131. #endif // #ifndef BOOST_INTERPROCESS_DETAIL_SP_COUNTED_IMPL_HPP_INCLUDED