File indexing completed on 2025-12-16 09:53:28
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED
0015 #define BOOST_INTERPROCESS_DETAIL_SHARED_COUNT_HPP_INCLUDED
0016
0017 #ifndef BOOST_CONFIG_HPP
0018 # include <boost/config.hpp>
0019 #endif
0020 #
0021 #if defined(BOOST_HAS_PRAGMA_ONCE)
0022 # pragma once
0023 #endif
0024
0025 #include <boost/interprocess/detail/config_begin.hpp>
0026 #include <boost/interprocess/detail/workaround.hpp>
0027
0028 #include <boost/intrusive/pointer_traits.hpp>
0029 #include <boost/interprocess/smart_ptr/detail/bad_weak_ptr.hpp>
0030 #include <boost/interprocess/smart_ptr/detail/sp_counted_impl.hpp>
0031 #include <boost/interprocess/detail/utilities.hpp>
0032 #include <boost/container/allocator_traits.hpp>
0033 #include <boost/move/adl_move_swap.hpp>
0034 #include <boost/intrusive/detail/minimal_less_equal_header.hpp> //std::less
0035 #include <boost/container/detail/placement_new.hpp>
0036
0037 namespace boost {
0038 namespace interprocess {
0039 namespace ipcdetail{
0040
0041 template<class T, class VoidAllocator, class Deleter>
0042 class weak_count;
0043
0044 template<class T, class VoidAllocator, class Deleter>
0045 class shared_count
0046 {
0047 public:
0048
0049 typedef typename boost::container::
0050 allocator_traits<VoidAllocator>::pointer void_ptr;
0051 typedef typename boost::intrusive::
0052 pointer_traits<void_ptr>::template
0053 rebind_pointer<T>::type pointer;
0054
0055 private:
0056 typedef sp_counted_impl_pd<VoidAllocator, Deleter> counted_impl;
0057
0058 typedef typename boost::intrusive::
0059 pointer_traits<void_ptr>::template
0060 rebind_pointer<counted_impl>::type counted_impl_ptr;
0061 typedef typename boost::intrusive::
0062 pointer_traits<void_ptr>::template
0063 rebind_pointer<sp_counted_base>::type counted_base_ptr;
0064
0065 typedef boost::container::allocator_traits<VoidAllocator> vallocator_traits;
0066
0067 typedef typename vallocator_traits::template
0068 portable_rebind_alloc<counted_impl>::type counted_impl_allocator;
0069
0070 typedef typename boost::intrusive::
0071 pointer_traits<void_ptr>::template
0072 rebind_pointer<const Deleter>::type const_deleter_pointer;
0073
0074 typedef typename boost::intrusive::
0075 pointer_traits<void_ptr>::template
0076 rebind_pointer<const VoidAllocator>::type const_allocator_pointer;
0077
0078 pointer m_px;
0079 counted_impl_ptr m_pi;
0080
0081 template <class T2, class VoidAllocator2, class Deleter2>
0082 friend class weak_count;
0083
0084 template <class T2, class VoidAllocator2, class Deleter2>
0085 friend class shared_count;
0086
0087 public:
0088
0089 shared_count()
0090 : m_px(0), m_pi(0)
0091 {}
0092
0093 template <class Ptr>
0094 shared_count(const shared_count &other_shared_count, const Ptr &p)
0095 : m_px(p), m_pi(other_shared_count.m_pi)
0096 {}
0097
0098 template <class Ptr>
0099 shared_count(const Ptr &p, const VoidAllocator &a, Deleter d)
0100 : m_px(p), m_pi(0)
0101 {
0102 BOOST_INTERPROCESS_TRY{
0103 if(p){
0104 counted_impl_allocator alloc(a);
0105 m_pi = alloc.allocate(1);
0106
0107 scoped_ptr<counted_impl,
0108 scoped_ptr_dealloc_functor<counted_impl_allocator> >
0109 deallocator(m_pi, alloc);
0110
0111
0112 ::new(ipcdetail::to_raw_pointer(m_pi), boost_container_new_t())counted_impl(p, a, d);
0113 deallocator.release();
0114 }
0115 }
0116 BOOST_INTERPROCESS_CATCH (...){
0117 d(p);
0118 BOOST_INTERPROCESS_RETHROW
0119 }
0120 BOOST_INTERPROCESS_CATCH_END
0121 }
0122
0123 ~shared_count()
0124 {
0125 if(m_pi)
0126 m_pi->release();
0127 }
0128
0129 shared_count(shared_count const & r)
0130 : m_px(r.m_px), m_pi(r.m_pi)
0131 { if( m_pi != 0 ) m_pi->add_ref_copy(); }
0132
0133
0134 template<class Y>
0135 explicit shared_count(shared_count<Y, VoidAllocator, Deleter> const & r)
0136 : m_px(r.m_px), m_pi(r.m_pi)
0137 { if( m_pi != 0 ) m_pi->add_ref_copy(); }
0138
0139
0140 template<class Y>
0141 explicit shared_count(const pointer & ptr, shared_count<Y, VoidAllocator, Deleter> const & r)
0142 : m_px(ptr), m_pi(r.m_pi)
0143 { if( m_pi != 0 ) m_pi->add_ref_copy(); }
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155 template<class Y>
0156 explicit shared_count(weak_count<Y, VoidAllocator, Deleter> const & r)
0157
0158 : m_px(r.m_px), m_pi( r.m_pi )
0159 {
0160 if( m_pi == 0 || !m_pi->add_ref_lock() ){
0161 throw( boost::interprocess::bad_weak_ptr() );
0162 }
0163 }
0164
0165 const pointer &to_raw_pointer() const
0166 { return m_px; }
0167
0168 pointer &to_raw_pointer()
0169 { return m_px; }
0170
0171 shared_count & operator= (shared_count const & r)
0172 {
0173 m_px = r.m_px;
0174 counted_impl_ptr tmp = r.m_pi;
0175 if( tmp != m_pi ){
0176 if(tmp != 0) tmp->add_ref_copy();
0177 if(m_pi != 0) m_pi->release();
0178 m_pi = tmp;
0179 }
0180 return *this;
0181 }
0182
0183 template<class Y>
0184 shared_count & operator= (shared_count<Y, VoidAllocator, Deleter> const & r)
0185 {
0186 m_px = r.m_px;
0187 counted_impl_ptr tmp = r.m_pi;
0188 if( tmp != m_pi ){
0189 if(tmp != 0) tmp->add_ref_copy();
0190 if(m_pi != 0) m_pi->release();
0191 m_pi = tmp;
0192 }
0193 return *this;
0194 }
0195
0196 void swap(shared_count & r)
0197 { ::boost::adl_move_swap(m_px, r.m_px); ::boost::adl_move_swap(m_pi, r.m_pi); }
0198
0199 long use_count() const
0200 { return m_pi != 0? m_pi->use_count(): 0; }
0201
0202 bool unique() const
0203 { return use_count() == 1; }
0204
0205 const_deleter_pointer get_deleter() const
0206 { return m_pi ? m_pi->get_deleter() : 0; }
0207
0208
0209
0210
0211 template<class T2, class VoidAllocator2, class Deleter2>
0212 bool internal_equal (shared_count<T2, VoidAllocator2, Deleter2> const & other) const
0213 { return this->m_pi == other.m_pi; }
0214
0215 template<class T2, class VoidAllocator2, class Deleter2>
0216 bool internal_less (shared_count<T2, VoidAllocator2, Deleter2> const & other) const
0217 { return std::less<counted_base_ptr>()(this->m_pi, other.m_pi); }
0218 };
0219
0220 template<class T, class VoidAllocator, class Deleter, class T2, class VoidAllocator2, class Deleter2> inline
0221 bool operator==(shared_count<T, VoidAllocator, Deleter> const & a, shared_count<T2, VoidAllocator2, Deleter2> const & b)
0222 { return a.internal_equal(b); }
0223
0224 template<class T, class VoidAllocator, class Deleter, class T2, class VoidAllocator2, class Deleter2> inline
0225 bool operator<(shared_count<T, VoidAllocator, Deleter> const & a, shared_count<T2, VoidAllocator2, Deleter2> const & b)
0226 { return a.internal_less(b); }
0227
0228
0229 template<class T, class VoidAllocator, class Deleter>
0230 class weak_count
0231 {
0232 public:
0233 typedef typename boost::container::
0234 allocator_traits<VoidAllocator>::pointer void_ptr;
0235 typedef typename boost::intrusive::
0236 pointer_traits<void_ptr>::template
0237 rebind_pointer<T>::type pointer;
0238
0239 private:
0240
0241 typedef sp_counted_impl_pd<VoidAllocator, Deleter> counted_impl;
0242
0243 typedef typename boost::intrusive::
0244 pointer_traits<void_ptr>::template
0245 rebind_pointer<counted_impl>::type counted_impl_ptr;
0246 typedef typename boost::intrusive::
0247 pointer_traits<void_ptr>::template
0248 rebind_pointer<sp_counted_base>::type counted_base_ptr;
0249
0250 pointer m_px;
0251 counted_impl_ptr m_pi;
0252
0253 template <class T2, class VoidAllocator2, class Deleter2>
0254 friend class weak_count;
0255
0256 template <class T2, class VoidAllocator2, class Deleter2>
0257 friend class shared_count;
0258
0259 public:
0260
0261 weak_count(): m_px(0), m_pi(0)
0262 {}
0263
0264 template <class Y>
0265 explicit weak_count(shared_count<Y, VoidAllocator, Deleter> const & r)
0266 : m_px(r.m_px), m_pi(r.m_pi)
0267 { if(m_pi != 0) m_pi->weak_add_ref(); }
0268
0269 weak_count(weak_count const & r)
0270 : m_px(r.m_px), m_pi(r.m_pi)
0271 { if(m_pi != 0) m_pi->weak_add_ref(); }
0272
0273 template<class Y>
0274 weak_count(weak_count<Y, VoidAllocator, Deleter> const & r)
0275 : m_px(r.m_px), m_pi(r.m_pi)
0276 { if(m_pi != 0) m_pi->weak_add_ref(); }
0277
0278 ~weak_count()
0279 { if(m_pi != 0) m_pi->weak_release(); }
0280
0281 template<class Y>
0282 weak_count & operator= (shared_count<Y, VoidAllocator, Deleter> const & r)
0283 {
0284 m_px = r.m_px;
0285 counted_impl_ptr tmp = r.m_pi;
0286 if(tmp != 0) tmp->weak_add_ref();
0287 if(m_pi != 0) m_pi->weak_release();
0288 m_pi = tmp;
0289 return *this;
0290 }
0291
0292 weak_count & operator= (weak_count const & r)
0293 {
0294 m_px = r.m_px;
0295 counted_impl_ptr tmp = r.m_pi;
0296 if(tmp != 0) tmp->weak_add_ref();
0297 if(m_pi != 0) m_pi->weak_release();
0298 m_pi = tmp;
0299 return *this;
0300 }
0301
0302 void set_pointer(const pointer &ptr)
0303 { m_px = ptr; }
0304
0305 template<class Y>
0306 weak_count & operator= (weak_count<Y, VoidAllocator, Deleter> const& r)
0307 {
0308 counted_impl_ptr tmp = r.m_pi;
0309 if(tmp != 0) tmp->weak_add_ref();
0310 if(m_pi != 0) m_pi->weak_release();
0311 m_pi = tmp;
0312 return *this;
0313 }
0314
0315 void swap(weak_count & r)
0316 { ::boost::adl_move_swap(m_px, r.m_px); ::boost::adl_move_swap(m_pi, r.m_pi); }
0317
0318 long use_count() const
0319 { return m_pi != 0? m_pi->use_count() : 0; }
0320
0321 template<class T2, class VoidAllocator2, class Deleter2>
0322 bool internal_equal (weak_count<T2, VoidAllocator2, Deleter2> const & other) const
0323 { return this->m_pi == other.m_pi; }
0324
0325 template<class T2, class VoidAllocator2, class Deleter2>
0326 bool internal_less (weak_count<T2, VoidAllocator2, Deleter2> const & other) const
0327 { return std::less<counted_base_ptr>()(this->m_pi, other.m_pi); }
0328 };
0329
0330 template<class T, class VoidAllocator, class Deleter, class T2, class VoidAllocator2, class Deleter2> inline
0331 bool operator==(weak_count<T, VoidAllocator, Deleter> const & a, weak_count<T2, VoidAllocator2, Deleter2> const & b)
0332 { return a.internal_equal(b); }
0333
0334 template<class T, class VoidAllocator, class Deleter, class T2, class VoidAllocator2, class Deleter2> inline
0335 bool operator<(weak_count<T, VoidAllocator, Deleter> const & a, weak_count<T2, VoidAllocator2, Deleter2> const & b)
0336 { return a.internal_less(b); }
0337
0338 }
0339 }
0340 }
0341
0342
0343 #include <boost/interprocess/detail/config_end.hpp>
0344
0345
0346 #endif