epoc32/include/stdapis/boost/multi_index/hashed_index.hpp
author William Roberts <williamr@symbian.org>
Tue, 16 Mar 2010 16:12:26 +0000
branchSymbian2
changeset 2 2fe1408b6811
permissions -rw-r--r--
Final list of Symbian^2 public API header files
williamr@2
     1
/* Copyright 2003-2007 Joaquín M López Muñoz.
williamr@2
     2
 * Distributed under the Boost Software License, Version 1.0.
williamr@2
     3
 * (See accompanying file LICENSE_1_0.txt or copy at
williamr@2
     4
 * http://www.boost.org/LICENSE_1_0.txt)
williamr@2
     5
 *
williamr@2
     6
 * See http://www.boost.org/libs/multi_index for library home page.
williamr@2
     7
 */
williamr@2
     8
williamr@2
     9
#ifndef BOOST_MULTI_INDEX_HASHED_INDEX_HPP
williamr@2
    10
#define BOOST_MULTI_INDEX_HASHED_INDEX_HPP
williamr@2
    11
williamr@2
    12
#if defined(_MSC_VER)&&(_MSC_VER>=1200)
williamr@2
    13
#pragma once
williamr@2
    14
#endif
williamr@2
    15
williamr@2
    16
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
williamr@2
    17
#include <algorithm>
williamr@2
    18
#include <boost/call_traits.hpp>
williamr@2
    19
#include <boost/detail/allocator_utilities.hpp>
williamr@2
    20
#include <boost/detail/no_exceptions_support.hpp>
williamr@2
    21
#include <boost/detail/workaround.hpp>
williamr@2
    22
#include <boost/limits.hpp>
williamr@2
    23
#include <boost/mpl/push_front.hpp>
williamr@2
    24
#include <boost/multi_index/detail/access_specifier.hpp>
williamr@2
    25
#include <boost/multi_index/detail/auto_space.hpp>
williamr@2
    26
#include <boost/multi_index/detail/bucket_array.hpp>
williamr@2
    27
#include <boost/multi_index/detail/hash_index_iterator.hpp>
williamr@2
    28
#include <boost/multi_index/detail/modify_key_adaptor.hpp>
williamr@2
    29
#include <boost/multi_index/detail/safe_ctr_proxy.hpp>
williamr@2
    30
#include <boost/multi_index/detail/safe_mode.hpp>
williamr@2
    31
#include <boost/multi_index/detail/scope_guard.hpp>
williamr@2
    32
#include <boost/multi_index/hashed_index_fwd.hpp>
williamr@2
    33
#include <boost/tuple/tuple.hpp>
williamr@2
    34
#include <cstddef>
williamr@2
    35
#include <functional>
williamr@2
    36
#include <utility>
williamr@2
    37
williamr@2
    38
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
williamr@2
    39
#include <boost/serialization/nvp.hpp>
williamr@2
    40
#endif
williamr@2
    41
williamr@2
    42
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
williamr@2
    43
#define BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT                       \
williamr@2
    44
  detail::scope_guard BOOST_JOIN(check_invariant_,__LINE__)=                 \
williamr@2
    45
    detail::make_obj_guard(*this,&hashed_index::check_invariant_);           \
williamr@2
    46
  BOOST_JOIN(check_invariant_,__LINE__).touch();
williamr@2
    47
#else
williamr@2
    48
#define BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT
williamr@2
    49
#endif
williamr@2
    50
williamr@2
    51
namespace boost{
williamr@2
    52
williamr@2
    53
namespace multi_index{
williamr@2
    54
williamr@2
    55
namespace detail{
williamr@2
    56
williamr@2
    57
/* hashed_index adds a layer of hashed indexing to a given Super */
williamr@2
    58
williamr@2
    59
/* Most of the implementation of unique and non-unique indices is
williamr@2
    60
 * shared. We tell from one another on instantiation time by using
williamr@2
    61
 * these tags.
williamr@2
    62
 */
williamr@2
    63
williamr@2
    64
struct hashed_unique_tag{};
williamr@2
    65
struct hashed_non_unique_tag{};
williamr@2
    66
williamr@2
    67
template<
williamr@2
    68
  typename KeyFromValue,typename Hash,typename Pred,
williamr@2
    69
  typename SuperMeta,typename TagList,typename Category
williamr@2
    70
>
williamr@2
    71
class hashed_index:
williamr@2
    72
  BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS SuperMeta::type
williamr@2
    73
williamr@2
    74
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
williamr@2
    75
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
williamr@2
    76
  ,public safe_ctr_proxy_impl<
williamr@2
    77
    hashed_index_iterator<
williamr@2
    78
      hashed_index_node<typename SuperMeta::type::node_type>,
williamr@2
    79
      bucket_array<typename SuperMeta::type::final_allocator_type> >,
williamr@2
    80
    hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category> >
williamr@2
    81
#else
williamr@2
    82
  ,public safe_mode::safe_container<
williamr@2
    83
    hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category> >
williamr@2
    84
#endif
williamr@2
    85
#endif
williamr@2
    86
williamr@2
    87
{ 
williamr@2
    88
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
williamr@2
    89
    BOOST_WORKAROUND(__MWERKS__,<=0x3003)
williamr@2
    90
/* The "ISO C++ Template Parser" option in CW8.3 has a problem with the
williamr@2
    91
 * lifetime of const references bound to temporaries --precisely what
williamr@2
    92
 * scopeguards are.
williamr@2
    93
 */
williamr@2
    94
williamr@2
    95
#pragma parse_mfunc_templ off
williamr@2
    96
#endif
williamr@2
    97
williamr@2
    98
  typedef typename SuperMeta::type                   super;
williamr@2
    99
williamr@2
   100
protected:
williamr@2
   101
  typedef hashed_index_node<
williamr@2
   102
    typename super::node_type>                       node_type;
williamr@2
   103
  typedef bucket_array<
williamr@2
   104
    typename super::final_allocator_type>            bucket_array_type;
williamr@2
   105
williamr@2
   106
public:
williamr@2
   107
  /* types */
williamr@2
   108
williamr@2
   109
  typedef typename KeyFromValue::result_type         key_type;
williamr@2
   110
  typedef typename node_type::value_type             value_type;
williamr@2
   111
  typedef KeyFromValue                               key_from_value;
williamr@2
   112
  typedef Hash                                       hasher;
williamr@2
   113
  typedef Pred                                       key_equal;
williamr@2
   114
  typedef tuple<std::size_t,
williamr@2
   115
    key_from_value,hasher,key_equal>                 ctor_args;
williamr@2
   116
  typedef typename super::final_allocator_type       allocator_type;
williamr@2
   117
  typedef typename allocator_type::pointer           pointer;
williamr@2
   118
  typedef typename allocator_type::const_pointer     const_pointer;
williamr@2
   119
  typedef typename allocator_type::reference         reference;
williamr@2
   120
  typedef typename allocator_type::const_reference   const_reference;
williamr@2
   121
  typedef std::size_t                                size_type;      
williamr@2
   122
  typedef std::ptrdiff_t                             difference_type;
williamr@2
   123
williamr@2
   124
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
williamr@2
   125
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
williamr@2
   126
  typedef safe_mode::safe_iterator<
williamr@2
   127
    hashed_index_iterator<
williamr@2
   128
      node_type,bucket_array_type>,
williamr@2
   129
    safe_ctr_proxy<
williamr@2
   130
      hashed_index_iterator<
williamr@2
   131
        node_type,bucket_array_type> > >             iterator;
williamr@2
   132
#else
williamr@2
   133
  typedef safe_mode::safe_iterator<
williamr@2
   134
    hashed_index_iterator<
williamr@2
   135
      node_type,bucket_array_type>,
williamr@2
   136
    hashed_index>                                    iterator;
williamr@2
   137
#endif
williamr@2
   138
#else
williamr@2
   139
  typedef hashed_index_iterator<
williamr@2
   140
    node_type,bucket_array_type>                     iterator;
williamr@2
   141
#endif
williamr@2
   142
williamr@2
   143
  typedef iterator                                   const_iterator;
williamr@2
   144
williamr@2
   145
  typedef iterator                                   local_iterator;
williamr@2
   146
  typedef const_iterator                             const_local_iterator;
williamr@2
   147
  typedef TagList                                    tag_list;
williamr@2
   148
williamr@2
   149
protected:
williamr@2
   150
  typedef typename super::final_node_type     final_node_type;
williamr@2
   151
  typedef tuples::cons<
williamr@2
   152
    ctor_args, 
williamr@2
   153
    typename super::ctor_args_list>           ctor_args_list;
williamr@2
   154
  typedef typename mpl::push_front<
williamr@2
   155
    typename super::index_type_list,
williamr@2
   156
    hashed_index>::type                       index_type_list;
williamr@2
   157
  typedef typename mpl::push_front<
williamr@2
   158
    typename super::iterator_type_list,
williamr@2
   159
    iterator>::type                           iterator_type_list;
williamr@2
   160
  typedef typename mpl::push_front<
williamr@2
   161
    typename super::const_iterator_type_list,
williamr@2
   162
    const_iterator>::type                     const_iterator_type_list;
williamr@2
   163
  typedef typename super::copy_map_type       copy_map_type;
williamr@2
   164
williamr@2
   165
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
williamr@2
   166
  typedef typename super::index_saver_type    index_saver_type;
williamr@2
   167
  typedef typename super::index_loader_type   index_loader_type;
williamr@2
   168
#endif
williamr@2
   169
williamr@2
   170
private:
williamr@2
   171
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
williamr@2
   172
#if BOOST_WORKAROUND(BOOST_MSVC,<1300)
williamr@2
   173
  typedef safe_ctr_proxy_impl<
williamr@2
   174
    hashed_index_iterator<
williamr@2
   175
      node_type,
williamr@2
   176
      bucket_array_type>,
williamr@2
   177
    hashed_index>                             safe_super;
williamr@2
   178
#else
williamr@2
   179
  typedef safe_mode::safe_container<
williamr@2
   180
    hashed_index>                             safe_super;
williamr@2
   181
#endif
williamr@2
   182
#endif
williamr@2
   183
williamr@2
   184
  typedef typename call_traits<value_type>::param_type value_param_type;
williamr@2
   185
  typedef typename call_traits<
williamr@2
   186
    key_type>::param_type                              key_param_type;
williamr@2
   187
williamr@2
   188
public:
williamr@2
   189
williamr@2
   190
  /* construct/destroy/copy
williamr@2
   191
   * Default and copy ctors are in the protected section as indices are
williamr@2
   192
   * not supposed to be created on their own. No range ctor either.
williamr@2
   193
   */
williamr@2
   194
williamr@2
   195
  hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& operator=(
williamr@2
   196
    const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)
williamr@2
   197
  {
williamr@2
   198
    this->final()=x.final();
williamr@2
   199
    return *this;
williamr@2
   200
  }
williamr@2
   201
williamr@2
   202
  allocator_type get_allocator()const
williamr@2
   203
  {
williamr@2
   204
    return this->final().get_allocator();
williamr@2
   205
  }
williamr@2
   206
williamr@2
   207
  /* size and capacity */
williamr@2
   208
williamr@2
   209
  bool      empty()const{return this->final_empty_();}
williamr@2
   210
  size_type size()const{return this->final_size_();}
williamr@2
   211
  size_type max_size()const{return this->final_max_size_();}
williamr@2
   212
williamr@2
   213
  /* iterators */
williamr@2
   214
williamr@2
   215
  iterator begin()
williamr@2
   216
  {
williamr@2
   217
    return make_iterator(
williamr@2
   218
      node_type::from_impl(buckets.at(first_bucket)->next()));
williamr@2
   219
  }
williamr@2
   220
williamr@2
   221
  const_iterator begin()const
williamr@2
   222
  {
williamr@2
   223
    return make_iterator(
williamr@2
   224
      node_type::from_impl(buckets.at(first_bucket)->next()));
williamr@2
   225
  }
williamr@2
   226
williamr@2
   227
  iterator       end(){return make_iterator(header());}
williamr@2
   228
  const_iterator end()const{return make_iterator(header());}
williamr@2
   229
williamr@2
   230
  /* modifiers */
williamr@2
   231
williamr@2
   232
  std::pair<iterator,bool> insert(value_param_type x)
williamr@2
   233
  {
williamr@2
   234
    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
williamr@2
   235
    std::pair<final_node_type*,bool> p=this->final_insert_(x);
williamr@2
   236
    return std::pair<iterator,bool>(make_iterator(p.first),p.second);
williamr@2
   237
  }
williamr@2
   238
williamr@2
   239
  iterator insert(iterator position,value_param_type x)
williamr@2
   240
  {
williamr@2
   241
    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
williamr@2
   242
    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
williamr@2
   243
    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
williamr@2
   244
    std::pair<final_node_type*,bool> p=this->final_insert_(
williamr@2
   245
      x,static_cast<final_node_type*>(position.get_node()));
williamr@2
   246
    return make_iterator(p.first);
williamr@2
   247
  }
williamr@2
   248
    
williamr@2
   249
  template<typename InputIterator>
williamr@2
   250
  void insert(InputIterator first,InputIterator last)
williamr@2
   251
  {
williamr@2
   252
    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
williamr@2
   253
    iterator hint=end();
williamr@2
   254
    for(;first!=last;++first)hint=insert(hint,*first);
williamr@2
   255
  }
williamr@2
   256
williamr@2
   257
  iterator erase(iterator position)
williamr@2
   258
  {
williamr@2
   259
    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
williamr@2
   260
    BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
williamr@2
   261
    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
williamr@2
   262
    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
williamr@2
   263
    this->final_erase_(static_cast<final_node_type*>(position++.get_node()));
williamr@2
   264
    return position;
williamr@2
   265
  }
williamr@2
   266
williamr@2
   267
  size_type erase(key_param_type k)
williamr@2
   268
  {
williamr@2
   269
    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
williamr@2
   270
williamr@2
   271
    size_type               s=0;
williamr@2
   272
    std::size_t             buc=buckets.position(hash(k));
williamr@2
   273
    hashed_index_node_impl* x=buckets.at(buc);
williamr@2
   274
    hashed_index_node_impl* y=x->next();
williamr@2
   275
    while(y!=x){
williamr@2
   276
      if(eq(k,key(node_type::from_impl(y)->value()))){
williamr@2
   277
        bool b;
williamr@2
   278
        do{
williamr@2
   279
          hashed_index_node_impl* z=y->next();
williamr@2
   280
          b=z!=x&&eq(
williamr@2
   281
            key(node_type::from_impl(y)->value()),
williamr@2
   282
            key(node_type::from_impl(z)->value()));
williamr@2
   283
          this->final_erase_(
williamr@2
   284
            static_cast<final_node_type*>(node_type::from_impl(y)));
williamr@2
   285
          y=z;
williamr@2
   286
          ++s;
williamr@2
   287
        }while(b);
williamr@2
   288
        break;
williamr@2
   289
      }
williamr@2
   290
      y=y->next();
williamr@2
   291
    }
williamr@2
   292
    return s;
williamr@2
   293
  }
williamr@2
   294
williamr@2
   295
  iterator erase(iterator first,iterator last)
williamr@2
   296
  {
williamr@2
   297
    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(first);
williamr@2
   298
    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(last);
williamr@2
   299
    BOOST_MULTI_INDEX_CHECK_IS_OWNER(first,*this);
williamr@2
   300
    BOOST_MULTI_INDEX_CHECK_IS_OWNER(last,*this);
williamr@2
   301
    BOOST_MULTI_INDEX_CHECK_VALID_RANGE(first,last);
williamr@2
   302
    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
williamr@2
   303
    while(first!=last){
williamr@2
   304
      first=erase(first);
williamr@2
   305
    }
williamr@2
   306
    return first;
williamr@2
   307
  }
williamr@2
   308
williamr@2
   309
  bool replace(iterator position,value_param_type x)
williamr@2
   310
  {
williamr@2
   311
    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
williamr@2
   312
    BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
williamr@2
   313
    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
williamr@2
   314
    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
williamr@2
   315
    return this->final_replace_(
williamr@2
   316
      x,static_cast<final_node_type*>(position.get_node()));
williamr@2
   317
  }
williamr@2
   318
williamr@2
   319
  template<typename Modifier>
williamr@2
   320
  bool modify(iterator position,Modifier mod)
williamr@2
   321
  {
williamr@2
   322
    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
williamr@2
   323
    BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
williamr@2
   324
    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
williamr@2
   325
    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
williamr@2
   326
williamr@2
   327
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
williamr@2
   328
    /* MSVC++ 6.0 optimizer on safe mode code chokes if this
williamr@2
   329
     * this is not added. Left it for all compilers as it does no
williamr@2
   330
     * harm.
williamr@2
   331
     */
williamr@2
   332
williamr@2
   333
    position.detach();
williamr@2
   334
#endif
williamr@2
   335
williamr@2
   336
    return this->final_modify_(
williamr@2
   337
      mod,static_cast<final_node_type*>(position.get_node()));
williamr@2
   338
  }
williamr@2
   339
williamr@2
   340
  template<typename Modifier>
williamr@2
   341
  bool modify_key(iterator position,Modifier mod)
williamr@2
   342
  {
williamr@2
   343
    BOOST_MULTI_INDEX_CHECK_VALID_ITERATOR(position);
williamr@2
   344
    BOOST_MULTI_INDEX_CHECK_DEREFERENCEABLE_ITERATOR(position);
williamr@2
   345
    BOOST_MULTI_INDEX_CHECK_IS_OWNER(position,*this);
williamr@2
   346
    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
williamr@2
   347
    return modify(
williamr@2
   348
      position,modify_key_adaptor<Modifier,value_type,KeyFromValue>(mod,key));
williamr@2
   349
  }
williamr@2
   350
williamr@2
   351
  void clear()
williamr@2
   352
  {
williamr@2
   353
    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
williamr@2
   354
    this->final_clear_();
williamr@2
   355
  }
williamr@2
   356
williamr@2
   357
  void swap(hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)
williamr@2
   358
  {
williamr@2
   359
    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
williamr@2
   360
    this->final_swap_(x.final());
williamr@2
   361
  }
williamr@2
   362
williamr@2
   363
  /* observers */
williamr@2
   364
williamr@2
   365
  key_from_value key_extractor()const{return key;}
williamr@2
   366
  hasher         hash_function()const{return hash;}
williamr@2
   367
  key_equal      key_eq()const{return eq;}
williamr@2
   368
  
williamr@2
   369
  /* lookup */
williamr@2
   370
williamr@2
   371
  /* Internally, these ops rely on const_iterator being the same
williamr@2
   372
   * type as iterator.
williamr@2
   373
   */
williamr@2
   374
williamr@2
   375
  template<typename CompatibleKey>
williamr@2
   376
  iterator find(const CompatibleKey& k)const
williamr@2
   377
  {
williamr@2
   378
    return find(k,hash,eq);
williamr@2
   379
  }
williamr@2
   380
williamr@2
   381
  template<
williamr@2
   382
    typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
williamr@2
   383
  >
williamr@2
   384
  iterator find(
williamr@2
   385
    const CompatibleKey& k,
williamr@2
   386
    const CompatibleHash& hash,const CompatiblePred& eq)const
williamr@2
   387
  {
williamr@2
   388
    std::size_t             buc=buckets.position(hash(k));
williamr@2
   389
    hashed_index_node_impl* x=buckets.at(buc);
williamr@2
   390
    hashed_index_node_impl* y=x->next();
williamr@2
   391
    while(y!=x){
williamr@2
   392
      if(eq(k,key(node_type::from_impl(y)->value()))){
williamr@2
   393
        return make_iterator(node_type::from_impl(y));
williamr@2
   394
      }
williamr@2
   395
      y=y->next();
williamr@2
   396
    }
williamr@2
   397
    return end();
williamr@2
   398
  }
williamr@2
   399
williamr@2
   400
  template<typename CompatibleKey>
williamr@2
   401
  size_type count(const CompatibleKey& k)const
williamr@2
   402
  {
williamr@2
   403
    return count(k,hash,eq);
williamr@2
   404
  }
williamr@2
   405
williamr@2
   406
  template<
williamr@2
   407
    typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
williamr@2
   408
  >
williamr@2
   409
  size_type count(
williamr@2
   410
    const CompatibleKey& k,
williamr@2
   411
    const CompatibleHash& hash,const CompatiblePred& eq)const
williamr@2
   412
  {
williamr@2
   413
    size_type               res=0;
williamr@2
   414
    std::size_t             buc=buckets.position(hash(k));
williamr@2
   415
    hashed_index_node_impl* x=buckets.at(buc);
williamr@2
   416
    hashed_index_node_impl* y=x->next();
williamr@2
   417
    while(y!=x){
williamr@2
   418
      if(eq(k,key(node_type::from_impl(y)->value()))){
williamr@2
   419
        do{
williamr@2
   420
          ++res;
williamr@2
   421
          y=y->next();
williamr@2
   422
        }while(y!=x&&eq(k,key(node_type::from_impl(y)->value())));
williamr@2
   423
        break;
williamr@2
   424
      }
williamr@2
   425
      y=y->next();
williamr@2
   426
    }
williamr@2
   427
    return res;
williamr@2
   428
  }
williamr@2
   429
williamr@2
   430
  template<typename CompatibleKey>
williamr@2
   431
  std::pair<iterator,iterator> equal_range(const CompatibleKey& k)const
williamr@2
   432
  {
williamr@2
   433
    return equal_range(k,hash,eq);
williamr@2
   434
  }
williamr@2
   435
williamr@2
   436
  template<
williamr@2
   437
    typename CompatibleKey,typename CompatibleHash,typename CompatiblePred
williamr@2
   438
  >
williamr@2
   439
  std::pair<iterator,iterator> equal_range(
williamr@2
   440
    const CompatibleKey& k,
williamr@2
   441
    const CompatibleHash& hash,const CompatiblePred& eq)const
williamr@2
   442
  {
williamr@2
   443
    std::size_t             buc=buckets.position(hash(k));
williamr@2
   444
    hashed_index_node_impl* x=buckets.at(buc);
williamr@2
   445
    hashed_index_node_impl* y=x->next();
williamr@2
   446
    while(y!=x){
williamr@2
   447
      if(eq(k,key(node_type::from_impl(y)->value()))){
williamr@2
   448
        hashed_index_node_impl* y0=y;
williamr@2
   449
        do{
williamr@2
   450
          y=y->next();
williamr@2
   451
        }while(y!=x&&eq(k,key(node_type::from_impl(y)->value())));
williamr@2
   452
        if(y==x){
williamr@2
   453
          do{
williamr@2
   454
            ++y;
williamr@2
   455
          }while(y==y->next());
williamr@2
   456
          y=y->next();
williamr@2
   457
        }
williamr@2
   458
        return std::pair<iterator,iterator>(
williamr@2
   459
          make_iterator(node_type::from_impl(y0)),
williamr@2
   460
          make_iterator(node_type::from_impl(y)));
williamr@2
   461
      }
williamr@2
   462
      y=y->next();
williamr@2
   463
    }
williamr@2
   464
    return std::pair<iterator,iterator>(end(),end());
williamr@2
   465
  }
williamr@2
   466
williamr@2
   467
  /* bucket interface */
williamr@2
   468
williamr@2
   469
  size_type bucket_count()const{return buckets.size();}
williamr@2
   470
  size_type max_bucket_count()const{return static_cast<size_type>(-1);}
williamr@2
   471
williamr@2
   472
  size_type bucket_size(size_type n)const
williamr@2
   473
  {
williamr@2
   474
    size_type               res=0;
williamr@2
   475
    hashed_index_node_impl* x=buckets.at(n);
williamr@2
   476
    hashed_index_node_impl* y=x->next();
williamr@2
   477
    while(y!=x){
williamr@2
   478
      ++res;
williamr@2
   479
      y=y->next();
williamr@2
   480
    }
williamr@2
   481
    return res;
williamr@2
   482
  }
williamr@2
   483
williamr@2
   484
  size_type bucket(key_param_type k)const
williamr@2
   485
  {
williamr@2
   486
    return buckets.position(hash(k));
williamr@2
   487
  }
williamr@2
   488
williamr@2
   489
  local_iterator begin(size_type n)
williamr@2
   490
  {
williamr@2
   491
    return const_cast<const hashed_index*>(this)->begin(n);
williamr@2
   492
  }
williamr@2
   493
williamr@2
   494
  const_local_iterator begin(size_type n)const
williamr@2
   495
  {
williamr@2
   496
    hashed_index_node_impl* x=buckets.at(n);
williamr@2
   497
    hashed_index_node_impl* y=x->next();
williamr@2
   498
    if(y==x)return end();
williamr@2
   499
    return make_iterator(node_type::from_impl(y));
williamr@2
   500
  }
williamr@2
   501
williamr@2
   502
  local_iterator end(size_type n)
williamr@2
   503
  {
williamr@2
   504
    return const_cast<const hashed_index*>(this)->end(n);
williamr@2
   505
  }
williamr@2
   506
williamr@2
   507
  const_local_iterator end(size_type n)const
williamr@2
   508
  {
williamr@2
   509
    hashed_index_node_impl* x=buckets.at(n);
williamr@2
   510
    if(x==x->next())return end();
williamr@2
   511
    do{
williamr@2
   512
      ++x;
williamr@2
   513
    }while(x==x->next());
williamr@2
   514
    return make_iterator(node_type::from_impl(x->next()));
williamr@2
   515
  }
williamr@2
   516
williamr@2
   517
  /* hash policy */
williamr@2
   518
williamr@2
   519
  float load_factor()const{return static_cast<float>(size())/bucket_count();}
williamr@2
   520
  float max_load_factor()const{return mlf;}
williamr@2
   521
  void  max_load_factor(float z){mlf=z;calculate_max_load();}
williamr@2
   522
williamr@2
   523
  void rehash(size_type n)
williamr@2
   524
  {
williamr@2
   525
    BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT;
williamr@2
   526
    if(size()<max_load&&n<=bucket_count())return;
williamr@2
   527
williamr@2
   528
    size_type bc =(std::numeric_limits<size_type>::max)();
williamr@2
   529
    float     fbc=static_cast<float>(1+size()/mlf);
williamr@2
   530
    if(bc>fbc){
williamr@2
   531
      bc=static_cast<size_type>(fbc);
williamr@2
   532
      if(bc<n)bc=n;
williamr@2
   533
    }
williamr@2
   534
    unchecked_rehash(bc);
williamr@2
   535
  }
williamr@2
   536
williamr@2
   537
BOOST_MULTI_INDEX_PROTECTED_IF_MEMBER_TEMPLATE_FRIENDS:
williamr@2
   538
  hashed_index(const ctor_args_list& args_list,const allocator_type& al):
williamr@2
   539
    super(args_list.get_tail(),al),
williamr@2
   540
    key(tuples::get<1>(args_list.get_head())),
williamr@2
   541
    hash(tuples::get<2>(args_list.get_head())),
williamr@2
   542
    eq(tuples::get<3>(args_list.get_head())),
williamr@2
   543
    buckets(al,header()->impl(),tuples::get<0>(args_list.get_head())),
williamr@2
   544
    mlf(1.0),
williamr@2
   545
    first_bucket(buckets.size())
williamr@2
   546
  {
williamr@2
   547
    calculate_max_load();
williamr@2
   548
  }
williamr@2
   549
williamr@2
   550
  hashed_index(
williamr@2
   551
    const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x):
williamr@2
   552
    super(x),
williamr@2
   553
williamr@2
   554
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
williamr@2
   555
    safe_super(),
williamr@2
   556
#endif
williamr@2
   557
williamr@2
   558
    key(x.key),
williamr@2
   559
    hash(x.hash),
williamr@2
   560
    eq(x.eq),
williamr@2
   561
    buckets(x.get_allocator(),header()->impl(),x.buckets.size()),
williamr@2
   562
    mlf(x.mlf),
williamr@2
   563
    max_load(x.max_load),
williamr@2
   564
    first_bucket(x.first_bucket)
williamr@2
   565
  {
williamr@2
   566
    /* Copy ctor just takes the internal configuration objects from x. The rest
williamr@2
   567
     * is done in subsequent call to copy_().
williamr@2
   568
     */
williamr@2
   569
  }
williamr@2
   570
williamr@2
   571
  ~hashed_index()
williamr@2
   572
  {
williamr@2
   573
    /* the container is guaranteed to be empty by now */
williamr@2
   574
  }
williamr@2
   575
williamr@2
   576
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
williamr@2
   577
  iterator make_iterator(node_type* node)
williamr@2
   578
  {
williamr@2
   579
    return iterator(node,&buckets,this);
williamr@2
   580
  }
williamr@2
   581
williamr@2
   582
  const_iterator make_iterator(node_type* node)const
williamr@2
   583
  {
williamr@2
   584
    return const_iterator(
williamr@2
   585
      node,
williamr@2
   586
      &const_cast<bucket_array_type&>(buckets),
williamr@2
   587
      const_cast<hashed_index*>(this));
williamr@2
   588
  }
williamr@2
   589
#else
williamr@2
   590
  iterator make_iterator(node_type* node)
williamr@2
   591
  {
williamr@2
   592
    return iterator(node,&buckets);
williamr@2
   593
  }
williamr@2
   594
williamr@2
   595
  const_iterator make_iterator(node_type* node)const
williamr@2
   596
  {
williamr@2
   597
    return const_iterator(node,&const_cast<bucket_array_type&>(buckets));
williamr@2
   598
  }
williamr@2
   599
#endif
williamr@2
   600
williamr@2
   601
  void copy_(
williamr@2
   602
    const hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
williamr@2
   603
    const copy_map_type& map)
williamr@2
   604
  {
williamr@2
   605
    for(hashed_index_node_impl* begin_org=x.buckets.begin(),
williamr@2
   606
                              * begin_cpy=buckets.begin(),
williamr@2
   607
                              * end_org=x.buckets.end();
williamr@2
   608
        begin_org!=end_org;++begin_org,++begin_cpy){
williamr@2
   609
williamr@2
   610
      hashed_index_node_impl* next_org=begin_org->next();
williamr@2
   611
      hashed_index_node_impl* cpy=begin_cpy;
williamr@2
   612
      while(next_org!=begin_org){
williamr@2
   613
        cpy->next()=
williamr@2
   614
          static_cast<node_type*>(
williamr@2
   615
            map.find(
williamr@2
   616
              static_cast<final_node_type*>(
williamr@2
   617
                node_type::from_impl(next_org))))->impl();
williamr@2
   618
        next_org=next_org->next();
williamr@2
   619
        cpy=cpy->next();
williamr@2
   620
      }
williamr@2
   621
      cpy->next()=begin_cpy;
williamr@2
   622
    }
williamr@2
   623
williamr@2
   624
    super::copy_(x,map);
williamr@2
   625
  }
williamr@2
   626
williamr@2
   627
  node_type* insert_(value_param_type v,node_type* x)
williamr@2
   628
  {
williamr@2
   629
    reserve(size()+1);
williamr@2
   630
williamr@2
   631
    std::size_t             buc=find_bucket(v);
williamr@2
   632
    hashed_index_node_impl* pos=buckets.at(buc);
williamr@2
   633
    if(!link_point(v,pos,Category()))return node_type::from_impl(pos);
williamr@2
   634
williamr@2
   635
    node_type* res=static_cast<node_type*>(super::insert_(v,x));
williamr@2
   636
    if(res==x){
williamr@2
   637
      link(x,pos);
williamr@2
   638
      if(first_bucket>buc)first_bucket=buc;
williamr@2
   639
    }
williamr@2
   640
    return res;
williamr@2
   641
  }
williamr@2
   642
williamr@2
   643
  node_type* insert_(value_param_type v,node_type* position,node_type* x)
williamr@2
   644
  {
williamr@2
   645
    reserve(size()+1);
williamr@2
   646
williamr@2
   647
    std::size_t             buc=find_bucket(v);
williamr@2
   648
    hashed_index_node_impl* pos=buckets.at(buc);
williamr@2
   649
    if(!link_point(v,pos,Category()))return node_type::from_impl(pos);
williamr@2
   650
williamr@2
   651
    node_type* res=static_cast<node_type*>(super::insert_(v,position,x));
williamr@2
   652
    if(res==x){
williamr@2
   653
      link(x,pos);
williamr@2
   654
      if(first_bucket>buc)first_bucket=buc;
williamr@2
   655
    }
williamr@2
   656
    return res;
williamr@2
   657
  }
williamr@2
   658
williamr@2
   659
  void erase_(node_type* x)
williamr@2
   660
  {
williamr@2
   661
    unlink(x);
williamr@2
   662
    first_bucket=buckets.first_nonempty(first_bucket);
williamr@2
   663
    super::erase_(x);
williamr@2
   664
williamr@2
   665
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
williamr@2
   666
    detach_iterators(x);
williamr@2
   667
#endif
williamr@2
   668
  }
williamr@2
   669
williamr@2
   670
  void delete_all_nodes_()
williamr@2
   671
  {
williamr@2
   672
    for(hashed_index_node_impl* x=buckets.begin(),*x_end=buckets.end();
williamr@2
   673
        x!=x_end;++x){
williamr@2
   674
      hashed_index_node_impl* y=x->next();
williamr@2
   675
      while(y!=x){
williamr@2
   676
        hashed_index_node_impl* z=y->next();
williamr@2
   677
        this->final_delete_node_(
williamr@2
   678
          static_cast<final_node_type*>(node_type::from_impl(y)));
williamr@2
   679
        y=z;
williamr@2
   680
      }
williamr@2
   681
    }
williamr@2
   682
  }
williamr@2
   683
williamr@2
   684
  void clear_()
williamr@2
   685
  {
williamr@2
   686
    super::clear_();
williamr@2
   687
    buckets.clear();
williamr@2
   688
    first_bucket=buckets.size();
williamr@2
   689
williamr@2
   690
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
williamr@2
   691
    safe_super::detach_dereferenceable_iterators();
williamr@2
   692
#endif
williamr@2
   693
  }
williamr@2
   694
williamr@2
   695
  void swap_(
williamr@2
   696
    hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x)
williamr@2
   697
  {
williamr@2
   698
    std::swap(key,x.key);
williamr@2
   699
    std::swap(hash,x.hash);
williamr@2
   700
    std::swap(eq,x.eq);
williamr@2
   701
    buckets.swap(x.buckets);
williamr@2
   702
    std::swap(mlf,x.mlf);
williamr@2
   703
    std::swap(max_load,x.max_load);
williamr@2
   704
    std::swap(first_bucket,x.first_bucket);
williamr@2
   705
williamr@2
   706
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
williamr@2
   707
    safe_super::swap(x);
williamr@2
   708
#endif
williamr@2
   709
williamr@2
   710
    super::swap_(x);
williamr@2
   711
  }
williamr@2
   712
williamr@2
   713
  bool replace_(value_param_type v,node_type* x)
williamr@2
   714
  {
williamr@2
   715
    if(eq(key(v),key(x->value()))){
williamr@2
   716
      return super::replace_(v,x);
williamr@2
   717
    }
williamr@2
   718
williamr@2
   719
    hashed_index_node_impl* y=prev(x);
williamr@2
   720
    unlink_next(y);
williamr@2
   721
williamr@2
   722
    BOOST_TRY{
williamr@2
   723
      std::size_t             buc=find_bucket(v);
williamr@2
   724
      hashed_index_node_impl* pos=buckets.at(buc);
williamr@2
   725
      if(link_point(v,pos,Category())&&super::replace_(v,x)){
williamr@2
   726
        link(x,pos);
williamr@2
   727
        if(first_bucket>buc){
williamr@2
   728
          first_bucket=buc;
williamr@2
   729
        }
williamr@2
   730
        else if(first_bucket<buc){
williamr@2
   731
          first_bucket=buckets.first_nonempty(first_bucket);
williamr@2
   732
        }
williamr@2
   733
        return true;
williamr@2
   734
      }
williamr@2
   735
      link(x,y);
williamr@2
   736
      return false;
williamr@2
   737
    }
williamr@2
   738
    BOOST_CATCH(...){
williamr@2
   739
      link(x,y);
williamr@2
   740
      BOOST_RETHROW;
williamr@2
   741
    }
williamr@2
   742
    BOOST_CATCH_END
williamr@2
   743
  }
williamr@2
   744
williamr@2
   745
  bool modify_(node_type* x)
williamr@2
   746
  {
williamr@2
   747
    unlink(x);
williamr@2
   748
williamr@2
   749
    std::size_t             buc;
williamr@2
   750
    hashed_index_node_impl* pos;
williamr@2
   751
    BOOST_TRY
williamr@2
   752
    {
williamr@2
   753
      buc=find_bucket(x->value());
williamr@2
   754
      pos=buckets.at(buc);
williamr@2
   755
      if(!link_point(x->value(),pos,Category())){
williamr@2
   756
        first_bucket=buckets.first_nonempty(first_bucket);
williamr@2
   757
        super::erase_(x);
williamr@2
   758
williamr@2
   759
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
williamr@2
   760
        detach_iterators(x);
williamr@2
   761
#endif
williamr@2
   762
        return false;
williamr@2
   763
      }
williamr@2
   764
williamr@2
   765
    }
williamr@2
   766
    BOOST_CATCH(...){
williamr@2
   767
      first_bucket=buckets.first_nonempty(first_bucket);
williamr@2
   768
      super::erase_(x);
williamr@2
   769
williamr@2
   770
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
williamr@2
   771
      detach_iterators(x);
williamr@2
   772
#endif
williamr@2
   773
williamr@2
   774
      BOOST_RETHROW;
williamr@2
   775
    }
williamr@2
   776
    BOOST_CATCH_END
williamr@2
   777
williamr@2
   778
    BOOST_TRY{
williamr@2
   779
      if(super::modify_(x)){
williamr@2
   780
        link(x,pos);
williamr@2
   781
        if(first_bucket>buc){
williamr@2
   782
          first_bucket=buc;
williamr@2
   783
        }
williamr@2
   784
        else if(first_bucket<buc){
williamr@2
   785
          first_bucket=buckets.first_nonempty(first_bucket);
williamr@2
   786
        }
williamr@2
   787
        return true;
williamr@2
   788
      }
williamr@2
   789
williamr@2
   790
      first_bucket=buckets.first_nonempty(first_bucket);
williamr@2
   791
williamr@2
   792
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
williamr@2
   793
      detach_iterators(x);
williamr@2
   794
#endif
williamr@2
   795
      return false;
williamr@2
   796
    }
williamr@2
   797
    BOOST_CATCH(...){
williamr@2
   798
      first_bucket=buckets.first_nonempty(first_bucket);
williamr@2
   799
williamr@2
   800
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
williamr@2
   801
      detach_iterators(x);
williamr@2
   802
#endif
williamr@2
   803
williamr@2
   804
      BOOST_RETHROW;
williamr@2
   805
    }
williamr@2
   806
    BOOST_CATCH_END
williamr@2
   807
  }
williamr@2
   808
williamr@2
   809
#if !defined(BOOST_MULTI_INDEX_DISABLE_SERIALIZATION)
williamr@2
   810
  /* serialization */
williamr@2
   811
williamr@2
   812
  template<typename Archive>
williamr@2
   813
  void save_(
williamr@2
   814
    Archive& ar,const unsigned int version,const index_saver_type& sm)const
williamr@2
   815
  {
williamr@2
   816
    ar<<serialization::make_nvp("position",buckets);
williamr@2
   817
    super::save_(ar,version,sm);
williamr@2
   818
  }
williamr@2
   819
williamr@2
   820
  template<typename Archive>
williamr@2
   821
  void load_(Archive& ar,const unsigned int version,const index_loader_type& lm)
williamr@2
   822
  {
williamr@2
   823
    ar>>serialization::make_nvp("position",buckets);
williamr@2
   824
    super::load_(ar,version,lm);
williamr@2
   825
  }
williamr@2
   826
#endif
williamr@2
   827
williamr@2
   828
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)
williamr@2
   829
  /* invariant stuff */
williamr@2
   830
williamr@2
   831
  bool invariant_()const
williamr@2
   832
  {
williamr@2
   833
    if(size()==0||begin()==end()){
williamr@2
   834
      if(size()!=0||begin()!=end())return false;
williamr@2
   835
    }
williamr@2
   836
    else{
williamr@2
   837
      size_type s0=0;
williamr@2
   838
      for(const_iterator it=begin(),it_end=end();it!=it_end;++it,++s0){}
williamr@2
   839
      if(s0!=size())return false;
williamr@2
   840
williamr@2
   841
      size_type s1=0;
williamr@2
   842
      for(size_type buc=0;buc<bucket_count();++buc){
williamr@2
   843
        size_type ss1=0;
williamr@2
   844
        for(const_local_iterator it=begin(buc),it_end=end(buc);
williamr@2
   845
            it!=it_end;++it,++ss1){
williamr@2
   846
          if(find_bucket(*it)!=buc)return false;
williamr@2
   847
        }
williamr@2
   848
        if(ss1!=bucket_size(buc))return false;
williamr@2
   849
        s1+=ss1;
williamr@2
   850
      }
williamr@2
   851
      if(s1!=size())return false;
williamr@2
   852
    }
williamr@2
   853
williamr@2
   854
    if(first_bucket!=buckets.first_nonempty(0))return false;
williamr@2
   855
williamr@2
   856
    return super::invariant_();
williamr@2
   857
  }
williamr@2
   858
williamr@2
   859
  /* This forwarding function eases things for the boost::mem_fn construct
williamr@2
   860
   * in BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT. Actually,
williamr@2
   861
   * final_check_invariant is already an inherited member function of index.
williamr@2
   862
   */
williamr@2
   863
  void check_invariant_()const{this->final_check_invariant_();}
williamr@2
   864
#endif
williamr@2
   865
williamr@2
   866
private:
williamr@2
   867
  node_type* header()const{return this->final_header();}
williamr@2
   868
williamr@2
   869
  std::size_t find_bucket(value_param_type v)const
williamr@2
   870
  {
williamr@2
   871
    return bucket(key(v));
williamr@2
   872
  }
williamr@2
   873
williamr@2
   874
  bool link_point(
williamr@2
   875
    value_param_type v,hashed_index_node_impl*& pos,hashed_unique_tag)
williamr@2
   876
  {
williamr@2
   877
    hashed_index_node_impl* x=pos->next();
williamr@2
   878
    while(x!=pos){
williamr@2
   879
      if(eq(key(v),key(node_type::from_impl(x)->value()))){
williamr@2
   880
        pos=x;
williamr@2
   881
        return false;
williamr@2
   882
      }
williamr@2
   883
      x=x->next();
williamr@2
   884
    }
williamr@2
   885
    return true;
williamr@2
   886
  }
williamr@2
   887
williamr@2
   888
  bool link_point(
williamr@2
   889
    value_param_type v,hashed_index_node_impl*& pos,hashed_non_unique_tag)
williamr@2
   890
  {
williamr@2
   891
    hashed_index_node_impl* prev=pos;
williamr@2
   892
    hashed_index_node_impl* x=pos->next();
williamr@2
   893
    while(x!=pos){
williamr@2
   894
      if(eq(key(v),key(node_type::from_impl(x)->value()))){
williamr@2
   895
        pos=prev;
williamr@2
   896
        return true;
williamr@2
   897
      }
williamr@2
   898
      prev=x;
williamr@2
   899
      x=x->next();
williamr@2
   900
    }
williamr@2
   901
    return true;
williamr@2
   902
  }
williamr@2
   903
  
williamr@2
   904
  void link(node_type* x,hashed_index_node_impl* pos)
williamr@2
   905
  {
williamr@2
   906
    hashed_index_node_impl::link(x->impl(),pos);
williamr@2
   907
  };
williamr@2
   908
williamr@2
   909
  void link(hashed_index_node_impl* x,hashed_index_node_impl* pos)
williamr@2
   910
  {
williamr@2
   911
    hashed_index_node_impl::link(x,pos);
williamr@2
   912
  };
williamr@2
   913
williamr@2
   914
  void unlink(node_type* x)
williamr@2
   915
  {
williamr@2
   916
    hashed_index_node_impl::unlink(x->impl());
williamr@2
   917
  };
williamr@2
   918
williamr@2
   919
  static hashed_index_node_impl* prev(node_type* x)
williamr@2
   920
  {
williamr@2
   921
    return hashed_index_node_impl::prev(x->impl());
williamr@2
   922
  }
williamr@2
   923
williamr@2
   924
  static void unlink_next(hashed_index_node_impl* x)
williamr@2
   925
  {
williamr@2
   926
    hashed_index_node_impl::unlink_next(x);
williamr@2
   927
  }
williamr@2
   928
williamr@2
   929
  void calculate_max_load()
williamr@2
   930
  {
williamr@2
   931
    float fml=static_cast<float>(mlf*bucket_count());
williamr@2
   932
    max_load=(std::numeric_limits<size_type>::max)();
williamr@2
   933
    if(max_load>fml)max_load=static_cast<size_type>(fml);
williamr@2
   934
  }
williamr@2
   935
williamr@2
   936
  void reserve(size_type n)
williamr@2
   937
  {
williamr@2
   938
    if(n>max_load){
williamr@2
   939
      size_type bc =(std::numeric_limits<size_type>::max)();
williamr@2
   940
      float     fbc=static_cast<float>(1+n/mlf);
williamr@2
   941
      if(bc>fbc)bc =static_cast<size_type>(fbc);
williamr@2
   942
      unchecked_rehash(bc);
williamr@2
   943
    }
williamr@2
   944
  }
williamr@2
   945
williamr@2
   946
  void unchecked_rehash(size_type n)
williamr@2
   947
  {
williamr@2
   948
    bucket_array_type buckets1(get_allocator(),header()->impl(),n);
williamr@2
   949
    auto_space<std::size_t,allocator_type> hashes(get_allocator(),size());
williamr@2
   950
williamr@2
   951
    std::size_t i=0;
williamr@2
   952
    hashed_index_node_impl* x=buckets.begin();
williamr@2
   953
    hashed_index_node_impl* x_end=buckets.end();
williamr@2
   954
    for(;x!=x_end;++x){
williamr@2
   955
      hashed_index_node_impl* y=x->next();
williamr@2
   956
      while(y!=x){
williamr@2
   957
        hashes.data()[i++]=hash(key(node_type::from_impl(y)->value()));
williamr@2
   958
        y=y->next();
williamr@2
   959
      }
williamr@2
   960
    }
williamr@2
   961
williamr@2
   962
    i=0;
williamr@2
   963
    x=buckets.begin();
williamr@2
   964
    for(;x!=x_end;++x){
williamr@2
   965
      hashed_index_node_impl* y=x->next();
williamr@2
   966
      while(y!=x){
williamr@2
   967
        hashed_index_node_impl* z=y->next();
williamr@2
   968
        std::size_t             buc1=buckets1.position(hashes.data()[i++]);
williamr@2
   969
        hashed_index_node_impl* x1=buckets1.at(buc1);
williamr@2
   970
        link(y,x1);
williamr@2
   971
        y=z;
williamr@2
   972
      }
williamr@2
   973
    }
williamr@2
   974
williamr@2
   975
    buckets.swap(buckets1);
williamr@2
   976
    calculate_max_load();
williamr@2
   977
    first_bucket=buckets.first_nonempty(0);
williamr@2
   978
  }
williamr@2
   979
williamr@2
   980
#if defined(BOOST_MULTI_INDEX_ENABLE_SAFE_MODE)
williamr@2
   981
  void detach_iterators(node_type* x)
williamr@2
   982
  {
williamr@2
   983
    iterator it=make_iterator(x);
williamr@2
   984
    safe_mode::detach_equivalent_iterators(it);
williamr@2
   985
  }
williamr@2
   986
#endif
williamr@2
   987
williamr@2
   988
  key_from_value               key;
williamr@2
   989
  hasher                       hash;
williamr@2
   990
  key_equal                    eq;
williamr@2
   991
  bucket_array_type            buckets;
williamr@2
   992
  float                        mlf;
williamr@2
   993
  size_type                    max_load;
williamr@2
   994
  std::size_t                  first_bucket;
williamr@2
   995
      
williamr@2
   996
#if defined(BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING)&&\
williamr@2
   997
    BOOST_WORKAROUND(__MWERKS__,<=0x3003)
williamr@2
   998
#pragma parse_mfunc_templ reset
williamr@2
   999
#endif
williamr@2
  1000
};
williamr@2
  1001
williamr@2
  1002
/*  specialized algorithms */
williamr@2
  1003
williamr@2
  1004
template<
williamr@2
  1005
  typename KeyFromValue,typename Hash,typename Pred,
williamr@2
  1006
  typename SuperMeta,typename TagList,typename Category
williamr@2
  1007
>
williamr@2
  1008
void swap(
williamr@2
  1009
  hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& x,
williamr@2
  1010
  hashed_index<KeyFromValue,Hash,Pred,SuperMeta,TagList,Category>& y)
williamr@2
  1011
{
williamr@2
  1012
  x.swap(y);
williamr@2
  1013
}
williamr@2
  1014
williamr@2
  1015
} /* namespace multi_index::detail */
williamr@2
  1016
williamr@2
  1017
/* sequenced index specifiers */
williamr@2
  1018
williamr@2
  1019
template<typename Arg1,typename Arg2,typename Arg3,typename Arg4>
williamr@2
  1020
struct hashed_unique
williamr@2
  1021
{
williamr@2
  1022
  typedef typename detail::hashed_index_args<
williamr@2
  1023
    Arg1,Arg2,Arg3,Arg4>                           index_args;
williamr@2
  1024
  typedef typename index_args::tag_list_type::type tag_list_type;
williamr@2
  1025
  typedef typename index_args::key_from_value_type key_from_value_type;
williamr@2
  1026
  typedef typename index_args::hash_type           hash_type;
williamr@2
  1027
  typedef typename index_args::pred_type           pred_type;
williamr@2
  1028
williamr@2
  1029
  template<typename Super>
williamr@2
  1030
  struct node_class
williamr@2
  1031
  {
williamr@2
  1032
    typedef detail::hashed_index_node<Super> type;
williamr@2
  1033
  };
williamr@2
  1034
williamr@2
  1035
  template<typename SuperMeta>
williamr@2
  1036
  struct index_class
williamr@2
  1037
  {
williamr@2
  1038
    typedef detail::hashed_index<
williamr@2
  1039
      key_from_value_type,hash_type,pred_type,
williamr@2
  1040
      SuperMeta,tag_list_type,detail::hashed_unique_tag> type;
williamr@2
  1041
  };
williamr@2
  1042
};
williamr@2
  1043
williamr@2
  1044
template<typename Arg1,typename Arg2,typename Arg3,typename Arg4>
williamr@2
  1045
struct hashed_non_unique
williamr@2
  1046
{
williamr@2
  1047
  typedef typename detail::hashed_index_args<
williamr@2
  1048
    Arg1,Arg2,Arg3,Arg4>                           index_args;
williamr@2
  1049
  typedef typename index_args::tag_list_type::type tag_list_type;
williamr@2
  1050
  typedef typename index_args::key_from_value_type key_from_value_type;
williamr@2
  1051
  typedef typename index_args::hash_type           hash_type;
williamr@2
  1052
  typedef typename index_args::pred_type           pred_type;
williamr@2
  1053
williamr@2
  1054
  template<typename Super>
williamr@2
  1055
  struct node_class
williamr@2
  1056
  {
williamr@2
  1057
    typedef detail::hashed_index_node<Super> type;
williamr@2
  1058
  };
williamr@2
  1059
williamr@2
  1060
  template<typename SuperMeta>
williamr@2
  1061
  struct index_class
williamr@2
  1062
  {
williamr@2
  1063
    typedef detail::hashed_index<
williamr@2
  1064
      key_from_value_type,hash_type,pred_type,
williamr@2
  1065
      SuperMeta,tag_list_type,detail::hashed_non_unique_tag> type;
williamr@2
  1066
  };
williamr@2
  1067
};
williamr@2
  1068
williamr@2
  1069
} /* namespace multi_index */
williamr@2
  1070
williamr@2
  1071
} /* namespace boost */
williamr@2
  1072
williamr@2
  1073
#undef BOOST_MULTI_INDEX_HASHED_INDEX_CHECK_INVARIANT
williamr@2
  1074
williamr@2
  1075
#endif