Stxxl
1.4.0
|
00001 /*************************************************************************** 00002 * include/stxxl/bits/containers/vector.h 00003 * 00004 * Part of the STXXL. See http://stxxl.sourceforge.net 00005 * 00006 * Copyright (C) 2002-2008 Roman Dementiev <dementiev@mpi-sb.mpg.de> 00007 * Copyright (C) 2007-2009 Johannes Singler <singler@ira.uka.de> 00008 * Copyright (C) 2008-2010 Andreas Beckmann <beckmann@cs.uni-frankfurt.de> 00009 * 00010 * Distributed under the Boost Software License, Version 1.0. 00011 * (See accompanying file LICENSE_1_0.txt or copy at 00012 * http://www.boost.org/LICENSE_1_0.txt) 00013 **************************************************************************/ 00014 00015 #ifndef STXXL_VECTOR_HEADER 00016 #define STXXL_VECTOR_HEADER 00017 00018 #include <vector> 00019 #include <queue> 00020 #include <algorithm> 00021 00022 #include <stxxl/bits/deprecated.h> 00023 #include <stxxl/bits/io/request_operations.h> 00024 #include <stxxl/bits/mng/mng.h> 00025 #include <stxxl/bits/mng/typed_block.h> 00026 #include <stxxl/bits/common/tmeta.h> 00027 #include <stxxl/bits/containers/pager.h> 00028 #include <stxxl/bits/common/is_sorted.h> 00029 #include <stxxl/bits/mng/buf_ostream.h> 00030 00031 __STXXL_BEGIN_NAMESPACE 00032 00033 #define STXXL_VERBOSE_VECTOR(msg) STXXL_VERBOSE1("vector[" << static_cast<const void *>(this) << "]::" << msg) 00034 00035 //! \weakgroup stlcont Containers 00036 //! \ingroup stllayer 00037 //! Containers with STL-compatible interface 00038 00039 00040 //! \weakgroup stlcontinternals Internals 00041 //! \ingroup stlcont 00042 //! \{ 00043 00044 template <typename size_type, size_type modulo2, size_type modulo1> 00045 class double_blocked_index 00046 { 00047 static const size_type modulo12 = modulo1 * modulo2; 00048 00049 size_type pos, block1, block2, offset; 00050 00051 //! \invariant block2 * modulo12 + block1 * modulo1 + offset == pos && 0 <= block1 < modulo2 && 0 <= offset < modulo1 00052 00053 void set(size_type pos) 00054 { 00055 this->pos = pos; 00056 block2 = pos / modulo12; 00057 pos -= block2 * modulo12; 00058 block1 = pos / modulo1; 00059 offset = (pos - block1 * modulo1); 00060 00061 assert(block2 * modulo12 + block1 * modulo1 + offset == this->pos); 00062 assert(/* 0 <= block1 && */ block1 < modulo2); 00063 assert(/* 0 <= offset && */ offset < modulo1); 00064 } 00065 00066 public: 00067 double_blocked_index() 00068 { 00069 set(0); 00070 } 00071 00072 double_blocked_index(size_type pos) 00073 { 00074 set(pos); 00075 } 00076 00077 double_blocked_index(size_type block2, size_type block1, size_type offset) 00078 { 00079 assert(/* 0 <= block1 && */ block1 < modulo2); 00080 assert(/* 0 <= offset && */ offset < modulo1); 00081 00082 this->block2 = block2; 00083 this->block1 = block1; 00084 this->offset = offset; 00085 pos = block2 * modulo12 + block1 * modulo1 + offset; 00086 } 00087 00088 double_blocked_index & operator = (size_type pos) 00089 { 00090 set(pos); 00091 return *this; 00092 } 00093 00094 //pre-increment operator 00095 double_blocked_index & operator ++ () 00096 { 00097 ++pos; 00098 ++offset; 00099 if (offset == modulo1) 00100 { 00101 offset = 0; 00102 ++block1; 00103 if (block1 == modulo2) 00104 { 00105 block1 = 0; 00106 ++block2; 00107 } 00108 } 00109 00110 assert(block2 * modulo12 + block1 * modulo1 + offset == this->pos); 00111 assert(/* 0 <= block1 && */ block1 < modulo2); 00112 assert(/* 0 <= offset && */ offset < modulo1); 00113 00114 return *this; 00115 } 00116 00117 //post-increment operator 00118 double_blocked_index operator ++ (int) 00119 { 00120 double_blocked_index former(*this); 00121 operator ++ (); 00122 return former; 00123 } 00124 00125 //pre-increment operator 00126 double_blocked_index & operator -- () 00127 { 00128 --pos; 00129 if (offset == 0) 00130 { 00131 offset = modulo1; 00132 if (block1 == 0) 00133 { 00134 block1 = modulo2; 00135 --block2; 00136 } 00137 --block1; 00138 } 00139 --offset; 00140 00141 assert(block2 * modulo12 + block1 * modulo1 + offset == this->pos); 00142 assert(/*0 <= block1 &&*/ block1 < modulo2); 00143 assert(/*0 <= offset &&*/ offset < modulo1); 00144 00145 return *this; 00146 } 00147 00148 //post-increment operator 00149 double_blocked_index operator -- (int) 00150 { 00151 double_blocked_index former(*this); 00152 operator -- (); 00153 return former; 00154 } 00155 00156 double_blocked_index operator + (size_type addend) const 00157 { 00158 return double_blocked_index(pos + addend); 00159 } 00160 00161 double_blocked_index & operator += (size_type addend) 00162 { 00163 set(pos + addend); 00164 return *this; 00165 } 00166 00167 double_blocked_index operator - (size_type addend) const 00168 { 00169 return double_blocked_index(pos - addend); 00170 } 00171 00172 size_type operator - (const double_blocked_index & dbi2) const 00173 { 00174 return pos - dbi2.pos; 00175 } 00176 00177 double_blocked_index & operator -= (size_type subtrahend) 00178 { 00179 set(pos - subtrahend); 00180 return *this; 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 bool operator >= (const double_blocked_index & dbi2) const 00209 { 00210 return pos >= dbi2.pos; 00211 } 00212 00213 double_blocked_index & operator >>= (size_type shift) 00214 { 00215 set(pos >> shift); 00216 return *this; 00217 } 00218 00219 size_type get_pos() const 00220 { 00221 return pos; 00222 } 00223 00224 const size_type & get_block2() const 00225 { 00226 return block2; 00227 } 00228 00229 const size_type & get_block1() const 00230 { 00231 return block1; 00232 } 00233 00234 const size_type & get_offset() const 00235 { 00236 return offset; 00237 } 00238 }; 00239 00240 00241 template <unsigned BlkSize_> 00242 class bid_vector : public std::vector<BID<BlkSize_> > 00243 { 00244 public: 00245 typedef std::vector<BID<BlkSize_> > _Derived; 00246 typedef typename _Derived::size_type size_type; 00247 typedef typename _Derived::value_type bid_type; 00248 00249 bid_vector(size_type _sz) : _Derived(_sz) 00250 { } 00251 }; 00252 00253 00254 template < 00255 typename Tp_, 00256 unsigned PgSz_, 00257 typename PgTp_, 00258 unsigned BlkSize_, 00259 typename AllocStr_, 00260 typename SzTp_> 00261 class vector; 00262 00263 00264 template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_, 00265 unsigned BlkSize_, typename PgTp_, unsigned PgSz_> 00266 class const_vector_iterator; 00267 00268 00269 //! \brief External vector iterator, model of \c ext_random_access_iterator concept 00270 template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_, 00271 unsigned BlkSize_, typename PgTp_, unsigned PgSz_> 00272 class vector_iterator 00273 { 00274 typedef vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> _Self; 00275 typedef const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> _CIterator; 00276 00277 friend class const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_>; 00278 00279 public: 00280 typedef _CIterator const_iterator; 00281 typedef _Self iterator; 00282 00283 typedef unsigned block_offset_type; 00284 typedef vector<Tp_, PgSz_, PgTp_, BlkSize_, AllocStr_, SzTp_> vector_type; 00285 friend class vector<Tp_, PgSz_, PgTp_, BlkSize_, AllocStr_, SzTp_>; 00286 typedef typename vector_type::bids_container_type bids_container_type; 00287 typedef typename bids_container_type::iterator bids_container_iterator; 00288 typedef typename bids_container_type::bid_type bid_type; 00289 typedef typename vector_type::block_type block_type; 00290 typedef typename vector_type::blocked_index_type blocked_index_type; 00291 00292 typedef std::random_access_iterator_tag iterator_category; 00293 typedef typename vector_type::size_type size_type; 00294 typedef typename vector_type::difference_type difference_type; 00295 typedef typename vector_type::value_type value_type; 00296 typedef typename vector_type::reference reference; 00297 typedef typename vector_type::const_reference const_reference; 00298 typedef typename vector_type::pointer pointer; 00299 typedef typename vector_type::const_pointer const_pointer; 00300 00301 protected: 00302 blocked_index_type 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 block_externally_updated() 00388 { 00389 p_vector->block_externally_updated(offset); 00390 } 00391 00392 _STXXL_DEPRECATED(void touch()) 00393 { 00394 block_externally_updated(); 00395 } 00396 00397 _Self & operator ++ () 00398 { 00399 offset++; 00400 return *this; 00401 } 00402 _Self operator ++ (int) 00403 { 00404 _Self __tmp = *this; 00405 offset++; 00406 return __tmp; 00407 } 00408 _Self & operator -- () 00409 { 00410 offset--; 00411 return *this; 00412 } 00413 _Self operator -- (int) 00414 { 00415 _Self __tmp = *this; 00416 offset--; 00417 return __tmp; 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 offset <= a.offset; 00438 } 00439 bool operator > (const _Self & a) const 00440 { 00441 assert(p_vector == a.p_vector); 00442 return offset > a.offset; 00443 } 00444 bool operator >= (const _Self & a) const 00445 { 00446 assert(p_vector == a.p_vector); 00447 return offset >= a.offset; 00448 } 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 offset <= a.offset; 00469 } 00470 bool operator > (const const_iterator & a) const 00471 { 00472 assert(p_vector == a.p_vector); 00473 return offset > a.offset; 00474 } 00475 bool operator >= (const const_iterator & a) const 00476 { 00477 assert(p_vector == a.p_vector); 00478 return offset >= a.offset; 00479 } 00480 00481 void flush() 00482 { 00483 p_vector->flush(); 00484 } 00485 #if 0 00486 std::ostream & operator << (std::ostream & o) const 00487 { 00488 o << "vectorpointer: " << ((void *)p_vector) << " offset: " << offset; 00489 return o; 00490 } 00491 #endif 00492 }; 00493 00494 //! \brief Const external vector iterator, model of \c ext_random_access_iterator concept 00495 template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_, 00496 unsigned BlkSize_, typename PgTp_, unsigned PgSz_> 00497 class const_vector_iterator 00498 { 00499 typedef const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> _Self; 00500 typedef vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> _NonConstIterator; 00501 00502 friend class vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_>; 00503 00504 public: 00505 typedef _Self const_iterator; 00506 typedef _NonConstIterator iterator; 00507 00508 typedef unsigned block_offset_type; 00509 typedef vector<Tp_, PgSz_, PgTp_, BlkSize_, AllocStr_, SzTp_> vector_type; 00510 friend class vector<Tp_, PgSz_, PgTp_, BlkSize_, AllocStr_, SzTp_>; 00511 typedef typename vector_type::bids_container_type bids_container_type; 00512 typedef typename bids_container_type::iterator bids_container_iterator; 00513 typedef typename bids_container_type::bid_type bid_type; 00514 typedef typename vector_type::block_type block_type; 00515 typedef typename vector_type::blocked_index_type blocked_index_type; 00516 00517 typedef std::random_access_iterator_tag iterator_category; 00518 typedef typename vector_type::size_type size_type; 00519 typedef typename vector_type::difference_type difference_type; 00520 typedef typename vector_type::value_type value_type; 00521 typedef typename vector_type::const_reference reference; 00522 typedef typename vector_type::const_reference const_reference; 00523 typedef typename vector_type::const_pointer pointer; 00524 typedef typename vector_type::const_pointer const_pointer; 00525 00526 protected: 00527 blocked_index_type offset; 00528 const vector_type * p_vector; 00529 00530 private: 00531 const_vector_iterator(const vector_type * v, size_type o) : offset(o), 00532 p_vector(v) 00533 { } 00534 00535 public: 00536 const_vector_iterator() : offset(0), p_vector(NULL) 00537 { } 00538 const_vector_iterator(const _Self & a) : 00539 offset(a.offset), 00540 p_vector(a.p_vector) 00541 { } 00542 00543 const_vector_iterator(const iterator & a) : 00544 offset(a.offset), 00545 p_vector(a.p_vector) 00546 { } 00547 00548 block_offset_type block_offset() const 00549 { 00550 return static_cast<block_offset_type>(offset.get_offset()); 00551 } 00552 bids_container_iterator bid() const 00553 { 00554 return ((vector_type *)p_vector)->bid(offset); 00555 } 00556 00557 difference_type operator - (const _Self & a) const 00558 { 00559 return offset - a.offset; 00560 } 00561 00562 difference_type operator - (const iterator & a) const 00563 { 00564 return offset - a.offset; 00565 } 00566 00567 _Self operator - (size_type op) const 00568 { 00569 return _Self(p_vector, offset.get_pos() - op); 00570 } 00571 00572 _Self operator + (size_type op) const 00573 { 00574 return _Self(p_vector, offset.get_pos() + op); 00575 } 00576 00577 _Self & operator -= (size_type op) 00578 { 00579 offset -= op; 00580 return *this; 00581 } 00582 00583 _Self & operator += (size_type op) 00584 { 00585 offset += op; 00586 return *this; 00587 } 00588 00589 const_reference operator * () const 00590 { 00591 return p_vector->const_element(offset); 00592 } 00593 00594 const_pointer operator -> () const 00595 { 00596 return &(p_vector->const_element(offset)); 00597 } 00598 00599 const_reference operator [] (size_type op) const 00600 { 00601 return p_vector->const_element(offset.get_pos() + op); 00602 } 00603 00604 void block_externally_updated() 00605 { 00606 p_vector->block_externally_updated(offset); 00607 } 00608 00609 _STXXL_DEPRECATED(void touch()) 00610 { 00611 block_externally_updated(); 00612 } 00613 00614 _Self & operator ++ () 00615 { 00616 offset++; 00617 return *this; 00618 } 00619 _Self operator ++ (int) 00620 { 00621 _Self tmp_ = *this; 00622 offset++; 00623 return tmp_; 00624 } 00625 _Self & operator -- () 00626 { 00627 offset--; 00628 return *this; 00629 } 00630 _Self operator -- (int) 00631 { 00632 _Self __tmp = *this; 00633 offset--; 00634 return __tmp; 00635 } 00636 bool operator == (const _Self & a) const 00637 { 00638 assert(p_vector == a.p_vector); 00639 return offset == a.offset; // or (offset + stxxl::int64(p_vector)) 00640 } 00641 bool operator != (const _Self & a) const 00642 { 00643 assert(p_vector == a.p_vector); 00644 return offset != a.offset; 00645 } 00646 bool operator < (const _Self & a) const 00647 { 00648 assert(p_vector == a.p_vector); 00649 return offset < a.offset; 00650 } 00651 bool operator <= (const _Self & a) const 00652 { 00653 assert(p_vector == a.p_vector); 00654 return offset <= a.offset; 00655 } 00656 bool operator > (const _Self & a) const 00657 { 00658 assert(p_vector == a.p_vector); 00659 return offset > a.offset; 00660 } 00661 bool operator >= (const _Self & a) const 00662 { 00663 assert(p_vector == a.p_vector); 00664 return offset >= a.offset; 00665 } 00666 00667 bool operator == (const iterator & a) const 00668 { 00669 assert(p_vector == a.p_vector); 00670 return offset == a.offset; // or (offset + stxxl::int64(p_vector)) 00671 } 00672 bool operator != (const iterator & a) const 00673 { 00674 assert(p_vector == a.p_vector); 00675 return offset != a.offset; 00676 } 00677 bool operator < (const iterator & a) const 00678 { 00679 assert(p_vector == a.p_vector); 00680 return offset < a.offset; 00681 } 00682 bool operator <= (const iterator & a) const 00683 { 00684 assert(p_vector == a.p_vector); 00685 return offset <= a.offset; 00686 } 00687 bool operator > (const iterator & a) const 00688 { 00689 assert(p_vector == a.p_vector); 00690 return offset > a.offset; 00691 } 00692 bool operator >= (const iterator & a) const 00693 { 00694 assert(p_vector == a.p_vector); 00695 return offset >= a.offset; 00696 } 00697 00698 void flush() 00699 { 00700 p_vector->flush(); 00701 } 00702 00703 #if 0 00704 std::ostream & operator << (std::ostream & o) const 00705 { 00706 o << "vector pointer: " << ((void *)p_vector) << " offset: " << offset; 00707 return o; 00708 } 00709 #endif 00710 }; 00711 00712 00713 //! \brief External vector container 00714 00715 //! For semantics of the methods see documentation of the STL std::vector 00716 //! \tparam Tp_ type of contained objects (POD with no references to internal memory) 00717 //! \tparam PgSz_ number of blocks in a page 00718 //! \tparam PgTp_ pager type, \c random_pager<x> or \c lru_pager<x>, where x is the default number of pages, 00719 //! default is \c lru_pager<8> 00720 //! \tparam BlkSize_ external block size in bytes, default is 2 MiB 00721 //! \tparam AllocStr_ one of allocation strategies: \c striping , \c RC , \c SR , or \c FR 00722 //! default is RC 00723 //! 00724 //! Memory consumption: BlkSize_*x*PgSz_ bytes 00725 //! \warning Do not store references to the elements of an external vector. Such references 00726 //! might be invalidated during any following access to elements of the vector 00727 template < 00728 typename Tp_, 00729 unsigned PgSz_ = 4, 00730 typename PgTp_ = lru_pager<8>, 00731 unsigned BlkSize_ = STXXL_DEFAULT_BLOCK_SIZE(Tp_), 00732 typename AllocStr_ = STXXL_DEFAULT_ALLOC_STRATEGY, 00733 typename SzTp_ = stxxl::uint64 // will be deprecated soon 00734 > 00735 class vector 00736 { 00737 public: 00738 typedef Tp_ value_type; 00739 typedef value_type & reference; 00740 typedef const value_type & const_reference; 00741 typedef value_type * pointer; 00742 typedef SzTp_ size_type; 00743 typedef stxxl::int64 difference_type; 00744 typedef const value_type * const_pointer; 00745 00746 typedef PgTp_ pager_type; 00747 typedef AllocStr_ alloc_strategy_type; 00748 00749 enum constants { 00750 block_size = BlkSize_, 00751 page_size = PgSz_, 00752 on_disk = -1 00753 }; 00754 00755 typedef vector_iterator<value_type, alloc_strategy_type, size_type, 00756 difference_type, block_size, pager_type, page_size> iterator; 00757 friend class vector_iterator<value_type, alloc_strategy_type, size_type, difference_type, block_size, pager_type, page_size>; 00758 typedef const_vector_iterator<value_type, alloc_strategy_type, 00759 size_type, difference_type, block_size, pager_type, page_size> const_iterator; 00760 friend class const_vector_iterator<value_type, alloc_strategy_type, size_type, difference_type, block_size, pager_type, page_size>; 00761 typedef std::reverse_iterator<iterator> reverse_iterator; 00762 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 00763 00764 typedef bid_vector<block_size> bids_container_type; 00765 typedef typename bids_container_type::iterator bids_container_iterator; 00766 typedef typename bids_container_type::const_iterator const_bids_container_iterator; 00767 00768 typedef typed_block<BlkSize_, Tp_> block_type; 00769 typedef double_blocked_index<SzTp_, PgSz_, block_type::size> blocked_index_type; 00770 00771 private: 00772 alloc_strategy_type alloc_strategy; 00773 size_type _size; 00774 bids_container_type _bids; 00775 mutable pager_type pager; 00776 00777 enum { valid_on_disk = 0, uninitialized = 1, dirty = 2 }; 00778 mutable std::vector<unsigned char> _page_status; 00779 mutable std::vector<int_type> _page_to_slot; 00780 mutable simple_vector<int_type> _slot_to_page; 00781 mutable std::queue<int_type> _free_slots; 00782 mutable simple_vector<block_type> * _cache; 00783 file * _from; 00784 block_manager * bm; 00785 config * cfg; 00786 bool exported; 00787 00788 size_type size_from_file_length(stxxl::uint64 file_length) const 00789 { 00790 stxxl::uint64 blocks_fit = file_length / stxxl::uint64(block_type::raw_size); 00791 size_type cur_size = blocks_fit * stxxl::uint64(block_type::size); 00792 stxxl::uint64 rest = file_length - blocks_fit * stxxl::uint64(block_type::raw_size); 00793 return (cur_size + rest / stxxl::uint64(sizeof(value_type))); 00794 } 00795 00796 stxxl::uint64 file_length() const 00797 { 00798 typedef stxxl::uint64 file_size_type; 00799 size_type cur_size = size(); 00800 size_type num_full_blocks = cur_size / block_type::size; 00801 if (cur_size % block_type::size != 0) 00802 { 00803 size_type rest = cur_size - num_full_blocks * block_type::size; 00804 return file_size_type(num_full_blocks) * block_type::raw_size + rest * sizeof(value_type); 00805 } 00806 return file_size_type(num_full_blocks) * block_type::raw_size; 00807 } 00808 00809 public: 00810 //! \brief Constructs external vector. 00811 //! 00812 //! \param n Number of elements. 00813 //! \param npages Number of cached pages. 00814 vector(size_type n = 0, unsigned_type npages = pager_type().size()) : 00815 _size(n), 00816 _bids(div_ceil(n, block_type::size)), 00817 pager (npages), 00818 _page_status(div_ceil(_bids.size(), page_size)), 00819 _page_to_slot(div_ceil(_bids.size(), page_size)), 00820 _slot_to_page(npages), 00821 _cache(NULL), 00822 _from(NULL), 00823 exported(false) 00824 { 00825 bm = block_manager::get_instance(); 00826 cfg = config::get_instance(); 00827 00828 allocate_page_cache(); 00829 int_type all_pages = div_ceil(_bids.size(), page_size); 00830 int_type i = 0; 00831 for ( ; i < all_pages; ++i) 00832 { 00833 _page_status[i] = uninitialized; 00834 _page_to_slot[i] = on_disk; 00835 } 00836 00837 for (i = 0; i < numpages(); ++i) 00838 _free_slots.push(i); 00839 00840 bm->new_blocks(alloc_strategy, _bids.begin(), _bids.end(), 0); 00841 } 00842 00843 void swap(vector & obj) 00844 { 00845 std::swap(alloc_strategy, obj.alloc_strategy); 00846 std::swap(_size, obj._size); 00847 std::swap(_bids, obj._bids); 00848 std::swap(pager, obj.pager); 00849 std::swap(_page_status, obj._page_status); 00850 std::swap(_page_to_slot, obj._page_to_slot); 00851 std::swap(_slot_to_page, obj._slot_to_page); 00852 std::swap(_free_slots, obj._free_slots); 00853 std::swap(_cache, obj._cache); 00854 std::swap(_from, obj._from); 00855 std::swap(exported, obj.exported); 00856 } 00857 00858 void allocate_page_cache() const 00859 { 00860 // numpages() might be zero 00861 if (!_cache && numpages() > 0) 00862 _cache = new simple_vector<block_type> (numpages() * page_size); 00863 } 00864 00865 // allows to free the cache, but you may not access any element until call allocate_pacge_cache() again 00866 void deallocate_page_cache() const 00867 { 00868 flush(); 00869 delete _cache; 00870 _cache = NULL; 00871 } 00872 00873 size_type capacity() const 00874 { 00875 return size_type(_bids.size()) * block_type::size; 00876 } 00877 //! \brief Returns the number of bytes that the vector has allocated on disks 00878 size_type raw_capacity() const 00879 { 00880 return size_type(_bids.size()) * block_type::raw_size; 00881 } 00882 00883 void reserve(size_type n) 00884 { 00885 if (n <= capacity()) 00886 return; 00887 00888 unsigned_type old_bids_size = _bids.size(); 00889 unsigned_type new_bids_size = div_ceil(n, block_type::size); 00890 unsigned_type new_pages = div_ceil(new_bids_size, page_size); 00891 _page_status.resize(new_pages, uninitialized); 00892 _page_to_slot.resize(new_pages, on_disk); 00893 00894 _bids.resize(new_bids_size); 00895 if (_from == NULL) 00896 { 00897 bm->new_blocks(alloc_strategy, _bids.begin() + old_bids_size, _bids.end(), old_bids_size); 00898 } 00899 else 00900 { 00901 size_type offset = size_type(old_bids_size) * size_type(block_type::raw_size); 00902 bids_container_iterator it = _bids.begin() + old_bids_size; 00903 for ( ; it != _bids.end(); ++it, offset += size_type(block_type::raw_size)) 00904 { 00905 (*it).storage = _from; 00906 (*it).offset = offset; 00907 } 00908 STXXL_VERBOSE_VECTOR("reserve(): Changing size of file " << ((void *)_from) << " to " 00909 << offset); 00910 _from->set_size(offset); 00911 } 00912 } 00913 00914 void resize(size_type n) 00915 { 00916 _resize(n); 00917 } 00918 00919 void resize(size_type n, bool shrink_capacity) 00920 { 00921 if (shrink_capacity) 00922 _resize_shrink_capacity(n); 00923 else 00924 _resize(n); 00925 } 00926 00927 private: 00928 void _resize(size_type n) 00929 { 00930 reserve(n); 00931 if (n < _size) { 00932 // mark excess pages as uninitialized and evict them from cache 00933 unsigned_type first_page_to_evict = div_ceil(n, block_type::size * page_size); 00934 for (unsigned_type i = first_page_to_evict; i < _page_status.size(); ++i) { 00935 if (_page_to_slot[i] != on_disk) { 00936 _free_slots.push(_page_to_slot[i]); 00937 _page_to_slot[i] = on_disk; 00938 } 00939 _page_status[i] = uninitialized; 00940 } 00941 } 00942 _size = n; 00943 } 00944 00945 void _resize_shrink_capacity(size_type n) 00946 { 00947 unsigned_type old_bids_size = _bids.size(); 00948 unsigned_type new_bids_size = div_ceil(n, block_type::size); 00949 00950 if (new_bids_size > old_bids_size) 00951 { 00952 reserve(n); 00953 } 00954 else if (new_bids_size < old_bids_size) 00955 { 00956 if (_from != NULL) 00957 _from->set_size(new_bids_size * block_type::raw_size); 00958 else 00959 bm->delete_blocks(_bids.begin() + old_bids_size, _bids.end()); 00960 00961 _bids.resize(new_bids_size); 00962 unsigned_type new_pages = div_ceil(new_bids_size, page_size); 00963 _page_status.resize(new_pages); 00964 00965 unsigned_type first_page_to_evict = div_ceil(new_bids_size, page_size); 00966 // clear dirty flag, so these pages will be never written 00967 std::fill(_page_status.begin() + first_page_to_evict, 00968 _page_status.end(), (unsigned char)valid_on_disk); 00969 } 00970 00971 _size = n; 00972 } 00973 00974 public: 00975 void clear() 00976 { 00977 _size = 0; 00978 if (_from == NULL) 00979 bm->delete_blocks(_bids.begin(), _bids.end()); 00980 00981 _bids.clear(); 00982 _page_status.clear(); 00983 _page_to_slot.clear(); 00984 while (!_free_slots.empty()) 00985 _free_slots.pop(); 00986 00987 00988 for (int_type i = 0; i < numpages(); ++i) 00989 _free_slots.push(i); 00990 } 00991 00992 void push_back(const_reference obj) 00993 { 00994 size_type old_size = _size; 00995 resize(old_size + 1); 00996 element(old_size) = obj; 00997 } 00998 void pop_back() 00999 { 01000 resize(_size - 1); 01001 } 01002 01003 reference back() 01004 { 01005 return element(_size - 1); 01006 } 01007 reference front() 01008 { 01009 return element(0); 01010 } 01011 const_reference back() const 01012 { 01013 return const_element(_size - 1); 01014 } 01015 const_reference front() const 01016 { 01017 return const_element(0); 01018 } 01019 01020 //! \brief Construct vector from a file 01021 //! \param from file to be constructed from 01022 //! \param size Number of elements. 01023 //! \param npages Number of cached pages. 01024 //! \warning Only one \c vector can be assigned to a particular (physical) file. 01025 //! The block size of the vector must be a multiple of the element size 01026 //! \c sizeof(Tp_) and the page size (4096). 01027 vector(file * from, size_type size = size_type(-1), size_type npages = pager_type ().size ()) : 01028 _size((size == size_type(-1)) ? size_from_file_length(from->size()) : size), 01029 _bids(div_ceil(_size, size_type(block_type::size))), 01030 pager(npages), 01031 _page_status(div_ceil(_bids.size(), page_size)), 01032 _page_to_slot(div_ceil(_bids.size(), page_size)), 01033 _slot_to_page(npages), 01034 _cache(NULL), 01035 _from(from), 01036 exported(false) 01037 { 01038 // initialize from file 01039 if (!block_type::has_only_data) 01040 { 01041 std::ostringstream str_; 01042 str_ << "The block size for a vector that is mapped to a file must be a multiple of the element size (" << 01043 sizeof(value_type) << ") and the page size (4096)."; 01044 throw std::runtime_error(str_.str()); 01045 } 01046 01047 bm = block_manager::get_instance(); 01048 cfg = config::get_instance(); 01049 01050 allocate_page_cache(); 01051 int_type all_pages = div_ceil(_bids.size(), page_size); 01052 int_type i = 0; 01053 for ( ; i < all_pages; ++i) 01054 { 01055 _page_status[i] = valid_on_disk; 01056 _page_to_slot[i] = on_disk; 01057 } 01058 01059 for (i = 0; i < numpages(); ++i) 01060 _free_slots.push(i); 01061 01062 01063 //allocate blocks equidistantly and in-order 01064 size_type offset = 0; 01065 bids_container_iterator it = _bids.begin(); 01066 for ( ; it != _bids.end(); ++it, offset += size_type(block_type::raw_size)) 01067 { 01068 (*it).storage = from; 01069 (*it).offset = offset; 01070 } 01071 from->set_size(offset); 01072 } 01073 01074 vector(const vector & obj) : 01075 _size(obj.size()), 01076 _bids(div_ceil(obj.size(), block_type::size)), 01077 pager(obj.numpages ()), 01078 _page_status(div_ceil(_bids.size(), page_size)), 01079 _page_to_slot(div_ceil(_bids.size(), page_size)), 01080 _slot_to_page(obj.numpages ()), 01081 _cache(NULL), 01082 _from(NULL), 01083 exported(false) 01084 { 01085 assert(!obj.exported); 01086 bm = block_manager::get_instance(); 01087 cfg = config::get_instance(); 01088 01089 allocate_page_cache(); 01090 int_type all_pages = div_ceil(_bids.size(), page_size); 01091 int_type i = 0; 01092 for ( ; i < all_pages; ++i) 01093 { 01094 _page_status[i] = uninitialized; 01095 _page_to_slot[i] = on_disk; 01096 } 01097 01098 for (i = 0; i < numpages(); ++i) 01099 _free_slots.push(i); 01100 01101 bm->new_blocks(alloc_strategy, _bids.begin(), _bids.end(), 0); 01102 01103 const_iterator inbegin = obj.begin(); 01104 const_iterator inend = obj.end(); 01105 std::copy(inbegin, inend, begin()); 01106 } 01107 01108 vector & operator = (const vector & obj) 01109 { 01110 if (&obj != this) 01111 { 01112 vector tmp(obj); 01113 this->swap(tmp); 01114 } 01115 return *this; 01116 } 01117 01118 size_type size() const 01119 { 01120 return _size; 01121 } 01122 bool empty() const 01123 { 01124 return (!_size); 01125 } 01126 iterator begin() 01127 { 01128 return iterator(this, 0); 01129 } 01130 const_iterator begin() const 01131 { 01132 return const_iterator(this, 0); 01133 } 01134 const_iterator cbegin() const 01135 { 01136 return begin(); 01137 } 01138 iterator end() 01139 { 01140 return iterator(this, _size); 01141 } 01142 const_iterator end() const 01143 { 01144 return const_iterator(this, _size); 01145 } 01146 const_iterator cend() const 01147 { 01148 return end(); 01149 } 01150 01151 reverse_iterator rbegin() 01152 { 01153 return reverse_iterator(end()); 01154 } 01155 const_reverse_iterator rbegin() const 01156 { 01157 return const_reverse_iterator(end()); 01158 } 01159 const_reverse_iterator crbegin() const 01160 { 01161 return const_reverse_iterator(end()); 01162 } 01163 reverse_iterator rend() 01164 { 01165 return reverse_iterator(begin()); 01166 } 01167 const_reverse_iterator rend() const 01168 { 01169 return const_reverse_iterator(begin()); 01170 } 01171 const_reverse_iterator crend() const 01172 { 01173 return const_reverse_iterator(begin()); 01174 } 01175 01176 reference operator [] (size_type offset) 01177 { 01178 return element(offset); 01179 } 01180 const_reference operator [] (size_type offset) const 01181 { 01182 return const_element(offset); 01183 } 01184 01185 bool is_element_cached(size_type offset) const 01186 { 01187 return is_page_cached(blocked_index_type(offset)); 01188 } 01189 01190 void flush() const 01191 { 01192 simple_vector<bool> non_free_slots(numpages()); 01193 int_type i = 0; 01194 for ( ; i < numpages(); i++) 01195 non_free_slots[i] = true; 01196 01197 while (!_free_slots.empty()) 01198 { 01199 non_free_slots[_free_slots.front()] = false; 01200 _free_slots.pop(); 01201 } 01202 01203 for (i = 0; i < numpages(); i++) 01204 { 01205 _free_slots.push(i); 01206 int_type page_no = _slot_to_page[i]; 01207 if (non_free_slots[i]) 01208 { 01209 STXXL_VERBOSE_VECTOR("flush(): flushing page " << i << " at address " 01210 << (int64(page_no) * int64(block_type::size) * int64(page_size))); 01211 write_page(page_no, i); 01212 01213 _page_to_slot[page_no] = on_disk; 01214 } 01215 } 01216 } 01217 01218 ~vector() 01219 { 01220 STXXL_VERBOSE_VECTOR("~vector()"); 01221 try 01222 { 01223 flush(); 01224 } 01225 catch (io_error e) 01226 { 01227 STXXL_ERRMSG("io_error thrown in ~vector(): " << e.what()); 01228 } 01229 catch (...) 01230 { 01231 STXXL_ERRMSG("Exception thrown in ~vector()"); 01232 } 01233 01234 if (!exported) 01235 { 01236 if (_from == NULL) 01237 bm->delete_blocks(_bids.begin(), _bids.end()); 01238 else // file must be truncated 01239 { 01240 STXXL_VERBOSE_VECTOR("~vector(): Changing size of file " << ((void *)_from) << " to " 01241 << file_length()); 01242 STXXL_VERBOSE_VECTOR("~vector(): size of the vector is " << size()); 01243 try 01244 { 01245 _from->set_size(file_length()); 01246 } 01247 catch (...) 01248 { 01249 STXXL_ERRMSG("Exception thrown in ~vector()...set_size()"); 01250 } 01251 } 01252 } 01253 delete _cache; 01254 } 01255 01256 //! \brief Export data such that it is persistent on the file system. 01257 //! Resulting files will be numbered ascending. 01258 void export_files(std::string filename_prefix) 01259 { 01260 int64 no = 0; 01261 for (bids_container_iterator i = _bids.begin(); i != _bids.end(); ++i) { 01262 std::ostringstream number; 01263 number << std::setw(9) << std::setfill('0') << no; 01264 size_type current_block_size = 01265 ((i + 1) == _bids.end() && _size % block_type::size > 0) ? 01266 (_size % block_type::size) * sizeof(value_type) : 01267 block_type::size * sizeof(value_type); 01268 (*i).storage->export_files((*i).offset, current_block_size, filename_prefix + number.str()); 01269 ++no; 01270 } 01271 exported = true; 01272 } 01273 01274 //! \brief Get the file associated with this vector, or NULL. 01275 file * get_file() const 01276 { 01277 return _from; 01278 } 01279 01280 //! \brief Set the blocks and the size of this container explicitly. 01281 //! The vector must be completely empty before. 01282 template <typename ForwardIterator> 01283 void set_content(const ForwardIterator & bid_begin, const ForwardIterator & bid_end, size_type n) 01284 { 01285 unsigned_type new_bids_size = div_ceil(n, block_type::size); 01286 _bids.resize(new_bids_size); 01287 std::copy(bid_begin, bid_end, _bids.begin()); 01288 unsigned_type new_pages = div_ceil(new_bids_size, page_size); 01289 _page_status.resize(new_pages, valid_on_disk); 01290 _page_to_slot.resize(new_pages, on_disk); 01291 _size = n; 01292 } 01293 01294 //! Number of pages used by the pager. 01295 inline int_type numpages() const 01296 { 01297 return pager.size (); 01298 } 01299 01300 private: 01301 bids_container_iterator bid(const size_type & offset) 01302 { 01303 return (_bids.begin() + 01304 static_cast<typename bids_container_type::size_type> 01305 (offset / block_type::size)); 01306 } 01307 bids_container_iterator bid(const blocked_index_type & offset) 01308 { 01309 return (_bids.begin() + 01310 static_cast<typename bids_container_type::size_type> 01311 (offset.get_block2() * PgSz_ + offset.get_block1())); 01312 } 01313 const_bids_container_iterator bid(const size_type & offset) const 01314 { 01315 return (_bids.begin() + 01316 static_cast<typename bids_container_type::size_type> 01317 (offset / block_type::size)); 01318 } 01319 const_bids_container_iterator bid(const blocked_index_type & offset) const 01320 { 01321 return (_bids.begin() + 01322 static_cast<typename bids_container_type::size_type> 01323 (offset.get_block2() * PgSz_ + offset.get_block1())); 01324 } 01325 01326 void read_page(int_type page_no, int_type cache_slot) const 01327 { 01328 if (_page_status[page_no] == uninitialized) 01329 return; 01330 STXXL_VERBOSE_VECTOR("read_page(): page_no=" << page_no << " cache_slot=" << cache_slot); 01331 request_ptr * reqs = new request_ptr[page_size]; 01332 int_type block_no = page_no * page_size; 01333 int_type last_block = STXXL_MIN(block_no + page_size, int_type(_bids.size())); 01334 int_type i = cache_slot * page_size, j = 0; 01335 for ( ; block_no < last_block; ++block_no, ++i, ++j) 01336 { 01337 reqs[j] = (*_cache)[i].read(_bids[block_no]); 01338 } 01339 assert(last_block - page_no * page_size > 0); 01340 wait_all(reqs, last_block - page_no * page_size); 01341 delete[] reqs; 01342 } 01343 void write_page(int_type page_no, int_type cache_slot) const 01344 { 01345 if (!(_page_status[page_no] & dirty)) 01346 return; 01347 STXXL_VERBOSE_VECTOR("write_page(): page_no=" << page_no << " cache_slot=" << cache_slot); 01348 request_ptr * reqs = new request_ptr[page_size]; 01349 int_type block_no = page_no * page_size; 01350 int_type last_block = STXXL_MIN(block_no + page_size, int_type(_bids.size())); 01351 assert(block_no < last_block); 01352 int_type i = cache_slot * page_size, j = 0; 01353 for ( ; block_no < last_block; ++block_no, ++i, ++j) 01354 { 01355 reqs[j] = (*_cache)[i].write(_bids[block_no]); 01356 } 01357 _page_status[page_no] = valid_on_disk; 01358 assert(last_block - page_no * page_size > 0); 01359 wait_all(reqs, last_block - page_no * page_size); 01360 delete[] reqs; 01361 } 01362 01363 reference element(size_type offset) 01364 { 01365 #ifdef STXXL_RANGE_CHECK 01366 assert(offset < size()); 01367 #endif 01368 return element(blocked_index_type(offset)); 01369 } 01370 01371 reference element(const blocked_index_type & offset) 01372 { 01373 #ifdef STXXL_RANGE_CHECK 01374 assert(offset.get_pos() < size()); 01375 #endif 01376 int_type page_no = offset.get_block2(); 01377 assert(page_no < int_type(_page_to_slot.size())); // fails if offset is too large, out of bound access 01378 int_type cache_slot = _page_to_slot[page_no]; 01379 if (cache_slot < 0) // == on_disk 01380 { 01381 if (_free_slots.empty()) // has to kick 01382 { 01383 int_type kicked_slot = pager.kick(); 01384 pager.hit(kicked_slot); 01385 int_type old_page_no = _slot_to_page[kicked_slot]; 01386 _page_to_slot[page_no] = kicked_slot; 01387 _page_to_slot[old_page_no] = on_disk; 01388 _slot_to_page[kicked_slot] = page_no; 01389 01390 write_page(old_page_no, kicked_slot); 01391 read_page(page_no, kicked_slot); 01392 01393 _page_status[page_no] = dirty; 01394 01395 return (*_cache)[kicked_slot * page_size + offset.get_block1()][offset.get_offset()]; 01396 } 01397 else 01398 { 01399 int_type free_slot = _free_slots.front(); 01400 _free_slots.pop(); 01401 pager.hit(free_slot); 01402 _page_to_slot[page_no] = free_slot; 01403 _slot_to_page[free_slot] = page_no; 01404 01405 read_page(page_no, free_slot); 01406 01407 _page_status[page_no] = dirty; 01408 01409 return (*_cache)[free_slot * page_size + offset.get_block1()][offset.get_offset()]; 01410 } 01411 } 01412 else 01413 { 01414 _page_status[page_no] = dirty; 01415 pager.hit(cache_slot); 01416 return (*_cache)[cache_slot * page_size + offset.get_block1()][offset.get_offset()]; 01417 } 01418 } 01419 01420 // don't forget to first flush() the vector's cache before updating pages externally 01421 void page_externally_updated(unsigned_type page_no) const 01422 { 01423 // fails if offset is too large, out of bound access 01424 assert(page_no < _page_status.size()); 01425 // "A dirty page has been marked as newly initialized. The page content will be lost." 01426 assert(!(_page_status[page_no] & dirty)); 01427 if (_page_to_slot[page_no] != on_disk) { 01428 // remove page from cache 01429 _free_slots.push(_page_to_slot[page_no]); 01430 _page_to_slot[page_no] = on_disk; 01431 } 01432 _page_status[page_no] = valid_on_disk; 01433 } 01434 01435 void block_externally_updated(size_type offset) const 01436 { 01437 page_externally_updated(offset / (block_type::size * page_size)); 01438 } 01439 01440 void block_externally_updated(const blocked_index_type & offset) const 01441 { 01442 page_externally_updated(offset.get_block2()); 01443 } 01444 01445 _STXXL_DEPRECATED(void touch(size_type offset) const) 01446 { 01447 page_externally_updated(offset / (block_type::size * page_size)); 01448 } 01449 01450 _STXXL_DEPRECATED(void touch(const blocked_index_type & offset) const) 01451 { 01452 page_externally_updated(offset.get_block2()); 01453 } 01454 01455 const_reference const_element(size_type offset) const 01456 { 01457 return const_element(blocked_index_type(offset)); 01458 } 01459 01460 const_reference const_element(const blocked_index_type & offset) const 01461 { 01462 int_type page_no = offset.get_block2(); 01463 assert(page_no < int_type(_page_to_slot.size())); // fails if offset is too large, out of bound access 01464 int_type cache_slot = _page_to_slot[page_no]; 01465 if (cache_slot < 0) // == on_disk 01466 { 01467 if (_free_slots.empty()) // has to kick 01468 { 01469 int_type kicked_slot = pager.kick(); 01470 pager.hit(kicked_slot); 01471 int_type old_page_no = _slot_to_page[kicked_slot]; 01472 _page_to_slot[page_no] = kicked_slot; 01473 _page_to_slot[old_page_no] = on_disk; 01474 _slot_to_page[kicked_slot] = page_no; 01475 01476 write_page(old_page_no, kicked_slot); 01477 read_page(page_no, kicked_slot); 01478 01479 return (*_cache)[kicked_slot * page_size + offset.get_block1()][offset.get_offset()]; 01480 } 01481 else 01482 { 01483 int_type free_slot = _free_slots.front(); 01484 _free_slots.pop(); 01485 pager.hit(free_slot); 01486 _page_to_slot[page_no] = free_slot; 01487 _slot_to_page[free_slot] = page_no; 01488 01489 read_page(page_no, free_slot); 01490 01491 return (*_cache)[free_slot * page_size + offset.get_block1()][offset.get_offset()]; 01492 } 01493 } 01494 else 01495 { 01496 pager.hit(cache_slot); 01497 return (*_cache)[cache_slot * page_size + offset.get_block1()][offset.get_offset()]; 01498 } 01499 } 01500 01501 bool is_page_cached(const blocked_index_type & offset) const 01502 { 01503 int_type page_no = offset.get_block2(); 01504 assert(page_no < int_type(_page_to_slot.size())); // fails if offset is too large, out of bound access 01505 int_type cache_slot = _page_to_slot[page_no]; 01506 return (cache_slot >= 0); // on_disk == -1 01507 } 01508 }; 01509 01510 template < 01511 typename Tp_, 01512 unsigned PgSz_, 01513 typename PgTp_, 01514 unsigned BlkSize_, 01515 typename AllocStr_, 01516 typename SzTp_> 01517 inline bool operator == (stxxl::vector<Tp_, PgSz_, PgTp_, BlkSize_, 01518 AllocStr_, SzTp_> & a, 01519 stxxl::vector<Tp_, PgSz_, PgTp_, BlkSize_, 01520 AllocStr_, SzTp_> & b) 01521 { 01522 return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin()); 01523 } 01524 01525 template < 01526 typename Tp_, 01527 unsigned PgSz_, 01528 typename PgTp_, 01529 unsigned BlkSize_, 01530 typename AllocStr_, 01531 typename SzTp_> 01532 inline bool operator != (stxxl::vector<Tp_, PgSz_, PgTp_, BlkSize_, 01533 AllocStr_, SzTp_> & a, 01534 stxxl::vector<Tp_, PgSz_, PgTp_, BlkSize_, 01535 AllocStr_, SzTp_> & b) 01536 { 01537 return !(a == b); 01538 } 01539 01540 template < 01541 typename Tp_, 01542 unsigned PgSz_, 01543 typename PgTp_, 01544 unsigned BlkSize_, 01545 typename AllocStr_, 01546 typename SzTp_> 01547 inline bool operator < (stxxl::vector<Tp_, PgSz_, PgTp_, BlkSize_, 01548 AllocStr_, SzTp_> & a, 01549 stxxl::vector<Tp_, PgSz_, PgTp_, BlkSize_, 01550 AllocStr_, SzTp_> & b) 01551 { 01552 return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end()); 01553 } 01554 01555 template < 01556 typename Tp_, 01557 unsigned PgSz_, 01558 typename PgTp_, 01559 unsigned BlkSize_, 01560 typename AllocStr_, 01561 typename SzTp_> 01562 inline bool operator > (stxxl::vector<Tp_, PgSz_, PgTp_, BlkSize_, 01563 AllocStr_, SzTp_> & a, 01564 stxxl::vector<Tp_, PgSz_, PgTp_, BlkSize_, 01565 AllocStr_, SzTp_> & b) 01566 { 01567 return b < a; 01568 } 01569 01570 template < 01571 typename Tp_, 01572 unsigned PgSz_, 01573 typename PgTp_, 01574 unsigned BlkSize_, 01575 typename AllocStr_, 01576 typename SzTp_> 01577 inline bool operator <= (stxxl::vector<Tp_, PgSz_, PgTp_, BlkSize_, 01578 AllocStr_, SzTp_> & a, 01579 stxxl::vector<Tp_, PgSz_, PgTp_, BlkSize_, 01580 AllocStr_, SzTp_> & b) 01581 { 01582 return !(b < a); 01583 } 01584 01585 template < 01586 typename Tp_, 01587 unsigned PgSz_, 01588 typename PgTp_, 01589 unsigned BlkSize_, 01590 typename AllocStr_, 01591 typename SzTp_> 01592 inline bool operator >= (stxxl::vector<Tp_, PgSz_, PgTp_, BlkSize_, 01593 AllocStr_, SzTp_> & a, 01594 stxxl::vector<Tp_, PgSz_, PgTp_, BlkSize_, 01595 AllocStr_, SzTp_> & b) 01596 { 01597 return !(a < b); 01598 } 01599 01600 //! \} 01601 01602 //////////////////////////////////////////////////////////////////////////// 01603 01604 // specialization for stxxl::vector, to use only const_iterators 01605 template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_, 01606 unsigned BlkSize_, typename PgTp_, unsigned PgSz_> 01607 bool is_sorted( 01608 stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> __first, 01609 stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> __last) 01610 { 01611 return is_sorted_helper( 01612 stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_>(__first), 01613 stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_>(__last)); 01614 } 01615 01616 template <typename Tp_, typename AllocStr_, typename SzTp_, typename DiffTp_, 01617 unsigned BlkSize_, typename PgTp_, unsigned PgSz_, typename _StrictWeakOrdering> 01618 bool is_sorted( 01619 stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> __first, 01620 stxxl::vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_> __last, 01621 _StrictWeakOrdering __comp) 01622 { 01623 return is_sorted_helper( 01624 stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_>(__first), 01625 stxxl::const_vector_iterator<Tp_, AllocStr_, SzTp_, DiffTp_, BlkSize_, PgTp_, PgSz_>(__last), 01626 __comp); 01627 } 01628 01629 //////////////////////////////////////////////////////////////////////////// 01630 01631 //! \addtogroup stlcont 01632 //! \{ 01633 01634 //! \brief External vector type generator 01635 01636 //! \tparam Tp_ type of contained objects (POD with no references to internal memory) 01637 //! \tparam PgSz_ number of blocks in a page 01638 //! \tparam Pages_ number of pages 01639 //! \tparam BlkSize_ external block size in bytes, default is 2 MiB 01640 //! \tparam AllocStr_ one of allocation strategies: \c striping , \c RC , \c SR , or \c FR 01641 //! default is RC 01642 //! \tparam Pager_ pager type: 01643 //! - \c random , 01644 //! - \c lru , is default 01645 //! 01646 //! Memory consumption of constructed vector is BlkSize_*Pages_*PgSz_ bytes 01647 //! Configured vector type is available as \c STACK_GENERATOR<>::result. <BR> <BR> 01648 //! Examples: 01649 //! - \c VECTOR_GENERATOR<double>::result external vector of \c double's , 01650 //! - \c VECTOR_GENERATOR<double,8>::result external vector of \c double's , 01651 //! with 8 blocks per page, 01652 //! - \c VECTOR_GENERATOR<double,8,2,512*1024,RC,lru>::result external vector of \c double's , 01653 //! with 8 blocks per page, 2 pages, 512 KiB blocks, Random Cyclic allocation 01654 //! and lru cache replacement strategy 01655 //! \warning Do not store references to the elements of an external vector. Such references 01656 //! might be invalidated during any following access to elements of the vector 01657 template < 01658 typename Tp_, 01659 unsigned PgSz_ = 4, 01660 unsigned Pages_ = 8, 01661 unsigned BlkSize_ = STXXL_DEFAULT_BLOCK_SIZE(Tp_), 01662 typename AllocStr_ = STXXL_DEFAULT_ALLOC_STRATEGY, 01663 pager_type Pager_ = lru 01664 > 01665 struct VECTOR_GENERATOR 01666 { 01667 typedef typename IF<Pager_ == lru, 01668 lru_pager<Pages_>, random_pager<Pages_> >::result PagerType; 01669 01670 typedef vector<Tp_, PgSz_, PagerType, BlkSize_, AllocStr_> result; 01671 }; 01672 01673 //////////////////////////////////////////////////////////////////////////// 01674 01675 //! \brief Buffered sequential writer to a vector using overlapped I/O 01676 01677 //! This buffered writer can be used to write a large sequential region of a 01678 //! vector using overlapped i/o. The object is created from an iterator range, 01679 //! which can then be written to using operator<<. 01680 01681 template <typename VectorType> 01682 class vector_bufwriter 01683 { 01684 public: 01685 01686 typedef typename VectorType::value_type value_type; 01687 01688 typedef VectorType vector_type; 01689 typedef typename VectorType::iterator vector_iterator_type; 01690 typedef typename VectorType::const_iterator vector_const_iterator_type; 01691 01692 private: 01693 01694 typedef buf_ostream<typename vector_iterator_type::block_type, typename vector_iterator_type::bids_container_iterator> buf_ostream_type; 01695 01696 vector_iterator_type m_begin, m_end; 01697 vector_const_iterator_type m_prev; 01698 buf_ostream_type* m_bufout; 01699 01700 unsigned_type m_nbuffers; 01701 01702 public: 01703 //! \brief Create overlapped writer for begin,end range. 01704 vector_bufwriter(vector_iterator_type begin, vector_iterator_type end, 01705 unsigned_type nbuffers = 0) 01706 : m_begin(begin), 01707 m_end(end), 01708 m_bufout(NULL) 01709 { 01710 if (nbuffers == 0) 01711 m_nbuffers = 2 * config::get_instance()->disks_number(); 01712 } 01713 01714 //! \brief Finish writing and flush output back to vector. 01715 ~vector_bufwriter() 01716 { 01717 finish(); 01718 } 01719 01720 //! \brief Write value to the current position and advance the internal iterator. 01721 vector_bufwriter& operator<< (const value_type& v) 01722 { 01723 if (!m_bufout) 01724 { 01725 if (m_begin.block_offset()) 01726 { 01727 // output position is not at the start of the block 01728 assert(m_begin != m_end); 01729 *m_begin = v; 01730 ++m_begin; 01731 01732 return *this; 01733 } 01734 else 01735 { 01736 // output position is start of block: create buffered writer 01737 01738 m_begin.flush(); // flush container 01739 01740 // create buffered write stream for blocks 01741 m_bufout = new buf_ostream_type(m_begin.bid(), m_nbuffers); 01742 m_prev = m_begin; 01743 01744 // drop through to normal output into buffered writer 01745 } 01746 } 01747 01748 assert(m_begin != m_end); 01749 01750 m_bufout->operator*() = v; 01751 m_bufout->operator++(); 01752 ++m_begin; 01753 01754 // if the pointer has finished a block, then we inform the vector that 01755 // this block has been updated. 01756 if (m_begin.block_offset() == 0) { 01757 if (m_prev != m_begin) { 01758 m_prev.block_externally_updated(); 01759 m_prev = m_begin; 01760 } 01761 } 01762 01763 return *this; 01764 } 01765 01766 //! \brief Finish writing and flush output back to vector. 01767 void finish() 01768 { 01769 if (m_bufout) 01770 { 01771 // must finish the block started in the buffered writer: fill it 01772 // with the data in the vector 01773 vector_const_iterator_type const_out = m_begin; 01774 01775 while (const_out.block_offset()) 01776 { 01777 m_bufout->operator*() = *const_out; 01778 m_bufout->operator++(); 01779 ++const_out; 01780 } 01781 01782 // inform the vector that the block has been updated. 01783 if (m_prev != m_begin) { 01784 m_prev.block_externally_updated(); 01785 m_prev = m_begin; 01786 } 01787 01788 delete m_bufout; 01789 m_bufout = NULL; 01790 } 01791 } 01792 }; 01793 01794 //////////////////////////////////////////////////////////////////////////// 01795 01796 //! \} 01797 01798 __STXXL_END_NAMESPACE 01799 01800 namespace std 01801 { 01802 template < 01803 typename Tp_, 01804 unsigned PgSz_, 01805 typename PgTp_, 01806 unsigned BlkSize_, 01807 typename AllocStr_, 01808 typename SzTp_> 01809 void swap(stxxl::vector<Tp_, PgSz_, PgTp_, BlkSize_, AllocStr_, SzTp_> & a, 01810 stxxl::vector<Tp_, PgSz_, PgTp_, BlkSize_, AllocStr_, SzTp_> & b) 01811 { 01812 a.swap(b); 01813 } 01814 } 01815 01816 #endif // !STXXL_VECTOR_HEADER 01817 // vim: et:ts=4:sw=4