File indexing completed on 2025-09-16 08:37:02
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP
0012 #define BOOST_INTERPROCESS_DETAIL_MANAGED_MEMORY_IMPL_HPP
0013
0014 #ifndef BOOST_CONFIG_HPP
0015 # include <boost/config.hpp>
0016 #endif
0017 #
0018 #if defined(BOOST_HAS_PRAGMA_ONCE)
0019 # pragma once
0020 #endif
0021
0022 #include <boost/interprocess/detail/config_begin.hpp>
0023 #include <boost/interprocess/detail/workaround.hpp>
0024
0025 #include <boost/interprocess/interprocess_fwd.hpp>
0026 #include <boost/interprocess/detail/utilities.hpp>
0027 #include <boost/interprocess/detail/os_file_functions.hpp>
0028 #include <boost/interprocess/creation_tags.hpp>
0029 #include <boost/interprocess/exceptions.hpp>
0030 #include <boost/interprocess/segment_manager.hpp>
0031 #include <boost/interprocess/sync/scoped_lock.hpp>
0032 #include <boost/interprocess/detail/nothrow.hpp>
0033 #include <boost/interprocess/detail/simple_swap.hpp>
0034
0035
0036 #include <boost/intrusive/detail/minimal_pair_header.hpp>
0037 #include <boost/assert.hpp>
0038
0039
0040
0041
0042
0043 namespace boost {
0044 namespace interprocess {
0045 namespace ipcdetail {
0046
0047 template<class BasicManagedMemoryImpl>
0048 class create_open_func;
0049
0050 template<
0051 class CharType,
0052 class MemoryAlgorithm,
0053 template<class IndexConfig> class IndexType
0054 >
0055 struct segment_manager_type
0056 {
0057 typedef segment_manager<CharType, MemoryAlgorithm, IndexType> type;
0058 };
0059
0060
0061
0062
0063
0064
0065
0066
0067 template < class CharType
0068 , class MemoryAlgorithm
0069 , template<class IndexConfig> class IndexType
0070 , std::size_t Offset = 0
0071 >
0072 class basic_managed_memory_impl
0073 {
0074
0075 basic_managed_memory_impl(const basic_managed_memory_impl &);
0076 basic_managed_memory_impl &operator=(const basic_managed_memory_impl &);
0077
0078 template<class BasicManagedMemoryImpl>
0079 friend class create_open_func;
0080
0081 public:
0082 typedef typename segment_manager_type
0083 <CharType, MemoryAlgorithm, IndexType>::type segment_manager;
0084 typedef CharType char_type;
0085 typedef MemoryAlgorithm memory_algorithm;
0086 typedef typename MemoryAlgorithm::mutex_family mutex_family;
0087 typedef CharType char_t;
0088 typedef typename MemoryAlgorithm::size_type size_type;
0089 typedef typename MemoryAlgorithm::difference_type difference_type;
0090 typedef difference_type handle_t;
0091 typedef typename segment_manager::
0092 const_named_iterator const_named_iterator;
0093 typedef typename segment_manager::
0094 const_unique_iterator const_unique_iterator;
0095
0096 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0097
0098 typedef typename
0099 segment_manager::char_ptr_holder_t char_ptr_holder_t;
0100
0101
0102 typedef typename segment_manager::multiallocation_chain multiallocation_chain;
0103
0104 #endif
0105
0106 static const size_type PayloadPerAllocation = segment_manager::PayloadPerAllocation;
0107
0108 private:
0109 typedef basic_managed_memory_impl
0110 <CharType, MemoryAlgorithm, IndexType, Offset> self_t;
0111 protected:
0112 template<class ManagedMemory, class CharT>
0113 static bool grow(const CharT *filename, size_type extra_bytes)
0114 {
0115 typedef typename ManagedMemory::device_type device_type;
0116
0117 BOOST_INTERPROCESS_TRY{
0118 offset_t old_size;
0119 {
0120 device_type f(open_or_create, filename, read_write);
0121 if(!f.get_size(old_size))
0122 return false;
0123 f.truncate(old_size + static_cast<offset_t>(extra_bytes));
0124 }
0125 ManagedMemory managed_memory(open_only, filename);
0126
0127 managed_memory.self_t::grow(extra_bytes);
0128 }
0129 BOOST_INTERPROCESS_CATCH(...){
0130 return false;
0131 } BOOST_INTERPROCESS_CATCH_END
0132 return true;
0133 }
0134
0135 template<class ManagedMemory, class CharT>
0136 static bool shrink_to_fit(const CharT *filename)
0137 {
0138 typedef typename ManagedMemory::device_type device_type;
0139 size_type new_size;
0140 BOOST_INTERPROCESS_TRY{
0141 ManagedMemory managed_memory(open_only, filename);
0142 managed_memory.get_size();
0143 managed_memory.self_t::shrink_to_fit();
0144 new_size = managed_memory.get_size();
0145 }
0146 BOOST_INTERPROCESS_CATCH(...){
0147 return false;
0148 } BOOST_INTERPROCESS_CATCH_END
0149
0150
0151 {
0152 device_type f(open_or_create, filename, read_write);
0153 f.truncate(static_cast<offset_t>(new_size));
0154 }
0155 return true;
0156 }
0157
0158
0159 basic_managed_memory_impl()
0160 : mp_header(0){}
0161
0162
0163 ~basic_managed_memory_impl()
0164 { this->close_impl(); }
0165
0166
0167 bool create_impl (void *addr, size_type size)
0168 {
0169 if(mp_header) return false;
0170
0171
0172 if(size < segment_manager::get_min_size())
0173 return false;
0174
0175
0176
0177 BOOST_INTERPROCESS_TRY{
0178
0179 BOOST_ASSERT((0 == (std::size_t)addr % boost::move_detail::alignment_of<segment_manager>::value));
0180 mp_header = ::new(addr, boost_container_new_t()) segment_manager(size);
0181 }
0182 BOOST_INTERPROCESS_CATCH(...){
0183 return false;
0184 } BOOST_INTERPROCESS_CATCH_END
0185 return true;
0186 }
0187
0188
0189 bool open_impl (void *addr, size_type)
0190 {
0191 if(mp_header) return false;
0192 mp_header = static_cast<segment_manager*>(addr);
0193 return true;
0194 }
0195
0196
0197 bool close_impl()
0198 {
0199 bool ret = mp_header != 0;
0200 mp_header = 0;
0201 return ret;
0202 }
0203
0204
0205 bool destroy_impl()
0206 {
0207 if(mp_header == 0)
0208 return false;
0209 mp_header->~segment_manager();
0210 this->close_impl();
0211 return true;
0212 }
0213
0214
0215 void grow(size_type extra_bytes)
0216 { mp_header->grow(extra_bytes); }
0217
0218 void shrink_to_fit()
0219 { mp_header->shrink_to_fit(); }
0220
0221 public:
0222
0223
0224 segment_manager *get_segment_manager() const
0225 { return mp_header; }
0226
0227
0228 void * get_address () const
0229 { return reinterpret_cast<char*>(mp_header) - Offset; }
0230
0231
0232 size_type get_size () const
0233 { return mp_header->get_size() + Offset; }
0234
0235
0236
0237 size_type get_free_memory() const
0238 { return mp_header->get_free_memory(); }
0239
0240
0241
0242 bool all_memory_deallocated()
0243 { return mp_header->all_memory_deallocated(); }
0244
0245
0246
0247 bool check_sanity()
0248 { return mp_header->check_sanity(); }
0249
0250
0251
0252 void zero_free_memory()
0253 { mp_header->zero_free_memory(); }
0254
0255
0256
0257 handle_t get_handle_from_address (const void *ptr) const
0258 {
0259 return (handle_t)(reinterpret_cast<const char*>(ptr) -
0260 reinterpret_cast<const char*>(this->get_address()));
0261 }
0262
0263
0264 bool belongs_to_segment (const void *ptr) const
0265 {
0266 return ptr >= this->get_address() &&
0267 ptr < (reinterpret_cast<const char*>(this->get_address()) + this->get_size());
0268 }
0269
0270
0271
0272 void * get_address_from_handle (handle_t offset) const
0273 { return reinterpret_cast<char*>(this->get_address()) + offset; }
0274
0275
0276
0277
0278 void* allocate (size_type nbytes)
0279 { return mp_header->allocate(nbytes); }
0280
0281
0282
0283
0284 void* allocate (size_type nbytes, const std::nothrow_t &tag)
0285 { return mp_header->allocate(nbytes, tag); }
0286
0287
0288
0289
0290 void * allocate_aligned (size_type nbytes, size_type alignment, const std::nothrow_t &tag)
0291 { return mp_header->allocate_aligned(nbytes, alignment, tag); }
0292
0293 template<class T>
0294 T * allocation_command (boost::interprocess::allocation_type command, size_type limit_size,
0295 size_type &prefer_in_recvd_out_size, T *&reuse)
0296 { return mp_header->allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse); }
0297
0298
0299
0300
0301 void * allocate_aligned(size_type nbytes, size_type alignment)
0302 { return mp_header->allocate_aligned(nbytes, alignment); }
0303
0304 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0305
0306
0307
0308
0309
0310 void allocate_many(size_type elem_bytes, size_type n_elements, multiallocation_chain &chain)
0311 { mp_header->allocate_many(elem_bytes, n_elements, chain); }
0312
0313
0314
0315 void allocate_many(const size_type *element_lengths, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain)
0316 { mp_header->allocate_many(element_lengths, n_elements, sizeof_element, chain); }
0317
0318
0319
0320 void allocate_many(const std::nothrow_t &tag, size_type elem_bytes, size_type n_elements, multiallocation_chain &chain)
0321 { mp_header->allocate_many(tag, elem_bytes, n_elements, chain); }
0322
0323
0324
0325
0326 void allocate_many(const std::nothrow_t &tag, const size_type *elem_sizes, size_type n_elements, size_type sizeof_element, multiallocation_chain &chain)
0327 { mp_header->allocate_many(tag, elem_sizes, n_elements, sizeof_element, chain); }
0328
0329
0330
0331 void deallocate_many(multiallocation_chain &chain)
0332 { mp_header->deallocate_many(chain); }
0333
0334 #endif
0335
0336
0337 void deallocate (void *addr)
0338 { if (mp_header) mp_header->deallocate(addr); }
0339
0340
0341
0342
0343 template <class T>
0344 std::pair<T*, size_type> find (char_ptr_holder_t name)
0345 { return mp_header->template find<T>(name); }
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363 template <class T>
0364 typename segment_manager::template construct_proxy<T>::type
0365 construct(char_ptr_holder_t name)
0366 { return mp_header->template construct<T>(name); }
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384 template <class T>
0385 typename segment_manager::template construct_proxy<T>::type
0386 find_or_construct(char_ptr_holder_t name)
0387 { return mp_header->template find_or_construct<T>(name); }
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405 template <class T>
0406 typename segment_manager::template construct_proxy<T>::type
0407 construct(char_ptr_holder_t name, const std::nothrow_t &tag)
0408 { return mp_header->template construct<T>(name, tag); }
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426 template <class T>
0427 typename segment_manager::template construct_proxy<T>::type
0428 find_or_construct(char_ptr_holder_t name, const std::nothrow_t &tag)
0429 { return mp_header->template find_or_construct<T>(name, tag); }
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447 template <class T>
0448 typename segment_manager::template construct_iter_proxy<T>::type
0449 construct_it(char_ptr_holder_t name)
0450 { return mp_header->template construct_it<T>(name); }
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470 template <class T>
0471 typename segment_manager::template construct_iter_proxy<T>::type
0472 find_or_construct_it(char_ptr_holder_t name)
0473 { return mp_header->template find_or_construct_it<T>(name); }
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484
0485
0486
0487
0488
0489
0490
0491 template <class T>
0492 typename segment_manager::template construct_iter_proxy<T>::type
0493 construct_it(char_ptr_holder_t name, const std::nothrow_t &tag)
0494 { return mp_header->template construct_it<T>(name, tag); }
0495
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512
0513
0514 template <class T>
0515 typename segment_manager::template construct_iter_proxy<T>::type
0516 find_or_construct_it(char_ptr_holder_t name, const std::nothrow_t &tag)
0517 { return mp_header->template find_or_construct_it<T>(name, tag); }
0518
0519
0520
0521
0522 template <class Func>
0523 void atomic_func(Func &f)
0524 { mp_header->atomic_func(f); }
0525
0526
0527
0528
0529
0530
0531 template <class Func>
0532 bool try_atomic_func(Func &f)
0533 { return mp_header->try_atomic_func(f); }
0534
0535
0536
0537
0538
0539
0540
0541
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551
0552
0553
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565 template <class T>
0566 bool destroy(const CharType *name)
0567 { return mp_header->template destroy<T>(name); }
0568
0569
0570
0571
0572
0573
0574
0575
0576
0577
0578
0579
0580
0581
0582
0583
0584
0585 template <class T>
0586 bool destroy(const unique_instance_t *const )
0587 { return mp_header->template destroy<T>(unique_instance); }
0588
0589
0590
0591
0592
0593
0594
0595
0596
0597
0598
0599
0600
0601
0602
0603
0604
0605 template <class T>
0606 void destroy_ptr(const T *ptr)
0607 { mp_header->template destroy_ptr<T>(ptr); }
0608
0609
0610
0611 template<class T>
0612 static const char_type *get_instance_name(const T *ptr)
0613 { return segment_manager::get_instance_name(ptr); }
0614
0615
0616
0617 template<class T>
0618 static instance_type get_instance_type(const T *ptr)
0619 { return segment_manager::get_instance_type(ptr); }
0620
0621
0622
0623 template<class T>
0624 static size_type get_instance_length(const T *ptr)
0625 { return segment_manager::get_instance_length(ptr); }
0626
0627
0628
0629
0630 void reserve_named_objects(size_type num)
0631 { mp_header->reserve_named_objects(num); }
0632
0633
0634
0635
0636 void reserve_unique_objects(size_type num)
0637 { mp_header->reserve_unique_objects(num); }
0638
0639
0640
0641 void shrink_to_fit_indexes()
0642 { mp_header->shrink_to_fit_indexes(); }
0643
0644
0645
0646 size_type get_num_named_objects()
0647 { return mp_header->get_num_named_objects(); }
0648
0649
0650
0651 size_type get_num_unique_objects()
0652 { return mp_header->get_num_unique_objects(); }
0653
0654
0655
0656 const_named_iterator named_begin() const
0657 { return mp_header->named_begin(); }
0658
0659
0660
0661 const_named_iterator named_end() const
0662 { return mp_header->named_end(); }
0663
0664
0665
0666 const_unique_iterator unique_begin() const
0667 { return mp_header->unique_begin(); }
0668
0669
0670
0671 const_unique_iterator unique_end() const
0672 { return mp_header->unique_end(); }
0673
0674
0675
0676 template<class T>
0677 struct allocator
0678 {
0679 typedef typename segment_manager::template allocator<T>::type type;
0680 };
0681
0682
0683
0684 template<class T>
0685 typename allocator<T>::type
0686 get_allocator()
0687 { return mp_header->template get_allocator<T>(); }
0688
0689
0690
0691 template<class T>
0692 struct deleter
0693 {
0694 typedef typename segment_manager::template deleter<T>::type type;
0695 };
0696
0697
0698
0699 template<class T>
0700 typename deleter<T>::type
0701 get_deleter()
0702 { return mp_header->template get_deleter<T>(); }
0703
0704 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0705
0706
0707
0708 template <class T>
0709 std::pair<T*, size_type> find_no_lock (char_ptr_holder_t name)
0710 { return mp_header->template find_no_lock<T>(name); }
0711 #endif
0712
0713 protected:
0714
0715
0716 void swap(basic_managed_memory_impl &other)
0717 { (simple_swap)(mp_header, other.mp_header); }
0718
0719 private:
0720 segment_manager *mp_header;
0721 };
0722
0723 template<class BasicManagedMemoryImpl>
0724 class create_open_func
0725 {
0726 typedef typename BasicManagedMemoryImpl::size_type size_type;
0727
0728 public:
0729
0730 create_open_func(BasicManagedMemoryImpl * const frontend, create_enum_t type)
0731 : m_frontend(frontend), m_type(type){}
0732
0733 bool operator()(void *addr, std::size_t size, bool created) const
0734 {
0735 if( ((m_type == DoOpen) && created) ||
0736 ((m_type == DoCreate) && !created) ||
0737
0738 size_type(-1) < size ){
0739 return false;
0740 }
0741 else if(created){
0742 return m_frontend->create_impl(addr, static_cast<size_type>(size));
0743 }
0744 else{
0745 return m_frontend->open_impl (addr, static_cast<size_type>(size));
0746 }
0747 }
0748
0749 static std::size_t get_min_size()
0750 {
0751 const size_type sz = BasicManagedMemoryImpl::segment_manager::get_min_size();
0752 if(sz > std::size_t(-1)){
0753
0754 BOOST_ASSERT(false);
0755 return std::size_t(-1);
0756 }
0757 else{
0758 return static_cast<std::size_t>(sz);
0759 }
0760 }
0761
0762 private:
0763 BasicManagedMemoryImpl *m_frontend;
0764 create_enum_t m_type;
0765 };
0766
0767 }
0768 }
0769 }
0770
0771 #include <boost/interprocess/detail/config_end.hpp>
0772
0773 #endif
0774