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