STXXL  1.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
stack.h
Go to the documentation of this file.
1 /***************************************************************************
2  * include/stxxl/bits/containers/stack.h
3  *
4  * Part of the STXXL. See http://stxxl.sourceforge.net
5  *
6  * Copyright (C) 2003-2004 Roman Dementiev <[email protected]>
7  * Copyright (C) 2009, 2010 Andreas Beckmann <[email protected]>
8  *
9  * Distributed under the Boost Software License, Version 1.0.
10  * (See accompanying file LICENSE_1_0.txt or copy at
11  * http://www.boost.org/LICENSE_1_0.txt)
12  **************************************************************************/
13 
14 #ifndef STXXL_CONTAINERS_STACK_HEADER
15 #define STXXL_CONTAINERS_STACK_HEADER
16 
17 #include <stack>
18 #include <vector>
19 
20 #include <stxxl/bits/deprecated.h>
30 
31 
33 
34 //! \defgroup stlcont_stack stack
35 //! \ingroup stlcont
36 //! External stack implementations
37 //! \{
38 
39 template <class ValueType,
40  unsigned BlocksPerPage = 4,
41  unsigned BlockSize = STXXL_DEFAULT_BLOCK_SIZE(ValueType),
42  class AllocStr = STXXL_DEFAULT_ALLOC_STRATEGY,
43  class SizeType = stxxl::int64>
45 {
46  typedef ValueType value_type;
47  enum { blocks_per_page = BlocksPerPage };
48  typedef AllocStr alloc_strategy;
49  enum { block_size = BlockSize };
50  typedef SizeType size_type;
51 };
52 
53 
54 //! External stack container.
55 //! <b> Introduction </b> to stack container: see \ref tutorial_stack tutorial. \n
56 //! <b> Design and Internals </b> of stack container: see \ref design_stack
57 //! Conservative implementation. Fits best if your access pattern consists of irregularly mixed
58 //! push'es and pop's.
59 //! For semantics of the methods see documentation of the STL \c std::stack. <BR>
60 //! To gain full bandwidth of disks \c StackConfig::BlocksPerPage must >= number of disks <BR>
61 //! \internal
62 template <class StackConfig>
63 class normal_stack : private noncopyable
64 {
65 public:
66  typedef StackConfig cfg;
67  //! type of the elements stored in the stack
68  typedef typename cfg::value_type value_type;
69  typedef typename cfg::alloc_strategy alloc_strategy_type;
70  //! type for sizes (64-bit)
71  typedef typename cfg::size_type size_type;
72  enum {
73  blocks_per_page = cfg::blocks_per_page,
74  block_size = cfg::block_size
75  };
76 
77  //! type of block used in disk-memory transfers
80 
81 private:
88  std::vector<bid_type> bids;
90 
91 public:
92  //! \name Constructors/Destructors
93  //! \{
94 
95  //! Default constructor: creates empty stack.
97  m_size(0),
98  cache_offset(0),
99  current_element(NULL),
100  cache(blocks_per_page * 2),
101  front_page(cache.begin() + blocks_per_page),
102  back_page(cache.begin()),
103  bids(0)
104  {
105  bids.reserve(blocks_per_page);
106  }
107 
108  //! \name Accessor Functions
109  //! \{
110 
111  void swap(normal_stack& obj)
112  {
113  std::swap(m_size, obj.m_size);
114  std::swap(cache_offset, obj.cache_offset);
115  std::swap(current_element, obj.current_element);
116  std::swap(cache, obj.cache);
117  std::swap(front_page, obj.front_page);
118  std::swap(back_page, obj.back_page);
119  std::swap(bids, obj.bids);
120  std::swap(alloc_strategy, obj.alloc_strategy);
121  }
122 
123  //! \}
124 
125  //! \name Constructors/Destructors
126  //! \{
127 
128  //! Copy-construction from a another stack of any type.
129  //! \param stack_ stack object (could be external or internal, important is that it must
130  //! have a copy constructor, \c top() and \c pop() methods )
131  template <class stack_type>
132  normal_stack(const stack_type& stack_) :
133  m_size(0),
134  cache_offset(0),
135  current_element(NULL),
136  cache(blocks_per_page * 2),
137  front_page(cache.begin() + blocks_per_page),
138  back_page(cache.begin()),
139  bids(0)
140  {
141  bids.reserve(blocks_per_page);
142 
143  stack_type stack_copy = stack_;
144  const size_type sz = stack_copy.size();
145  size_type i;
146 
147  std::vector<value_type> tmp(sz);
148 
149  for (i = 0; i < sz; ++i)
150  {
151  tmp[sz - i - 1] = stack_copy.top();
152  stack_copy.pop();
153  }
154  for (i = 0; i < sz; ++i)
155  this->push(tmp[i]);
156  }
157 
158  virtual ~normal_stack()
159  {
161  block_manager::get_instance()->delete_blocks(bids.begin(), bids.end());
162  }
163 
164  //! \}
165 
166  //! \name Capacity
167  //! \{
168 
169  //! Returns the number of elements contained in the stack
170  size_type size() const
171  {
172  return m_size;
173  }
174 
175  //! Returns true if the stack is empty.
176  bool empty() const
177  {
178  return (!m_size);
179  }
180 
181  //! \}
182 
183  //! \name Accessor Functions
184  //! \{
185 
186  //! Return mutable reference to the element at the top of the
187  //! stack. Precondition: stack is not empty().
189  {
190  assert(m_size > 0);
191  return (*current_element);
192  }
193 
194  //! Return constant reference to the element at the top of the
195  //! stack. Precondition: stack is not empty().
196  const value_type & top() const
197  {
198  assert(m_size > 0);
199  return (*current_element);
200  }
201 
202  //! Inserts an element at the top of the stack. Postconditions: size() is
203  //! incremented by 1, and top() is the inserted element.
204  void push(const value_type& val)
205  {
206  assert(cache_offset <= 2 * blocks_per_page * block_type::size);
207  //assert(cache_offset >= 0);
208 
209  if (UNLIKELY(cache_offset == 2 * blocks_per_page * block_type::size)) // cache overflow
210  {
211  STXXL_VERBOSE2("growing, size: " << m_size);
212 
213  bids.resize(bids.size() + blocks_per_page);
214  typename std::vector<bid_type>::iterator cur_bid = bids.end() - blocks_per_page;
215  block_manager::get_instance()->new_blocks(alloc_strategy, cur_bid, bids.end(), cur_bid - bids.begin());
216 
217  simple_vector<request_ptr> requests(blocks_per_page);
218 
219  for (int i = 0; i < blocks_per_page; ++i, ++cur_bid)
220  {
221  requests[i] = (back_page + i)->write(*cur_bid);
222  }
223 
224 
225  std::swap(back_page, front_page);
226 
227  bids.reserve(bids.size() + blocks_per_page);
228 
229  cache_offset = blocks_per_page * block_type::size + 1;
230  current_element = &((*front_page)[0]);
231  ++m_size;
232 
233  wait_all(requests.begin(), blocks_per_page);
234 
235  *current_element = val;
236 
237  return;
238  }
239 
240  current_element = element(cache_offset);
241  *current_element = val;
242  ++m_size;
243  ++cache_offset;
244  }
245 
246  //! Removes the element at the top of the stack. Precondition: stack is not
247  //! empty(). Postcondition: size() is decremented.
248  void pop()
249  {
250  assert(cache_offset <= 2 * blocks_per_page * block_type::size);
251  assert(cache_offset > 0);
252  assert(m_size > 0);
253 
254  if (UNLIKELY(cache_offset == 1 && bids.size() >= blocks_per_page))
255  {
256  STXXL_VERBOSE2("shrinking, size: " << m_size);
257 
258  simple_vector<request_ptr> requests(blocks_per_page);
259 
260  {
261  typename std::vector<bid_type>::const_iterator cur_bid = bids.end();
262  for (int i = blocks_per_page - 1; i >= 0; --i)
263  {
264  requests[i] = (front_page + i)->read(*(--cur_bid));
265  }
266  }
267 
268  std::swap(front_page, back_page);
269 
270  cache_offset = blocks_per_page * block_type::size;
271  --m_size;
272  current_element = &((*(back_page + (blocks_per_page - 1)))[block_type::size - 1]);
273 
274  wait_all(requests.begin(), blocks_per_page);
275 
276  block_manager::get_instance()->delete_blocks(bids.end() - blocks_per_page, bids.end());
277  bids.resize(bids.size() - blocks_per_page);
278 
279  return;
280  }
281 
282  --m_size;
283 
284  current_element = element((--cache_offset) - 1);
285  }
286 
287  //! \}
288 
289 private:
291  {
292  if (offset < blocks_per_page * block_type::size)
293  return &((*(back_page + offset / block_type::size))[offset % block_type::size]);
294 
295 
296  unsigned_type unbiased_offset = offset - blocks_per_page * block_type::size;
297  return &((*(front_page + unbiased_offset / block_type::size))[unbiased_offset % block_type::size]);
298  }
299 };
300 
301 
302 //! Efficient implementation that uses prefetching and overlapping using internal buffers.
303 //!
304 //! Use it if your access pattern consists of many repeated push'es and pop's
305 //! For semantics of the methods see documentation of the STL \c std::stack.
306 //! \warning The amortized complexity of operation is not O(1/DB), rather O(DB)
307 template <class StackConfig>
309 {
310 public:
311  typedef StackConfig cfg;
312  //! type of the elements stored in the stack
313  typedef typename cfg::value_type value_type;
314  typedef typename cfg::alloc_strategy alloc_strategy_type;
315  //! type for sizes (64-bit)
316  typedef typename cfg::size_type size_type;
317  enum {
318  blocks_per_page = cfg::blocks_per_page,
319  block_size = cfg::block_size
320  };
321 
322  //! type of block used in disk-memory transfers
325 
326 private:
334  std::vector<bid_type> bids;
336 
337 public:
338  //! \name Constructors/Destructor
339  //! \{
340 
341  //! Default constructor: creates empty stack.
343  m_size(0),
344  cache_offset(0),
345  current_element(NULL),
346  cache(blocks_per_page * 2),
347  cache_buffers(cache.begin()),
348  overlap_buffers(cache.begin() + blocks_per_page),
349  requests(blocks_per_page),
350  bids(0)
351  {
352  bids.reserve(blocks_per_page);
353  }
354 
355  //! \}
356 
357  //! \name Accessor Functions
358  //! \{
359 
361  {
362  std::swap(m_size, obj.m_size);
363  std::swap(cache_offset, obj.cache_offset);
364  std::swap(current_element, obj.current_element);
365  std::swap(cache, obj.cache);
366  std::swap(cache_buffers, obj.cache_buffers);
367  std::swap(overlap_buffers, obj.overlap_buffers);
368  std::swap(requests, obj.requests);
369  std::swap(bids, obj.bids);
370  std::swap(alloc_strategy, obj.alloc_strategy);
371  }
372 
373  //! \}
374 
375  //! \name Constructors/Destructors
376  //! \{
377 
378  //! Copy-construction from a another stack of any type.
379  //! \param stack_ stack object (could be external or internal, important is that it must
380  //! have a copy constructor, \c top() and \c pop() methods )
381  template <class stack_type>
382  grow_shrink_stack(const stack_type& stack_) :
383  m_size(0),
384  cache_offset(0),
385  current_element(NULL),
386  cache(blocks_per_page * 2),
387  cache_buffers(cache.begin()),
388  overlap_buffers(cache.begin() + blocks_per_page),
389  requests(blocks_per_page),
390  bids(0)
391  {
392  bids.reserve(blocks_per_page);
393 
394  stack_type stack_copy = stack_;
395  const size_type sz = stack_copy.size();
396  size_type i;
397 
398  std::vector<value_type> tmp(sz);
399 
400  for (i = 0; i < sz; ++i)
401  {
402  tmp[sz - i - 1] = stack_copy.top();
403  stack_copy.pop();
404  }
405  for (i = 0; i < sz; ++i)
406  this->push(tmp[i]);
407  }
409  {
411  try
412  {
413  if (requests[0].get())
414  wait_all(requests.begin(), blocks_per_page);
415  }
416  catch (const io_error&)
417  { }
418  block_manager::get_instance()->delete_blocks(bids.begin(), bids.end());
419  }
420 
421  //! \}
422 
423  //! \name Capacity
424  //! \{
425 
426  //! Returns the number of elements contained in the stack
427  size_type size() const
428  {
429  return m_size;
430  }
431  //! Returns true if the stack is empty.
432  bool empty() const
433  {
434  return (!m_size);
435  }
436 
437  //! \}
438 
439  //! \name Accessor Functions
440  //! \{
441 
442  //! Return mutable reference to the element at the top of the
443  //! stack. Precondition: stack is not empty().
445  {
446  assert(m_size > 0);
447  return (*current_element);
448  }
449 
450  //! Return constant reference to the element at the top of the
451  //! stack. Precondition: stack is not empty().
452  const value_type & top() const
453  {
454  assert(m_size > 0);
455  return (*current_element);
456  }
457 
458  //! Inserts an element at the top of the stack. Postconditions: size() is
459  //! incremented by 1, and top() is the inserted element.
460  void push(const value_type& val)
461  {
462  assert(cache_offset <= blocks_per_page * block_type::size);
463  //assert(cache_offset >= 0);
464 
465  if (UNLIKELY(cache_offset == blocks_per_page * block_type::size)) // cache overflow
466  {
467  STXXL_VERBOSE2("growing, size: " << m_size);
468 
469  bids.resize(bids.size() + blocks_per_page);
470  typename std::vector<bid_type>::iterator cur_bid = bids.end() - blocks_per_page;
471  block_manager::get_instance()->new_blocks(alloc_strategy, cur_bid, bids.end(), cur_bid - bids.begin());
472 
473  for (int i = 0; i < blocks_per_page; ++i, ++cur_bid)
474  {
475  if (requests[i].get())
476  requests[i]->wait();
477 
478  requests[i] = (cache_buffers + i)->write(*cur_bid);
479  }
480 
481  std::swap(cache_buffers, overlap_buffers);
482 
483  bids.reserve(bids.size() + blocks_per_page);
484 
485  cache_offset = 1;
486  current_element = &((*cache_buffers)[0]);
487  ++m_size;
488 
489  *current_element = val;
490 
491  return;
492  }
493 
494  current_element = &((*(cache_buffers + cache_offset / block_type::size))[cache_offset % block_type::size]);
495  *current_element = val;
496  ++m_size;
497  ++cache_offset;
498  }
499 
500  //! Removes the element at the top of the stack. Precondition: stack is not
501  //! empty(). Postcondition: size() is decremented.
502  void pop()
503  {
504  assert(cache_offset <= blocks_per_page * block_type::size);
505  assert(cache_offset > 0);
506  assert(m_size > 0);
507 
508  if (UNLIKELY(cache_offset == 1 && bids.size() >= blocks_per_page))
509  {
510  STXXL_VERBOSE2("shrinking, size: " << m_size);
511 
512  if (requests[0].get())
513  wait_all(requests.begin(), blocks_per_page);
514 
515 
516  std::swap(cache_buffers, overlap_buffers);
517 
518  if (bids.size() > blocks_per_page)
519  {
520  STXXL_VERBOSE2("prefetching, size: " << m_size);
521  typename std::vector<bid_type>::const_iterator cur_bid = bids.end() - blocks_per_page;
522  for (int i = blocks_per_page - 1; i >= 0; --i)
523  requests[i] = (overlap_buffers + i)->read(*(--cur_bid));
524  }
525 
526  block_manager::get_instance()->delete_blocks(bids.end() - blocks_per_page, bids.end());
527  bids.resize(bids.size() - blocks_per_page);
528 
529  cache_offset = blocks_per_page * block_type::size;
530  --m_size;
531  current_element = &((*(cache_buffers + (blocks_per_page - 1)))[block_type::size - 1]);
532 
533  return;
534  }
535 
536  --m_size;
537  unsigned_type cur_offset = (--cache_offset) - 1;
538  current_element = &((*(cache_buffers + cur_offset / block_type::size))[cur_offset % block_type::size]);
539  }
540 
541  //! \}
542 };
543 
544 //! Efficient implementation that uses prefetching and overlapping using (shared) buffers pools.
545 //! \warning This is a single buffer stack! Each direction change (push() followed by pop() or vice versa) may cause one I/O.
546 template <class StackConfig>
548 {
549 public:
550  typedef StackConfig cfg;
551  //! type of the elements stored in the stack
552  typedef typename cfg::value_type value_type;
553  typedef typename cfg::alloc_strategy alloc_strategy_type;
554  //! type for sizes (64-bit)
555  typedef typename cfg::size_type size_type;
556  enum {
557  blocks_per_page = cfg::blocks_per_page, // stack of this type has only one page
558  block_size = cfg::block_size
559  };
560 
561  //! type of block used in disk-memory transfers
564 
565 private:
567 
571  std::vector<bid_type> bids;
576 
577 public:
578  //! \name Constructors/Destructors
579  //! \{
580 
581  //! Default constructor: creates empty stack. The stack will use the
582  //! read_write_pool for prefetching and buffered writing.
583  //! \param pool_ block write/prefetch pool
584  //! \param prefetch_aggressiveness number of blocks that will be used from prefetch pool
586  pool_type& pool_,
587  unsigned_type prefetch_aggressiveness = 0)
588  : m_size(0),
589  cache_offset(0),
590  cache(new block_type),
591  pref_aggr(prefetch_aggressiveness),
592  owned_pool(NULL),
593  pool(&pool_)
594  {
595  STXXL_VERBOSE2("grow_shrink_stack2::grow_shrink_stack2(...)");
596  }
597 
598  //! Default constructor: creates empty stack. The stack will use the pair
599  //! of prefetch_pool and write_pool for prefetching and buffered writing.
600  //! This constructor is deprecated in favor of the read_write_pool
601  //! constructor.
602  //!
603  //! \param p_pool_ prefetch pool, that will be used for block prefetching
604  //! \param w_pool_ write pool, that will be used for block writing
605  //! \param prefetch_aggressiveness number of blocks that will be used from prefetch pool
608  prefetch_pool<block_type>& p_pool_,
609  write_pool<block_type>& w_pool_,
610  unsigned_type prefetch_aggressiveness = 0)
611  ) :
612  m_size(0),
613  cache_offset(0),
614  cache(new block_type),
615  pref_aggr(prefetch_aggressiveness),
616  owned_pool(new pool_type(p_pool_, w_pool_)),
617  pool(owned_pool)
618  {
619  STXXL_VERBOSE2("grow_shrink_stack2::grow_shrink_stack2(...)");
620  }
621 
622  //! \}
623 
624  //! \name Accessor Functions
625  //! \{
626 
628  {
629  std::swap(m_size, obj.m_size);
630  std::swap(cache_offset, obj.cache_offset);
631  std::swap(cache, obj.cache);
632  std::swap(bids, obj.bids);
633  std::swap(alloc_strategy, obj.alloc_strategy);
634  std::swap(pref_aggr, obj.pref_aggr);
635  std::swap(owned_pool, obj.owned_pool);
636  std::swap(pool, obj.pool);
637  }
638 
639  //! \}
640 
641  //! \name Constructors/Destructors
642  //! \{
643 
645  {
646  try
647  {
648  STXXL_VERBOSE2("grow_shrink_stack2::~grow_shrink_stack2()");
649  const int_type bids_size = bids.size();
650  const int_type last_pref = STXXL_MAX(int_type(bids_size) - int_type(pref_aggr), (int_type)0);
651  int_type i;
652  for (i = bids_size - 1; i >= last_pref; --i)
653  {
654  // clean the prefetch buffer
655  pool->invalidate(bids[i]);
656  }
657  typename std::vector<bid_type>::iterator cur = bids.begin();
658  typename std::vector<bid_type>::const_iterator end = bids.end();
659  for ( ; cur != end; ++cur)
660  {
661  // FIXME: read_write_pool needs something like cancel_write(bid)
662  block_type* b = NULL; // w_pool.steal(*cur);
663  if (b)
664  {
665  pool->add(cache); // return buffer
666  cache = b;
667  }
668  }
669  delete cache;
670  }
671  catch (const io_error&)
672  { }
673  block_manager::get_instance()->delete_blocks(bids.begin(), bids.end());
674  delete owned_pool;
675  }
676 
677  //! \}
678 
679  //! \name Capacity
680  //! \{
681 
682  //! Returns the number of elements contained in the stack
683  size_type size() const
684  {
685  return m_size;
686  }
687  //! Returns true if the stack is empty.
688  bool empty() const
689  {
690  return (!m_size);
691  }
692 
693  //! \}
694 
695  //! \name Accessor Functions
696  //! \{
697 
698  //! Inserts an element at the top of the stack. Postconditions: size() is
699  //! incremented by 1, and top() is the inserted element.
700  void push(const value_type& val)
701  {
702  STXXL_VERBOSE3("grow_shrink_stack2::push(" << val << ")");
703  assert(cache_offset <= block_type::size);
704 
705  if (UNLIKELY(cache_offset == block_type::size))
706  {
707  STXXL_VERBOSE2("grow_shrink_stack2::push(" << val << ") growing, size: " << m_size);
708 
709  bids.resize(bids.size() + 1);
710  typename std::vector<bid_type>::iterator cur_bid = bids.end() - 1;
711  block_manager::get_instance()->new_blocks(alloc_strategy, cur_bid, bids.end(), cur_bid - bids.begin());
712  pool->write(cache, bids.back());
713  cache = pool->steal();
714  const int_type bids_size = bids.size();
715  const int_type last_pref = STXXL_MAX(int_type(bids_size) - int_type(pref_aggr) - 1, (int_type)0);
716  for (int_type i = bids_size - 2; i >= last_pref; --i)
717  {
718  // clean prefetch buffers
719  pool->invalidate(bids[i]);
720  }
721  cache_offset = 0;
722  }
723  (*cache)[cache_offset] = val;
724  ++m_size;
725  ++cache_offset;
726 
727  assert(cache_offset > 0);
728  assert(cache_offset <= block_type::size);
729  }
730 
731  //! Return mutable reference to the element at the top of the
732  //! stack. Precondition: stack is not empty().
734  {
735  assert(m_size > 0);
736  assert(cache_offset > 0);
737  assert(cache_offset <= block_type::size);
738  return (*cache)[cache_offset - 1];
739  }
740 
741  //! Return constant reference to the element at the top of the
742  //! stack. Precondition: stack is not empty().
743  const value_type & top() const
744  {
745  assert(m_size > 0);
746  assert(cache_offset > 0);
747  assert(cache_offset <= block_type::size);
748  return (*cache)[cache_offset - 1];
749  }
750 
751  //! Removes the element at the top of the stack. Precondition: stack is not
752  //! empty(). Postcondition: size() is decremented.
753  void pop()
754  {
755  STXXL_VERBOSE3("grow_shrink_stack2::pop()");
756  assert(m_size > 0);
757  assert(cache_offset > 0);
758  assert(cache_offset <= block_type::size);
759  if (UNLIKELY(cache_offset == 1 && (!bids.empty())))
760  {
761  STXXL_VERBOSE2("grow_shrink_stack2::pop() shrinking, size = " << m_size);
762 
763  bid_type last_block = bids.back();
764  bids.pop_back();
765  pool->read(cache, last_block)->wait();
766  block_manager::get_instance()->delete_block(last_block);
767  rehint();
768  cache_offset = block_type::size + 1;
769  }
770 
771  --cache_offset;
772  --m_size;
773  }
774 
775  //! \}
776 
777  //! \name Miscellaneous
778  //! \{
779 
780  //! Sets level of prefetch aggressiveness (number of blocks from the
781  //! prefetch pool used for prefetching).
782  //! \param new_p new value for the prefetch aggressiveness
784  {
785  if (pref_aggr > new_p)
786  {
787  const int_type bids_size = bids.size();
788  const int_type last_pref = STXXL_MAX(int_type(bids_size) - int_type(pref_aggr), (int_type)0);
789  for (int_type i = bids_size - new_p - 1; i >= last_pref; --i)
790  {
791  // clean prefetch buffers
792  pool->invalidate(bids[i]);
793  }
794  }
795  pref_aggr = new_p;
796  rehint();
797  }
798 
799  //! Returns number of blocks used for prefetching.
801  {
802  return pref_aggr;
803  }
804 
805  //! \}
806 
807 private:
808  //! hint the last pref_aggr external blocks.
809  void rehint()
810  {
811  const int_type bids_size = bids.size();
812  const int_type last_pref = STXXL_MAX(int_type(bids_size) - int_type(pref_aggr), (int_type)0);
813  for (int_type i = bids_size - 1; i >= last_pref; --i)
814  {
815  pool->hint(bids[i]); // prefetch
816  }
817  }
818 };
819 
820 
821 //! A stack that migrates from internal memory to external when its size exceeds a certain threshold.
822 //!
823 //! For semantics of the methods see documentation of the STL \c std::stack.
824 template <unsigned_type CritSize, class ExternalStack, class InternalStack>
826 {
827 public:
828  typedef typename ExternalStack::cfg cfg;
829  //! type of the elements stored in the stack
830  typedef typename cfg::value_type value_type;
831  //! type for sizes (64-bit)
832  typedef typename cfg::size_type size_type;
833  enum {
834  blocks_per_page = cfg::blocks_per_page,
835  block_size = cfg::block_size
836  };
837 
838  typedef InternalStack int_stack_type;
839  typedef ExternalStack ext_stack_type;
840 
841 private:
842  enum { critical_size = CritSize };
843 
846 
847  //! Copy-construction from a another stack of any type.
848  //! \warning not implemented yet!
849  template <class stack_type>
850  migrating_stack(const stack_type& stack_);
851 
852 public:
853  //! \name Constructors/Destructors
854  //! \{
855 
856  //! Default constructor: creates empty stack.
858  : int_impl(new int_stack_type()), ext_impl(NULL)
859  { }
860 
862  {
863  delete int_impl;
864  delete ext_impl;
865  }
866 
867  //! \}
868 
869  //! \name Accessor Functions
870  //! \{
871 
873  {
874  std::swap(int_impl, obj.int_impl);
875  std::swap(ext_impl, obj.ext_impl);
876  }
877 
878  //! \}
879 
880  //! \name Miscellaneous
881  //! \{
882 
883  //! Returns true if current implementation is internal, otherwise false.
884  bool internal() const
885  {
886  assert((int_impl && !ext_impl) || (!int_impl && ext_impl));
887  return (int_impl != NULL);
888  }
889  //! Returns true if current implementation is external, otherwise false.
890  bool external() const
891  {
892  assert((int_impl && !ext_impl) || (!int_impl && ext_impl));
893  return (ext_impl != NULL);
894  }
895 
896  //! \}
897 
898  //! \name Capacity
899  //! \{
900 
901  //! Returns true if the stack is empty.
902  bool empty() const
903  {
904  assert((int_impl && !ext_impl) || (!int_impl && ext_impl));
905  return (int_impl) ? int_impl->empty() : ext_impl->empty();
906  }
907  //! Returns the number of elements contained in the stack
908  size_type size() const
909  {
910  assert((int_impl && !ext_impl) || (!int_impl && ext_impl));
911  return (int_impl) ? size_type(int_impl->size()) : ext_impl->size();
912  }
913 
914  //! \}
915 
916  //! \name Accessor Functions
917  //! \{
918 
919  //! Return mutable reference to the element at the top of the
920  //! stack. Precondition: stack is not empty().
922  {
923  assert((int_impl && !ext_impl) || (!int_impl && ext_impl));
924  return (int_impl) ? int_impl->top() : ext_impl->top();
925  }
926 
927  //! Return constant reference to the element at the top of the
928  //! stack. Precondition: stack is not empty().
929  const value_type & top() const
930  {
931  assert((int_impl && !ext_impl) || (!int_impl && ext_impl));
932  return (int_impl) ? int_impl->top() : ext_impl->top();
933  }
934 
935  //! Inserts an element at the top of the stack. Postconditions: size() is
936  //! incremented by 1, and top() is the inserted element.
937  void push(const value_type& val)
938  {
939  assert((int_impl && !ext_impl) || (!int_impl && ext_impl));
940 
941  if (int_impl)
942  {
943  int_impl->push(val);
944  if (UNLIKELY(int_impl->size() == critical_size))
945  {
946  // migrate to external stack
947  ext_impl = new ext_stack_type(*int_impl);
948  delete int_impl;
949  int_impl = NULL;
950  }
951  }
952  else
953  ext_impl->push(val);
954  }
955 
956  //! Removes the element at the top of the stack. Precondition: stack is not
957  //! empty(). Postcondition: size() is decremented.
958  void pop()
959  {
960  assert((int_impl && !ext_impl) || (!int_impl && ext_impl));
961 
962  if (int_impl)
963  int_impl->pop();
964  else
965  ext_impl->pop();
966  }
967 
968  //! \}
969 };
970 
973 
974 //! \brief Stack type generator \n
975 //! <b> Introduction </b> to stack container: see \ref tutorial_stack tutorial. \n
976 //! <b> Design and Internals </b> of stack container: see \ref design_stack.
977 //!
978 //! \tparam ValueType type of contained objects (POD with no references to internal memory)
979 //!
980 //! \tparam Externality selects stack implementation, default: \b external. One of
981 //! - \c external, external container, implementation is chosen according to \c Behaviour parameter.
982 //! - \c migrating, migrates from internal implementation given by \c IntStackType parameter
983 //! to external implementation given by \c Behaviour parameter when size exceeds \c MigrCritSize
984 //! - \c internal, choses \c IntStackType implementation
985 //!
986 //! \tparam Behaviour chooses \b external implementation, default: \b stxxl::normal_stack. One of:
987 //! - \c normal, conservative version, implemented in \c stxxl::normal_stack
988 //! - \c grow_shrink, efficient version, implemented in \c stxxl::grow_shrink_stack
989 //! - \c grow_shrink2, efficient version, implemented in \c stxxl::grow_shrink_stack2
990 //!
991 //! \tparam BlocksPerPage defines how many blocks has one page of internal cache of an
992 //! \b external implementation, default is \b 4. All \b external implementations have
993 //! \b two pages.
994 //!
995 //! \tparam BlockSize external block size in bytes, default is <b>2 MiB</b>.
996 //!
997 //! \tparam IntStackType type of internal stack used for some implementations, default: \b std::stack.
998 //!
999 //! \tparam MigrCritSize threshold value for number of elements when
1000 //! stxxl::migrating_stack migrates to the external memory, default: <b>2 x BlocksPerPage x BlockSize</b>.
1001 //!
1002 //! \tparam AllocStr one of allocation strategies: striping, RC, SR, or FR. Default is \b RC.
1003 //!
1004 //! \tparam SizeType size type, default is \b stxxl::int64.
1005 //!
1006 //! The configured stack type is available as STACK_GENERATOR<>::result.
1007 //!
1008 template <
1009  class ValueType,
1010  stack_externality Externality = external,
1011  stack_behaviour Behaviour = normal,
1012  unsigned BlocksPerPage = 4,
1013  unsigned BlockSize = STXXL_DEFAULT_BLOCK_SIZE(ValueType),
1014 
1015  class IntStackType = std::stack<ValueType>,
1016  unsigned_type MigrCritSize = (2* BlocksPerPage* BlockSize),
1017 
1018  class AllocStr = STXXL_DEFAULT_ALLOC_STRATEGY,
1019  class SizeType = stxxl::int64
1020  >
1022 {
1024 
1025  typedef typename IF<Behaviour == grow_shrink,
1029  typedef typename IF<Externality == migrating,
1031 
1032 public:
1034 };
1035 
1036 //! \}
1037 
1039 
1040 
1041 namespace std {
1042 
1043 template <class StackConfig>
1046 {
1047  a.swap(b);
1048 }
1049 
1050 template <class StackConfig>
1053 {
1054  a.swap(b);
1055 }
1056 
1057 template <class StackConfig>
1060 {
1061  a.swap(b);
1062 }
1063 
1064 template <stxxl::unsigned_type CritSize, class ExternalStack, class InternalStack>
1067 {
1068  a.swap(b);
1069 }
1070 
1071 } // namespace std
1072 
1073 #endif // !STXXL_CONTAINERS_STACK_HEADER
1074 // vim: et:ts=4:sw=4
cfg::size_type size_type
type for sizes (64-bit)
Definition: stack.h:555
#define STXXL_VERBOSE(x)
Definition: verbose.h:102
simple_vector< block_type >::iterator front_page
Definition: stack.h:86
void swap(normal_stack &obj)
Definition: stack.h:111
External stack container. Introduction to stack container: see STXXL Stack tutorial. Design and Internals of stack container: see Stack Conservative implementation. Fits best if your access pattern consists of irregularly mixed push&#39;es and pop&#39;s. For semantics of the methods see documentation of the STL std::stack. To gain full bandwidth of disks StackConfig::BlocksPerPage must &gt;= number of disks
Definition: stack.h:63
#define STXXL_DEFAULT_BLOCK_SIZE(type)
value_type * current_element
Definition: stack.h:329
std::vector< bid_type > bids
Definition: stack.h:571
simple_vector< block_type > cache
Definition: stack.h:85
A stack that migrates from internal memory to external when its size exceeds a certain threshold...
Definition: stack.h:825
virtual ~migrating_stack()
Definition: stack.h:861
cfg::size_type size_type
type for sizes (64-bit)
Definition: stack.h:832
simple_vector< block_type >::iterator cache_buffers
Definition: stack.h:331
StackConfig cfg
Definition: stack.h:311
void push(const value_type &val)
Inserts an element at the top of the stack. Postconditions: size() is incremented by 1...
Definition: stack.h:460
long long int int64
Definition: types.h:40
value_type & top()
Return mutable reference to the element at the top of the stack. Precondition: stack is not empty()...
Definition: stack.h:188
IF< Externality==migrating, migrating_stack< MigrCritSize, ExtStackType, IntStackType >, ExtStackType >::result MigrOrNotStackType
Definition: stack.h:1030
stack_config_generator< ValueType, BlocksPerPage, BlockSize, AllocStr, SizeType > cfg
Definition: stack.h:1023
cfg::alloc_strategy alloc_strategy_type
Definition: stack.h:69
virtual ~normal_stack()
Definition: stack.h:158
IF< Behaviour==grow_shrink, grow_shrink_stack< cfg >, grow_shrink_stack2< cfg > >::result GrShrTp
Definition: stack.h:1027
BID< block_size > bid_type
Definition: stack.h:563
bool external() const
Returns true if current implementation is external, otherwise false.
Definition: stack.h:890
size_type size() const
Returns the number of elements contained in the stack.
Definition: stack.h:908
alloc_strategy_type alloc_strategy
Definition: stack.h:335
stack_behaviour
Definition: stack.h:972
value_type * element(unsigned_type offset)
Definition: stack.h:290
BID< block_size > bid_type
Definition: stack.h:324
virtual ~grow_shrink_stack2()
Definition: stack.h:644
void push(const value_type &val)
Inserts an element at the top of the stack. Postconditions: size() is incremented by 1...
Definition: stack.h:204
value_type & top()
Return mutable reference to the element at the top of the stack. Precondition: stack is not empty()...
Definition: stack.h:733
grow_shrink_stack(const stack_type &stack_)
Copy-construction from a another stack of any type.
Definition: stack.h:382
cfg::alloc_strategy alloc_strategy_type
Definition: stack.h:553
#define STXXL_DEFAULT_ALLOC_STRATEGY
Definition: block_alloc.h:259
size_type size() const
Returns the number of elements contained in the stack.
Definition: stack.h:170
size_type size() const
Returns the number of elements contained in the stack.
Definition: stack.h:427
migrating_stack()
Default constructor: creates empty stack.
Definition: stack.h:857
#define STXXL_VERBOSE2(x)
Definition: verbose.h:107
cfg::value_type value_type
type of the elements stored in the stack
Definition: stack.h:313
cfg::alloc_strategy alloc_strategy_type
Definition: stack.h:314
#define STXXL_DEPRECATED(x)
Definition: deprecated.h:30
typed_block< block_size, value_type > block_type
type of block used in disk-memory transfers
Definition: stack.h:78
void wait_all(request_iterator_ reqs_begin, request_iterator_ reqs_end)
Collection of functions to track statuses of a number of requests.
alloc_strategy_type alloc_strategy
Definition: stack.h:89
void set_prefetch_aggr(unsigned_type new_p)
Sets level of prefetch aggressiveness (number of blocks from the prefetch pool used for prefetching)...
Definition: stack.h:783
unsigned_type pref_aggr
Definition: stack.h:573
ext_stack_type * ext_impl
Definition: stack.h:845
const value_type & top() const
Return constant reference to the element at the top of the stack. Precondition: stack is not empty()...
Definition: stack.h:196
void pop()
Removes the element at the top of the stack. Precondition: stack is not empty(). Postcondition: size(...
Definition: stack.h:958
IF< Externality==internal, IntStackType, MigrOrNotStackType >::result result
Definition: stack.h:1033
typed_block< block_size, value_type > block_type
type of block used in disk-memory transfers
Definition: stack.h:562
Implements dynamically resizable buffered writing pool.
Definition: write_pool.h:34
stack_externality
Definition: stack.h:971
simple_vector< block_type > cache
Definition: stack.h:330
simple_vector< block_type >::iterator back_page
Definition: stack.h:87
const value_type & top() const
Return constant reference to the element at the top of the stack. Precondition: stack is not empty()...
Definition: stack.h:452
Implements dynamically resizable prefetching pool.
Definition: prefetch_pool.h:30
Block containing elements of fixed length.
Definition: typed_block.h:238
int_stack_type * int_impl
Definition: stack.h:844
value_type * current_element
Definition: stack.h:84
std::vector< bid_type > bids
Definition: stack.h:334
#define STXXL_VERBOSE3(x)
Definition: verbose.h:113
bool empty() const
Returns true if the stack is empty.
Definition: stack.h:176
Implements dynamically resizable buffered writing and prefetched reading pool.
const Tp & STXXL_MAX(const Tp &a, const Tp &b)
Definition: utils.h:154
choose_int_types< my_pointer_size >::int_type int_type
Definition: types.h:66
void swap(grow_shrink_stack2 &obj)
Definition: stack.h:627
iterator begin()
return mutable iterator to first element
Definition: simple_vector.h:92
void swap(grow_shrink_stack &obj)
Definition: stack.h:360
grow_shrink_stack2(pool_type &pool_, unsigned_type prefetch_aggressiveness=0)
Default constructor: creates empty stack. The stack will use the read_write_pool for prefetching and ...
Definition: stack.h:585
#define UNLIKELY(c)
Definition: utils.h:226
std::vector< bid_type > bids
Definition: stack.h:88
virtual ~grow_shrink_stack()
Definition: stack.h:408
bool empty() const
Returns true if the stack is empty.
Definition: stack.h:688
ExternalStack::cfg cfg
Definition: stack.h:828
#define STXXL_BEGIN_NAMESPACE
Definition: namespace.h:16
void push(const value_type &val)
Inserts an element at the top of the stack. Postconditions: size() is incremented by 1...
Definition: stack.h:937
pool_type * pool
Definition: stack.h:575
read_write_pool< block_type > pool_type
Definition: stack.h:566
void rehint()
hint the last pref_aggr external blocks.
Definition: stack.h:809
unsigned_type get_prefetch_aggr() const
Returns number of blocks used for prefetching.
Definition: stack.h:800
cfg::value_type value_type
type of the elements stored in the stack
Definition: stack.h:68
void pop()
Removes the element at the top of the stack. Precondition: stack is not empty(). Postcondition: size(...
Definition: stack.h:502
const value_type & top() const
Return constant reference to the element at the top of the stack. Precondition: stack is not empty()...
Definition: stack.h:929
bool empty() const
Returns true if the stack is empty.
Definition: stack.h:902
pool_type * owned_pool
Definition: stack.h:574
cfg::size_type size_type
type for sizes (64-bit)
Definition: stack.h:316
const value_type & top() const
Return constant reference to the element at the top of the stack. Precondition: stack is not empty()...
Definition: stack.h:743
normal_stack()
Default constructor: creates empty stack.
Definition: stack.h:96
bool empty() const
Returns true if the stack is empty.
Definition: stack.h:432
Efficient implementation that uses prefetching and overlapping using (shared) buffers pools...
Definition: stack.h:547
size_type size() const
Returns the number of elements contained in the stack.
Definition: stack.h:683
Simpler non-growing vector without initialization.
Definition: simple_vector.h:37
unsigned_type cache_offset
Definition: stack.h:83
BID< block_size > bid_type
Definition: stack.h:79
size_type m_size
Definition: stack.h:82
alloc_strategy_type alloc_strategy
Definition: stack.h:572
simple_vector< request_ptr > requests
Definition: stack.h:333
choose_int_types< my_pointer_size >::unsigned_type unsigned_type
Definition: types.h:67
value_type & top()
Return mutable reference to the element at the top of the stack. Precondition: stack is not empty()...
Definition: stack.h:444
value_type & top()
Return mutable reference to the element at the top of the stack. Precondition: stack is not empty()...
Definition: stack.h:921
Type1 result
Definition: tmeta.h:33
unsigned_type cache_offset
Definition: stack.h:569
InternalStack int_stack_type
Definition: stack.h:838
Stack type generator Introduction to stack container: see STXXL Stack tutorial. Design and Internals of stack container: see Stack.
Definition: stack.h:1021
void swap(migrating_stack &obj)
Definition: stack.h:872
IF template metaprogramming statement.
Definition: tmeta.h:31
void pop()
Removes the element at the top of the stack. Precondition: stack is not empty(). Postcondition: size(...
Definition: stack.h:248
Efficient implementation that uses prefetching and overlapping using internal buffers.
Definition: stack.h:308
cfg::size_type size_type
type for sizes (64-bit)
Definition: stack.h:71
ExternalStack ext_stack_type
Definition: stack.h:839
cfg::value_type value_type
type of the elements stored in the stack
Definition: stack.h:830
cfg::value_type value_type
type of the elements stored in the stack
Definition: stack.h:552
block_type * cache
Definition: stack.h:570
normal_stack(const stack_type &stack_)
Copy-construction from a another stack of any type.
Definition: stack.h:132
value_type * iterator
Definition: simple_vector.h:53
simple_vector< block_type >::iterator overlap_buffers
Definition: stack.h:332
void push(const value_type &val)
Inserts an element at the top of the stack. Postconditions: size() is incremented by 1...
Definition: stack.h:700
typed_block< block_size, value_type > block_type
type of block used in disk-memory transfers
Definition: stack.h:323
grow_shrink_stack()
Default constructor: creates empty stack.
Definition: stack.h:342
#define STXXL_PRETTY_FUNCTION_NAME
StackConfig cfg
Definition: stack.h:66
void pop()
Removes the element at the top of the stack. Precondition: stack is not empty(). Postcondition: size(...
Definition: stack.h:753
#define STXXL_END_NAMESPACE
Definition: namespace.h:17
unsigned_type cache_offset
Definition: stack.h:328
IF< Behaviour==normal, normal_stack< cfg >, GrShrTp >::result ExtStackType
Definition: stack.h:1028