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