File indexing completed on 2025-01-18 09:38:35
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
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 typedef MemoryAlgorithm memory_algorithm;
0079
0080 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0081
0082
0083 typedef typename MemoryAlgorithm::multiallocation_chain multiallocation_chain;
0084 typedef typename MemoryAlgorithm::difference_type difference_type;
0085 typedef typename MemoryAlgorithm::size_type size_type;
0086
0087 #endif
0088
0089
0090
0091 static const size_type PayloadPerAllocation = MemoryAlgorithm::PayloadPerAllocation;
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104 segment_manager_base(size_type sz, size_type reserved_bytes)
0105 : MemoryAlgorithm(sz, reserved_bytes)
0106 {
0107 BOOST_ASSERT((sizeof(segment_manager_base<MemoryAlgorithm>) == sizeof(MemoryAlgorithm)));
0108 }
0109
0110
0111
0112 size_type get_size() const
0113 { return MemoryAlgorithm::get_size(); }
0114
0115
0116
0117 size_type get_free_memory() const
0118 { return MemoryAlgorithm::get_free_memory(); }
0119
0120
0121
0122 static size_type get_min_size (size_type size)
0123 { return MemoryAlgorithm::get_min_size(size); }
0124
0125
0126
0127 void * allocate (size_type nbytes, const std::nothrow_t &)
0128 { return MemoryAlgorithm::allocate(nbytes); }
0129
0130
0131
0132
0133
0134 MemoryAlgorithm &get_memory_algorithm()
0135 { return static_cast<MemoryAlgorithm&>(*this); }
0136
0137
0138
0139
0140
0141 const MemoryAlgorithm &get_memory_algorithm() const
0142 { return static_cast<const MemoryAlgorithm&>(*this); }
0143
0144 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0145
0146
0147
0148
0149 void allocate_many(size_type elem_bytes, size_type n_elements, multiallocation_chain &chain)
0150 {
0151 size_type prev_size = chain.size();
0152 MemoryAlgorithm::allocate_many(elem_bytes, n_elements, chain);
0153 if(!elem_bytes || chain.size() == prev_size){
0154 throw bad_alloc();
0155 }
0156 }
0157
0158
0159
0160 void allocate_many(const size_type *element_lengths, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain)
0161 {
0162 size_type prev_size = chain.size();
0163 MemoryAlgorithm::allocate_many(element_lengths, n_elements, sizeof_element, chain);
0164 if(!sizeof_element || chain.size() == prev_size){
0165 throw bad_alloc();
0166 }
0167 }
0168
0169
0170
0171 void allocate_many(const std::nothrow_t &, size_type elem_bytes, size_type n_elements, multiallocation_chain &chain)
0172 { MemoryAlgorithm::allocate_many(elem_bytes, n_elements, chain); }
0173
0174
0175
0176
0177 void allocate_many(const std::nothrow_t &, const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain)
0178 { MemoryAlgorithm::allocate_many(elem_sizes, n_elements, sizeof_element, chain); }
0179
0180
0181
0182 void deallocate_many(multiallocation_chain &chain)
0183 { MemoryAlgorithm::deallocate_many(chain); }
0184
0185 #endif
0186
0187
0188
0189 void * allocate(size_type nbytes)
0190 {
0191 void * ret = MemoryAlgorithm::allocate(nbytes);
0192 if(!ret)
0193 throw bad_alloc();
0194 return ret;
0195 }
0196
0197
0198
0199 void * allocate_aligned (size_type nbytes, size_type alignment, const std::nothrow_t &)
0200 { return MemoryAlgorithm::allocate_aligned(nbytes, alignment); }
0201
0202
0203
0204 void * allocate_aligned(size_type nbytes, size_type alignment)
0205 {
0206 void * ret = MemoryAlgorithm::allocate_aligned(nbytes, alignment);
0207 if(!ret)
0208 throw bad_alloc();
0209 return ret;
0210 }
0211
0212 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0213
0214 template<class T>
0215 T *allocation_command (boost::interprocess::allocation_type command, size_type limit_size,
0216 size_type &prefer_in_recvd_out_size, T *&reuse)
0217 {
0218 T *ret = MemoryAlgorithm::allocation_command
0219 (command | boost::interprocess::nothrow_allocation, limit_size, prefer_in_recvd_out_size, reuse);
0220 if(!(command & boost::interprocess::nothrow_allocation) && !ret)
0221 throw bad_alloc();
0222 return ret;
0223 }
0224
0225 void *raw_allocation_command (boost::interprocess::allocation_type command, size_type limit_objects,
0226 size_type &prefer_in_recvd_out_size, void *&reuse, size_type sizeof_object = 1)
0227 {
0228 void *ret = MemoryAlgorithm::raw_allocation_command
0229 ( command | boost::interprocess::nothrow_allocation, limit_objects,
0230 prefer_in_recvd_out_size, reuse, sizeof_object);
0231 if(!(command & boost::interprocess::nothrow_allocation) && !ret)
0232 throw bad_alloc();
0233 return ret;
0234 }
0235
0236 #endif
0237
0238
0239
0240 void deallocate (void *addr)
0241 { MemoryAlgorithm::deallocate(addr); }
0242
0243
0244
0245 void grow(size_type extra_size)
0246 { MemoryAlgorithm::grow(extra_size); }
0247
0248
0249
0250 void shrink_to_fit()
0251 { MemoryAlgorithm::shrink_to_fit(); }
0252
0253
0254
0255 bool all_memory_deallocated()
0256 { return MemoryAlgorithm::all_memory_deallocated(); }
0257
0258
0259
0260 bool check_sanity()
0261 { return MemoryAlgorithm::check_sanity(); }
0262
0263
0264
0265 void zero_free_memory()
0266 { MemoryAlgorithm::zero_free_memory(); }
0267
0268
0269 size_type size(const void *ptr) const
0270 { return MemoryAlgorithm::size(ptr); }
0271
0272 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0273 protected:
0274 void * prot_anonymous_construct
0275 (size_type num, bool dothrow, ipcdetail::in_place_interface &table)
0276 {
0277 typedef ipcdetail::block_header<size_type> block_header_t;
0278 block_header_t block_info ( size_type(table.size*num)
0279 , size_type(table.alignment)
0280 , anonymous_type
0281 , 1
0282 , 0);
0283
0284
0285 void *ptr_struct = this->allocate(block_info.total_size(), nothrow<>::get());
0286
0287
0288 if(!ptr_struct){
0289 if(dothrow){
0290 throw bad_alloc();
0291 }
0292 else{
0293 return 0;
0294 }
0295 }
0296
0297
0298 ipcdetail::mem_algo_deallocator<MemoryAlgorithm> mem(ptr_struct, *this);
0299
0300
0301 block_header_t * hdr = ::new(ptr_struct, boost_container_new_t()) block_header_t(block_info);
0302 void *ptr = 0;
0303 ptr = hdr->value();
0304
0305
0306 ipcdetail::array_construct(ptr, num, table);
0307
0308
0309 mem.release();
0310 return ptr;
0311 }
0312
0313
0314 void prot_anonymous_destroy(const void *object, ipcdetail::in_place_interface &table)
0315 {
0316
0317
0318 typedef ipcdetail::block_header<size_type> block_header_t;
0319 block_header_t *ctrl_data = block_header_t::block_header_from_value(object, table.size, table.alignment);
0320
0321
0322
0323
0324
0325 if(ctrl_data->alloc_type() != anonymous_type){
0326
0327 BOOST_ASSERT(0);
0328 }
0329
0330
0331
0332 std::size_t destroyed = 0;
0333 table.destroy_n(const_cast<void*>(object), ctrl_data->m_value_bytes/table.size, destroyed);
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 std::size_t destroyed;
0991 table.destroy_n(values, num, destroyed);
0992 this->deallocate(memory);
0993 return true;
0994 }
0995
0996 template <class CharT>
0997 bool priv_generic_named_destroy(const CharT *name,
0998 IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
0999 ipcdetail::in_place_interface &table,
1000 ipcdetail::false_ is_intrusive_index)
1001 {
1002 (void)is_intrusive_index;
1003 typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > char_aware_index_type;
1004 typedef typename char_aware_index_type::iterator index_it;
1005 typedef typename char_aware_index_type::key_type key_type;
1006
1007
1008 scoped_lock<rmutex> guard(m_header);
1009
1010
1011 index_it it = index.find(key_type (name,
1012 std::char_traits<CharT>::length(name)));
1013
1014
1015 if(it == index.end()){
1016
1017
1018 return false;
1019 }
1020 return this->priv_generic_named_destroy_impl<CharT>(it, index, table);
1021 }
1022
1023 template <class CharT>
1024 bool priv_generic_named_destroy_impl
1025 (const typename IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> >::iterator &it,
1026 IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index,
1027 ipcdetail::in_place_interface &table)
1028 {
1029 typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > char_aware_index_type;
1030 typedef typename char_aware_index_type::iterator index_it;
1031
1032
1033 block_header_t *ctrl_data = reinterpret_cast<block_header_t*>
1034 (ipcdetail::to_raw_pointer(it->second.m_ptr));
1035 char *stored_name = static_cast<char*>(static_cast<void*>(const_cast<CharT*>(it->first.name())));
1036 (void)stored_name;
1037
1038
1039
1040 std::size_t num = ctrl_data->m_value_bytes/table.size;
1041 void *values = ctrl_data->value();
1042
1043
1044 BOOST_ASSERT((ctrl_data->m_value_bytes % table.size) == 0);
1045 BOOST_ASSERT(static_cast<void*>(stored_name) == static_cast<void*>(ctrl_data->template name<CharT>()));
1046 BOOST_ASSERT(sizeof(CharT) == ctrl_data->sizeof_char());
1047
1048
1049 index.erase(it);
1050
1051
1052 ctrl_data->~block_header_t();
1053
1054 void *memory;
1055 if(is_node_index_t::value){
1056 index_it *ihdr = block_header_t::template
1057 to_first_header<index_it>(ctrl_data);
1058 ihdr->~index_it();
1059 memory = ihdr;
1060 }
1061 else{
1062 memory = ctrl_data;
1063 }
1064
1065
1066 std::size_t destroyed;
1067 table.destroy_n(values, num, destroyed);
1068 this->deallocate(memory);
1069 return true;
1070 }
1071
1072 template<class CharT>
1073 void * priv_generic_named_construct
1074 (unsigned char type, const CharT *name, size_type num, bool try2find,
1075 bool dothrow, ipcdetail::in_place_interface &table,
1076 IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index, ipcdetail::true_ is_intrusive)
1077 {
1078 (void)is_intrusive;
1079 std::size_t namelen = std::char_traits<CharT>::length(name);
1080
1081 block_header_t block_info ( size_type(table.size*num)
1082 , size_type(table.alignment)
1083 , type
1084 , sizeof(CharT)
1085 , namelen);
1086
1087 typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type_t;
1088 typedef typename index_type_t::iterator index_it;
1089 typedef std::pair<index_it, bool> index_ib;
1090
1091
1092 scoped_lock<rmutex> guard(m_header);
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105 index_ib insert_ret;
1106
1107 typename index_type_t::insert_commit_data commit_data;
1108 typedef typename index_type_t::value_type intrusive_value_type;
1109
1110 BOOST_TRY{
1111 ipcdetail::intrusive_compare_key<CharT> key(name, namelen);
1112 insert_ret = index.insert_check(key, commit_data);
1113 }
1114
1115 BOOST_CATCH(...){
1116 if(dothrow)
1117 BOOST_RETHROW
1118 return 0;
1119 }
1120 BOOST_CATCH_END
1121
1122 index_it it = insert_ret.first;
1123
1124
1125
1126 if(!insert_ret.second){
1127 if(try2find){
1128 return it->get_block_header()->value();
1129 }
1130 if(dothrow){
1131 throw interprocess_exception(already_exists_error);
1132 }
1133 else{
1134 return 0;
1135 }
1136 }
1137
1138
1139 void *buffer_ptr;
1140
1141
1142 if(dothrow){
1143 buffer_ptr = this->allocate
1144 (block_info.template total_size_with_header<intrusive_value_type>());
1145 }
1146 else{
1147 buffer_ptr = this->allocate
1148 (block_info.template total_size_with_header<intrusive_value_type>(), nothrow<>::get());
1149 if(!buffer_ptr)
1150 return 0;
1151 }
1152
1153
1154 intrusive_value_type * intrusive_hdr = ::new(buffer_ptr, boost_container_new_t()) intrusive_value_type();
1155 block_header_t * hdr = ::new(intrusive_hdr->get_block_header(), boost_container_new_t())block_header_t(block_info);
1156 void *ptr = 0;
1157 ptr = hdr->value();
1158
1159
1160 CharT *name_ptr = static_cast<CharT *>(hdr->template name<CharT>());
1161 std::char_traits<CharT>::copy(name_ptr, name, namelen+1);
1162
1163 BOOST_TRY{
1164
1165 it = index.insert_commit(*intrusive_hdr, commit_data);
1166 }
1167
1168 BOOST_CATCH(...){
1169 if(dothrow)
1170 BOOST_RETHROW
1171 return 0;
1172 }
1173 BOOST_CATCH_END
1174
1175
1176
1177 ipcdetail::mem_algo_deallocator<segment_manager_base_type> mem
1178 (buffer_ptr, *static_cast<segment_manager_base_type*>(this));
1179
1180
1181
1182
1183
1184 value_eraser<index_type_t> v_eraser(index, it);
1185
1186
1187 ipcdetail::array_construct(ptr, num, table);
1188
1189
1190 v_eraser.release();
1191 mem.release();
1192 return ptr;
1193 }
1194
1195
1196
1197 template<class CharT>
1198 void * priv_generic_named_construct
1199 (unsigned char type, const CharT *name, size_type num, bool try2find, bool dothrow,
1200 ipcdetail::in_place_interface &table,
1201 IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > &index, ipcdetail::false_ is_intrusive)
1202 {
1203 (void)is_intrusive;
1204 std::size_t namelen = std::char_traits<CharT>::length(name);
1205
1206 block_header_t block_info ( size_type(table.size*num)
1207 , size_type(table.alignment)
1208 , type
1209 , sizeof(CharT)
1210 , namelen);
1211
1212 typedef IndexType<ipcdetail::index_config<CharT, MemoryAlgorithm> > index_type_t;
1213 typedef typename index_type_t::key_type key_type;
1214 typedef typename index_type_t::mapped_type mapped_type;
1215 typedef typename index_type_t::value_type value_type;
1216 typedef typename index_type_t::iterator index_it;
1217 typedef std::pair<index_it, bool> index_ib;
1218
1219
1220 scoped_lock<rmutex> guard(m_header);
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233 index_ib insert_ret;
1234 BOOST_TRY{
1235 insert_ret = index.insert(value_type(key_type (name, namelen), mapped_type(0)));
1236 }
1237
1238 BOOST_CATCH(...){
1239 if(dothrow)
1240 BOOST_RETHROW;
1241 return 0;
1242 }
1243 BOOST_CATCH_END
1244
1245 index_it it = insert_ret.first;
1246
1247
1248
1249 if(!insert_ret.second){
1250 if(try2find){
1251 block_header_t *hdr = static_cast<block_header_t*>
1252 (ipcdetail::to_raw_pointer(it->second.m_ptr));
1253 return hdr->value();
1254 }
1255 return 0;
1256 }
1257
1258
1259 value_eraser<index_type_t> v_eraser(index, it);
1260
1261
1262 void *buffer_ptr;
1263 block_header_t * hdr;
1264
1265
1266 if(is_node_index_t::value){
1267 size_type total_size = block_info.template total_size_with_header<index_it>();
1268 if(dothrow){
1269 buffer_ptr = this->allocate(total_size);
1270 }
1271 else{
1272 buffer_ptr = this->allocate(total_size, nothrow<>::get());
1273 if(!buffer_ptr)
1274 return 0;
1275 }
1276 index_it *idr = ::new(buffer_ptr, boost_container_new_t()) index_it(it);
1277 hdr = block_header_t::template from_first_header<index_it>(idr);
1278 }
1279 else{
1280 if(dothrow){
1281 buffer_ptr = this->allocate(block_info.total_size());
1282 }
1283 else{
1284 buffer_ptr = this->allocate(block_info.total_size(), nothrow<>::get());
1285 if(!buffer_ptr)
1286 return 0;
1287 }
1288 hdr = static_cast<block_header_t*>(buffer_ptr);
1289 }
1290
1291 hdr = ::new(hdr, boost_container_new_t())block_header_t(block_info);
1292 void *ptr = 0;
1293 ptr = hdr->value();
1294
1295
1296 CharT *name_ptr = static_cast<CharT *>(hdr->template name<CharT>());
1297 std::char_traits<CharT>::copy(name_ptr, name, namelen+1);
1298
1299
1300
1301
1302 const_cast<key_type &>(it->first).name(name_ptr);
1303 it->second.m_ptr = hdr;
1304
1305
1306 ipcdetail::mem_algo_deallocator<segment_manager_base_type> mem
1307 (buffer_ptr, *static_cast<segment_manager_base_type*>(this));
1308
1309
1310 ipcdetail::array_construct(ptr, num, table);
1311
1312
1313 mem.release();
1314
1315
1316 v_eraser.release();
1317 return ptr;
1318 }
1319
1320 private:
1321
1322 segment_manager *get_this_pointer()
1323 { return this; }
1324
1325 typedef typename MemoryAlgorithm::mutex_family::recursive_mutex_type rmutex;
1326
1327 scoped_lock<rmutex> priv_get_lock(bool use_lock)
1328 {
1329 scoped_lock<rmutex> local(m_header, defer_lock);
1330 if(use_lock){
1331 local.lock();
1332 }
1333 return scoped_lock<rmutex>(boost::move(local));
1334 }
1335
1336
1337
1338 struct header_t
1339 : public rmutex
1340 {
1341 named_index_t m_named_index;
1342 unique_index_t m_unique_index;
1343
1344 header_t(segment_manager_base_t *segment_mngr_base)
1345 : m_named_index (segment_mngr_base)
1346 , m_unique_index(segment_mngr_base)
1347 {}
1348 } m_header;
1349
1350 #endif
1351 };
1352
1353
1354 }}
1355
1356 #include <boost/interprocess/detail/config_end.hpp>
1357
1358 #endif
1359