00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #ifndef STXXL_VECTOR_HEADER
00015 #define STXXL_VECTOR_HEADER
00016
00017 #include <vector>
00018 #include <algorithm>
00019
00020 #include <stxxl/bits/mng/mng.h>
00021 #include <stxxl/bits/common/tmeta.h>
00022 #include <stxxl/bits/containers/pager.h>
00023
00024
00025 __STXXL_BEGIN_NAMESPACE
00026
00030
00031
00035
00036 template <unsigned_type modulo2, unsigned_type modulo1>
00037 class double_blocked_index
00038 {
00039 static const unsigned_type modulo12 = modulo1 * modulo2;
00040
00041 unsigned_type pos;
00042 unsigned_type block1, block2;
00043 unsigned_type offset;
00044
00046
00047 void set(unsigned_type pos)
00048 {
00049 this->pos = pos;
00050 block2 = pos / modulo12;
00051 pos -= block2 * modulo12;
00052 block1 = pos / modulo1;
00053 offset = (pos - block1 * modulo1);
00054
00055 assert(block2 * modulo12 + block1 * modulo1 + offset == this->pos);
00056 assert( block1 < modulo2);
00057 assert( offset < modulo1);
00058 }
00059
00060 public:
00061 double_blocked_index()
00062 {
00063 set(0);
00064 }
00065
00066 double_blocked_index(unsigned_type pos)
00067 {
00068 set(pos);
00069 }
00070
00071 double_blocked_index(unsigned_type block2, unsigned_type block1, unsigned_type)
00072 {
00073 this->block2 = block2;
00074 this->block1 = block1;
00075 this->offset = offset;
00076 pos = block2 * modulo12 + block1 * modulo1 + offset;
00077
00078 assert(block2 * modulo12 + block1 * modulo1 + offset == this->pos);
00079 assert( block1 < modulo2);
00080 assert( offset < modulo1);
00081 }
00082
00083 double_blocked_index & operator = (unsigned_type pos)
00084 {
00085 set(pos);
00086 return *this;
00087 }
00088
00089
00090 double_blocked_index & operator ++ ()
00091 {
00092 ++pos;
00093 ++offset;
00094 if (offset == modulo1)
00095 {
00096 offset = 0;
00097 ++block1;
00098 if (block1 == modulo2)
00099 {
00100 block1 = 0;
00101 ++block2;
00102 }
00103 }
00104
00105 assert(block2 * modulo12 + block1 * modulo1 + offset == this->pos);
00106 assert( block1 < modulo2);
00107 assert( offset < modulo1);
00108
00109 return *this;
00110 }
00111
00112
00113 double_blocked_index operator ++ (int)
00114 {
00115 double_blocked_index former(*this);
00116 operator ++();
00117 return former;
00118 }
00119
00120
00121 double_blocked_index & operator -- ()
00122 {
00123 --pos;
00124 if (offset == 0)
00125 {
00126 offset = modulo1;
00127 if (block1 == 0)
00128 {
00129 block1 = modulo2;
00130 --block2;
00131 }
00132 --block1;
00133 }
00134 --offset;
00135
00136 assert(block2 * modulo12 + block1 * modulo1 + offset == this->pos);
00137 assert( block1 < modulo2);
00138 assert( offset < modulo1);
00139
00140 return *this;
00141 }
00142
00143
00144 double_blocked_index operator -- (int)
00145 {
00146 double_blocked_index former(*this);
00147 operator --();
00148 return former;
00149 }
00150
00151 double_blocked_index operator + (unsigned_type addend) const
00152 {
00153 return double_blocked_index(pos + addend);
00154 }
00155
00156 double_blocked_index & operator += (unsigned_type addend)
00157 {
00158 set(pos + addend);
00159 return *this;
00160 }
00161
00162 double_blocked_index operator - (unsigned_type addend) const
00163 {
00164 return double_blocked_index(pos - addend);
00165 }
00166
00167 unsigned_type operator - (const double_blocked_index & dbi2) const
00168 {
00169 return pos - dbi2.pos;
00170 }
00171
00172 double_blocked_index & operator -= (unsigned_type subtrahend)
00173 {
00174 set(pos - subtrahend);
00175 return *this;
00176 }
00177
00178 bool operator == (const double_blocked_index & dbi2) const
00179 {
00180 return pos == dbi2.pos;
00181 }
00182
00183 bool operator != (const double_blocked_index & dbi2) const
00184 {
00185 return pos != dbi2.pos;
00186 }
00187
00188 bool operator < (const double_blocked_index & dbi2) const
00189 {
00190 return pos < dbi2.pos;
00191 }
00192
00193 bool operator <= (const double_blocked_index & dbi2) const
00194 {
00195 return pos <= dbi2.pos;
00196 }
00197
00198 bool operator > (const double_blocked_index & dbi2) const
00199 {
00200 return pos > dbi2.pos;
00201 }
00202
00203 bool operator >= (const double_blocked_index & dbi2) const
00204 {
00205 return pos >= dbi2.pos;
00206 }
00207
00208 double_blocked_index & operator >>= (unsigned_type shift)
00209 {
00210 set(pos >> shift);
00211 return *this;
00212 }
00213
00214 unsigned_type get_pos() const
00215 {
00216 return pos;
00217 }
00218
00219 const unsigned_type & get_block2() const
00220 {
00221 return block2;
00222 }
00223
00224 const unsigned_type & get_block1() const
00225 {
00226 return block1;
00227 }
00228
00229 const unsigned_type & get_offset() const
00230 {
00231 return offset;
00232 }
00233 };
00234
00235
00236 template <unsigned BlkSize_>
00237 class bid_vector : public std::vector<BID<BlkSize_> >
00238 {
00239 public:
00240 enum
00241 { block_size = BlkSize_ };
00242 typedef bid_vector<block_size> _Self;
00243 typedef std::vector<BID<BlkSize_> > _Derived;
00244 typedef unsigned size_type;
00245
00246 bid_vector(size_type _sz) : _Derived(_sz)
00247 { }
00248 };
00249
00250
00251 template <
00252 typename Tp_,
00253 unsigned PgSz_,
00254 typename PgTp_,
00255 unsigned BlkSize_,
00256 typename AllocStr_,
00257 typename SzTp_>
00258 class vector;
00259
00260
00261 template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_,
00262 unsigned BlkSize_, typename PgTp_, unsigned PgSz_>
00263 class const_vector_iterator;
00264
00265
00267 template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_,
00268 unsigned BlkSize_, typename PgTp_, unsigned PgSz_>
00269 class vector_iterator
00270 {
00271 typedef vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_,
00272 BlkSize_, PgTp_, PgSz_> _Self;
00273 typedef const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_,
00274 BlkSize_, PgTp_, PgSz_> _CIterator;
00275
00276 friend class const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_>;
00277
00278 public:
00279 typedef _CIterator const_iterator;
00280 typedef _Self iterator;
00281
00282 typedef SzTp_ size_type;
00283 typedef DiffTp_ difference_type;
00284 typedef unsigned block_offset_type;
00285 typedef vector<Tp_, PgSz_, PgTp_, BlkSize_, AllocStr_, SzTp_> vector_type;
00286 friend class vector<Tp_, PgSz_, PgTp_, BlkSize_, AllocStr_, SzTp_>;
00287 typedef bid_vector<BlkSize_> bids_container_type;
00288 typedef typename bids_container_type::iterator bids_container_iterator;
00289 typedef typed_block<BlkSize_, Tp_> block_type;
00290 typedef BID<BlkSize_> bid_type;
00291
00292 typedef std::random_access_iterator_tag iterator_category;
00293 typedef typename vector_type::value_type value_type;
00294 typedef typename vector_type::reference reference;
00295 typedef typename vector_type::const_reference const_reference;
00296 typedef typename vector_type::pointer pointer;
00297 typedef typename vector_type::const_pointer const_pointer;
00298
00299 enum { block_size = BlkSize_ };
00300
00301 protected:
00302 double_blocked_index<PgSz_, block_type::size> offset;
00303 vector_type * p_vector;
00304
00305 private:
00306 vector_iterator(vector_type * v, size_type o) : offset(o),
00307 p_vector(v)
00308 { }
00309
00310 public:
00311 vector_iterator() : offset(0), p_vector(NULL) { }
00312 vector_iterator(const _Self & a) :
00313 offset(a.offset),
00314 p_vector(a.p_vector) { }
00315
00316 block_offset_type block_offset() const
00317 {
00318 return static_cast<block_offset_type>(offset.get_offset());
00319 }
00320 bids_container_iterator bid() const
00321 {
00322 return p_vector->bid(offset);
00323 }
00324
00325 difference_type operator - (const _Self & a) const
00326 {
00327 return offset - a.offset;
00328 }
00329
00330 difference_type operator - (const const_iterator & a) const
00331 {
00332 return offset - a.offset;
00333 }
00334
00335 _Self operator - (size_type op) const
00336 {
00337 return _Self(p_vector, offset.get_pos() - op);
00338 }
00339
00340 _Self operator + (size_type op) const
00341 {
00342 return _Self(p_vector, offset.get_pos() + op);
00343 }
00344
00345 _Self & operator -= (size_type op)
00346 {
00347 offset -= op;
00348 return *this;
00349 }
00350
00351 _Self & operator += (size_type op)
00352 {
00353 offset += op;
00354 return *this;
00355 }
00356
00357 reference operator * ()
00358 {
00359 return p_vector->element(offset);
00360 }
00361
00362 pointer operator -> ()
00363 {
00364 return &(p_vector->element(offset));
00365 }
00366
00367 const_reference operator * () const
00368 {
00369 return p_vector->const_element(offset);
00370 }
00371
00372 const_pointer operator -> () const
00373 {
00374 return &(p_vector->const_element(offset));
00375 }
00376
00377 reference operator [] (size_type op)
00378 {
00379 return p_vector->element(offset.get_pos() + op);
00380 }
00381
00382 const_reference operator [] (size_type op) const
00383 {
00384 return p_vector->const_element(offset.get_pos() + op);
00385 }
00386
00387 void touch()
00388 {
00389 p_vector->touch(offset);
00390 }
00391
00392 _Self & operator ++ ()
00393 {
00394 offset++;
00395 return *this;
00396 }
00397 _Self operator ++ (int)
00398 {
00399 _Self __tmp = *this;
00400 offset++;
00401 return __tmp;
00402 }
00403 _Self & operator -- ()
00404 {
00405 offset--;
00406 return *this;
00407 }
00408 _Self operator -- (int)
00409 {
00410 _Self __tmp = *this;
00411 offset--;
00412 return __tmp;
00413 }
00414 bool operator == (const _Self & a) const
00415 {
00416 assert(p_vector == a.p_vector);
00417 return offset == a.offset;
00418 }
00419 bool operator != (const _Self & a) const
00420 {
00421 assert(p_vector == a.p_vector);
00422 return offset != a.offset;
00423 }
00424 bool operator < (const _Self & a) const
00425 {
00426 assert(p_vector == a.p_vector);
00427 return offset < a.offset;
00428 }
00429 bool operator <= (const _Self & a) const
00430 {
00431 assert(p_vector == a.p_vector);
00432 return offset <= a.offset;
00433 }
00434 bool operator > (const _Self & a) const
00435 {
00436 assert(p_vector == a.p_vector);
00437 return a > *this;
00438 }
00439 bool operator >= (const _Self & a) const
00440 {
00441 assert(p_vector == a.p_vector);
00442 return a >= *this;
00443 }
00444
00445 bool operator == (const const_iterator & a) const
00446 {
00447 assert(p_vector == a.p_vector);
00448 return offset == a.offset;
00449 }
00450 bool operator != (const const_iterator & a) const
00451 {
00452 assert(p_vector == a.p_vector);
00453 return offset != a.offset;
00454 }
00455 bool operator < (const const_iterator & a) const
00456 {
00457 assert(p_vector == a.p_vector);
00458 return offset < a.offset;
00459 }
00460 bool operator <= (const const_iterator & a) const
00461 {
00462 assert(p_vector == a.p_vector);
00463 return offset <= a.offset;
00464 }
00465 bool operator > (const const_iterator & a) const
00466 {
00467 assert(p_vector == a.p_vector);
00468 return a > *this;
00469 }
00470 bool operator >= (const const_iterator & a) const
00471 {
00472 assert(p_vector == a.p_vector);
00473 return a >= *this;
00474 }
00475
00476 void flush()
00477 {
00478 p_vector->flush();
00479 }
00480
00481
00482
00483
00484
00485
00486 };
00487
00489 template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_,
00490 unsigned BlkSize_, typename PgTp_, unsigned PgSz_>
00491 class const_vector_iterator
00492 {
00493 typedef const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_,
00494 BlkSize_, PgTp_, PgSz_> _Self;
00495 typedef vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_,
00496 BlkSize_, PgTp_, PgSz_> _NonConstIterator;
00497
00498 friend class vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_>;
00499
00500 public:
00501 typedef _Self const_iterator;
00502 typedef _NonConstIterator iterator;
00503
00504 typedef SzTp_ size_type;
00505 typedef DiffTp_ difference_type;
00506 typedef unsigned block_offset_type;
00507 typedef vector<Tp_, PgSz_, PgTp_, BlkSize_, AllocStr_, SzTp_> vector_type;
00508 friend class vector<Tp_, PgSz_, PgTp_, BlkSize_, AllocStr_, SzTp_>;
00509 typedef bid_vector<BlkSize_> bids_container_type;
00510 typedef typename bids_container_type::iterator bids_container_iterator;
00511 typedef typed_block<BlkSize_, Tp_> block_type;
00512 typedef BID<BlkSize_> bid_type;
00513
00514 typedef std::random_access_iterator_tag iterator_category;
00515 typedef typename vector_type::value_type value_type;
00516 typedef typename vector_type::reference reference;
00517 typedef typename vector_type::const_reference const_reference;
00518 typedef typename vector_type::pointer pointer;
00519 typedef typename vector_type::const_pointer const_pointer;
00520
00521 enum { block_size = BlkSize_ };
00522
00523 protected:
00524 double_blocked_index<PgSz_, block_type::size> offset;
00525 const vector_type * p_vector;
00526
00527 private:
00528 const_vector_iterator(const vector_type * v, size_type o) : offset(o),
00529 p_vector(v)
00530 { }
00531
00532 public:
00533 const_vector_iterator() : offset(0), p_vector(NULL)
00534 { }
00535 const_vector_iterator(const _Self & a) :
00536 offset(a.offset),
00537 p_vector(a.p_vector)
00538 { }
00539
00540 const_vector_iterator(const iterator & a) :
00541 offset(a.offset),
00542 p_vector(a.p_vector)
00543 { }
00544
00545 block_offset_type block_offset() const
00546 {
00547 return static_cast<block_offset_type>(offset.get_offset());
00548 }
00549 bids_container_iterator bid() const
00550 {
00551 return ((vector_type *)p_vector)->bid(offset);
00552 }
00553
00554 difference_type operator - (const _Self & a) const
00555 {
00556 return offset - a.offset;
00557 }
00558
00559 difference_type operator - (const iterator & a) const
00560 {
00561 return offset - a.offset;
00562 }
00563
00564 _Self operator - (size_type op) const
00565 {
00566 return _Self(p_vector, offset.get_pos() - op);
00567 }
00568
00569 _Self operator + (size_type op) const
00570 {
00571 return _Self(p_vector, offset.get_pos() + op);
00572 }
00573
00574 _Self & operator -= (size_type op)
00575 {
00576 offset -= op;
00577 return *this;
00578 }
00579
00580 _Self & operator += (size_type op)
00581 {
00582 offset += op;
00583 return *this;
00584 }
00585
00586 const_reference operator * () const
00587 {
00588 return p_vector->const_element(offset);
00589 }
00590
00591 const_pointer operator -> () const
00592 {
00593 return &(p_vector->const_element(offset));
00594 }
00595
00596 const_reference operator [] (size_type op) const
00597 {
00598 return p_vector->const_element(offset.get_pos() + op);
00599 }
00600
00601 void touch()
00602 {
00603 p_vector->touch(offset);
00604 }
00605
00606 _Self & operator ++ ()
00607 {
00608 offset++;
00609 return *this;
00610 }
00611 _Self operator ++ (int)
00612 {
00613 _Self tmp_ = *this;
00614 offset++;
00615 return tmp_;
00616 }
00617 _Self & operator -- ()
00618 {
00619 offset--;
00620 return *this;
00621 }
00622 _Self operator -- (int)
00623 {
00624 _Self __tmp = *this;
00625 offset--;
00626 return __tmp;
00627 }
00628 bool operator == (const _Self & a) const
00629 {
00630 assert(p_vector == a.p_vector);
00631 return offset == a.offset;
00632 }
00633 bool operator != (const _Self & a) const
00634 {
00635 assert(p_vector == a.p_vector);
00636 return offset != a.offset;
00637 }
00638 bool operator < (const _Self & a) const
00639 {
00640 assert(p_vector == a.p_vector);
00641 return offset < a.offset;
00642 }
00643 bool operator <= (const _Self & a) const
00644 {
00645 assert(p_vector == a.p_vector);
00646 return offset <= a.offset;
00647 }
00648 bool operator > (const _Self & a) const
00649 {
00650 assert(p_vector == a.p_vector);
00651 return offset > a.offset;
00652 }
00653 bool operator >= (const _Self & a) const
00654 {
00655 assert(p_vector == a.p_vector);
00656 return offset >= a.offset;
00657 }
00658
00659 bool operator == (const iterator & a) const
00660 {
00661 assert(p_vector == a.p_vector);
00662 return offset == a.offset;
00663 }
00664 bool operator != (const iterator & a) const
00665 {
00666 assert(p_vector == a.p_vector);
00667 return offset != a.offset;
00668 }
00669 bool operator < (const iterator & a) const
00670 {
00671 assert(p_vector == a.p_vector);
00672 return offset < a.offset;
00673 }
00674 bool operator <= (const iterator & a) const
00675 {
00676 assert(p_vector == a.p_vector);
00677 return offset <= a.offset;
00678 }
00679 bool operator > (const iterator & a) const
00680 {
00681 assert(p_vector == a.p_vector);
00682 return offset > a.offset;
00683 }
00684 bool operator >= (const iterator & a) const
00685 {
00686 assert(p_vector == a.p_vector);
00687 return offset >= a.offset;
00688 }
00689
00690 void flush()
00691 {
00692 p_vector->flush();
00693 }
00694
00695 std::ostream & operator << (std::ostream & o) const
00696 {
00697 o << "vectorpointer: " << ((void *)p_vector) << " offset: " << offset;
00698 return o;
00699 }
00700 };
00701
00702
00704
00717 template <
00718 typename Tp_,
00719 unsigned PgSz_ = 4,
00720 typename PgTp_ = lru_pager<8>,
00721 unsigned BlkSize_ = STXXL_DEFAULT_BLOCK_SIZE(Tp_),
00722 typename AllocStr_ = STXXL_DEFAULT_ALLOC_STRATEGY,
00723 typename SzTp_ = stxxl::uint64
00724 >
00725 class vector
00726 {
00727 public:
00728 typedef Tp_ value_type;
00729 typedef value_type & reference;
00730 typedef const value_type & const_reference;
00731 typedef value_type * pointer;
00732 typedef SzTp_ size_type;
00733 typedef stxxl::int64 difference_type;
00734 typedef const value_type * const_pointer;
00735
00736 typedef PgTp_ pager_type;
00737 typedef AllocStr_ alloc_strategy;
00738
00739 enum {
00740 block_size = BlkSize_,
00741 page_size = PgSz_,
00742 n_pages = pager_type::n_pages,
00743 on_disk = -1
00744 };
00745
00746 typedef vector_iterator<value_type, alloc_strategy, size_type,
00747 difference_type, block_size, pager_type, page_size> iterator;
00748 friend class vector_iterator<value_type, alloc_strategy, size_type, difference_type, block_size, pager_type, page_size>;
00749 typedef const_vector_iterator<value_type, alloc_strategy,
00750 size_type, difference_type, block_size, pager_type, page_size> const_iterator;
00751 friend class const_vector_iterator<value_type, alloc_strategy, size_type, difference_type, block_size, pager_type, page_size>;
00752
00753 typedef bid_vector<block_size> bids_container_type;
00754 typedef typename bids_container_type::
00755 iterator bids_container_iterator;
00756 typedef typename bids_container_type::
00757 const_iterator const_bids_container_iterator;
00758
00759 typedef typed_block<BlkSize_, Tp_> block_type;
00760
00761 private:
00762 alloc_strategy _alloc_strategy;
00763 size_type _size;
00764 bids_container_type _bids;
00765
00766 mutable pager_type pager;
00767
00768 enum { uninitialized = 1, dirty = 2 };
00769 mutable std::vector<unsigned char> _page_status;
00770 mutable std::vector<int_type> _last_page;
00771 mutable simple_vector<int_type> _page_no;
00772 mutable std::queue<int_type> _free_pages;
00773 mutable simple_vector<block_type> _cache;
00774 file * _from;
00775 block_manager * bm;
00776 config * cfg;
00777
00778 size_type size_from_file_length(stxxl::uint64 file_length)
00779 {
00780 stxxl::uint64 blocks_fit = file_length / stxxl::uint64(block_type::raw_size);
00781 size_type cur_size = blocks_fit * stxxl::uint64(block_type::size);
00782 stxxl::uint64 rest = file_length - blocks_fit * stxxl::uint64(block_type::raw_size);
00783 return (cur_size + rest / stxxl::uint64(sizeof(value_type)));
00784 }
00785 stxxl::uint64 file_length()
00786 {
00787 size_type cur_size = size();
00788 if (cur_size % size_type(block_type::size))
00789 {
00790 stxxl::uint64 full_blocks_length = size_type(_bids.size() - 1) * size_type(block_type::raw_size);
00791 size_type rest = cur_size - size_type(_bids.size() - 1) * size_type(block_type::size);
00792 return full_blocks_length + rest * size_type(sizeof(value_type));
00793 }
00794 return size_type(_bids.size()) * size_type(block_type::raw_size);
00795 }
00796
00797 public:
00798 vector(size_type n = 0) :
00799 _size(n),
00800 _bids(div_and_round_up(n, block_type::size)),
00801 _page_status(div_and_round_up(_bids.size(), page_size)),
00802 _last_page(div_and_round_up(_bids.size(), page_size)),
00803 _page_no(n_pages),
00804 _cache(n_pages * page_size),
00805 _from(NULL)
00806 {
00807 bm = block_manager::get_instance();
00808 cfg = config::get_instance();
00809
00810 int_type all_pages = div_and_round_up(_bids.size(), page_size);
00811 int_type i = 0;
00812 for ( ; i < all_pages; ++i)
00813 {
00814 _page_status[i] = uninitialized;
00815 _last_page[i] = on_disk;
00816 }
00817
00818 for (i = 0; i < n_pages; ++i)
00819 _free_pages.push(i);
00820
00821
00822 bm->new_blocks(_alloc_strategy, _bids.begin(),
00823 _bids.end());
00824 }
00825
00826 void swap(vector & obj)
00827 {
00828 std::swap(_alloc_strategy, obj._alloc_strategy);
00829 std::swap(_size, obj._size);
00830 std::swap(_bids, obj._bids);
00831 std::swap(pager, obj.pager);
00832 std::swap(_page_status, obj._page_status);
00833 std::swap(_last_page, obj._last_page);
00834 std::swap(_page_no, obj._page_no);
00835 std::swap(_free_pages, obj._free_pages);
00836 std::swap(_cache, obj._cache);
00837 std::swap(_from, obj._from);
00838 }
00839 size_type capacity() const
00840 {
00841 return size_type(_bids.size()) * block_type::size;
00842 }
00843 void reserve(size_type n)
00844 {
00845 if (n <= capacity())
00846 return;
00847
00848
00849 unsigned_type old_bids_size = _bids.size();
00850 unsigned_type new_bids_size = div_and_round_up(n, block_type::size);
00851 unsigned_type new_pages = div_and_round_up(new_bids_size, page_size);
00852 _page_status.resize(new_pages, uninitialized);
00853 _last_page.resize(new_pages, on_disk);
00854
00855 _bids.resize(new_bids_size);
00856 if (_from == NULL)
00857 bm->new_blocks(offset_allocator<alloc_strategy>(old_bids_size, _alloc_strategy),
00858 _bids.begin() + old_bids_size, _bids.end());
00859
00860 else
00861 {
00862 size_type offset = size_type(old_bids_size) * size_type(block_type::raw_size);
00863 bids_container_iterator it = _bids.begin() + old_bids_size;
00864 for ( ; it != _bids.end(); ++it, offset += size_type(block_type::raw_size))
00865 {
00866 (*it).storage = _from;
00867 (*it).offset = offset;
00868 }
00869 STXXL_VERBOSE1("vector::reserve(): Changing size of file " << ((void *)_from) << " to "
00870 << offset);
00871 _from->set_size(offset);
00872 }
00873 }
00874 void resize(size_type n)
00875 {
00876 #ifndef STXXL_FREE_EXTMEMORY_ON_VECTOR_RESIZE
00877 reserve(n);
00878 #else
00879 unsigned_type old_bids_size = _bids.size();
00880 unsigned_type new_bids_size = div_and_round_up(n, block_type::size);
00881
00882
00883 if (new_bids_size > old_bids_size)
00884 {
00885 reserve(n);
00886 }
00887 else if (new_bids_size < old_bids_size)
00888 {
00889 bm->delete_blocks(_bids.begin() + new_bids_size, _bids.end());
00890 _bids.resize(new_bids_size);
00891
00892 unsigned_type first_page_to_evict = div_and_round_up(new_bids_size, page_size);
00893 std::fill(_page_status.begin() + first_page_to_evict,
00894 _page_status.end(), 0);
00895
00896 }
00897 #endif
00898
00899 _size = n;
00900 }
00901 void clear()
00902 {
00903 _size = 0;
00904 bm->delete_blocks(_bids.begin(), _bids.end());
00905
00906 _bids.clear();
00907 _page_status.clear();
00908 _last_page.clear();
00909 while (!_free_pages.empty())
00910 _free_pages.pop();
00911
00912
00913 for (int_type i = 0; i < n_pages; ++i)
00914 _free_pages.push(i);
00915 }
00916 void push_back(const_reference obj)
00917 {
00918 size_type old_size = _size;
00919 resize(old_size + 1);
00920 element(old_size) = obj;
00921 }
00922 void pop_back()
00923 {
00924 resize(_size - 1);
00925 }
00926 reference back()
00927 {
00928 return element(_size - 1);
00929 }
00930 reference front()
00931 {
00932 return element(0);
00933 }
00934 const_reference back() const
00935 {
00936 return const_element(_size - 1);
00937 }
00938 const_reference front() const
00939 {
00940 return const_element(0);
00941 }
00948 vector(file * from) :
00949 _size(size_from_file_length(from->size())),
00950 _bids(div_and_round_up(_size, size_type(block_type::size))),
00951 _page_status(div_and_round_up(_bids.size(), page_size)),
00952 _last_page(div_and_round_up(_bids.size(), page_size)),
00953 _page_no(n_pages),
00954 _cache(n_pages * page_size),
00955 _from(from)
00956 {
00957
00958 assert(from->get_disk_number() == -1);
00959
00960 if (block_type::has_filler)
00961 {
00962 std::ostringstream str_;
00963 str_ << "The block size for the vector, mapped to a file must me a multiple of the element size (" <<
00964 sizeof(value_type) << ") and the page size (4096).";
00965 throw std::runtime_error(str_.str());
00966 }
00967
00968 bm = block_manager::get_instance();
00969 cfg = config::get_instance();
00970
00971 int_type all_pages = div_and_round_up(_bids.size(), page_size);
00972 int_type i = 0;
00973 for ( ; i < all_pages; ++i)
00974 {
00975 _page_status[i] = 0;
00976 _last_page[i] = on_disk;
00977 }
00978
00979 for (i = 0; i < n_pages; ++i)
00980 _free_pages.push(i);
00981
00982
00983 size_type offset = 0;
00984 bids_container_iterator it = _bids.begin();
00985 for ( ; it != _bids.end(); ++it, offset += size_type(block_type::raw_size))
00986 {
00987 (*it).storage = from;
00988 (*it).offset = offset;
00989 }
00990 from->set_size(offset);
00991 }
00992
00993 vector(const vector & obj) :
00994 _size(obj.size()),
00995 _bids(div_and_round_up(obj.size(), block_type::size)),
00996 _page_status(div_and_round_up(_bids.size(), page_size)),
00997 _last_page(div_and_round_up(_bids.size(), page_size)),
00998 _page_no(n_pages),
00999 _cache(n_pages * page_size),
01000 _from(NULL)
01001 {
01002 bm = block_manager::get_instance();
01003 cfg = config::get_instance();
01004
01005 int_type all_pages = div_and_round_up(_bids.size(), page_size);
01006 int_type i = 0;
01007 for ( ; i < all_pages; ++i)
01008 {
01009 _page_status[i] = uninitialized;
01010 _last_page[i] = on_disk;
01011 }
01012
01013 for (i = 0; i < n_pages; ++i)
01014 _free_pages.push(i);
01015
01016
01017 bm->new_blocks(_alloc_strategy, _bids.begin(),
01018 _bids.end());
01019
01020 const_iterator inbegin = obj.begin();
01021 const_iterator inend = obj.end();
01022 std::copy(inbegin, inend, begin());
01023 }
01024
01025 vector & operator = (const vector & obj)
01026 {
01027 if (&obj != this)
01028 {
01029 vector tmp(obj);
01030 this->swap(tmp);
01031 }
01032 return *this;
01033 }
01034
01035 size_type size() const
01036 {
01037 return _size;
01038 }
01039 bool empty() const
01040 {
01041 return (!_size);
01042 }
01043 iterator begin()
01044 {
01045 return iterator(this, 0);
01046 }
01047 const_iterator begin() const
01048 {
01049 return const_iterator(this, 0);
01050 }
01051 iterator end()
01052 {
01053 return iterator(this, _size);
01054 }
01055 const_iterator end() const
01056 {
01057 return const_iterator(this, _size);
01058 }
01059 reference operator [] (size_type offset)
01060 {
01061 return element(offset);
01062 }
01063 const_reference operator [] (size_type offset) const
01064 {
01065 return const_element(offset);
01066 }
01067
01068 void flush() const
01069 {
01070 simple_vector<bool> non_free_pages(n_pages);
01071 int_type i = 0;
01072 for ( ; i < n_pages; i++)
01073 non_free_pages[i] = true;
01074
01075
01076 while (!_free_pages.empty())
01077 {
01078 non_free_pages[_free_pages.front()] = false;
01079 _free_pages.pop();
01080 }
01081
01082 for (i = 0; i < n_pages; i++)
01083 {
01084 _free_pages.push(i);
01085 int_type page_no = _page_no[i];
01086 if (non_free_pages[i])
01087 {
01088 STXXL_VERBOSE1("vector: flushing page " << i << " address: " << (int64(page_no) *
01089 int64(block_type::size) * int64(page_size)));
01090 if (_page_status[page_no] & dirty)
01091 write_page(page_no, i);
01092
01093
01094 _last_page[page_no] = on_disk;
01095 _page_status[page_no] = 0;
01096 }
01097 }
01098 }
01099 ~vector()
01100 {
01101 try
01102 {
01103 flush();
01104 }
01105 catch (...)
01106 {
01107 STXXL_VERBOSE("An exception in the ~vector()");
01108 }
01109
01110 bm->delete_blocks(_bids.begin(), _bids.end());
01111
01112 if (_from)
01113 {
01114 STXXL_VERBOSE1("~vector(): Changing size of file " << ((void *)_from) << " to "
01115 << file_length());
01116 STXXL_VERBOSE1("~vector(): size of the vector is " << size());
01117 _from->set_size(file_length());
01118 }
01119 }
01120
01121 private:
01122 bids_container_iterator bid(const size_type & offset)
01123 {
01124 return (_bids.begin() +
01125 static_cast<typename bids_container_type::size_type>
01126 (offset / block_type::size));
01127 }
01128 bids_container_iterator bid(const double_blocked_index<PgSz_, block_type::size> & offset)
01129 {
01130 return (_bids.begin() +
01131 static_cast<typename bids_container_type::size_type>
01132 (offset.get_block2() * PgSz_ + offset.get_block1()));
01133 }
01134 const_bids_container_iterator bid(const size_type & offset) const
01135 {
01136 return (_bids.begin() +
01137 static_cast<typename bids_container_type::size_type>
01138 (offset / block_type::size));
01139 }
01140 const_bids_container_iterator bid(const double_blocked_index<PgSz_, block_type::size> & offset) const
01141 {
01142 return (_bids.begin() +
01143 static_cast<typename bids_container_type::size_type>
01144 (offset.get_block2() * PgSz_ + offset.get_block1()));
01145 }
01146 void read_page(int_type page_no, int_type cache_page) const
01147 {
01148 STXXL_VERBOSE1("vector " << this << ": reading page_no=" << page_no << " cache_page=" << cache_page);
01149 request_ptr * reqs = new request_ptr[page_size];
01150 int_type block_no = page_no * page_size;
01151 int_type last_block = STXXL_MIN(block_no + page_size, int_type(_bids.size()));
01152 int_type i = cache_page * page_size, j = 0;
01153 for ( ; block_no < last_block; ++block_no, ++i, ++j)
01154 {
01155 reqs[j] = _cache[i].read(_bids[block_no]);
01156 }
01157 assert(last_block - page_no * page_size > 0);
01158 wait_all(reqs, last_block - page_no * page_size);
01159 delete[] reqs;
01160 }
01161 void write_page(int_type page_no, int_type cache_page) const
01162 {
01163 STXXL_VERBOSE1("vector " << this << ": writing page_no=" << page_no << " cache_page=" << cache_page);
01164 request_ptr * reqs = new request_ptr[page_size];
01165 int_type block_no = page_no * page_size;
01166 int_type last_block = STXXL_MIN(block_no + page_size, int_type(_bids.size()));
01167 int_type i = cache_page * page_size, j = 0;
01168 for ( ; block_no < last_block; ++block_no, ++i, ++j)
01169 {
01170 reqs[j] = _cache[i].write(_bids[block_no]);
01171 }
01172 assert(last_block - page_no * page_size > 0);
01173 wait_all(reqs, last_block - page_no * page_size);
01174 delete[] reqs;
01175 }
01176 reference element(size_type offset)
01177 {
01178 return element(double_blocked_index<PgSz_, block_type::size>(offset));
01179 }
01180
01181 reference element(const double_blocked_index<PgSz_, block_type::size> & offset)
01182 {
01183 int_type page_no = offset.get_block2();
01184 assert(page_no < int_type(_last_page.size()));
01185 int_type last_page = _last_page[page_no];
01186 if (last_page < 0)
01187 {
01188 if (_free_pages.empty())
01189 {
01190 int_type kicked_page = pager.kick();
01191 pager.hit(kicked_page);
01192 int_type old_page_no = _page_no[kicked_page];
01193 _last_page[page_no] = kicked_page;
01194 _last_page[old_page_no] = on_disk;
01195 _page_no[kicked_page] = page_no;
01196
01197
01198 if (_page_status[old_page_no] & dirty)
01199 {
01200
01201 write_page(old_page_no, kicked_page);
01202 }
01203
01204 if (_page_status[page_no] != uninitialized)
01205 {
01206 read_page(page_no, kicked_page);
01207 }
01208
01209 _page_status[page_no] = dirty;
01210
01211 return _cache[kicked_page * page_size + offset.get_block1()][offset.get_offset()];
01212 }
01213 else
01214 {
01215 int_type free_page = _free_pages.front();
01216 _free_pages.pop();
01217 pager.hit(free_page);
01218 _last_page[page_no] = free_page;
01219 _page_no[free_page] = page_no;
01220
01221 if (_page_status[page_no] != uninitialized)
01222 {
01223 read_page(page_no, free_page);
01224 }
01225
01226 _page_status[page_no] = dirty;
01227
01228 return _cache[free_page * page_size + offset.get_block1()][offset.get_offset()];
01229 }
01230 }
01231 else
01232 {
01233 _page_status[page_no] = dirty;
01234 pager.hit(last_page);
01235 return _cache[last_page * page_size + offset.get_block1()][offset.get_offset()];
01236 }
01237 }
01238 void touch(size_type offset) const
01239 {
01240
01241 assert(offset / (block_type::size * page_size)< _page_status.size());
01242 _page_status[offset / (block_type::size * page_size)] = 0;
01243 }
01244
01245 void touch(const double_blocked_index<PgSz_, block_type::size> & offset) const
01246 {
01247
01248 assert(offset.get_block2() < _page_status.size());
01249 _page_status[offset.get_block2()] = 0;
01250 }
01251
01252 const_reference const_element(size_type offset) const
01253 {
01254 return const_element(double_blocked_index<PgSz_, block_type::size>(offset));
01255 }
01256
01257 const_reference const_element(const double_blocked_index<PgSz_, block_type::size> & offset) const
01258 {
01259 int_type page_no = offset.get_block2();
01260 assert(page_no < int_type(_last_page.size()));
01261 int_type last_page = _last_page[page_no];
01262 if (last_page < 0)
01263 {
01264 if (_free_pages.empty())
01265 {
01266 int_type kicked_page = pager.kick();
01267 pager.hit(kicked_page);
01268 int_type old_page_no = _page_no[kicked_page];
01269 _last_page[page_no] = kicked_page;
01270 _last_page[old_page_no] = on_disk;
01271 _page_no[kicked_page] = page_no;
01272
01273
01274 if (_page_status[old_page_no] & dirty)
01275 {
01276
01277 write_page(old_page_no, kicked_page);
01278 }
01279
01280 if (_page_status[page_no] != uninitialized)
01281 {
01282 read_page(page_no, kicked_page);
01283 }
01284
01285 _page_status[page_no] = 0;
01286
01287 return _cache[kicked_page * page_size + offset.get_block1()][offset.get_offset()];
01288 }
01289 else
01290 {
01291 int_type free_page = _free_pages.front();
01292 _free_pages.pop();
01293 pager.hit(free_page);
01294 _last_page[page_no] = free_page;
01295 _page_no[free_page] = page_no;
01296
01297 if (_page_status[page_no] != uninitialized)
01298 {
01299 read_page(page_no, free_page);
01300 }
01301
01302 _page_status[page_no] = 0;
01303
01304 return _cache[free_page * page_size + offset.get_block1()][offset.get_offset()];
01305 }
01306 }
01307 else
01308 {
01309 pager.hit(last_page);
01310 return _cache[last_page * page_size + offset.get_block1()][offset.get_offset()];
01311 }
01312 }
01313 };
01314
01315 template <
01316 typename Tp_,
01317 unsigned PgSz_,
01318 typename PgTp_,
01319 unsigned BlkSize_,
01320 typename AllocStr_,
01321 typename SzTp_>
01322 inline bool operator == (stxxl::vector<Tp_, PgSz_, PgTp_, BlkSize_,
01323 AllocStr_, SzTp_> & a,
01324 stxxl::vector<Tp_, PgSz_, PgTp_, BlkSize_,
01325 AllocStr_, SzTp_> & b)
01326 {
01327 return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin());
01328 }
01329
01330 template <
01331 typename Tp_,
01332 unsigned PgSz_,
01333 typename PgTp_,
01334 unsigned BlkSize_,
01335 typename AllocStr_,
01336 typename SzTp_>
01337 inline bool operator != (stxxl::vector<Tp_, PgSz_, PgTp_, BlkSize_,
01338 AllocStr_, SzTp_> & a,
01339 stxxl::vector<Tp_, PgSz_, PgTp_, BlkSize_,
01340 AllocStr_, SzTp_> & b)
01341 {
01342 return !(a == b);
01343 }
01344
01345 template <
01346 typename Tp_,
01347 unsigned PgSz_,
01348 typename PgTp_,
01349 unsigned BlkSize_,
01350 typename AllocStr_,
01351 typename SzTp_>
01352 inline bool operator < (stxxl::vector<Tp_, PgSz_, PgTp_, BlkSize_,
01353 AllocStr_, SzTp_> & a,
01354 stxxl::vector<Tp_, PgSz_, PgTp_, BlkSize_,
01355 AllocStr_, SzTp_> & b)
01356 {
01357 return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
01358 }
01359
01360 template <
01361 typename Tp_,
01362 unsigned PgSz_,
01363 typename PgTp_,
01364 unsigned BlkSize_,
01365 typename AllocStr_,
01366 typename SzTp_>
01367 inline bool operator > (stxxl::vector<Tp_, PgSz_, PgTp_, BlkSize_,
01368 AllocStr_, SzTp_> & a,
01369 stxxl::vector<Tp_, PgSz_, PgTp_, BlkSize_,
01370 AllocStr_, SzTp_> & b)
01371 {
01372 return b < a;
01373 }
01374
01375 template <
01376 typename Tp_,
01377 unsigned PgSz_,
01378 typename PgTp_,
01379 unsigned BlkSize_,
01380 typename AllocStr_,
01381 typename SzTp_>
01382 inline bool operator <= (stxxl::vector<Tp_, PgSz_, PgTp_, BlkSize_,
01383 AllocStr_, SzTp_> & a,
01384 stxxl::vector<Tp_, PgSz_, PgTp_, BlkSize_,
01385 AllocStr_, SzTp_> & b)
01386 {
01387 return !(b < a);
01388 }
01389
01390 template <
01391 typename Tp_,
01392 unsigned PgSz_,
01393 typename PgTp_,
01394 unsigned BlkSize_,
01395 typename AllocStr_,
01396 typename SzTp_>
01397 inline bool operator >= (stxxl::vector<Tp_, PgSz_, PgTp_, BlkSize_,
01398 AllocStr_, SzTp_> & a,
01399 stxxl::vector<Tp_, PgSz_, PgTp_, BlkSize_,
01400 AllocStr_, SzTp_> & b)
01401 {
01402 return !(a < b);
01403 }
01404
01406
01409
01411
01434 template <
01435 typename Tp_,
01436 unsigned PgSz_ = 4,
01437 unsigned Pages_ = 8,
01438 unsigned BlkSize_ = STXXL_DEFAULT_BLOCK_SIZE(Tp_),
01439 typename AllocStr_ = STXXL_DEFAULT_ALLOC_STRATEGY,
01440 pager_type Pager_ = lru
01441 >
01442 struct VECTOR_GENERATOR
01443 {
01444 typedef typename IF<Pager_ == lru,
01445 lru_pager<Pages_>, random_pager<Pages_> >::result PagerType;
01446
01447 typedef vector<Tp_, PgSz_, PagerType, BlkSize_, AllocStr_> result;
01448 };
01449
01450
01452
01453 __STXXL_END_NAMESPACE
01454
01455
01456 namespace std
01457 {
01458 template <
01459 typename Tp_,
01460 unsigned PgSz_,
01461 typename PgTp_,
01462 unsigned BlkSize_,
01463 typename AllocStr_,
01464 typename SzTp_>
01465 void swap(stxxl::vector<Tp_, PgSz_, PgTp_, BlkSize_, AllocStr_, SzTp_> & a,
01466 stxxl::vector<Tp_, PgSz_, PgTp_, BlkSize_, AllocStr_, SzTp_> & b)
01467 {
01468 a.swap(b);
01469 }
01470 }
01471
01472 #endif // !STXXL_VECTOR_HEADER