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