File indexing completed on 2025-10-30 08:20:55
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_HPP
0012 #define BOOST_INTERPROCESS_SEGMENT_MANAGER_HPP
0013
0014 #ifndef BOOST_CONFIG_HPP
0015 # include <boost/config.hpp>
0016 #endif
0017 #
0018 #if defined(BOOST_HAS_PRAGMA_ONCE)
0019 # pragma once
0020 #endif
0021
0022 #include <boost/interprocess/detail/config_begin.hpp>
0023 #include <boost/interprocess/detail/workaround.hpp>
0024
0025 #include <boost/interprocess/detail/type_traits.hpp>
0026
0027 #include <boost/interprocess/detail/transform_iterator.hpp>
0028
0029 #include <boost/interprocess/detail/mpl.hpp>
0030 #include <boost/interprocess/detail/nothrow.hpp>
0031 #include <boost/interprocess/detail/segment_manager_helper.hpp>
0032 #include <boost/interprocess/detail/named_proxy.hpp>
0033 #include <boost/interprocess/detail/utilities.hpp>
0034 #include <boost/interprocess/offset_ptr.hpp>
0035 #include <boost/interprocess/indexes/iset_index.hpp>
0036 #include <boost/interprocess/exceptions.hpp>
0037 #include <boost/interprocess/allocators/allocator.hpp>
0038 #include <boost/interprocess/smart_ptr/deleter.hpp>
0039 #include <boost/move/utility_core.hpp>
0040 #include <boost/interprocess/sync/scoped_lock.hpp>
0041
0042 #include <boost/container/detail/minimal_char_traits_header.hpp>
0043 #include <boost/container/detail/placement_new.hpp>
0044
0045 #include <cstddef> //std::size_t
0046 #include <boost/intrusive/detail/minimal_pair_header.hpp>
0047 #include <boost/assert.hpp>
0048 #ifndef BOOST_NO_EXCEPTIONS
0049 #include <exception>
0050 #endif
0051 #include <typeinfo>
0052
0053
0054
0055
0056
0057
0058 namespace boost{
0059 namespace interprocess{
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070 template<class MemoryAlgorithm>
0071 class segment_manager_base
0072 : private MemoryAlgorithm
0073 {
0074 public:
0075 typedef segment_manager_base<MemoryAlgorithm> segment_manager_base_type;
0076 typedef typename MemoryAlgorithm::void_pointer void_pointer;
0077 typedef typename MemoryAlgorithm::mutex_family mutex_family;
0078 static const std::size_t MemAlignment = MemoryAlgorithm::Alignment;
0079 typedef MemoryAlgorithm memory_algorithm;
0080
0081 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0082
0083
0084 typedef typename MemoryAlgorithm::multiallocation_chain multiallocation_chain;
0085 typedef typename MemoryAlgorithm::difference_type difference_type;
0086 typedef typename MemoryAlgorithm::size_type size_type;
0087
0088 #endif
0089
0090
0091
0092 static const size_type PayloadPerAllocation = MemoryAlgorithm::PayloadPerAllocation;
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105 segment_manager_base(size_type sz, size_type reserved_bytes)
0106 : MemoryAlgorithm(sz, reserved_bytes)
0107 {
0108 BOOST_ASSERT((sizeof(segment_manager_base<MemoryAlgorithm>) == sizeof(MemoryAlgorithm)));
0109 }
0110
0111
0112
0113 size_type get_size() const
0114 { return MemoryAlgorithm::get_size(); }
0115
0116
0117
0118 size_type get_free_memory() const
0119 { return MemoryAlgorithm::get_free_memory(); }
0120
0121
0122
0123 static size_type get_min_size (size_type size)
0124 { return MemoryAlgorithm::get_min_size(size); }
0125
0126
0127
0128 void * allocate (size_type nbytes, const std::nothrow_t &)
0129 { return MemoryAlgorithm::allocate(nbytes); }
0130
0131
0132
0133
0134
0135 MemoryAlgorithm &get_memory_algorithm()
0136 { return static_cast<MemoryAlgorithm&>(*this); }
0137
0138
0139
0140
0141
0142 const MemoryAlgorithm &get_memory_algorithm() const
0143 { return static_cast<const MemoryAlgorithm&>(*this); }
0144
0145 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0146
0147
0148
0149
0150 void allocate_many(size_type elem_bytes, size_type n_elements, multiallocation_chain &chain)
0151 {
0152 size_type prev_size = chain.size();
0153 MemoryAlgorithm::allocate_many(elem_bytes, n_elements, chain);
0154 if(!elem_bytes || chain.size() == prev_size){
0155 throw bad_alloc();
0156 }
0157 }
0158
0159
0160
0161 void allocate_many(const size_type *element_lengths, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain)
0162 {
0163 size_type prev_size = chain.size();
0164 MemoryAlgorithm::allocate_many(element_lengths, n_elements, sizeof_element, chain);
0165 if(!sizeof_element || chain.size() == prev_size){
0166 throw bad_alloc();
0167 }
0168 }
0169
0170
0171
0172 void allocate_many(const std::nothrow_t &, size_type elem_bytes, size_type n_elements, multiallocation_chain &chain)
0173 { MemoryAlgorithm::allocate_many(elem_bytes, n_elements, chain); }
0174
0175
0176
0177
0178 void allocate_many(const std::nothrow_t &, const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain)
0179 { MemoryAlgorithm::allocate_many(elem_sizes, n_elements, sizeof_element, chain); }
0180
0181
0182
0183 void deallocate_many(multiallocation_chain &chain)
0184 { MemoryAlgorithm::deallocate_many(chain); }
0185
0186 #endif
0187
0188
0189
0190 void * allocate(size_type nbytes)
0191 {
0192 void * ret = MemoryAlgorithm::allocate(nbytes);
0193 if(!ret)
0194 throw bad_alloc();
0195 return ret;
0196 }
0197
0198
0199
0200 void * allocate_aligned (size_type nbytes, size_type alignment, const std::nothrow_t &)
0201 { return MemoryAlgorithm::allocate_aligned(nbytes, alignment); }
0202
0203
0204
0205 void * allocate_aligned(size_type nbytes, size_type alignment)
0206 {
0207 void * ret = MemoryAlgorithm::allocate_aligned(nbytes, alignment);
0208 if(!ret)
0209 throw bad_alloc();
0210 return ret;
0211 }
0212
0213 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0214
0215 template<class T>
0216 T *allocation_command (boost::interprocess::allocation_type command, size_type limit_size,
0217 size_type &prefer_in_recvd_out_size, T *&reuse)
0218 {
0219 T *ret = MemoryAlgorithm::allocation_command
0220 (command | boost::interprocess::nothrow_allocation, limit_size, prefer_in_recvd_out_size, reuse);
0221 if(!(command & boost::interprocess::nothrow_allocation) && !ret)
0222 throw bad_alloc();
0223 return ret;
0224 }
0225
0226 void *raw_allocation_command (boost::interprocess::allocation_type command, size_type limit_objects,
0227 size_type &prefer_in_recvd_out_size, void *&reuse, size_type sizeof_object = 1)
0228 {
0229 void *ret = MemoryAlgorithm::raw_allocation_command
0230 ( command | boost::interprocess::nothrow_allocation, limit_objects,
0231 prefer_in_recvd_out_size, reuse, sizeof_object);
0232 if(!(command & boost::interprocess::nothrow_allocation) && !ret)
0233 throw bad_alloc();
0234 return ret;
0235 }
0236
0237 #endif
0238
0239
0240
0241 void deallocate (void *addr)
0242 { MemoryAlgorithm::deallocate(addr); }
0243
0244
0245
0246 void grow(size_type extra_size)
0247 {
0248
0249 BOOST_INTERPROCESS_STATIC_ASSERT(!(ipcdetail::is_same<void*, void_pointer>::value));
0250 MemoryAlgorithm::grow(extra_size);
0251 }
0252
0253
0254
0255 void shrink_to_fit()
0256 { MemoryAlgorithm::shrink_to_fit(); }
0257
0258
0259
0260 bool all_memory_deallocated()
0261 { return MemoryAlgorithm::all_memory_deallocated(); }
0262
0263
0264
0265 bool check_sanity()
0266 { return MemoryAlgorithm::check_sanity(); }
0267
0268
0269
0270 void zero_free_memory()
0271 { MemoryAlgorithm::zero_free_memory(); }
0272
0273
0274 size_type size(const void *ptr) const
0275 { return MemoryAlgorithm::size(ptr); }
0276 };
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294 template<class CharType
0295 ,class MemoryAlgorithm
0296 ,template<class IndexConfig> class IndexType>
0297 class segment_manager
0298 : public segment_manager_base<MemoryAlgorithm>
0299 {
0300 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0301
0302 segment_manager();
0303 segment_manager(const segment_manager &);
0304 segment_manager &operator=(const segment_manager &);
0305 typedef segment_manager_base<MemoryAlgorithm> segment_manager_base_t;
0306 #endif
0307
0308 public:
0309 typedef MemoryAlgorithm memory_algorithm;
0310 typedef typename segment_manager_base_t::void_pointer void_pointer;
0311 typedef typename segment_manager_base_t::size_type size_type;
0312 typedef typename segment_manager_base_t::difference_type difference_type;
0313 typedef CharType char_type;
0314
0315 typedef segment_manager_base<MemoryAlgorithm> segment_manager_base_type;
0316
0317 static const size_type PayloadPerAllocation = segment_manager_base_t::PayloadPerAllocation;
0318 static const size_type MemAlignment = segment_manager_base_t::MemAlignment;
0319
0320 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0321 private:
0322 typedef ipcdetail::block_header<size_type> block_header_t;
0323 typedef ipcdetail::index_config<CharType, MemoryAlgorithm> index_config_named;
0324 typedef ipcdetail::index_config<char, MemoryAlgorithm> index_config_unique;
0325 typedef IndexType<index_config_named> index_type;
0326 typedef ipcdetail::bool_<is_intrusive_index<index_type>::value > is_intrusive_t;
0327 typedef ipcdetail::bool_<is_node_index<index_type>::value> is_node_index_t;
0328
0329 public:
0330 typedef IndexType<index_config_named> named_index_t;
0331 typedef IndexType<index_config_unique> unique_index_t;
0332 typedef ipcdetail::char_ptr_holder<CharType> char_ptr_holder_t;
0333 typedef ipcdetail::segment_manager_iterator_transform
0334 <typename named_index_t::const_iterator
0335 ,is_intrusive_index<index_type>::value> named_transform;
0336
0337 typedef ipcdetail::segment_manager_iterator_transform
0338 <typename unique_index_t::const_iterator
0339 ,is_intrusive_index<index_type>::value> unique_transform;
0340 #endif
0341
0342 typedef typename segment_manager_base_t::mutex_family mutex_family;
0343
0344 typedef transform_iterator
0345 <typename named_index_t::const_iterator, named_transform> const_named_iterator;
0346 typedef transform_iterator
0347 <typename unique_index_t::const_iterator, unique_transform> const_unique_iterator;
0348
0349 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0350
0351
0352 template<class T>
0353 struct construct_proxy
0354 {
0355 typedef ipcdetail::named_proxy<segment_manager, T, false> type;
0356 };
0357
0358
0359 template<class T>
0360 struct construct_iter_proxy
0361 {
0362 typedef ipcdetail::named_proxy<segment_manager, T, true> type;
0363 };
0364
0365 #endif
0366
0367
0368
0369
0370
0371 explicit segment_manager(size_type segment_size)
0372 : segment_manager_base_t(segment_size, priv_get_reserved_bytes())
0373 , m_header(static_cast<segment_manager_base_t*>(get_this_pointer()))
0374 {
0375 (void) anonymous_instance; (void) unique_instance;
0376
0377 const void * const this_addr = this;
0378 const void *const segm_addr = static_cast<segment_manager_base_t*>(this);
0379 (void)this_addr; (void)segm_addr;
0380 BOOST_ASSERT( this_addr == segm_addr);
0381 const std::size_t void_ptr_alignment = boost::move_detail::alignment_of<void_pointer>::value; (void)void_ptr_alignment;
0382 BOOST_ASSERT((0 == (std::size_t)this_addr % boost::move_detail::alignment_of<segment_manager>::value));
0383 }
0384
0385
0386
0387
0388 template <class T>
0389 std::pair<T*, size_type> find (char_ptr_holder_t name)
0390 { return this->priv_find_impl<T>(name, true); }
0391
0392
0393
0394
0395
0396
0397 template <class T>
0398 std::pair<T*, size_type> find_no_lock (char_ptr_holder_t name)
0399 { return this->priv_find_impl<T>(name, false); }
0400
0401
0402
0403 template <class T>
0404 typename construct_proxy<T>::type
0405 construct(char_ptr_holder_t name)
0406 { return typename construct_proxy<T>::type (this, name, false, true); }
0407
0408
0409
0410 template <class T>
0411 typename construct_proxy<T>::type find_or_construct(char_ptr_holder_t name)
0412 { return typename construct_proxy<T>::type (this, name, true, true); }
0413
0414
0415
0416 template <class T>
0417 typename construct_proxy<T>::type
0418 construct(char_ptr_holder_t name, const std::nothrow_t &)
0419 { return typename construct_proxy<T>::type (this, name, false, false); }
0420
0421
0422
0423 template <class T>
0424 typename construct_proxy<T>::type
0425 find_or_construct(char_ptr_holder_t name, const std::nothrow_t &)
0426 { return typename construct_proxy<T>::type (this, name, true, false); }
0427
0428
0429 template <class T>
0430 typename construct_iter_proxy<T>::type
0431 construct_it(char_ptr_holder_t name)
0432 { return typename construct_iter_proxy<T>::type (this, name, false, true); }
0433
0434
0435
0436 template <class T>
0437 typename construct_iter_proxy<T>::type
0438 find_or_construct_it(char_ptr_holder_t name)
0439 { return typename construct_iter_proxy<T>::type (this, name, true, true); }
0440
0441
0442
0443 template <class T>
0444 typename construct_iter_proxy<T>::type
0445 construct_it(char_ptr_holder_t name, const std::nothrow_t &)
0446 { return typename construct_iter_proxy<T>::type (this, name, false, false); }
0447
0448
0449
0450 template <class T>
0451 typename construct_iter_proxy<T>::type
0452 find_or_construct_it(char_ptr_holder_t name, const std::nothrow_t &)
0453 { return typename construct_iter_proxy<T>::type (this, name, true, false); }
0454
0455
0456
0457
0458 template <class Func>
0459 void atomic_func(Func &f)
0460 { scoped_lock<rmutex> guard(m_header); f(); }
0461
0462
0463
0464
0465
0466
0467 template <class Func>
0468 bool try_atomic_func(Func &f)
0469 {
0470 scoped_lock<rmutex> guard(m_header, try_to_lock);
0471 if(guard){
0472 f();
0473 return true;
0474 }
0475 else{
0476 return false;
0477 }
0478 }
0479
0480
0481
0482 template <class T>
0483 bool destroy(char_ptr_holder_t name)
0484 {
0485 BOOST_ASSERT(!name.is_anonymous());
0486
0487 if(name.is_unique()){
0488 return this->priv_generic_named_destroy<T, char>(typeid(T).name(), m_header.m_unique_index);
0489 }
0490 else{
0491 return this->priv_generic_named_destroy<T, CharType>(name.get(), m_header.m_named_index);
0492 }
0493 }
0494
0495
0496
0497 template <class T>
0498 void destroy_ptr(const T *p)
0499 {
0500 priv_destroy_ptr(p);
0501 }
0502
0503
0504
0505 template<class T>
0506 static const CharType *get_instance_name(const T *ptr)
0507 { return priv_get_instance_name(block_header_t::block_header_from_value(ptr)); }
0508
0509
0510
0511 template<class T>
0512 static size_type get_instance_length(const T *ptr)
0513 { return priv_get_instance_length(block_header_t::block_header_from_value(ptr), sizeof(T)); }
0514
0515
0516
0517 template<class T>
0518 static instance_type get_instance_type(const T *ptr)
0519 { return priv_get_instance_type(block_header_t::block_header_from_value(ptr)); }
0520
0521
0522
0523
0524 void reserve_named_objects(size_type num)
0525 {
0526
0527 scoped_lock<rmutex> guard(m_header);
0528
0529 m_header.m_named_index.reserve(num);
0530 }
0531
0532
0533
0534
0535 void reserve_unique_objects(size_type num)
0536 {
0537
0538 scoped_lock<rmutex> guard(m_header);
0539
0540 m_header.m_unique_index.reserve(num);
0541 }
0542
0543
0544
0545 void shrink_to_fit_indexes()
0546 {
0547
0548 scoped_lock<rmutex> guard(m_header);
0549
0550 m_header.m_named_index.shrink_to_fit();
0551 m_header.m_unique_index.shrink_to_fit();
0552 }
0553
0554
0555
0556 size_type get_num_named_objects()
0557 {
0558
0559 scoped_lock<rmutex> guard(m_header);
0560
0561 return m_header.m_named_index.size();
0562 }
0563
0564
0565
0566 size_type get_num_unique_objects()
0567 {
0568
0569 scoped_lock<rmutex> guard(m_header);
0570
0571 return m_header.m_unique_index.size();
0572 }
0573
0574
0575
0576 static size_type get_min_size()
0577 { return segment_manager_base_t::get_min_size(priv_get_reserved_bytes()); }
0578
0579
0580
0581 const_named_iterator named_begin() const
0582 {
0583 return (make_transform_iterator)
0584 (m_header.m_named_index.begin(), named_transform());
0585 }
0586
0587
0588
0589 const_named_iterator named_end() const
0590 {
0591 return (make_transform_iterator)
0592 (m_header.m_named_index.end(), named_transform());
0593 }
0594
0595
0596
0597 const_unique_iterator unique_begin() const
0598 {
0599 return (make_transform_iterator)
0600 (m_header.m_unique_index.begin(), unique_transform());
0601 }
0602
0603
0604
0605 const_unique_iterator unique_end() const
0606 {
0607 return (make_transform_iterator)
0608 (m_header.m_unique_index.end(), unique_transform());
0609 }
0610
0611
0612
0613 template<class T>
0614 struct allocator
0615 {
0616 typedef boost::interprocess::allocator<T, segment_manager> type;
0617 };
0618
0619
0620
0621 template<class T>
0622 typename allocator<T>::type
0623 get_allocator()
0624 { return typename allocator<T>::type(this); }
0625
0626
0627
0628 template<class T>
0629 struct deleter
0630 {
0631 typedef boost::interprocess::deleter<T, segment_manager> type;
0632 };
0633
0634
0635
0636 template<class T>
0637 typename deleter<T>::type
0638 get_deleter()
0639 { return typename deleter<T>::type(this); }
0640
0641 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0642
0643
0644
0645
0646 template<class Proxy>
0647 typename Proxy::object_type * generic_construct
0648 (Proxy& pr, const CharType *name, size_type num, bool try2find, bool dothrow)
0649 {
0650 typedef typename Proxy::object_type object_type;
0651
0652
0653 if(num > ((size_type)-1)/sizeof(object_type)){
0654 return ipcdetail::null_or_bad_alloc<object_type>(dothrow);
0655 }
0656 if(name == 0){
0657 return this->priv_anonymous_construct(pr, num, dothrow);
0658 }
0659 else if(name == reinterpret_cast<const CharType*>(-1)){
0660 return this->priv_generic_named_construct
0661 (pr, unique_type, typeid(object_type).name(), num, try2find, dothrow, m_header.m_unique_index);
0662 }
0663 else{
0664 return this->priv_generic_named_construct
0665 (pr, named_type, name, num, try2find, dothrow, m_header.m_named_index);
0666 }
0667 }
0668
0669 private:
0670
0671
0672
0673 template <class T>
0674 std::pair<T*, size_type> priv_find_impl (const CharType* name, bool lock)
0675 {
0676
0677 BOOST_ASSERT(name != 0);
0678 size_type sz;
0679 void *ret;
0680
0681 if(name == reinterpret_cast<const CharType*>(-1)){
0682 ret = priv_generic_find<T>(typeid(T).name(), m_header.m_unique_index, sz, lock);
0683 }
0684 else{
0685 ret = priv_generic_find<T>(name, m_header.m_named_index, sz, lock);
0686 }
0687 return std::pair<T*, size_type>(static_cast<T*>(ret), sz);
0688 }
0689
0690
0691
0692
0693 template <class T>
0694 std::pair<T*, size_type> priv_find_impl (const ipcdetail::unique_instance_t*, bool lock)
0695 {
0696 size_type size;
0697 void *ret = priv_generic_find<T>(typeid(T).name(), m_header.m_unique_index, size, lock);
0698 return std::pair<T*, size_type>(static_cast<T*>(ret), size);
0699 }
0700
0701
0702 template<class Proxy>
0703 typename Proxy::object_type * priv_anonymous_construct(Proxy pr, size_type num, bool dothrow)
0704 {
0705 typedef typename Proxy::object_type object_type;
0706 BOOST_CONSTEXPR_OR_CONST std::size_t t_alignment = boost::move_detail::alignment_of<object_type>::value;
0707 block_header_t block_info ( size_type(sizeof(object_type)*num)
0708 , size_type(t_alignment)
0709 , anonymous_type
0710 , 1
0711 , 0);
0712
0713
0714 const std::size_t total_size = block_info.template total_anonymous_size<t_alignment>();
0715 #if (BOOST_INTERPROCESS_SEGMENT_MANAGER_ABI < 2)
0716 void *ptr_struct = this->allocate(total_size, nothrow<>::get());
0717 #else
0718 void* ptr_struct = this->allocate_aligned(total_size, t_alignment, nothrow<>::get());
0719 #endif
0720 if(!ptr_struct){
0721 return ipcdetail::null_or_bad_alloc<object_type>(dothrow);
0722 }
0723
0724
0725 ipcdetail::mem_algo_deallocator<segment_manager_base_type> mem
0726 (ptr_struct, *static_cast<segment_manager_base_type*>(this));
0727
0728
0729 const std::size_t front_space = block_header_t::template front_space_without_header<t_alignment>();
0730
0731 block_header_t * const hdr = ::new((char*)ptr_struct + front_space, boost_container_new_t()) block_header_t(block_info);
0732 BOOST_ASSERT(is_ptr_aligned(hdr));
0733 void *ptr = 0;
0734 ptr = hdr->value();
0735
0736
0737 pr.construct_n(ptr, num);
0738
0739
0740 mem.release();
0741 object_type* const pret = static_cast<object_type*>(ptr);
0742 BOOST_ASSERT(is_ptr_aligned(pret));
0743 return pret;
0744 }
0745
0746
0747 template <class T>
0748 void priv_anonymous_destroy(const T *object)
0749 {
0750 BOOST_ASSERT(is_ptr_aligned(object));
0751
0752 block_header_t *ctrl_data = block_header_t::block_header_from_value(object);
0753
0754
0755
0756
0757
0758
0759 BOOST_ASSERT(ctrl_data->alloc_type() == anonymous_type);
0760
0761
0762
0763 priv_destroy_n(object, ctrl_data->value_bytes()/sizeof(T));
0764
0765 BOOST_CONSTEXPR_OR_CONST std::size_t t_alignment =
0766 boost::move_detail::alignment_of<T>::value;
0767 const std::size_t front_space = block_header_t::template front_space_without_header<t_alignment>();
0768 this->deallocate((char*)ctrl_data - front_space);
0769 }
0770
0771 template<class T>
0772 void priv_destroy_ptr(const T *ptr)
0773 {
0774 BOOST_ASSERT(is_ptr_aligned(ptr));
0775 block_header_t *ctrl_data = block_header_t::block_header_from_value(ptr);
0776 switch(ctrl_data->alloc_type()){
0777 case anonymous_type:
0778 this->priv_anonymous_destroy(ptr);
0779 break;
0780
0781 case named_type:
0782 this->priv_generic_named_destroy<T, CharType>
0783 (ctrl_data, m_header.m_named_index, is_node_index_t());
0784 break;
0785
0786 case unique_type:
0787 this->priv_generic_named_destroy<T, char>
0788 (ctrl_data, m_header.m_unique_index, is_node_index_t());
0789 break;
0790
0791 default:
0792
0793 BOOST_ASSERT(0);
0794 break;
0795 }
0796 }
0797
0798 template<class T>
0799 static void priv_destroy_n(T* memory, std::size_t num)
0800 {
0801 for (std::size_t destroyed = 0; destroyed < num; ++destroyed)
0802 (memory++)->~T();
0803 }
0804
0805
0806
0807 static const CharType *priv_get_instance_name(block_header_t *ctrl_data)
0808 {
0809 boost::interprocess::allocation_type type = ctrl_data->alloc_type();
0810 if(type == anonymous_type){
0811 BOOST_ASSERT(ctrl_data->name_length() == 0);
0812 return 0;
0813 }
0814
0815 BOOST_ASSERT(ctrl_data->name_length() != 0);
0816 CharType *name = static_cast<CharType*>(ctrl_data->template name<CharType>());
0817
0818
0819 BOOST_ASSERT(ctrl_data->name_length() == std::char_traits<CharType>::length(name));
0820 return name;
0821 }
0822
0823 static size_type priv_get_instance_length(block_header_t *ctrl_data, size_type sizeofvalue)
0824 {
0825
0826 BOOST_ASSERT((ctrl_data->value_bytes() %sizeofvalue) == 0);
0827 return ctrl_data->value_bytes()/sizeofvalue;
0828 }
0829
0830
0831
0832 static instance_type priv_get_instance_type(block_header_t *ctrl_data)
0833 {
0834
0835 BOOST_ASSERT((instance_type)ctrl_data->alloc_type() < max_allocation_type);
0836 return (instance_type)ctrl_data->alloc_type();
0837 }
0838
0839 static size_type priv_get_reserved_bytes()
0840 {
0841
0842
0843 return sizeof(segment_manager) - sizeof(segment_manager_base_t);
0844 }
0845
0846 template <class T, class CharT>
0847 T *priv_generic_find
0848 (const CharT* name,
0849 IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
0850 size_type &length, bool use_lock)
0851 {
0852 typedef IndexType<ipcdetail::index_config
0853 <CharT, MemoryAlgorithm> > index_t;
0854 typedef typename index_t::iterator index_it;
0855 typedef typename index_t::compare_key_type compare_key_t;
0856
0857
0858 scoped_lock<rmutex> guard(priv_get_lock(use_lock));
0859
0860
0861 compare_key_t key (name, std::char_traits<CharT>::length(name));
0862 index_it it = index.find(key);
0863
0864
0865 void *ret_ptr = 0;
0866 length = 0;
0867
0868
0869 if(it != index.end()){
0870
0871 block_header_t *ctrl_data = priv_block_header_from_it(it, is_intrusive_t());
0872
0873
0874 BOOST_ASSERT((ctrl_data->value_bytes() % sizeof(T)) == 0);
0875 ret_ptr = ctrl_data->value();
0876 length = ctrl_data->value_bytes()/ sizeof(T);
0877 }
0878 return static_cast<T*>(ret_ptr);
0879 }
0880
0881 template <class T, class CharT>
0882 bool priv_generic_named_destroy
0883 (block_header_t *block_header
0884 ,IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index
0885 ,ipcdetail::true_ is_node_index)
0886 {
0887 (void)is_node_index;
0888 typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_t;
0889 typedef typename index_t::index_data_t index_data_t;
0890
0891 index_data_t* si = block_header_t::template to_first_header<index_data_t>(block_header);
0892 return this->priv_generic_named_destroy_impl<T, CharT>(*si, index);
0893 }
0894
0895 template <class T, class CharT>
0896 bool priv_generic_named_destroy
0897 (block_header_t *block_header
0898 ,IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index
0899 ,ipcdetail::false_ is_node_index)
0900 {
0901 (void)is_node_index;
0902 CharT *name = static_cast<CharT*>(block_header->template name<CharT>());
0903 return this->priv_generic_named_destroy<T, CharT>(name, index);
0904 }
0905
0906 template <class T, class CharT>
0907 bool priv_generic_named_destroy(const CharT *name,
0908 IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index)
0909 {
0910 typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_t;
0911 typedef typename index_t::iterator index_it;
0912 typedef typename index_t::compare_key_type compare_key_t;
0913
0914
0915 scoped_lock<rmutex> guard(m_header);
0916
0917
0918 compare_key_t key(name, std::char_traits<CharT>::length(name));
0919 index_it it = index.find(key);
0920
0921
0922 if(it == index.end()){
0923
0924
0925 return false;
0926 }
0927 return this->priv_generic_named_destroy_impl<T, CharT>(it, index);
0928 }
0929
0930 template <class T, class CharT>
0931 bool priv_generic_named_destroy_impl
0932 (typename IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> >::iterator it,
0933 IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index)
0934 {
0935 typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_t;
0936 typedef typename index_t::index_data_t index_data_t;
0937
0938
0939 BOOST_CONSTEXPR_OR_CONST std::size_t t_alignment =
0940 boost::move_detail::alignment_of<T>::value;
0941 block_header_t *ctrl_data = priv_block_header_from_it(it, is_intrusive_t());
0942
0943
0944 BOOST_ASSERT((ctrl_data->value_bytes() % sizeof(T)) == 0);
0945
0946
0947 index.erase(it);
0948
0949 void *memory;
0950 BOOST_IF_CONSTEXPR(is_node_index_t::value || is_intrusive_t::value){
0951 index_data_t*ihdr = block_header_t::template to_first_header<index_data_t>(ctrl_data);
0952 const std::size_t front_space = block_header_t::template front_space_with_header<t_alignment, index_data_t>();
0953 memory = (char*)ihdr - front_space;
0954 ihdr->~index_data_t();
0955 }
0956 else{
0957 const std::size_t front_space = block_header_t::template front_space_without_header<t_alignment>();
0958 memory = (char*)ctrl_data - front_space;
0959 }
0960
0961
0962 priv_destroy_n(static_cast<T*>(ctrl_data->value()), ctrl_data->value_bytes()/sizeof(T));
0963
0964
0965 ctrl_data->~block_header_t();
0966
0967 this->deallocate(memory);
0968 return true;
0969 }
0970
0971 template<class IndexIt>
0972 static block_header_t* priv_block_header_from_it(IndexIt it, ipcdetail::true_)
0973 { return block_header_t::from_first_header(&*it); }
0974
0975 template<class IndexIt>
0976 static block_header_t* priv_block_header_from_it(IndexIt it, ipcdetail::false_ )
0977 {
0978 return static_cast<block_header_t*>(ipcdetail::to_raw_pointer(it->second.m_ptr));
0979 }
0980
0981
0982
0983 template<class Proxy, class CharT>
0984 typename Proxy::object_type * priv_generic_named_construct
0985 (Proxy pr, unsigned char type, const CharT *name, size_type num, bool try2find, bool dothrow,
0986 IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index)
0987 {
0988 typedef typename Proxy::object_type object_type;
0989 std::size_t namelen = std::char_traits<CharT>::length(name);
0990 BOOST_CONSTEXPR_OR_CONST std::size_t t_alignment = boost::move_detail::alignment_of<object_type>::value;
0991
0992 block_header_t block_info ( size_type(sizeof(object_type)*num)
0993 , size_type(t_alignment)
0994 , type
0995 , sizeof(CharT)
0996 , namelen);
0997
0998 typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_t;
0999 typedef typename index_t::iterator index_it;
1000 typedef typename index_t::compare_key_type compare_key_t;
1001 typedef typename index_t::insert_commit_data commit_data_t;
1002 typedef typename index_t::index_data_t index_data_t;
1003
1004
1005 scoped_lock<rmutex> guard(m_header);
1006
1007
1008
1009
1010
1011 index_it existing_it;
1012 bool found = false;
1013
1014 commit_data_t commit_data;
1015 BOOST_INTERPROCESS_TRY{
1016 typedef std::pair<index_it, bool> index_ib;
1017 index_ib insert_ret = index.insert_check(compare_key_t(name, namelen), commit_data);
1018 existing_it = insert_ret.first;
1019 found = !insert_ret.second;
1020 }
1021
1022 BOOST_INTERPROCESS_CATCH(...){
1023 if(dothrow)
1024 BOOST_INTERPROCESS_RETHROW
1025 return 0;
1026 }
1027 BOOST_INTERPROCESS_CATCH_END
1028
1029
1030 if(found){
1031 if(try2find){
1032 return static_cast<object_type*>(priv_block_header_from_it(existing_it, is_intrusive_t())->value());
1033 }
1034 return ipcdetail::null_or_already_exists<object_type>(dothrow);
1035 }
1036
1037
1038 void *buffer_ptr;
1039 block_header_t * hdr;
1040 std::size_t front_space;
1041
1042
1043 BOOST_IF_CONSTEXPR(is_node_index_t::value || is_intrusive_t::value){
1044 const size_type total_size = block_info.template total_named_size_with_header<t_alignment, CharT, index_data_t>(namelen);
1045 #if (BOOST_INTERPROCESS_SEGMENT_MANAGER_ABI < 2)
1046 buffer_ptr = this->allocate(total_size, nothrow<>::get());
1047 #else
1048 buffer_ptr = this->allocate_aligned(total_size, t_alignment, nothrow<>::get());
1049 #endif
1050
1051 if(!buffer_ptr)
1052 return ipcdetail::null_or_bad_alloc<object_type>(dothrow);
1053
1054 front_space = block_header_t::template front_space_with_header<t_alignment, index_data_t>();
1055 hdr = block_header_t::template from_first_header(reinterpret_cast<index_data_t*>((void*)((char*)buffer_ptr + front_space)));
1056 }
1057 else{
1058 const size_type total_size = block_info.template total_named_size<t_alignment, CharT>(namelen);
1059 #if (BOOST_INTERPROCESS_SEGMENT_MANAGER_ABI < 2)
1060 buffer_ptr = this->allocate(total_size, nothrow<>::get());
1061 #else
1062 buffer_ptr = this->allocate_aligned(total_size, t_alignment, nothrow<>::get());
1063 #endif
1064
1065 front_space = block_header_t::template front_space_without_header<t_alignment>();
1066
1067
1068 if (!buffer_ptr)
1069 return ipcdetail::null_or_bad_alloc<object_type>(dothrow);
1070 hdr = reinterpret_cast<block_header_t*>((void*)((char*)buffer_ptr + front_space));
1071 }
1072
1073 BOOST_ASSERT(is_ptr_aligned(hdr));
1074 hdr = ::new(hdr, boost_container_new_t()) block_header_t(block_info);
1075
1076
1077 ipcdetail::mem_algo_deallocator<segment_manager_base_type> mem
1078 (buffer_ptr, *static_cast<segment_manager_base_type*>(this));
1079
1080 void *ptr = hdr->value();
1081
1082
1083 hdr->store_name_length(static_cast<typename block_header_t::name_len_t>(namelen));
1084 CharT *name_ptr = static_cast<CharT *>(hdr->template name<CharT>());
1085 std::char_traits<CharT>::copy(name_ptr, name, namelen+1);
1086
1087 index_it it;
1088 BOOST_INTERPROCESS_TRY{
1089 BOOST_IF_CONSTEXPR(is_node_index_t::value || is_intrusive_t::value) {
1090 index_data_t* index_data = ::new((char*)buffer_ptr + front_space, boost_container_new_t()) index_data_t();
1091 BOOST_ASSERT(is_ptr_aligned(index_data));
1092 it = index.insert_commit(compare_key_t(name_ptr, namelen), hdr, *index_data, commit_data);
1093 }
1094 else{
1095 index_data_t id;
1096 it = index.insert_commit(compare_key_t(name_ptr, namelen), hdr, id, commit_data);
1097 }
1098 }
1099
1100 BOOST_INTERPROCESS_CATCH(...){
1101 if(dothrow)
1102 BOOST_INTERPROCESS_RETHROW
1103 return 0;
1104 }
1105 BOOST_INTERPROCESS_CATCH_END
1106
1107
1108
1109 value_eraser<index_t> v_eraser(index, it);
1110
1111
1112 pr.construct_n(ptr, num);
1113
1114
1115 v_eraser.release();
1116 mem.release();
1117 object_type* const pret = static_cast<object_type*>(ptr);
1118 BOOST_ASSERT(is_ptr_aligned(pret));
1119 return pret;
1120 }
1121
1122 private:
1123
1124 segment_manager *get_this_pointer()
1125 { return this; }
1126
1127 typedef typename MemoryAlgorithm::mutex_family::recursive_mutex_type rmutex;
1128
1129 scoped_lock<rmutex> priv_get_lock(bool use_lock)
1130 {
1131 scoped_lock<rmutex> local(m_header, defer_lock);
1132 if(use_lock){
1133 local.lock();
1134 }
1135 return scoped_lock<rmutex>(boost::move(local));
1136 }
1137
1138
1139
1140 struct header_t
1141 : public rmutex
1142 {
1143 named_index_t m_named_index;
1144 unique_index_t m_unique_index;
1145
1146 header_t(segment_manager_base_t *segment_mngr_base)
1147 : m_named_index (segment_mngr_base)
1148 , m_unique_index(segment_mngr_base)
1149 {}
1150 } m_header;
1151
1152 #endif
1153 };
1154
1155
1156 }}
1157
1158 #include <boost/interprocess/detail/config_end.hpp>
1159
1160 #endif
1161