File indexing completed on 2025-09-14 08:35:24
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_INTERPROCESS_SEGMENT_MANAGER_BASE_HPP
0012 #define BOOST_INTERPROCESS_SEGMENT_MANAGER_BASE_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
0026 #include <boost/interprocess/exceptions.hpp>
0027
0028 #include <boost/interprocess/detail/type_traits.hpp>
0029 #include <boost/interprocess/detail/utilities.hpp>
0030
0031 #include <boost/container/detail/type_traits.hpp> //alignment_of
0032 #include <boost/container/detail/minimal_char_traits_header.hpp>
0033 #include <boost/container/detail/placement_new.hpp>
0034
0035 #include <boost/intrusive/pointer_traits.hpp>
0036
0037 #include <boost/move/detail/type_traits.hpp> //make_unsigned
0038 #include <boost/move/detail/force_ptr.hpp>
0039
0040 #include <boost/assert.hpp> //BOOST_ASSERT
0041
0042 #include <cstddef> //std::size_t
0043
0044
0045 namespace boost{
0046 namespace interprocess{
0047
0048 template<class MemoryManager>
0049 class segment_manager_base;
0050
0051
0052
0053 enum instance_type { anonymous_type, named_type, unique_type, max_allocation_type };
0054
0055 namespace ipcdetail{
0056
0057 template<class MemoryAlgorithm>
0058 class mem_algo_deallocator
0059 {
0060 void * m_ptr;
0061 MemoryAlgorithm & m_algo;
0062
0063 public:
0064 mem_algo_deallocator(void *ptr, MemoryAlgorithm &algo)
0065 : m_ptr(ptr), m_algo(algo)
0066 {}
0067
0068 void release()
0069 { m_ptr = 0; }
0070
0071 ~mem_algo_deallocator()
0072 { if(m_ptr) m_algo.deallocate(m_ptr); }
0073 };
0074
0075 #if !defined(BOOST_INTERPROCESS_SEGMENT_MANAGER_ABI)
0076 #define BOOST_INTERPROCESS_SEGMENT_MANAGER_ABI 2
0077 #endif
0078
0079 #if (BOOST_INTERPROCESS_SEGMENT_MANAGER_ABI == 1)
0080
0081 template<class size_type>
0082 struct block_header
0083 {
0084 private:
0085 const size_type m_value_bytes;
0086 const unsigned short m_num_char;
0087 const unsigned char m_value_alignment;
0088 const unsigned char m_alloc_type_sizeof_char;
0089
0090 public:
0091 typedef std::size_t name_len_t;
0092
0093 block_header(size_type val_bytes
0094 ,size_type val_alignment
0095 ,unsigned char al_type
0096 ,std::size_t szof_char
0097 ,std::size_t num_char
0098 )
0099 : m_value_bytes(val_bytes)
0100 , m_num_char((unsigned short)num_char)
0101 , m_value_alignment((unsigned char)val_alignment)
0102 , m_alloc_type_sizeof_char( (unsigned char)((al_type << 5u) | ((unsigned char)szof_char & 0x1F)) )
0103 {};
0104
0105 template<std::size_t>
0106 size_type total_anonymous_size() const
0107 {
0108 return this->value_offset() + m_value_bytes;
0109 }
0110
0111 template<std::size_t, class>
0112 size_type total_named_size(std::size_t namelen) const
0113 {
0114 (void)namelen;
0115 BOOST_ASSERT(namelen == m_num_char);
0116 return name_offset() + (m_num_char+1u)*sizeof_char();
0117 }
0118
0119 template<std::size_t, class, class Header>
0120 size_type total_named_size_with_header(std::size_t namelen) const
0121 {
0122 BOOST_ASSERT(namelen == m_num_char);
0123 return get_rounded_size
0124 ( size_type(sizeof(Header))
0125 , size_type(::boost::container::dtl::alignment_of<block_header<size_type> >::value))
0126 + this->template total_named_size<0, char>(namelen);
0127 }
0128
0129 size_type value_bytes() const
0130 { return m_value_bytes; }
0131
0132 unsigned char alloc_type() const
0133 { return (m_alloc_type_sizeof_char >> 5u)&(unsigned char)0x7; }
0134
0135 unsigned char sizeof_char() const
0136 { return m_alloc_type_sizeof_char & (unsigned char)0x1F; }
0137
0138 template<class CharType>
0139 CharType *name() const
0140 {
0141 return const_cast<CharType*>(move_detail::force_ptr<const CharType*>
0142 (reinterpret_cast<const char*>(this) + name_offset()));
0143 }
0144
0145 unsigned short name_length() const
0146 { return m_num_char; }
0147
0148 void *value() const
0149 {
0150 return const_cast<char*>((reinterpret_cast<const char*>(this) + this->value_offset()));
0151 }
0152
0153 template<class T>
0154 static block_header *block_header_from_value(T *value)
0155 {
0156
0157 const std::size_t algn = ::boost::container::dtl::alignment_of<T>::value;
0158 block_header* hdr =
0159 const_cast<block_header*>
0160 (move_detail::force_ptr<const block_header*>(reinterpret_cast<const char*>(value) -
0161 get_rounded_size(sizeof(block_header), algn)));
0162
0163
0164 BOOST_ASSERT(hdr->m_value_alignment == algn);
0165 BOOST_ASSERT(hdr->m_value_bytes % sizeof(T) == 0);
0166 return hdr;
0167 }
0168
0169 template<class Header>
0170 static block_header *from_first_header(Header *header)
0171 {
0172 block_header * hdr =
0173 move_detail::force_ptr<block_header*>(reinterpret_cast<char*>(header) +
0174 get_rounded_size( size_type(sizeof(Header))
0175 , size_type(::boost::container::dtl::alignment_of<block_header >::value)));
0176
0177 return hdr;
0178 }
0179
0180 template<class Header>
0181 static const block_header *from_first_header(const Header *header)
0182 { return from_first_header(const_cast<Header*>(header)); }
0183
0184 template<class Header>
0185 static Header *to_first_header(block_header *bheader)
0186 {
0187 Header * hdr =
0188 move_detail::force_ptr<Header*>(reinterpret_cast<char*>(bheader) -
0189 get_rounded_size( size_type(sizeof(Header))
0190 , size_type(::boost::container::dtl::alignment_of<block_header >::value)));
0191
0192 return hdr;
0193 }
0194
0195 template<std::size_t>
0196 static size_type front_space_without_header()
0197 { return 0u; }
0198
0199 template<std::size_t, class>
0200 static size_type front_space_with_header()
0201 { return 0u; }
0202
0203 void store_name_length(std::size_t)
0204 {}
0205
0206 private:
0207 size_type value_offset() const
0208 {
0209 return get_rounded_size(size_type(sizeof(block_header)), size_type(m_value_alignment));
0210 }
0211
0212 size_type name_offset() const
0213 {
0214 return this->value_offset() + get_rounded_size(size_type(m_value_bytes), size_type(sizeof_char()));
0215 }
0216 };
0217
0218 #elif (BOOST_INTERPROCESS_SEGMENT_MANAGER_ABI == 2)
0219
0220 template <class BlockHeader, class Header>
0221 struct sm_between_headers
0222 {
0223 BOOST_STATIC_CONSTEXPR std::size_t value
0224 = sizeof(Header)
0225 + ct_rounded_size< sizeof(BlockHeader), boost::move_detail::alignment_of<Header>::value>::value
0226 - sizeof(BlockHeader);
0227 };
0228
0229 template <std::size_t TypeAlignment, class BlockHeader, class Header>
0230 struct sg_offsets_with_header
0231 {
0232 private:
0233 BOOST_STATIC_CONSTEXPR std::size_t between_headers = sm_between_headers<BlockHeader, Header>::value;
0234 BOOST_STATIC_CONSTEXPR std::size_t both_headers = between_headers + sizeof(BlockHeader);
0235 BOOST_STATIC_CONSTEXPR std::size_t total_prefix = ct_rounded_size<both_headers, TypeAlignment>::value;
0236
0237 public:
0238 BOOST_STATIC_CONSTEXPR std::size_t block_header_prefix = total_prefix - sizeof(BlockHeader);
0239 BOOST_STATIC_CONSTEXPR std::size_t front_space = total_prefix - both_headers;
0240
0241 BOOST_INTERPROCESS_STATIC_ASSERT((total_prefix % TypeAlignment) == 0);
0242 BOOST_INTERPROCESS_STATIC_ASSERT((front_space % boost::move_detail::alignment_of<Header>::value) == 0);
0243 BOOST_INTERPROCESS_STATIC_ASSERT((block_header_prefix % boost::move_detail::alignment_of<BlockHeader>::value) == 0);
0244 BOOST_INTERPROCESS_STATIC_ASSERT(total_prefix == (sizeof(BlockHeader) + sizeof(Header) + front_space + (between_headers - sizeof(Header))));
0245 };
0246
0247 template <std::size_t TypeAlignment, class BlockHeader>
0248 struct sg_offsets_without_header
0249 {
0250 BOOST_STATIC_CONSTEXPR std::size_t total_prefix = ct_rounded_size<sizeof(BlockHeader), TypeAlignment>::value;
0251
0252 public:
0253 BOOST_STATIC_CONSTEXPR std::size_t block_header_prefix = total_prefix - sizeof(BlockHeader);
0254 BOOST_STATIC_CONSTEXPR std::size_t front_space = block_header_prefix;
0255 };
0256
0257 template<class size_type>
0258 struct block_header
0259 {
0260 private:
0261 const size_type m_alloc_type : 2;
0262 const size_type m_value_bytes : sizeof(size_type)*CHAR_BIT - 2u;
0263
0264 public:
0265 typedef unsigned short name_len_t;
0266
0267 block_header(size_type val_bytes
0268 ,size_type
0269 ,unsigned char al_type
0270 ,std::size_t
0271 ,std::size_t
0272 )
0273 : m_alloc_type(al_type & 3u)
0274 , m_value_bytes(val_bytes & (~size_type(0) >> 2u))
0275 {};
0276
0277 template<std::size_t TypeAlignment>
0278 size_type total_anonymous_size() const
0279 {
0280 BOOST_CONSTEXPR_OR_CONST std::size_t block_header_prefix =
0281 sg_offsets_without_header<TypeAlignment, block_header>::block_header_prefix;
0282 return block_header_prefix + this->value_offset() + m_value_bytes;
0283 }
0284
0285 template<std::size_t TypeAlignment, class CharType>
0286 size_type total_named_size(std::size_t namelen) const
0287 {
0288 BOOST_CONSTEXPR_OR_CONST std::size_t block_header_prefix =
0289 sg_offsets_without_header<TypeAlignment, block_header>::block_header_prefix;
0290 return block_header_prefix
0291 + name_offset< ::boost::move_detail::alignment_of<CharType>::value>()
0292 + (namelen + 1u) * sizeof(CharType);
0293 }
0294
0295 template<std::size_t TypeAlignment, class CharType, class Header>
0296 size_type total_named_size_with_header(std::size_t namelen) const
0297 {
0298 typedef sg_offsets_with_header<TypeAlignment, block_header, Header> offsets_t;
0299 return offsets_t::block_header_prefix
0300 + name_offset< ::boost::move_detail::alignment_of<CharType>::value>()
0301 + (namelen + 1u) * sizeof(CharType);
0302 }
0303
0304 size_type value_bytes() const
0305 { return m_value_bytes; }
0306
0307 unsigned char alloc_type() const
0308 { return m_alloc_type; }
0309
0310 template<class CharType>
0311 CharType *name() const
0312 {
0313 return const_cast<CharType*>(move_detail::force_ptr<const CharType*>
0314 (reinterpret_cast<const char*>(this) +
0315 this->template name_offset< ::boost::move_detail::alignment_of<CharType>::value>()));
0316 }
0317
0318 name_len_t name_length() const
0319 {
0320 if(m_alloc_type == anonymous_type)
0321 return 0;
0322 return *(move_detail::force_ptr<const name_len_t*>
0323 (reinterpret_cast<const char*>(this) + this->name_length_offset()));
0324 }
0325
0326 void *value() const
0327 { return const_cast<char*>((reinterpret_cast<const char*>(this) + this->value_offset())); }
0328
0329 template<class T>
0330 static block_header *block_header_from_value(T *value)
0331 {
0332 BOOST_ASSERT(is_ptr_aligned(value, ::boost::container::dtl::alignment_of<T>::value));
0333 block_header* hdr =
0334 const_cast<block_header*>
0335 (move_detail::force_ptr<const block_header*>
0336 (reinterpret_cast<const char*>(value) - value_offset()));
0337
0338
0339 BOOST_ASSERT(hdr->m_value_bytes % sizeof(T) == 0);
0340 return hdr;
0341 }
0342
0343 template<class Header>
0344 static block_header *from_first_header(Header *header)
0345 {
0346 BOOST_ASSERT(is_ptr_aligned(header));
0347 block_header * const hdr = move_detail::force_ptr<block_header*>(
0348 reinterpret_cast<char*>(header) + sm_between_headers<block_header, Header>::value);
0349
0350 BOOST_ASSERT(is_ptr_aligned(hdr));
0351 return hdr;
0352 }
0353
0354 template<class Header>
0355 static const block_header *from_first_header(const Header *header)
0356 { return from_first_header(const_cast<Header*>(header)); }
0357
0358 template<class Header>
0359 static Header *to_first_header(block_header *bheader)
0360 {
0361 BOOST_ASSERT(is_ptr_aligned(bheader));
0362 Header * hdr = move_detail::force_ptr<Header*>(
0363 reinterpret_cast<char*>(bheader) - sm_between_headers<block_header, Header>::value);
0364
0365 BOOST_ASSERT(is_ptr_aligned(hdr));
0366 return hdr;
0367 }
0368
0369 template<std::size_t TypeAlignment, class Header>
0370 static size_type front_space_with_header()
0371 { return sg_offsets_with_header<TypeAlignment, block_header, Header>::front_space; }
0372
0373 template<std::size_t TypeAlignment>
0374 static size_type front_space_without_header()
0375 { return sg_offsets_without_header<TypeAlignment, block_header>::front_space; }
0376
0377 void store_name_length(name_len_t namelen)
0378 {
0379 ::new( reinterpret_cast<char*>(this) + this->name_length_offset()
0380 , boost_container_new_t()
0381 ) name_len_t(namelen);
0382 }
0383
0384 private:
0385
0386 static size_type value_offset()
0387 { return size_type(sizeof(block_header)); }
0388
0389 template<std::size_t CharAlign>
0390 size_type name_offset() const
0391 { return get_rounded_size(this->name_length_offset()+sizeof(name_len_t), CharAlign); }
0392
0393 size_type name_length_offset() const
0394 {
0395 return this->value_offset() + get_rounded_size(m_value_bytes, ::boost::move_detail::alignment_of<name_len_t>::value);
0396 }
0397 };
0398
0399
0400 #else
0401
0402 #error "Incorrect BOOST_INTERPROCESS_SEGMENT_MANAGER_ABI value!"
0403
0404 #endif
0405
0406 template<class CharT>
0407 struct intrusive_compare_key
0408 {
0409 typedef CharT char_type;
0410
0411 intrusive_compare_key(const CharT* str_, std::size_t len_)
0412 : mp_str(str_), m_len(len_)
0413 {}
0414
0415 const CharT* str() const
0416 {
0417 return mp_str;
0418 }
0419
0420 std::size_t len() const
0421 {
0422 return m_len;
0423 }
0424
0425 const CharT* mp_str;
0426 std::size_t m_len;
0427 };
0428
0429
0430
0431 template<instance_type type>
0432 class instance_t
0433 {
0434 instance_t(){}
0435 };
0436
0437 template<class T>
0438 struct char_if_void
0439 {
0440 typedef T type;
0441 };
0442
0443 template<>
0444 struct char_if_void<void>
0445 {
0446 typedef char type;
0447 };
0448
0449 typedef instance_t<anonymous_type> anonymous_instance_t;
0450 typedef instance_t<unique_type> unique_instance_t;
0451
0452
0453 template<class Hook, class CharType, class SizeType>
0454 struct intrusive_value_type_impl
0455 : public Hook
0456 {
0457 private:
0458
0459 intrusive_value_type_impl(const intrusive_value_type_impl &);
0460 intrusive_value_type_impl& operator=(const intrusive_value_type_impl &);
0461
0462 public:
0463 typedef CharType char_type;
0464 typedef SizeType size_type;
0465 typedef block_header<size_type> block_header_t;
0466
0467 intrusive_value_type_impl(){}
0468
0469 CharType *name() const
0470 { return get_block_header()->template name<CharType>(); }
0471
0472 unsigned short name_length() const
0473 { return get_block_header()->name_length(); }
0474
0475 void *value() const
0476 { return get_block_header()->value(); }
0477
0478 private:
0479 const block_header_t *get_block_header() const
0480 { return block_header_t::from_first_header(this); }
0481 };
0482
0483 template<class CharType>
0484 class char_ptr_holder
0485 {
0486 public:
0487 char_ptr_holder(const CharType *name)
0488 : m_name(name)
0489 {}
0490
0491 char_ptr_holder(const anonymous_instance_t *)
0492 : m_name(static_cast<CharType*>(0))
0493 {}
0494
0495 char_ptr_holder(const unique_instance_t *)
0496 : m_name(reinterpret_cast<CharType*>(-1))
0497 {}
0498
0499 operator const CharType *()
0500 { return m_name; }
0501
0502 const CharType *get() const
0503 { return m_name; }
0504
0505 bool is_unique() const
0506 { return m_name == reinterpret_cast<CharType*>(-1); }
0507
0508 bool is_anonymous() const
0509 { return m_name == static_cast<CharType*>(0); }
0510
0511 private:
0512 const CharType *m_name;
0513 };
0514
0515
0516
0517 template<class CharT, class VoidPointer>
0518 struct index_key
0519 {
0520 typedef typename boost::intrusive::
0521 pointer_traits<VoidPointer>::template
0522 rebind_pointer<const CharT>::type const_char_ptr_t;
0523 typedef CharT char_type;
0524 typedef typename boost::intrusive::pointer_traits<const_char_ptr_t>::difference_type difference_type;
0525 typedef typename boost::move_detail::make_unsigned<difference_type>::type size_type;
0526
0527 private:
0528
0529 const_char_ptr_t mp_str;
0530
0531 size_type m_len;
0532 public:
0533
0534
0535 index_key (const char_type *nm, size_type length)
0536 : mp_str(nm), m_len(length)
0537 {}
0538
0539
0540 bool operator < (const index_key & right) const
0541 {
0542 return (m_len < right.m_len) ||
0543 (m_len == right.m_len &&
0544 std::char_traits<char_type>::compare
0545 (to_raw_pointer(mp_str),to_raw_pointer(right.mp_str), m_len) < 0);
0546 }
0547
0548
0549 bool operator == (const index_key & right) const
0550 {
0551 return m_len == right.m_len &&
0552 std::char_traits<char_type>::compare
0553 (to_raw_pointer(mp_str), to_raw_pointer(right.mp_str), m_len) == 0;
0554 }
0555
0556 void name(const CharT *nm)
0557 { mp_str = nm; }
0558
0559 void name_length(size_type len)
0560 { m_len = len; }
0561
0562 const CharT *name() const
0563 { return to_raw_pointer(mp_str); }
0564
0565 size_type name_length() const
0566 { return m_len; }
0567 };
0568
0569
0570
0571 template<class VoidPointer>
0572 struct index_data
0573 {
0574 typedef VoidPointer void_pointer;
0575 void_pointer m_ptr;
0576 explicit index_data(void *ptr) : m_ptr(ptr){}
0577
0578 void *value() const
0579 { return static_cast<void*>(to_raw_pointer(m_ptr)); }
0580 };
0581
0582 template<class MemoryAlgorithm>
0583 struct segment_manager_base_type
0584 { typedef segment_manager_base<MemoryAlgorithm> type; };
0585
0586 template<class CharT, class MemoryAlgorithm>
0587 struct index_config
0588 {
0589 typedef typename MemoryAlgorithm::void_pointer void_pointer;
0590 typedef CharT char_type;
0591 typedef index_key<CharT, void_pointer> key_type;
0592 typedef index_data<void_pointer> mapped_type;
0593 typedef typename segment_manager_base_type
0594 <MemoryAlgorithm>::type segment_manager_base;
0595
0596 template<class HeaderBase>
0597 struct intrusive_value_type
0598 {
0599 typedef intrusive_value_type_impl
0600 < HeaderBase
0601 , CharT
0602 , typename segment_manager_base::size_type
0603 > type;
0604 };
0605
0606 typedef intrusive_compare_key<CharT> compare_key_type;
0607 };
0608
0609 template<class Iterator, bool intrusive>
0610 class segment_manager_iterator_value_adaptor
0611 {
0612 typedef typename Iterator::value_type iterator_val_t;
0613 typedef typename iterator_val_t::char_type char_type;
0614
0615 public:
0616 segment_manager_iterator_value_adaptor(const typename Iterator::value_type &val)
0617 : m_val(&val)
0618 {}
0619
0620 const char_type *name() const
0621 { return m_val->name(); }
0622
0623 unsigned short name_length() const
0624 { return m_val->name_length(); }
0625
0626 const void *value() const
0627 { return m_val->value(); }
0628
0629 const typename Iterator::value_type *m_val;
0630 };
0631
0632
0633 template<class Iterator>
0634 class segment_manager_iterator_value_adaptor<Iterator, false>
0635 {
0636 typedef typename Iterator::value_type iterator_val_t;
0637 typedef typename iterator_val_t::first_type first_type;
0638 typedef typename iterator_val_t::second_type second_type;
0639 typedef typename first_type::char_type char_type;
0640 typedef typename first_type::size_type size_type;
0641
0642 public:
0643 segment_manager_iterator_value_adaptor(const typename Iterator::value_type &val)
0644 : m_val(&val)
0645 {}
0646
0647 const char_type *name() const
0648 { return m_val->first.name(); }
0649
0650 size_type name_length() const
0651 { return m_val->first.name_length(); }
0652
0653 const void *value() const
0654 {
0655 return move_detail::force_ptr<block_header<size_type>*>
0656 (to_raw_pointer(m_val->second.m_ptr))->value();
0657 }
0658
0659 const typename Iterator::value_type *m_val;
0660 };
0661
0662 template<class Iterator, bool intrusive>
0663 struct segment_manager_iterator_transform
0664 {
0665 typedef segment_manager_iterator_value_adaptor<Iterator, intrusive> result_type;
0666
0667 template <class T> result_type operator()(const T &arg) const
0668 { return result_type(arg); }
0669 };
0670
0671
0672 template<class T>
0673 inline T* null_or_bad_alloc(bool dothrow)
0674 {
0675 if (dothrow)
0676 throw bad_alloc();
0677 return 0;
0678 }
0679
0680 template<class T>
0681 inline T* null_or_already_exists(bool dothrow)
0682 {
0683 if (dothrow)
0684 throw interprocess_exception(already_exists_error);
0685 return 0;
0686 }
0687
0688 }
0689
0690
0691
0692 static const ipcdetail::anonymous_instance_t * anonymous_instance = 0;
0693 static const ipcdetail::unique_instance_t * unique_instance = 0;
0694
0695 namespace ipcdetail_really_deep_namespace {
0696
0697
0698
0699 struct dummy
0700 {
0701 dummy()
0702 {
0703 (void)anonymous_instance;
0704 (void)unique_instance;
0705 }
0706 };
0707
0708 }
0709
0710 }}
0711
0712 #include <boost/interprocess/detail/config_end.hpp>
0713
0714 #endif
0715