• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • Examples
  • File List

stack.h

00001 /***************************************************************************
00002  *  include/stxxl/bits/containers/stack.h
00003  *
00004  *  Part of the STXXL. See http://stxxl.sourceforge.net
00005  *
00006  *  Copyright (C) 2003-2004 Roman Dementiev <[email protected]>
00007  *
00008  *  Distributed under the Boost Software License, Version 1.0.
00009  *  (See accompanying file LICENSE_1_0.txt or copy at
00010  *  http://www.boost.org/LICENSE_1_0.txt)
00011  **************************************************************************/
00012 
00013 #ifndef STXXL_STACK_HEADER
00014 #define STXXL_STACK_HEADER
00015 
00016 #include <stack>
00017 #include <vector>
00018 
00019 #include <stxxl/bits/mng/mng.h>
00020 #include <stxxl/bits/mng/typed_block.h>
00021 #include <stxxl/bits/common/simple_vector.h>
00022 #include <stxxl/bits/common/tmeta.h>
00023 #include <stxxl/bits/mng/read_write_pool.h>
00024 #include <stxxl/bits/mng/write_pool.h>
00025 #include <stxxl/bits/mng/prefetch_pool.h>
00026 
00027 
00028 __STXXL_BEGIN_NAMESPACE
00029 
00032 
00033 template <class ValTp,
00034           unsigned BlocksPerPage = 4,
00035           unsigned BlkSz = STXXL_DEFAULT_BLOCK_SIZE(ValTp),
00036           class AllocStr = STXXL_DEFAULT_ALLOC_STRATEGY,
00037           class SzTp = stxxl::int64>
00038 struct stack_config_generator
00039 {
00040     typedef ValTp value_type;
00041     enum { blocks_per_page = BlocksPerPage };
00042     typedef AllocStr alloc_strategy;
00043     enum { block_size = BlkSz };
00044     typedef SzTp size_type;
00045 };
00046 
00047 
00049 
00055 template <class Config_>
00056 class normal_stack : private noncopyable
00057 {
00058 public:
00059     typedef Config_ cfg;
00060     typedef typename cfg::value_type value_type;
00061     typedef typename cfg::alloc_strategy alloc_strategy_type;
00062     typedef typename cfg::size_type size_type;
00063     enum {
00064         blocks_per_page = cfg::blocks_per_page,
00065         block_size = cfg::block_size
00066     };
00067 
00068     typedef typed_block<block_size, value_type> block_type;
00069     typedef BID<block_size> bid_type;
00070 
00071 private:
00072     size_type size_;
00073     unsigned_type cache_offset;
00074     value_type * current_element;
00075     simple_vector<block_type> cache;
00076     typename simple_vector<block_type>::iterator front_page;
00077     typename simple_vector<block_type>::iterator back_page;
00078     std::vector<bid_type> bids;
00079     alloc_strategy_type alloc_strategy;
00080 
00081 public:
00082     normal_stack() :
00083         size_(0),
00084         cache_offset(0),
00085         current_element(NULL),
00086         cache(blocks_per_page * 2),
00087         front_page(cache.begin() + blocks_per_page),
00088         back_page(cache.begin()),
00089         bids(0)
00090     {
00091         bids.reserve(blocks_per_page);
00092     }
00093 
00094     void swap(normal_stack & obj)
00095     {
00096         std::swap(size_, obj.size_);
00097         std::swap(cache_offset, obj.cache_offset);
00098         std::swap(current_element, obj.current_element);
00099         std::swap(cache, obj.cache);
00100         std::swap(front_page, obj.front_page);
00101         std::swap(back_page, obj.back_page);
00102         std::swap(bids, obj.bids);
00103         std::swap(alloc_strategy, obj.alloc_strategy);
00104     }
00105 
00109     template <class stack_type>
00110     normal_stack(const stack_type & stack_) :
00111         size_(0),
00112         cache_offset(0),
00113         current_element(NULL),
00114         cache(blocks_per_page * 2),
00115         front_page(cache.begin() + blocks_per_page),
00116         back_page(cache.begin()),
00117         bids(0)
00118     {
00119         bids.reserve(blocks_per_page);
00120 
00121         stack_type stack_copy = stack_;
00122         const size_type sz = stack_copy.size();
00123         size_type i;
00124 
00125         std::vector<value_type> tmp(sz);
00126 
00127         for (i = 0; i < sz; ++i)
00128         {
00129             tmp[sz - i - 1] = stack_copy.top();
00130             stack_copy.pop();
00131         }
00132         for (i = 0; i < sz; ++i)
00133             this->push(tmp[i]);
00134     }
00135     virtual ~normal_stack()
00136     {
00137         STXXL_VERBOSE(STXXL_PRETTY_FUNCTION_NAME);
00138         block_manager::get_instance()->delete_blocks(bids.begin(), bids.end());
00139     }
00140     size_type size() const
00141     {
00142         return size_;
00143     }
00144     bool empty() const
00145     {
00146         return (!size_);
00147     }
00148     value_type & top()
00149     {
00150         assert(size_ > 0);
00151         return (*current_element);
00152     }
00153     const value_type & top() const
00154     {
00155         assert(size_ > 0);
00156         return (*current_element);
00157     }
00158     void push(const value_type & val)
00159     {
00160         assert(cache_offset <= 2 * blocks_per_page * block_type::size);
00161         //assert(cache_offset >= 0);
00162 
00163         if (cache_offset == 2 * blocks_per_page * block_type::size) // cache overflow
00164         {
00165             STXXL_VERBOSE2("growing, size: " << size_);
00166 
00167             bids.resize(bids.size() + blocks_per_page);
00168             typename std::vector<bid_type>::iterator cur_bid = bids.end() - blocks_per_page;
00169             block_manager::get_instance()->new_blocks(alloc_strategy, cur_bid, bids.end(), cur_bid - bids.begin());
00170 
00171             simple_vector<request_ptr> requests(blocks_per_page);
00172 
00173             for (int i = 0; i < blocks_per_page; ++i, ++cur_bid)
00174             {
00175                 requests[i] = (back_page + i)->write(*cur_bid);
00176             }
00177 
00178 
00179             std::swap(back_page, front_page);
00180 
00181             bids.reserve(bids.size() + blocks_per_page);
00182 
00183             cache_offset = blocks_per_page * block_type::size + 1;
00184             current_element = &((*front_page)[0]);
00185             ++size_;
00186 
00187             wait_all(requests.begin(), blocks_per_page);
00188 
00189             *current_element = val;
00190 
00191             return;
00192         }
00193 
00194         current_element = element(cache_offset);
00195         *current_element = val;
00196         ++size_;
00197         ++cache_offset;
00198     }
00199     void pop()
00200     {
00201         assert(cache_offset <= 2 * blocks_per_page * block_type::size);
00202         assert(cache_offset > 0);
00203         assert(size_ > 0);
00204 
00205         if (cache_offset == 1 && bids.size() >= blocks_per_page)
00206         {
00207             STXXL_VERBOSE2("shrinking, size: " << size_);
00208 
00209             simple_vector<request_ptr> requests(blocks_per_page);
00210 
00211             {
00212                 typename std::vector<bid_type>::const_iterator cur_bid = bids.end();
00213                 for (int i = blocks_per_page - 1; i >= 0; --i)
00214                 {
00215                     requests[i] = (front_page + i)->read(*(--cur_bid));
00216                 }
00217             }
00218 
00219             std::swap(front_page, back_page);
00220 
00221             cache_offset = blocks_per_page * block_type::size;
00222             --size_;
00223             current_element = &((*(back_page + (blocks_per_page - 1)))[block_type::size - 1]);
00224 
00225             wait_all(requests.begin(), blocks_per_page);
00226 
00227             block_manager::get_instance()->delete_blocks(bids.end() - blocks_per_page, bids.end());
00228             bids.resize(bids.size() - blocks_per_page);
00229 
00230             return;
00231         }
00232 
00233         --size_;
00234 
00235         current_element = element((--cache_offset) - 1);
00236     }
00237 
00238 private:
00239     value_type * element(unsigned_type offset)
00240     {
00241         if (offset < blocks_per_page * block_type::size)
00242             return &((*(back_page + offset / block_type::size))[offset % block_type::size]);
00243 
00244 
00245         unsigned_type unbiased_offset = offset - blocks_per_page * block_type::size;
00246         return &((*(front_page + unbiased_offset / block_type::size))[unbiased_offset % block_type::size]);
00247     }
00248 };
00249 
00250 
00252 
00256 template <class Config_>
00257 class grow_shrink_stack : private noncopyable
00258 {
00259 public:
00260     typedef Config_ cfg;
00261     typedef typename cfg::value_type value_type;
00262     typedef typename cfg::alloc_strategy alloc_strategy_type;
00263     typedef typename cfg::size_type size_type;
00264     enum {
00265         blocks_per_page = cfg::blocks_per_page,
00266         block_size = cfg::block_size,
00267     };
00268 
00269     typedef typed_block<block_size, value_type> block_type;
00270     typedef BID<block_size> bid_type;
00271 
00272 private:
00273     size_type size_;
00274     unsigned_type cache_offset;
00275     value_type * current_element;
00276     simple_vector<block_type> cache;
00277     typename simple_vector<block_type>::iterator cache_buffers;
00278     typename simple_vector<block_type>::iterator overlap_buffers;
00279     simple_vector<request_ptr> requests;
00280     std::vector<bid_type> bids;
00281     alloc_strategy_type alloc_strategy;
00282 
00283 public:
00284     grow_shrink_stack() :
00285         size_(0),
00286         cache_offset(0),
00287         current_element(NULL),
00288         cache(blocks_per_page * 2),
00289         cache_buffers(cache.begin()),
00290         overlap_buffers(cache.begin() + blocks_per_page),
00291         requests(blocks_per_page),
00292         bids(0)
00293     {
00294         bids.reserve(blocks_per_page);
00295     }
00296 
00297     void swap(grow_shrink_stack & obj)
00298     {
00299         std::swap(size_, obj.size_);
00300         std::swap(cache_offset, obj.cache_offset);
00301         std::swap(current_element, obj.current_element);
00302         std::swap(cache, obj.cache);
00303         std::swap(cache_buffers, obj.cache_buffers);
00304         std::swap(overlap_buffers, obj.overlap_buffers);
00305         std::swap(requests, obj.requests);
00306         std::swap(bids, obj.bids);
00307         std::swap(alloc_strategy, obj.alloc_strategy);
00308     }
00309 
00313     template <class stack_type>
00314     grow_shrink_stack(const stack_type & stack_) :
00315         size_(0),
00316         cache_offset(0),
00317         current_element(NULL),
00318         cache(blocks_per_page * 2),
00319         cache_buffers(cache.begin()),
00320         overlap_buffers(cache.begin() + blocks_per_page),
00321         requests(blocks_per_page),
00322         bids(0)
00323     {
00324         bids.reserve(blocks_per_page);
00325 
00326         stack_type stack_copy = stack_;
00327         const size_type sz = stack_copy.size();
00328         size_type i;
00329 
00330         std::vector<value_type> tmp(sz);
00331 
00332         for (i = 0; i < sz; ++i)
00333         {
00334             tmp[sz - i - 1] = stack_copy.top();
00335             stack_copy.pop();
00336         }
00337         for (i = 0; i < sz; ++i)
00338             this->push(tmp[i]);
00339     }
00340     virtual ~grow_shrink_stack()
00341     {
00342         STXXL_VERBOSE(STXXL_PRETTY_FUNCTION_NAME);
00343         try
00344         {
00345             if (requests[0].get())
00346                 wait_all(requests.begin(), blocks_per_page);
00347         }
00348         catch (const io_error & ex)
00349         { }
00350         block_manager::get_instance()->delete_blocks(bids.begin(), bids.end());
00351     }
00352     size_type size() const
00353     {
00354         return size_;
00355     }
00356     bool empty() const
00357     {
00358         return (!size_);
00359     }
00360     value_type & top()
00361     {
00362         assert(size_ > 0);
00363         return (*current_element);
00364     }
00365     const value_type & top() const
00366     {
00367         assert(size_ > 0);
00368         return (*current_element);
00369     }
00370     void push(const value_type & val)
00371     {
00372         assert(cache_offset <= blocks_per_page * block_type::size);
00373         //assert(cache_offset >= 0);
00374 
00375         if (cache_offset == blocks_per_page * block_type::size) // cache overflow
00376         {
00377             STXXL_VERBOSE2("growing, size: " << size_);
00378 
00379             bids.resize(bids.size() + blocks_per_page);
00380             typename std::vector<bid_type>::iterator cur_bid = bids.end() - blocks_per_page;
00381             block_manager::get_instance()->new_blocks(alloc_strategy, cur_bid, bids.end(), cur_bid - bids.begin());
00382 
00383             for (int i = 0; i < blocks_per_page; ++i, ++cur_bid)
00384             {
00385                 if (requests[i].get())
00386                     requests[i]->wait();
00387 
00388                 requests[i] = (cache_buffers + i)->write(*cur_bid);
00389             }
00390 
00391             std::swap(cache_buffers, overlap_buffers);
00392 
00393             bids.reserve(bids.size() + blocks_per_page);
00394 
00395             cache_offset = 1;
00396             current_element = &((*cache_buffers)[0]);
00397             ++size_;
00398 
00399             *current_element = val;
00400 
00401             return;
00402         }
00403 
00404         current_element = &((*(cache_buffers + cache_offset / block_type::size))[cache_offset % block_type::size]);
00405         *current_element = val;
00406         ++size_;
00407         ++cache_offset;
00408     }
00409     void pop()
00410     {
00411         assert(cache_offset <= blocks_per_page * block_type::size);
00412         assert(cache_offset > 0);
00413         assert(size_ > 0);
00414 
00415         if (cache_offset == 1 && bids.size() >= blocks_per_page)
00416         {
00417             STXXL_VERBOSE2("shrinking, size: " << size_);
00418 
00419             if (requests[0].get())
00420                 wait_all(requests.begin(), blocks_per_page);
00421 
00422 
00423             std::swap(cache_buffers, overlap_buffers);
00424 
00425             if (bids.size() > blocks_per_page)
00426             {
00427                 STXXL_VERBOSE2("prefetching, size: " << size_);
00428                 typename std::vector<bid_type>::const_iterator cur_bid = bids.end() - blocks_per_page;
00429                 for (int i = blocks_per_page - 1; i >= 0; --i)
00430                     requests[i] = (overlap_buffers + i)->read(*(--cur_bid));
00431             }
00432 
00433             block_manager::get_instance()->delete_blocks(bids.end() - blocks_per_page, bids.end());
00434             bids.resize(bids.size() - blocks_per_page);
00435 
00436             cache_offset = blocks_per_page * block_type::size;
00437             --size_;
00438             current_element = &((*(cache_buffers + (blocks_per_page - 1)))[block_type::size - 1]);
00439 
00440             return;
00441         }
00442 
00443         --size_;
00444         unsigned_type cur_offset = (--cache_offset) - 1;
00445         current_element = &((*(cache_buffers + cur_offset / block_type::size))[cur_offset % block_type::size]);
00446     }
00447 };
00448 
00451 template <class Config_>
00452 class grow_shrink_stack2 : private noncopyable
00453 {
00454 public:
00455     typedef Config_ cfg;
00456     typedef typename cfg::value_type value_type;
00457     typedef typename cfg::alloc_strategy alloc_strategy_type;
00458     typedef typename cfg::size_type size_type;
00459     enum {
00460         blocks_per_page = cfg::blocks_per_page,     // stack of this type has only one page
00461         block_size = cfg::block_size,
00462     };
00463 
00464     typedef typed_block<block_size, value_type> block_type;
00465     typedef BID<block_size> bid_type;
00466 
00467 private:
00468     typedef read_write_pool<block_type> pool_type;
00469 
00470     size_type size_;
00471     unsigned_type cache_offset;
00472     block_type * cache;
00473     std::vector<bid_type> bids;
00474     alloc_strategy_type alloc_strategy;
00475     unsigned_type pref_aggr;
00476     pool_type * owned_pool;
00477     pool_type * pool;
00478 
00479 public:
00483     grow_shrink_stack2(
00484         pool_type & pool_,
00485         unsigned_type prefetch_aggressiveness = 0) :
00486         size_(0),
00487         cache_offset(0),
00488         cache(new block_type),
00489         pref_aggr(prefetch_aggressiveness),
00490         owned_pool(NULL),
00491         pool(&pool_)
00492     {
00493         STXXL_VERBOSE2("grow_shrink_stack2::grow_shrink_stack2(...)");
00494     }
00495 
00500     _STXXL_DEPRECATED(grow_shrink_stack2(
00501         prefetch_pool<block_type> & p_pool_,
00502         write_pool<block_type> & w_pool_,
00503         unsigned_type prefetch_aggressiveness = 0)) :
00504         size_(0),
00505         cache_offset(0),
00506         cache(new block_type),
00507         pref_aggr(prefetch_aggressiveness),
00508         owned_pool(new pool_type(p_pool_, w_pool_)),
00509         pool(owned_pool)
00510     {
00511         STXXL_VERBOSE2("grow_shrink_stack2::grow_shrink_stack2(...)");
00512     }
00513 
00514     void swap(grow_shrink_stack2 & obj)
00515     {
00516         std::swap(size_, obj.size_);
00517         std::swap(cache_offset, obj.cache_offset);
00518         std::swap(cache, obj.cache);
00519         std::swap(bids, obj.bids);
00520         std::swap(alloc_strategy, obj.alloc_strategy);
00521         std::swap(pref_aggr, obj.pref_aggr);
00522         std::swap(owned_pool, obj.owned_pool);
00523         std::swap(pool, obj.pool);
00524     }
00525 
00526     virtual ~grow_shrink_stack2()
00527     {
00528         try
00529         {
00530             STXXL_VERBOSE2("grow_shrink_stack2::~grow_shrink_stack2()");
00531             const int_type bids_size = bids.size();
00532             const int_type last_pref = STXXL_MAX(int_type(bids_size) - int_type(pref_aggr), (int_type)0);
00533             int_type i;
00534             for (i = bids_size - 1; i >= last_pref; --i)
00535             {
00536                 // clean the prefetch buffer
00537                 pool->invalidate(bids[i]);
00538             }
00539             typename std::vector<bid_type>::iterator cur = bids.begin();
00540             typename std::vector<bid_type>::const_iterator end = bids.end();
00541             for ( ; cur != end; ++cur)
00542             {
00543                 // FIXME: read_write_pool needs something like cancel_write(bid)
00544                 block_type * b = NULL;  // w_pool.steal(*cur);
00545                 if (b)
00546                 {
00547                     pool->add(cache);   // return buffer
00548                     cache = b;
00549                 }
00550             }
00551             delete cache;
00552         }
00553         catch (const io_error & ex)
00554         { }
00555         block_manager::get_instance()->delete_blocks(bids.begin(), bids.end());
00556         delete owned_pool;
00557     }
00558 
00559     size_type size() const
00560     {
00561         return size_;
00562     }
00563 
00564     bool empty() const
00565     {
00566         return (!size_);
00567     }
00568 
00569     void push(const value_type & val)
00570     {
00571         STXXL_VERBOSE3("grow_shrink_stack2::push(" << val << ")");
00572         assert(cache_offset <= block_type::size);
00573 
00574         if (cache_offset == block_type::size)
00575         {
00576             STXXL_VERBOSE2("grow_shrink_stack2::push(" << val << ") growing, size: " << size_);
00577 
00578             bids.resize(bids.size() + 1);
00579             typename std::vector<bid_type>::iterator cur_bid = bids.end() - 1;
00580             block_manager::get_instance()->new_blocks(alloc_strategy, cur_bid, bids.end(), cur_bid - bids.begin());
00581             pool->write(cache, bids.back());
00582             cache = pool->steal();
00583             const int_type bids_size = bids.size();
00584             const int_type last_pref = STXXL_MAX(int_type(bids_size) - int_type(pref_aggr) - 1, (int_type)0);
00585             for (int_type i = bids_size - 2; i >= last_pref; --i)
00586             {
00587                 // clean prefetch buffers
00588                 pool->invalidate(bids[i]);
00589             }
00590             cache_offset = 0;
00591         }
00592         (*cache)[cache_offset] = val;
00593         ++size_;
00594         ++cache_offset;
00595 
00596         assert(cache_offset > 0);
00597         assert(cache_offset <= block_type::size);
00598     }
00599 
00600     value_type & top()
00601     {
00602         assert(size_ > 0);
00603         assert(cache_offset > 0);
00604         assert(cache_offset <= block_type::size);
00605         return (*cache)[cache_offset - 1];
00606     }
00607 
00608     const value_type & top() const
00609     {
00610         assert(size_ > 0);
00611         assert(cache_offset > 0);
00612         assert(cache_offset <= block_type::size);
00613         return (*cache)[cache_offset - 1];
00614     }
00615 
00616     void pop()
00617     {
00618         STXXL_VERBOSE3("grow_shrink_stack2::pop()");
00619         assert(size_ > 0);
00620         assert(cache_offset > 0);
00621         assert(cache_offset <= block_type::size);
00622         if (cache_offset == 1 && (!bids.empty()))
00623         {
00624             STXXL_VERBOSE2("grow_shrink_stack2::pop() shrinking, size = " << size_);
00625 
00626             bid_type last_block = bids.back();
00627             bids.pop_back();
00628             pool->read(cache, last_block)->wait();
00629             block_manager::get_instance()->delete_block(last_block);
00630             rehint();
00631             cache_offset = block_type::size + 1;
00632         }
00633 
00634         --cache_offset;
00635         --size_;
00636     }
00637 
00641     void set_prefetch_aggr(unsigned_type new_p)
00642     {
00643         if (pref_aggr > new_p)
00644         {
00645             const int_type bids_size = bids.size();
00646             const int_type last_pref = STXXL_MAX(int_type(bids_size) - int_type(pref_aggr), (int_type)0);
00647             for (int_type i = bids_size - new_p - 1; i >= last_pref; --i)
00648             {
00649                 // clean prefetch buffers
00650                 pool->invalidate(bids[i]);
00651             }
00652         }
00653         pref_aggr = new_p;
00654         rehint();
00655     }
00656 
00658     unsigned_type get_prefetch_aggr() const
00659     {
00660         return pref_aggr;
00661     }
00662 
00663 private:
00665     void rehint()
00666     {
00667         const int_type bids_size = bids.size();
00668         const int_type last_pref = STXXL_MAX(int_type(bids_size) - int_type(pref_aggr), (int_type)0);
00669         for (int_type i = bids_size - 1; i >= last_pref; --i)
00670         {
00671             pool->hint(bids[i]);  // prefetch
00672         }
00673     }
00674 };
00675 
00676 
00678 
00680 template <unsigned_type CritSize, class ExternalStack, class InternalStack>
00681 class migrating_stack : private noncopyable
00682 {
00683 public:
00684     typedef typename ExternalStack::cfg cfg;
00685     typedef typename cfg::value_type value_type;
00686     typedef typename cfg::size_type size_type;
00687     enum {
00688         blocks_per_page = cfg::blocks_per_page,
00689         block_size = cfg::block_size
00690     };
00691 
00692 
00693     typedef InternalStack int_stack_type;
00694     typedef ExternalStack ext_stack_type;
00695 
00696 private:
00697     enum { critical_size = CritSize };
00698 
00699     int_stack_type * int_impl;
00700     ext_stack_type * ext_impl;
00701 
00702     // not implemented yet
00703     template <class stack_type>
00704     migrating_stack(const stack_type & stack_);
00705 
00706 public:
00707     migrating_stack() : int_impl(new int_stack_type()), ext_impl(NULL) { }
00708 
00709     void swap(migrating_stack & obj)
00710     {
00711         std::swap(int_impl, obj.int_impl);
00712         std::swap(ext_impl, obj.ext_impl);
00713     }
00714 
00716     bool internal() const
00717     {
00718         assert((int_impl && !ext_impl) || (!int_impl && ext_impl));
00719         return int_impl;
00720     }
00722     bool external() const
00723     {
00724         assert((int_impl && !ext_impl) || (!int_impl && ext_impl));
00725         return ext_impl;
00726     }
00727 
00728     bool empty() const
00729     {
00730         assert((int_impl && !ext_impl) || (!int_impl && ext_impl));
00731         return (int_impl) ? int_impl->empty() : ext_impl->empty();
00732     }
00733     size_type size() const
00734     {
00735         assert((int_impl && !ext_impl) || (!int_impl && ext_impl));
00736         return (int_impl) ? int_impl->size() : ext_impl->size();
00737     }
00738     value_type & top()
00739     {
00740         assert((int_impl && !ext_impl) || (!int_impl && ext_impl));
00741         return (int_impl) ? int_impl->top() : ext_impl->top();
00742     }
00743     const value_type & top() const
00744     {
00745         assert((int_impl && !ext_impl) || (!int_impl && ext_impl));
00746         return (int_impl) ? int_impl->top() : ext_impl->top();
00747     }
00748     void push(const value_type & val)
00749     {
00750         assert((int_impl && !ext_impl) || (!int_impl && ext_impl));
00751 
00752         if (int_impl)
00753         {
00754             int_impl->push(val);
00755             if (int_impl->size() == critical_size)
00756             {
00757                 // migrate to external stack
00758                 ext_impl = new ext_stack_type(*int_impl);
00759                 delete int_impl;
00760                 int_impl = NULL;
00761             }
00762         }
00763         else
00764             ext_impl->push(val);
00765     }
00766     void pop()
00767     {
00768         assert((int_impl && !ext_impl) || (!int_impl && ext_impl));
00769 
00770         if (int_impl)
00771             int_impl->pop();
00772         else
00773             ext_impl->pop();
00774     }
00775     virtual ~migrating_stack()
00776     {
00777         delete int_impl;
00778         delete ext_impl;
00779     }
00780 };
00781 
00783 
00784 
00787 
00788 enum stack_externality { external, migrating, internal };
00789 enum stack_behaviour { normal, grow_shrink, grow_shrink2 };
00790 
00792 
00828 template <
00829     class ValTp,
00830     stack_externality Externality = external,
00831     stack_behaviour Behaviour = normal,
00832     unsigned BlocksPerPage = 4,
00833     unsigned BlkSz = STXXL_DEFAULT_BLOCK_SIZE(ValTp),
00834 
00835     class IntStackTp = std::stack<ValTp>,
00836     unsigned_type MigrCritSize = (2 * BlocksPerPage * BlkSz),
00837 
00838     class AllocStr = STXXL_DEFAULT_ALLOC_STRATEGY,
00839     class SzTp = stxxl::int64
00840     >
00841 class STACK_GENERATOR
00842 {
00843     typedef stack_config_generator<ValTp, BlocksPerPage, BlkSz, AllocStr, SzTp> cfg;
00844 
00845     typedef typename IF<Behaviour == grow_shrink,
00846                         grow_shrink_stack<cfg>,
00847                         grow_shrink_stack2<cfg> >::result GrShrTp;
00848     typedef typename IF<Behaviour == normal, normal_stack<cfg>, GrShrTp>::result ExtStackTp;
00849     typedef typename IF<Externality == migrating,
00850                         migrating_stack<MigrCritSize, ExtStackTp, IntStackTp>, ExtStackTp>::result MigrOrNotStackTp;
00851 
00852 public:
00853     typedef typename IF<Externality == internal, IntStackTp, MigrOrNotStackTp>::result result;
00854 };
00855 
00857 
00858 __STXXL_END_NAMESPACE
00859 
00860 
00861 namespace std
00862 {
00863     template <class Config_>
00864     void swap(stxxl::normal_stack<Config_> & a,
00865               stxxl::normal_stack<Config_> & b)
00866     {
00867         a.swap(b);
00868     }
00869 
00870     template <class Config_>
00871     void swap(stxxl::grow_shrink_stack<Config_> & a,
00872               stxxl::grow_shrink_stack<Config_> & b)
00873     {
00874         a.swap(b);
00875     }
00876 
00877     template <class Config_>
00878     void swap(stxxl::grow_shrink_stack2<Config_> & a,
00879               stxxl::grow_shrink_stack2<Config_> & b)
00880     {
00881         a.swap(b);
00882     }
00883 
00884     template <stxxl::unsigned_type CritSize, class ExternalStack, class InternalStack>
00885     void swap(stxxl::migrating_stack<CritSize, ExternalStack, InternalStack> & a,
00886               stxxl::migrating_stack<CritSize, ExternalStack, InternalStack> & b)
00887     {
00888         a.swap(b);
00889     }
00890 }
00891 
00892 #endif // !STXXL_STACK_HEADER
00893 // vim: et:ts=4:sw=4

Generated by  doxygen 1.7.1