Warning, file /include/boost/interprocess/indexes/iunordered_set_index.hpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_INTERPROCESS_IUNORDERED_SET_INDEX_HPP
0012 #define BOOST_INTERPROCESS_IUNORDERED_SET_INDEX_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/detail/utilities.hpp>
0026 #include <boost/interprocess/allocators/allocator.hpp>
0027 #include <boost/interprocess/containers/vector.hpp>
0028 #include <boost/intrusive/unordered_set.hpp>
0029 #include <boost/intrusive/detail/minimal_pair_header.hpp>
0030 #include <boost/intrusive/detail/minimal_less_equal_header.hpp> //std::less
0031 #include <boost/container/detail/minimal_char_traits_header.hpp> //std::char_traits
0032 #include <boost/container/detail/placement_new.hpp>
0033 #include <boost/intrusive/detail/hash.hpp>
0034
0035
0036
0037
0038
0039 namespace boost { namespace interprocess {
0040
0041 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0042
0043
0044
0045 template <class MapConfig>
0046 struct iunordered_set_index_aux
0047 {
0048 typedef typename
0049 MapConfig::segment_manager_base segment_manager_base;
0050
0051 typedef typename
0052 segment_manager_base::void_pointer void_pointer;
0053
0054 typedef typename bi::make_unordered_set_base_hook
0055 < bi::void_pointer<void_pointer>
0056 >::type derivation_hook;
0057
0058 typedef typename MapConfig::template
0059 intrusive_value_type<derivation_hook>::type value_type;
0060
0061 typedef typename MapConfig::
0062 intrusive_compare_key_type intrusive_compare_key_type;
0063
0064 typedef std::equal_to<value_type> value_equal;
0065
0066 typedef typename MapConfig::char_type char_type;
0067
0068 struct equal_function
0069 {
0070 bool operator()(const intrusive_compare_key_type &i, const value_type &b) const
0071 {
0072 return (i.m_len == b.name_length()) &&
0073 (std::char_traits<char_type>::compare
0074 (i.mp_str, b.name(), i.m_len) == 0);
0075 }
0076
0077 bool operator()(const value_type &b, const intrusive_compare_key_type &i) const
0078 {
0079 return (i.m_len == b.name_length()) &&
0080 (std::char_traits<char_type>::compare
0081 (i.mp_str, b.name(), i.m_len) == 0);
0082 }
0083
0084 bool operator()(const value_type &b1, const value_type &b2) const
0085 {
0086 return (b1.name_length() == b2.name_length()) &&
0087 (std::char_traits<char_type>::compare
0088 (b1.name(), b2.name(), b1.name_length()) == 0);
0089 }
0090 };
0091
0092 struct hash_function
0093 {
0094 typedef value_type argument_type;
0095 typedef std::size_t result_type;
0096
0097 std::size_t hash_char_range(const char_type* beg, const char_type* end) const
0098 {
0099 std::size_t seed = 0;
0100 while (beg != end) {
0101 boost::intrusive::detail::hash_combine_size_t(seed, boost::intrusive::detail::internal_hash_functor<char_type>()(*beg));
0102 ++beg;
0103 }
0104 return seed;
0105 }
0106
0107 std::size_t operator()(const value_type &val) const
0108 {
0109 const char_type* beg = ipcdetail::to_raw_pointer(val.name()),
0110 * end = beg + val.name_length();
0111 return hash_char_range(beg, end);
0112 }
0113
0114 std::size_t operator()(const intrusive_compare_key_type &i) const
0115 {
0116 const char_type *beg = i.mp_str,
0117 *end = beg + i.m_len;
0118 return hash_char_range(beg, end);
0119 }
0120 };
0121
0122 typedef typename bi::make_unordered_set
0123 < value_type
0124 , bi::hash<hash_function>
0125 , bi::equal<equal_function>
0126 , bi::size_type<typename segment_manager_base::size_type>
0127 >::type index_t;
0128 typedef typename index_t::bucket_type bucket_type;
0129 typedef allocator
0130 <bucket_type, segment_manager_base> allocator_type;
0131
0132 struct allocator_holder
0133 {
0134 allocator_holder(segment_manager_base *mngr)
0135 : alloc(mngr)
0136 {}
0137 allocator_type alloc;
0138 bucket_type init_bucket;
0139 };
0140 };
0141 #endif
0142
0143
0144
0145
0146 template <class MapConfig>
0147 class iunordered_set_index
0148
0149 : private iunordered_set_index_aux<MapConfig>::allocator_holder
0150 , public iunordered_set_index_aux<MapConfig>::index_t
0151 {
0152 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0153 typedef iunordered_set_index_aux<MapConfig> index_aux;
0154 typedef typename index_aux::index_t index_type;
0155 typedef typename MapConfig::
0156 intrusive_compare_key_type intrusive_compare_key_type;
0157 typedef typename index_aux::equal_function equal_function;
0158 typedef typename index_aux::hash_function hash_function;
0159 typedef typename MapConfig::char_type char_type;
0160 typedef typename
0161 iunordered_set_index_aux<MapConfig>::allocator_type allocator_type;
0162 typedef typename
0163 iunordered_set_index_aux<MapConfig>::allocator_holder allocator_holder;
0164 #endif
0165
0166 public:
0167 typedef typename index_type::iterator iterator;
0168 typedef typename index_type::const_iterator const_iterator;
0169 typedef typename index_type::insert_commit_data insert_commit_data;
0170 typedef typename index_type::value_type value_type;
0171 typedef typename index_type::bucket_ptr bucket_ptr;
0172 typedef typename index_type::bucket_type bucket_type;
0173 typedef typename index_type::bucket_traits bucket_traits;
0174 typedef typename index_type::size_type size_type;
0175 typedef typename index_type::difference_type difference_type;
0176
0177 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0178 private:
0179 typedef typename index_aux::
0180 segment_manager_base segment_manager_base;
0181
0182 static const std::size_t InitBufferSize = 64;
0183
0184 static bucket_ptr create_buckets(allocator_type &alloc, size_type num)
0185 {
0186 num = index_type::suggested_upper_bucket_count(num);
0187 bucket_ptr buckets = alloc.allocate(num);
0188 bucket_ptr buckets_init = buckets;
0189 for(size_type i = 0; i < num; ++i){
0190 ::new(to_raw_pointer(buckets_init++), boost_container_new_t())bucket_type();
0191 }
0192 return buckets;
0193 }
0194
0195 static size_type shrink_buckets
0196 ( bucket_ptr buckets, size_type old_size
0197 , allocator_type &alloc, size_type new_size)
0198 {
0199 if(old_size <= new_size )
0200 return old_size;
0201 size_type received_size = new_size;
0202 if(!alloc.allocation_command
0203 (boost::interprocess::try_shrink_in_place | boost::interprocess::nothrow_allocation, old_size, received_size, buckets)){
0204 return old_size;
0205 }
0206
0207 for( bucket_type *p = ipcdetail::to_raw_pointer(buckets) + received_size
0208 , *pend = ipcdetail::to_raw_pointer(buckets) + old_size
0209 ; p != pend
0210 ; ++p){
0211 p->~bucket_type();
0212 }
0213
0214 bucket_ptr shunk_p = alloc.allocation_command
0215 (boost::interprocess::shrink_in_place | boost::interprocess::nothrow_allocation, received_size, received_size, buckets);
0216 BOOST_ASSERT(buckets == shunk_p); (void)shunk_p;
0217
0218 bucket_ptr buckets_init = buckets + difference_type(received_size);
0219 for(size_type i = 0; i < (old_size - received_size); ++i){
0220 to_raw_pointer(buckets_init++)->~bucket_type();
0221 }
0222 return received_size;
0223 }
0224
0225 static bucket_ptr expand_or_create_buckets
0226 ( bucket_ptr old_buckets, const size_type old_num
0227 , allocator_type &alloc, const size_type new_num)
0228 {
0229 size_type received_size = new_num;
0230 bucket_ptr reuse(old_buckets);
0231 bucket_ptr ret = alloc.allocation_command
0232 (boost::interprocess::expand_fwd | boost::interprocess::allocate_new, new_num, received_size, reuse);
0233 if(ret == old_buckets){
0234 bucket_ptr buckets_init = old_buckets + difference_type(old_num);
0235 for(size_type i = 0; i < (new_num - old_num); ++i){
0236 ::new(to_raw_pointer(buckets_init++), boost_container_new_t())bucket_type();
0237 }
0238 }
0239 else{
0240 bucket_ptr buckets_init = ret;
0241 for(size_type i = 0; i < new_num; ++i){
0242 ::new(to_raw_pointer(buckets_init++), boost_container_new_t())bucket_type();
0243 }
0244 }
0245 return ret;
0246 }
0247
0248 static void destroy_buckets
0249 (allocator_type &alloc, bucket_ptr buckets, size_type num)
0250 {
0251 bucket_ptr buckets_destroy = buckets;
0252 for(size_type i = 0; i < num; ++i){
0253 to_raw_pointer(buckets_destroy++)->~bucket_type();
0254 }
0255 alloc.deallocate(buckets, num);
0256 }
0257
0258 iunordered_set_index<MapConfig>* get_this_pointer()
0259 { return this; }
0260
0261 #endif
0262
0263 public:
0264
0265
0266 iunordered_set_index(segment_manager_base *mngr)
0267 : allocator_holder(mngr)
0268 , index_type(bucket_traits(&get_this_pointer()->init_bucket, 1))
0269 {}
0270
0271 ~iunordered_set_index()
0272 {
0273 index_type::clear();
0274 if(index_type::bucket_pointer() != bucket_ptr(&this->init_bucket)){
0275 destroy_buckets(this->alloc, index_type::bucket_pointer(), index_type::bucket_count());
0276 }
0277 }
0278
0279
0280
0281 void reserve(size_type new_n)
0282 {
0283
0284 size_type old_n = this->bucket_count();
0285 if(new_n <= old_n)
0286 return;
0287 bucket_ptr old_p = this->bucket_pointer();
0288 new_n = index_type::suggested_upper_bucket_count(new_n);
0289 bucket_ptr new_p;
0290
0291 BOOST_TRY{
0292 if(old_p != bucket_ptr(&this->init_bucket))
0293 new_p = expand_or_create_buckets(old_p, old_n, this->alloc, new_n);
0294 else
0295 new_p = create_buckets(this->alloc, new_n);
0296 }
0297 BOOST_CATCH(...){
0298 return;
0299 } BOOST_CATCH_END
0300
0301
0302 this->rehash(bucket_traits(new_p, new_n));
0303 if(new_p != old_p && old_p != bucket_ptr(&this->init_bucket)){
0304 destroy_buckets(this->alloc, old_p, old_n);
0305 }
0306 }
0307
0308
0309
0310 void shrink_to_fit()
0311 {
0312 size_type cur_size = this->size();
0313 size_type cur_count = this->bucket_count();
0314 bucket_ptr old_p = this->bucket_pointer();
0315
0316 if(!this->size() && old_p != bucket_ptr(&this->init_bucket)){
0317 this->rehash(bucket_traits(bucket_ptr(&this->init_bucket), 1));
0318 destroy_buckets(this->alloc, old_p, cur_count);
0319 }
0320 else{
0321 size_type sug_count = 0;
0322 sug_count = index_type::suggested_upper_bucket_count(cur_size);
0323
0324 if(sug_count >= cur_count)
0325 return;
0326
0327 BOOST_TRY{
0328 shrink_buckets(old_p, cur_count, this->alloc, sug_count);
0329 }
0330 BOOST_CATCH(...){
0331 return;
0332 } BOOST_CATCH_END
0333
0334
0335
0336 this->rehash(bucket_traits(old_p, sug_count));
0337 }
0338 }
0339
0340 iterator find(const intrusive_compare_key_type &key)
0341 { return index_type::find(key, hash_function(), equal_function()); }
0342
0343 const_iterator find(const intrusive_compare_key_type &key) const
0344 { return index_type::find(key, hash_function(), equal_function()); }
0345
0346 std::pair<iterator, bool>insert_check
0347 (const intrusive_compare_key_type &key, insert_commit_data &commit_data)
0348 { return index_type::insert_check(key, hash_function(), equal_function(), commit_data); }
0349
0350 iterator insert_commit(value_type &val, insert_commit_data &commit_data)
0351 {
0352 iterator it = index_type::insert_commit(val, commit_data);
0353 size_type cur_size = this->size();
0354 if(cur_size > this->bucket_count()){
0355 BOOST_TRY{
0356 this->reserve(cur_size);
0357 }
0358 BOOST_CATCH(...){
0359
0360
0361
0362
0363
0364
0365
0366 index_type::erase(it);
0367 BOOST_RETHROW
0368 } BOOST_CATCH_END
0369 }
0370 return it;
0371 }
0372 };
0373
0374 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
0375
0376
0377
0378 template<class MapConfig>
0379 struct is_intrusive_index
0380 <boost::interprocess::iunordered_set_index<MapConfig> >
0381 {
0382 static const bool value = true;
0383 };
0384 #endif
0385
0386 }}
0387
0388 #include <boost/interprocess/detail/config_end.hpp>
0389
0390 #endif