File indexing completed on 2025-07-05 08:35:59
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/core/no_exceptions_support.hpp>
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 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 { MemoryAlgorithm::grow(extra_size); }
0248
0249
0250
0251 void shrink_to_fit()
0252 { MemoryAlgorithm::shrink_to_fit(); }
0253
0254
0255
0256 bool all_memory_deallocated()
0257 { return MemoryAlgorithm::all_memory_deallocated(); }
0258
0259
0260
0261 bool check_sanity()
0262 { return MemoryAlgorithm::check_sanity(); }
0263
0264
0265
0266 void zero_free_memory()
0267 { MemoryAlgorithm::zero_free_memory(); }
0268
0269
0270 size_type size(const void *ptr) const
0271 { return MemoryAlgorithm::size(ptr); }
0272
0273 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0274 protected:
0275 void * prot_anonymous_construct
0276 (size_type num, bool dothrow, ipcdetail::in_place_interface &table)
0277 {
0278 typedef ipcdetail::block_header<size_type> block_header_t;
0279 block_header_t block_info ( size_type(table.size*num)
0280 , size_type(table.alignment)
0281 , anonymous_type
0282 , 1
0283 , 0);
0284
0285
0286 void *ptr_struct = this->allocate(block_info.total_size(), nothrow<>::get());
0287
0288
0289 if(!ptr_struct){
0290 if(dothrow){
0291 throw bad_alloc();
0292 }
0293 else{
0294 return 0;
0295 }
0296 }
0297
0298
0299 ipcdetail::mem_algo_deallocator<MemoryAlgorithm> mem(ptr_struct, *this);
0300
0301
0302 block_header_t * hdr = ::new(ptr_struct, boost_container_new_t()) block_header_t(block_info);
0303 void *ptr = 0;
0304 ptr = hdr->value();
0305
0306
0307 table.construct_n(ptr, num);
0308
0309
0310 mem.release();
0311 return ptr;
0312 }
0313
0314
0315 void prot_anonymous_destroy(const void *object, ipcdetail::in_place_interface &table)
0316 {
0317
0318
0319 typedef ipcdetail::block_header<size_type> block_header_t;
0320 block_header_t *ctrl_data = block_header_t::block_header_from_value(object, table.size, table.alignment);
0321
0322
0323
0324
0325
0326 if(ctrl_data->alloc_type() != anonymous_type){
0327
0328 BOOST_ASSERT(0);
0329 }
0330
0331
0332
0333 table.destroy_n(const_cast<void*>(object), ctrl_data->m_value_bytes/table.size);
0334 this->deallocate(ctrl_data);
0335 }
0336 #endif
0337 };
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355 template<class CharType
0356 ,class MemoryAlgorithm
0357 ,template<class IndexConfig> class IndexType>
0358 class segment_manager
0359 : public segment_manager_base<MemoryAlgorithm>
0360 {
0361 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0362
0363 segment_manager();
0364 segment_manager(const segment_manager &);
0365 segment_manager &operator=(const segment_manager &);
0366 typedef segment_manager_base<MemoryAlgorithm> segment_manager_base_t;
0367 #endif
0368
0369 public:
0370 typedef MemoryAlgorithm memory_algorithm;
0371 typedef typename segment_manager_base_t::void_pointer void_pointer;
0372 typedef typename segment_manager_base_t::size_type size_type;
0373 typedef typename segment_manager_base_t::difference_type difference_type;
0374 typedef CharType char_type;
0375
0376 typedef segment_manager_base<MemoryAlgorithm> segment_manager_base_type;
0377
0378 static const size_type PayloadPerAllocation = segment_manager_base_t::PayloadPerAllocation;
0379
0380 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0381 private:
0382 typedef ipcdetail::block_header<size_type> block_header_t;
0383 typedef ipcdetail::index_config<CharType, MemoryAlgorithm> index_config_named;
0384 typedef ipcdetail::index_config<char, MemoryAlgorithm> index_config_unique;
0385 typedef IndexType<index_config_named> index_type;
0386 typedef ipcdetail::bool_<is_intrusive_index<index_type>::value > is_intrusive_t;
0387 typedef ipcdetail::bool_<is_node_index<index_type>::value> is_node_index_t;
0388
0389 public:
0390 typedef IndexType<index_config_named> named_index_t;
0391 typedef IndexType<index_config_unique> unique_index_t;
0392 typedef ipcdetail::char_ptr_holder<CharType> char_ptr_holder_t;
0393 typedef ipcdetail::segment_manager_iterator_transform
0394 <typename named_index_t::const_iterator
0395 ,is_intrusive_index<index_type>::value> named_transform;
0396
0397 typedef ipcdetail::segment_manager_iterator_transform
0398 <typename unique_index_t::const_iterator
0399 ,is_intrusive_index<index_type>::value> unique_transform;
0400 #endif
0401
0402 typedef typename segment_manager_base_t::mutex_family mutex_family;
0403
0404 typedef transform_iterator
0405 <typename named_index_t::const_iterator, named_transform> const_named_iterator;
0406 typedef transform_iterator
0407 <typename unique_index_t::const_iterator, unique_transform> const_unique_iterator;
0408
0409 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0410
0411
0412 template<class T>
0413 struct construct_proxy
0414 {
0415 typedef ipcdetail::named_proxy<segment_manager, T, false> type;
0416 };
0417
0418
0419 template<class T>
0420 struct construct_iter_proxy
0421 {
0422 typedef ipcdetail::named_proxy<segment_manager, T, true> type;
0423 };
0424
0425 #endif
0426
0427
0428
0429
0430
0431 explicit segment_manager(size_type segment_size)
0432 : segment_manager_base_t(segment_size, priv_get_reserved_bytes())
0433 , m_header(static_cast<segment_manager_base_t*>(get_this_pointer()))
0434 {
0435 (void) anonymous_instance; (void) unique_instance;
0436
0437 const void * const this_addr = this;
0438 const void *const segm_addr = static_cast<segment_manager_base_t*>(this);
0439 (void)this_addr; (void)segm_addr;
0440 BOOST_ASSERT( this_addr == segm_addr);
0441 const std::size_t void_ptr_alignment = boost::move_detail::alignment_of<void_pointer>::value; (void)void_ptr_alignment;
0442 BOOST_ASSERT((0 == (std::size_t)this_addr % boost::move_detail::alignment_of<segment_manager>::value));
0443 }
0444
0445
0446
0447
0448 template <class T>
0449 std::pair<T*, size_type> find (char_ptr_holder_t name)
0450 { return this->priv_find_impl<T>(name, true); }
0451
0452
0453
0454
0455
0456
0457 template <class T>
0458 std::pair<T*, size_type> find_no_lock (char_ptr_holder_t name)
0459 { return this->priv_find_impl<T>(name, false); }
0460
0461
0462
0463 template <class T>
0464 typename construct_proxy<T>::type
0465 construct(char_ptr_holder_t name)
0466 { return typename construct_proxy<T>::type (this, name, false, true); }
0467
0468
0469
0470 template <class T>
0471 typename construct_proxy<T>::type find_or_construct(char_ptr_holder_t name)
0472 { return typename construct_proxy<T>::type (this, name, true, true); }
0473
0474
0475
0476 template <class T>
0477 typename construct_proxy<T>::type
0478 construct(char_ptr_holder_t name, const std::nothrow_t &)
0479 { return typename construct_proxy<T>::type (this, name, false, false); }
0480
0481
0482
0483 template <class T>
0484 typename construct_proxy<T>::type
0485 find_or_construct(char_ptr_holder_t name, const std::nothrow_t &)
0486 { return typename construct_proxy<T>::type (this, name, true, false); }
0487
0488
0489 template <class T>
0490 typename construct_iter_proxy<T>::type
0491 construct_it(char_ptr_holder_t name)
0492 { return typename construct_iter_proxy<T>::type (this, name, false, true); }
0493
0494
0495
0496 template <class T>
0497 typename construct_iter_proxy<T>::type
0498 find_or_construct_it(char_ptr_holder_t name)
0499 { return typename construct_iter_proxy<T>::type (this, name, true, true); }
0500
0501
0502
0503 template <class T>
0504 typename construct_iter_proxy<T>::type
0505 construct_it(char_ptr_holder_t name, const std::nothrow_t &)
0506 { return typename construct_iter_proxy<T>::type (this, name, false, false); }
0507
0508
0509
0510 template <class T>
0511 typename construct_iter_proxy<T>::type
0512 find_or_construct_it(char_ptr_holder_t name, const std::nothrow_t &)
0513 { return typename construct_iter_proxy<T>::type (this, name, true, false); }
0514
0515
0516
0517
0518 template <class Func>
0519 void atomic_func(Func &f)
0520 { scoped_lock<rmutex> guard(m_header); f(); }
0521
0522
0523
0524
0525
0526
0527 template <class Func>
0528 bool try_atomic_func(Func &f)
0529 {
0530 scoped_lock<rmutex> guard(m_header, try_to_lock);
0531 if(guard){
0532 f();
0533 return true;
0534 }
0535 else{
0536 return false;
0537 }
0538 }
0539
0540
0541
0542 template <class T>
0543 bool destroy(char_ptr_holder_t name)
0544 {
0545 BOOST_ASSERT(!name.is_anonymous());
0546 ipcdetail::placement_destroy<T> dtor;
0547
0548 if(name.is_unique()){
0549 return this->priv_generic_named_destroy<char>
0550 ( typeid(T).name(), m_header.m_unique_index , dtor, is_intrusive_t());
0551 }
0552 else{
0553 return this->priv_generic_named_destroy<CharType>
0554 ( name.get(), m_header.m_named_index, dtor, is_intrusive_t());
0555 }
0556 }
0557
0558
0559
0560 template <class T>
0561 void destroy_ptr(const T *p)
0562 {
0563
0564 typedef typename ipcdetail::char_if_void<T>::type data_t;
0565 ipcdetail::placement_destroy<data_t> dtor;
0566 priv_destroy_ptr(p, dtor);
0567 }
0568
0569
0570
0571 template<class T>
0572 static const CharType *get_instance_name(const T *ptr)
0573 { return priv_get_instance_name(block_header_t::block_header_from_value(ptr)); }
0574
0575
0576
0577 template<class T>
0578 static size_type get_instance_length(const T *ptr)
0579 { return priv_get_instance_length(block_header_t::block_header_from_value(ptr), sizeof(T)); }
0580
0581
0582
0583 template<class T>
0584 static instance_type get_instance_type(const T *ptr)
0585 { return priv_get_instance_type(block_header_t::block_header_from_value(ptr)); }
0586
0587
0588
0589
0590 void reserve_named_objects(size_type num)
0591 {
0592
0593 scoped_lock<rmutex> guard(m_header);
0594
0595 m_header.m_named_index.reserve(num);
0596 }
0597
0598
0599
0600
0601 void reserve_unique_objects(size_type num)
0602 {
0603
0604 scoped_lock<rmutex> guard(m_header);
0605
0606 m_header.m_unique_index.reserve(num);
0607 }
0608
0609
0610
0611 void shrink_to_fit_indexes()
0612 {
0613
0614 scoped_lock<rmutex> guard(m_header);
0615
0616 m_header.m_named_index.shrink_to_fit();
0617 m_header.m_unique_index.shrink_to_fit();
0618 }
0619
0620
0621
0622 size_type get_num_named_objects()
0623 {
0624
0625 scoped_lock<rmutex> guard(m_header);
0626
0627 return m_header.m_named_index.size();
0628 }
0629
0630
0631
0632 size_type get_num_unique_objects()
0633 {
0634
0635 scoped_lock<rmutex> guard(m_header);
0636
0637 return m_header.m_unique_index.size();
0638 }
0639
0640
0641
0642 static size_type get_min_size()
0643 { return segment_manager_base_t::get_min_size(priv_get_reserved_bytes()); }
0644
0645
0646
0647 const_named_iterator named_begin() const
0648 {
0649 return (make_transform_iterator)
0650 (m_header.m_named_index.begin(), named_transform());
0651 }
0652
0653
0654
0655 const_named_iterator named_end() const
0656 {
0657 return (make_transform_iterator)
0658 (m_header.m_named_index.end(), named_transform());
0659 }
0660
0661
0662
0663 const_unique_iterator unique_begin() const
0664 {
0665 return (make_transform_iterator)
0666 (m_header.m_unique_index.begin(), unique_transform());
0667 }
0668
0669
0670
0671 const_unique_iterator unique_end() const
0672 {
0673 return (make_transform_iterator)
0674 (m_header.m_unique_index.end(), unique_transform());
0675 }
0676
0677
0678
0679 template<class T>
0680 struct allocator
0681 {
0682 typedef boost::interprocess::allocator<T, segment_manager> type;
0683 };
0684
0685
0686
0687 template<class T>
0688 typename allocator<T>::type
0689 get_allocator()
0690 { return typename allocator<T>::type(this); }
0691
0692
0693
0694 template<class T>
0695 struct deleter
0696 {
0697 typedef boost::interprocess::deleter<T, segment_manager> type;
0698 };
0699
0700
0701
0702 template<class T>
0703 typename deleter<T>::type
0704 get_deleter()
0705 { return typename deleter<T>::type(this); }
0706
0707 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0708
0709
0710
0711
0712 template<class T>
0713 T *generic_construct(const CharType *name,
0714 size_type num,
0715 bool try2find,
0716 bool dothrow,
0717 ipcdetail::in_place_interface &table)
0718 {
0719 return static_cast<T*>
0720 (priv_generic_construct(name, num, try2find, dothrow, table));
0721 }
0722
0723 private:
0724
0725
0726
0727 template <class T>
0728 std::pair<T*, size_type> priv_find_impl (const CharType* name, bool lock)
0729 {
0730
0731 BOOST_ASSERT(name != 0);
0732 ipcdetail::placement_destroy<T> table;
0733 size_type sz;
0734 void *ret;
0735
0736 if(name == reinterpret_cast<const CharType*>(-1)){
0737 ret = priv_generic_find<char> (typeid(T).name(), m_header.m_unique_index, table, sz, is_intrusive_t(), lock);
0738 }
0739 else{
0740 ret = priv_generic_find<CharType> (name, m_header.m_named_index, table, sz, is_intrusive_t(), lock);
0741 }
0742 return std::pair<T*, size_type>(static_cast<T*>(ret), sz);
0743 }
0744
0745
0746
0747
0748 template <class T>
0749 std::pair<T*, size_type> priv_find_impl (const ipcdetail::unique_instance_t* name, bool lock)
0750 {
0751 ipcdetail::placement_destroy<T> table;
0752 size_type size;
0753 void *ret = priv_generic_find<char>(name, m_header.m_unique_index, table, size, is_intrusive_t(), lock);
0754 return std::pair<T*, size_type>(static_cast<T*>(ret), size);
0755 }
0756
0757 void *priv_generic_construct
0758 (const CharType *name, size_type num, bool try2find, bool dothrow, ipcdetail::in_place_interface &table)
0759 {
0760 void *ret;
0761
0762 if(num > ((std::size_t)-1)/table.size){
0763 if(dothrow)
0764 throw bad_alloc();
0765 else
0766 return 0;
0767 }
0768 if(name == 0){
0769 ret = this->prot_anonymous_construct(num, dothrow, table);
0770 }
0771 else if(name == reinterpret_cast<const CharType*>(-1)){
0772 ret = this->priv_generic_named_construct<char>
0773 (unique_type, table.type_name, num, try2find, dothrow, table, m_header.m_unique_index, is_intrusive_t());
0774 }
0775 else{
0776 ret = this->priv_generic_named_construct<CharType>
0777 (named_type, name, num, try2find, dothrow, table, m_header.m_named_index, is_intrusive_t());
0778 }
0779 return ret;
0780 }
0781
0782 void priv_destroy_ptr(const void *ptr, ipcdetail::in_place_interface &dtor)
0783 {
0784 block_header_t *ctrl_data = block_header_t::block_header_from_value(ptr, dtor.size, dtor.alignment);
0785 switch(ctrl_data->alloc_type()){
0786 case anonymous_type:
0787 this->prot_anonymous_destroy(ptr, dtor);
0788 break;
0789
0790 case named_type:
0791 this->priv_generic_named_destroy<CharType>
0792 (ctrl_data, m_header.m_named_index, dtor, is_node_index_t());
0793 break;
0794
0795 case unique_type:
0796 this->priv_generic_named_destroy<char>
0797 (ctrl_data, m_header.m_unique_index, dtor, is_node_index_t());
0798 break;
0799
0800 default:
0801
0802 BOOST_ASSERT(0);
0803 break;
0804 }
0805 }
0806
0807
0808
0809 static const CharType *priv_get_instance_name(block_header_t *ctrl_data)
0810 {
0811 boost::interprocess::allocation_type type = ctrl_data->alloc_type();
0812 if(type == anonymous_type){
0813 BOOST_ASSERT((type == anonymous_type && ctrl_data->m_num_char == 0) ||
0814 (type == unique_type && ctrl_data->m_num_char != 0) );
0815 return 0;
0816 }
0817 CharType *name = static_cast<CharType*>(ctrl_data->template name<CharType>());
0818
0819
0820 BOOST_ASSERT(ctrl_data->sizeof_char() == sizeof(CharType));
0821 BOOST_ASSERT(ctrl_data->m_num_char == std::char_traits<CharType>::length(name));
0822 return name;
0823 }
0824
0825 static size_type priv_get_instance_length(block_header_t *ctrl_data, size_type sizeofvalue)
0826 {
0827
0828 BOOST_ASSERT((ctrl_data->value_bytes() %sizeofvalue) == 0);
0829 return ctrl_data->value_bytes()/sizeofvalue;
0830 }
0831
0832
0833
0834 static instance_type priv_get_instance_type(block_header_t *ctrl_data)
0835 {
0836
0837 BOOST_ASSERT((instance_type)ctrl_data->alloc_type() < max_allocation_type);
0838 return (instance_type)ctrl_data->alloc_type();
0839 }
0840
0841 static size_type priv_get_reserved_bytes()
0842 {
0843
0844
0845 return sizeof(segment_manager) - sizeof(segment_manager_base_t);
0846 }
0847
0848 template <class CharT>
0849 void *priv_generic_find
0850 (const CharT* name,
0851 IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
0852 ipcdetail::in_place_interface &table,
0853 size_type &length, ipcdetail::true_ is_intrusive, bool use_lock)
0854 {
0855 (void)is_intrusive;
0856 typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type_t;
0857 typedef typename index_type_t::iterator index_it;
0858
0859
0860 scoped_lock<rmutex> guard(priv_get_lock(use_lock));
0861
0862
0863 ipcdetail::intrusive_compare_key<CharT> key
0864 (name, std::char_traits<CharT>::length(name));
0865 index_it it = index.find(key);
0866
0867
0868 void *ret_ptr = 0;
0869 length = 0;
0870
0871
0872 if(it != index.end()){
0873
0874 block_header_t *ctrl_data = it->get_block_header();
0875
0876
0877 BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0);
0878 BOOST_ASSERT(ctrl_data->sizeof_char() == sizeof(CharT));
0879 ret_ptr = ctrl_data->value();
0880 length = ctrl_data->m_value_bytes/table.size;
0881 }
0882 return ret_ptr;
0883 }
0884
0885 template <class CharT>
0886 void *priv_generic_find
0887 (const CharT* name,
0888 IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
0889 ipcdetail::in_place_interface &table,
0890 size_type &length, ipcdetail::false_ is_intrusive, bool use_lock)
0891 {
0892 (void)is_intrusive;
0893 typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > char_aware_index_type;
0894 typedef typename char_aware_index_type::key_type key_type;
0895 typedef typename char_aware_index_type::iterator index_it;
0896
0897
0898 scoped_lock<rmutex> guard(priv_get_lock(use_lock));
0899
0900
0901 index_it it = index.find(key_type(name, std::char_traits<CharT>::length(name)));
0902
0903
0904 void *ret_ptr = 0;
0905 length = 0;
0906
0907
0908 if(it != index.end()){
0909
0910 block_header_t *ctrl_data = reinterpret_cast<block_header_t*>
0911 (ipcdetail::to_raw_pointer(it->second.m_ptr));
0912
0913
0914 BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0);
0915 BOOST_ASSERT(ctrl_data->sizeof_char() == sizeof(CharT));
0916 ret_ptr = ctrl_data->value();
0917 length = ctrl_data->m_value_bytes/table.size;
0918 }
0919 return ret_ptr;
0920 }
0921
0922 template <class CharT>
0923 bool priv_generic_named_destroy
0924 (block_header_t *block_header,
0925 IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
0926 ipcdetail::in_place_interface &table, ipcdetail::true_ is_node_index)
0927 {
0928 (void)is_node_index;
0929 typedef typename IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> >::iterator index_it;
0930
0931 index_it *ihdr = block_header_t::template to_first_header<index_it>(block_header);
0932 return this->priv_generic_named_destroy_impl<CharT>(*ihdr, index, table);
0933 }
0934
0935 template <class CharT>
0936 bool priv_generic_named_destroy
0937 (block_header_t *block_header,
0938 IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
0939 ipcdetail::in_place_interface &table,
0940 ipcdetail::false_ is_node_index)
0941 {
0942 (void)is_node_index;
0943 CharT *name = static_cast<CharT*>(block_header->template name<CharT>());
0944 return this->priv_generic_named_destroy<CharT>(name, index, table, is_intrusive_t());
0945 }
0946
0947 template <class CharT>
0948 bool priv_generic_named_destroy(const CharT *name,
0949 IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
0950 ipcdetail::in_place_interface &table, ipcdetail::true_ is_intrusive_index)
0951 {
0952 (void)is_intrusive_index;
0953 typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type_t;
0954 typedef typename index_type_t::iterator index_it;
0955 typedef typename index_type_t::value_type intrusive_value_type;
0956
0957
0958 scoped_lock<rmutex> guard(m_header);
0959
0960
0961 ipcdetail::intrusive_compare_key<CharT> key
0962 (name, std::char_traits<CharT>::length(name));
0963 index_it it = index.find(key);
0964
0965
0966 if(it == index.end()){
0967
0968
0969 return false;
0970 }
0971
0972 block_header_t *ctrl_data = it->get_block_header();
0973 intrusive_value_type *iv = intrusive_value_type::get_intrusive_value_type(ctrl_data);
0974 void *memory = iv;
0975 void *values = ctrl_data->value();
0976 std::size_t num = ctrl_data->m_value_bytes/table.size;
0977
0978
0979 BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0);
0980 BOOST_ASSERT(sizeof(CharT) == ctrl_data->sizeof_char());
0981
0982
0983 index.erase(it);
0984
0985
0986 ctrl_data->~block_header_t();
0987 iv->~intrusive_value_type();
0988
0989
0990 table.destroy_n(values, num);
0991 this->deallocate(memory);
0992 return true;
0993 }
0994
0995 template <class CharT>
0996 bool priv_generic_named_destroy(const CharT *name,
0997 IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
0998 ipcdetail::in_place_interface &table,
0999 ipcdetail::false_ is_intrusive_index)
1000 {
1001 (void)is_intrusive_index;
1002 typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > char_aware_index_type;
1003 typedef typename char_aware_index_type::iterator index_it;
1004 typedef typename char_aware_index_type::key_type key_type;
1005
1006
1007 scoped_lock<rmutex> guard(m_header);
1008
1009
1010 index_it it = index.find(key_type (name,
1011 std::char_traits<CharT>::length(name)));
1012
1013
1014 if(it == index.end()){
1015
1016
1017 return false;
1018 }
1019 return this->priv_generic_named_destroy_impl<CharT>(it, index, table);
1020 }
1021
1022 template <class CharT>
1023 bool priv_generic_named_destroy_impl
1024 (const typename IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> >::iterator &it,
1025 IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
1026 ipcdetail::in_place_interface &table)
1027 {
1028 typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > char_aware_index_type;
1029 typedef typename char_aware_index_type::iterator index_it;
1030
1031
1032 block_header_t *ctrl_data = reinterpret_cast<block_header_t*>
1033 (ipcdetail::to_raw_pointer(it->second.m_ptr));
1034 char *stored_name = static_cast<char*>(static_cast<void*>(const_cast<CharT*>(it->first.name())));
1035 (void)stored_name;
1036
1037
1038
1039 std::size_t num = ctrl_data->m_value_bytes/table.size;
1040 void *values = ctrl_data->value();
1041
1042
1043 BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0);
1044 BOOST_ASSERT(static_cast<void*>(stored_name) == static_cast<void*>(ctrl_data->template name<CharT>()));
1045 BOOST_ASSERT(sizeof(CharT) == ctrl_data->sizeof_char());
1046
1047
1048 index.erase(it);
1049
1050
1051 ctrl_data->~block_header_t();
1052
1053 void *memory;
1054 if(is_node_index_t::value){
1055 index_it *ihdr = block_header_t::template
1056 to_first_header<index_it>(ctrl_data);
1057 ihdr->~index_it();
1058 memory = ihdr;
1059 }
1060 else{
1061 memory = ctrl_data;
1062 }
1063
1064
1065 table.destroy_n(values, num);
1066 this->deallocate(memory);
1067 return true;
1068 }
1069
1070 template<class CharT>
1071 void * priv_generic_named_construct
1072 (unsigned char type, const CharT *name, size_type num, bool try2find,
1073 bool dothrow, ipcdetail::in_place_interface &table,
1074 IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index, ipcdetail::true_ is_intrusive)
1075 {
1076 (void)is_intrusive;
1077 std::size_t namelen = std::char_traits<CharT>::length(name);
1078
1079 block_header_t block_info ( size_type(table.size*num)
1080 , size_type(table.alignment)
1081 , type
1082 , sizeof(CharT)
1083 , namelen);
1084
1085 typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type_t;
1086 typedef typename index_type_t::iterator index_it;
1087 typedef std::pair<index_it, bool> index_ib;
1088
1089
1090 scoped_lock<rmutex> guard(m_header);
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103 index_ib insert_ret;
1104
1105 typename index_type_t::insert_commit_data commit_data;
1106 typedef typename index_type_t::value_type intrusive_value_type;
1107
1108 BOOST_TRY{
1109 ipcdetail::intrusive_compare_key<CharT> key(name, namelen);
1110 insert_ret = index.insert_check(key, commit_data);
1111 }
1112
1113 BOOST_CATCH(...){
1114 if(dothrow)
1115 BOOST_RETHROW
1116 return 0;
1117 }
1118 BOOST_CATCH_END
1119
1120 index_it it = insert_ret.first;
1121
1122
1123
1124 if(!insert_ret.second){
1125 if(try2find){
1126 return it->get_block_header()->value();
1127 }
1128 if(dothrow){
1129 throw interprocess_exception(already_exists_error);
1130 }
1131 else{
1132 return 0;
1133 }
1134 }
1135
1136
1137 void *buffer_ptr;
1138
1139
1140 if(dothrow){
1141 buffer_ptr = this->allocate
1142 (block_info.template total_size_with_header<intrusive_value_type>());
1143 }
1144 else{
1145 buffer_ptr = this->allocate
1146 (block_info.template total_size_with_header<intrusive_value_type>(), nothrow<>::get());
1147 if(!buffer_ptr)
1148 return 0;
1149 }
1150
1151
1152 intrusive_value_type * intrusive_hdr = ::new(buffer_ptr, boost_container_new_t()) intrusive_value_type();
1153 block_header_t * hdr = ::new(intrusive_hdr->get_block_header(), boost_container_new_t())block_header_t(block_info);
1154 void *ptr = 0;
1155 ptr = hdr->value();
1156
1157
1158 CharT *name_ptr = static_cast<CharT *>(hdr->template name<CharT>());
1159 std::char_traits<CharT>::copy(name_ptr, name, namelen+1);
1160
1161 BOOST_TRY{
1162
1163 it = index.insert_commit(*intrusive_hdr, commit_data);
1164 }
1165
1166 BOOST_CATCH(...){
1167 if(dothrow)
1168 BOOST_RETHROW
1169 return 0;
1170 }
1171 BOOST_CATCH_END
1172
1173
1174
1175 ipcdetail::mem_algo_deallocator<segment_manager_base_type> mem
1176 (buffer_ptr, *static_cast<segment_manager_base_type*>(this));
1177
1178
1179
1180
1181
1182 value_eraser<index_type_t> v_eraser(index, it);
1183
1184
1185 table.construct_n(ptr, num);
1186
1187
1188 v_eraser.release();
1189 mem.release();
1190 return ptr;
1191 }
1192
1193
1194
1195 template<class CharT>
1196 void * priv_generic_named_construct
1197 (unsigned char type, const CharT *name, size_type num, bool try2find, bool dothrow,
1198 ipcdetail::in_place_interface &table,
1199 IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index, ipcdetail::false_ is_intrusive)
1200 {
1201 (void)is_intrusive;
1202 std::size_t namelen = std::char_traits<CharT>::length(name);
1203
1204 block_header_t block_info ( size_type(table.size*num)
1205 , size_type(table.alignment)
1206 , type
1207 , sizeof(CharT)
1208 , namelen);
1209
1210 typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type_t;
1211 typedef typename index_type_t::key_type key_type;
1212 typedef typename index_type_t::mapped_type mapped_type;
1213 typedef typename index_type_t::value_type value_type;
1214 typedef typename index_type_t::iterator index_it;
1215 typedef std::pair<index_it, bool> index_ib;
1216
1217
1218 scoped_lock<rmutex> guard(m_header);
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231 index_ib insert_ret;
1232 BOOST_TRY{
1233 insert_ret = index.insert(value_type(key_type (name, namelen), mapped_type(0)));
1234 }
1235
1236 BOOST_CATCH(...){
1237 if(dothrow)
1238 BOOST_RETHROW;
1239 return 0;
1240 }
1241 BOOST_CATCH_END
1242
1243 index_it it = insert_ret.first;
1244
1245
1246
1247 if(!insert_ret.second){
1248 if(try2find){
1249 block_header_t *hdr = static_cast<block_header_t*>
1250 (ipcdetail::to_raw_pointer(it->second.m_ptr));
1251 return hdr->value();
1252 }
1253 return 0;
1254 }
1255
1256
1257 value_eraser<index_type_t> v_eraser(index, it);
1258
1259
1260 void *buffer_ptr;
1261 block_header_t * hdr;
1262
1263
1264 if(is_node_index_t::value){
1265 size_type total_size = block_info.template total_size_with_header<index_it>();
1266 if(dothrow){
1267 buffer_ptr = this->allocate(total_size);
1268 }
1269 else{
1270 buffer_ptr = this->allocate(total_size, nothrow<>::get());
1271 if(!buffer_ptr)
1272 return 0;
1273 }
1274 index_it *idr = ::new(buffer_ptr, boost_container_new_t()) index_it(it);
1275 hdr = block_header_t::template from_first_header<index_it>(idr);
1276 }
1277 else{
1278 if(dothrow){
1279 buffer_ptr = this->allocate(block_info.total_size());
1280 }
1281 else{
1282 buffer_ptr = this->allocate(block_info.total_size(), nothrow<>::get());
1283 if(!buffer_ptr)
1284 return 0;
1285 }
1286 hdr = static_cast<block_header_t*>(buffer_ptr);
1287 }
1288
1289 hdr = ::new(hdr, boost_container_new_t())block_header_t(block_info);
1290 void *ptr = 0;
1291 ptr = hdr->value();
1292
1293
1294 CharT *name_ptr = static_cast<CharT *>(hdr->template name<CharT>());
1295 std::char_traits<CharT>::copy(name_ptr, name, namelen+1);
1296
1297
1298
1299
1300 const_cast<key_type &>(it->first).name(name_ptr);
1301 it->second.m_ptr = hdr;
1302
1303
1304 ipcdetail::mem_algo_deallocator<segment_manager_base_type> mem
1305 (buffer_ptr, *static_cast<segment_manager_base_type*>(this));
1306
1307
1308 table.construct_n(ptr, num);
1309
1310
1311 mem.release();
1312
1313
1314 v_eraser.release();
1315 return ptr;
1316 }
1317
1318 private:
1319
1320 segment_manager *get_this_pointer()
1321 { return this; }
1322
1323 typedef typename MemoryAlgorithm::mutex_family::recursive_mutex_type rmutex;
1324
1325 scoped_lock<rmutex> priv_get_lock(bool use_lock)
1326 {
1327 scoped_lock<rmutex> local(m_header, defer_lock);
1328 if(use_lock){
1329 local.lock();
1330 }
1331 return scoped_lock<rmutex>(boost::move(local));
1332 }
1333
1334
1335
1336 struct header_t
1337 : public rmutex
1338 {
1339 named_index_t m_named_index;
1340 unique_index_t m_unique_index;
1341
1342 header_t(segment_manager_base_t *segment_mngr_base)
1343 : m_named_index (segment_mngr_base)
1344 , m_unique_index(segment_mngr_base)
1345 {}
1346 } m_header;
1347
1348 #endif
1349 };
1350
1351
1352 }}
1353
1354 #include <boost/interprocess/detail/config_end.hpp>
1355
1356 #endif
1357