Stxxl  1.4.0
include/stxxl/bits/containers/vector.h
Go to the documentation of this file.
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 &lt; modulo2 && 0 <= offset &lt; 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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines