STXXL  1.4.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
sequence.h
Go to the documentation of this file.
1 /***************************************************************************
2  * include/stxxl/bits/containers/sequence.h
3  *
4  * based on include/stxxl/bits/containers/queue.h
5  *
6  * Part of the STXXL. See http://stxxl.sourceforge.net
7  *
8  * Copyright (C) 2012-2013 Timo Bingmann <[email protected]>
9  *
10  * Distributed under the Boost Software License, Version 1.0.
11  * (See accompanying file LICENSE_1_0.txt or copy at
12  * http://www.boost.org/LICENSE_1_0.txt)
13  **************************************************************************/
14 
15 #ifndef STXXL_CONTAINERS_SEQUENCE_HEADER
16 #define STXXL_CONTAINERS_SEQUENCE_HEADER
17 
18 #include <deque>
19 
20 #include <stxxl/bits/deprecated.h>
27 
28 
30 
31 #ifndef STXXL_VERBOSE_SEQUENCE
32 #define STXXL_VERBOSE_SEQUENCE STXXL_VERBOSE2
33 #endif
34 
35 //! \addtogroup stlcont
36 //! \{
37 
38 //! \brief External sequence or deque container without random access. \n
39 //! <b> Introduction </b> to sequence container: see \ref tutorial_sequence tutorial. \n
40 //! <b> Design and Internals </b> of sequence container: see \ref design_queue
41 
42 /**
43  * Sequence is a primitive container consisting of only a sequence of blocks in
44  * external memory. The sequence provides appending methods similar to a deque:
45  * push_back and push_front; and also the corresponding pop functions. However,
46  * different from stxxl::deque (which is a vector in disguise), the sequence
47  * does not allow random access. Instead, the sequence can only be iterated
48  * using streams: either from front to back or in reverse.
49  *
50  * As with queue and stack, sequences of pushes and pops are made efficient
51  * using overlapping or read-ahead via block pools. The stream access likewise
52  * uses overlapped I/O, just like stream::vector_iterator2stream.
53  *
54  * \tparam ValueType type of the contained objects (POD with no references to internal memory)
55  * \tparam BlockSize size of the external memory block in bytes, default is \c STXXL_DEFAULT_BLOCK_SIZE(ValTp)
56  * \tparam AllocStr parallel disk allocation strategy, default is \c STXXL_DEFAULT_ALLOC_STRATEGY
57  * \tparam SizeType size data type, default is \c stxxl::uint64
58  */
59 template <class ValueType,
60  unsigned BlockSize = STXXL_DEFAULT_BLOCK_SIZE(ValueType),
61  class AllocStr = STXXL_DEFAULT_ALLOC_STRATEGY,
62  class SizeType = stxxl::uint64>
63 class sequence : private noncopyable
64 {
65 public:
66  typedef ValueType value_type;
67  typedef AllocStr alloc_strategy_type;
68  typedef SizeType size_type;
69  enum {
70  block_size = BlockSize
71  };
72 
75 
76  typedef std::deque<bid_type> bid_deque_type;
77 
78 private:
80 
81  /// current number of items in the sequence
83 
84  /// whether the m_pool object is own and should be deleted.
86 
87  /// read_write_pool of blocks
89 
90  /// current front block of sequence
92 
93  /// current back block of sequence
95 
96  /// pointer to current front element in m_front_block
98 
99  /// pointer to current back element in m_back_block
101 
102  /// block allocation strategy
104 
105  /// block allocation counter
107 
108  /// allocated block identifiers
110 
111  /// block manager used
113 
114  /// number of blocks to prefetch
116 
117 public:
118  //! \name Constructors/Destructors
119  //! \{
120 
121  //! Constructs empty sequence with own write and prefetch block pool
122  //!
123  //! \param D number of parallel disks, defaulting to the configured number of scratch disks,
124  //! memory consumption will be 2 * D + 2 blocks
125  //! (first and last block, D blocks as write cache, D block for prefetching)
126  explicit sequence(int_type D = -1) :
127  m_size(0),
128  m_owns_pool(true),
129  m_alloc_count(0),
130  m_bm(block_manager::get_instance())
131  {
132  if (D < 1) D = config::get_instance()->disks_number();
133  STXXL_VERBOSE_SEQUENCE("sequence[" << this << "]::sequence(D)");
134  m_pool = new pool_type(D, D + 2);
135  init();
136  }
137 
138  //! Constructs empty sequence with own write and prefetch block pool
139  //!
140  //! \param w_pool_size number of blocks in the write pool, must be at least 2, recommended at least 3
141  //! \param p_pool_size number of blocks in the prefetch pool, recommended at least 1
142  //! \param blocks2prefetch defines the number of blocks to prefetch (\c front side),
143  //! default is number of block in the prefetch pool
144  explicit sequence(unsigned_type w_pool_size, unsigned_type p_pool_size, int blocks2prefetch = -1) :
145  m_size(0),
146  m_owns_pool(true),
147  m_alloc_count(0),
148  m_bm(block_manager::get_instance())
149  {
150  STXXL_VERBOSE_SEQUENCE("sequence[" << this << "]::sequence(sizes)");
151  m_pool = new pool_type(p_pool_size, w_pool_size);
152  init(blocks2prefetch);
153  }
154 
155  //! Constructs empty sequence
156  //!
157  //! \param pool block write/prefetch pool
158  //! \param blocks2prefetch defines the number of blocks to prefetch (\c front side), default is number of blocks in the prefetch pool
159  //! \warning Number of blocks in the write pool must be at least 2, recommended at least 3
160  //! \warning Number of blocks in the prefetch pool recommended at least 1
161  sequence(pool_type& pool, int blocks2prefetch = -1) :
162  m_size(0),
163  m_owns_pool(false),
164  m_pool(&pool),
165  m_alloc_count(0),
166  m_bm(block_manager::get_instance())
167  {
168  STXXL_VERBOSE_SEQUENCE("sequence[" << this << "]::sequence(pool)");
169  init(blocks2prefetch);
170  }
171 
172  //! \}
173 
174  //! \name Modifiers
175  //! \{
176 
177  void swap(sequence& obj)
178  {
179  std::swap(m_size, obj.m_size);
180  std::swap(m_owns_pool, obj.m_owns_pool);
181  std::swap(m_pool, obj.m_pool);
182  std::swap(m_front_block, obj.m_front_block);
183  std::swap(m_back_block, obj.m_back_block);
184  std::swap(m_front_element, obj.m_front_element);
185  std::swap(m_back_element, obj.m_back_element);
186  std::swap(m_alloc_strategy, obj.m_alloc_strategy);
187  std::swap(m_alloc_count, obj.m_alloc_count);
188  std::swap(m_bids, obj.m_bids);
189  std::swap(m_bm, obj.m_bm);
190  std::swap(m_blocks2prefetch, obj.m_blocks2prefetch);
191  }
192 
193  //! \}
194 
195 private:
196  void init(int blocks2prefetch = -1)
197  {
198  if (m_pool->size_write() < 2) {
199  STXXL_ERRMSG("sequence: invalid configuration, not enough blocks (" << m_pool->size_write() <<
200  ") in write pool, at least 2 are needed, resizing to 3");
201  m_pool->resize_write(3);
202  }
203 
204  if (m_pool->size_write() < 3) {
205  STXXL_MSG("sequence: inefficient configuration, no blocks for buffered writing available");
206  }
207 
208  if (m_pool->size_prefetch() < 1) {
209  STXXL_MSG("sequence: inefficient configuration, no blocks for prefetching available");
210  }
211 
212  /// initialize empty sequence
213  m_front_block = m_back_block = m_pool->steal();
214  m_back_element = m_back_block->begin() - 1;
215  m_front_element = m_back_block->begin();
216  set_prefetch_aggr(blocks2prefetch);
217  }
218 
219 public:
220  //! \name Miscellaneous
221  //! \{
222 
223  //! Defines the number of blocks to prefetch (\c front side).
224  //! This method should be called whenever the prefetch pool is resized
225  //! \param blocks2prefetch defines the number of blocks to prefetch (\c front side),
226  //! a negative value means to use the number of blocks in the prefetch pool
227  void set_prefetch_aggr(int_type blocks2prefetch)
228  {
229  if (blocks2prefetch < 0)
230  m_blocks2prefetch = m_pool->size_prefetch();
231  else
232  m_blocks2prefetch = blocks2prefetch;
233  }
234 
235  //! Returns the number of blocks prefetched from the \c front side
237  {
238  return m_blocks2prefetch;
239  }
240 
241  //! \}
242 
243  //! \name Modifiers
244  //! \{
245 
246  //! Adds an element to the front of the sequence
247  void push_front(const value_type& val)
248  {
249  if (UNLIKELY(m_front_element == m_front_block->begin()))
250  {
251  if (m_size == 0)
252  {
253  STXXL_VERBOSE1("sequence::push_front Case 0");
254  assert(m_front_block == m_back_block);
255  m_front_element = m_back_element = m_front_block->end() - 1;
256  *m_front_element = val;
257  ++m_size;
258  return;
259  }
260  // front block is completely filled
261  else if (m_front_block == m_back_block)
262  {
263  // can not write the front block because it
264  // is the same as the back block, must keep it memory
265  STXXL_VERBOSE1("sequence::push_front Case 1");
266  }
267  else if (size() < 2 * block_type::size)
268  {
269  STXXL_VERBOSE1("sequence::push_front Case 1.5");
270  // only two blocks with a gap at the end, move elements within memory
271  assert(m_bids.empty());
272  size_t gap = m_back_block->end() - (m_back_element + 1);
273  assert(gap > 0);
274  std::copy_backward(m_back_block->begin(), m_back_element + 1, m_back_block->end());
275  std::copy_backward(m_front_block->end() - gap, m_front_block->end(), m_back_block->begin() + gap);
276  std::copy_backward(m_front_block->begin(), m_front_block->end() - gap, m_front_block->end());
277  m_front_element += gap;
278  m_back_element += gap;
279 
280  --m_front_element;
281  *m_front_element = val;
282  ++m_size;
283  return;
284  }
285  else
286  {
287  STXXL_VERBOSE1("sequence::push_front Case 2");
288  // write the front block
289  // need to allocate new block
290  bid_type newbid;
291 
292  m_bm->new_block(m_alloc_strategy, newbid, m_alloc_count++);
293 
294  STXXL_VERBOSE_SEQUENCE("sequence[" << this << "]: push_front block " << m_front_block << " @ " << FMT_BID(newbid));
295  m_bids.push_front(newbid);
296  m_pool->write(m_front_block, newbid);
297  if (m_bids.size() <= m_blocks2prefetch) {
298  STXXL_VERBOSE1("sequence::push Case Hints");
299  m_pool->hint(newbid);
300  }
301  }
302 
303  m_front_block = m_pool->steal();
304  m_front_element = m_front_block->end() - 1;
305  *m_front_element = val;
306  ++m_size;
307  }
308  else // not at beginning of a block
309  {
310  --m_front_element;
311  *m_front_element = val;
312  ++m_size;
313  }
314  }
315 
316  //! Adds an element to the end of the sequence
317  void push_back(const value_type& val)
318  {
319  if (UNLIKELY(m_back_element == m_back_block->begin() + (block_type::size - 1)))
320  {
321  // back block is completely filled
322  if (m_front_block == m_back_block)
323  {
324  // can not write the back block because it
325  // is the same as the front block, must keep it memory
326  STXXL_VERBOSE1("sequence::push_back Case 1");
327  }
328  else if (size() < 2 * block_type::size)
329  {
330  STXXL_VERBOSE1("sequence::push_back Case 1.5");
331  // only two blocks with a gap in the beginning, move elements within memory
332  assert(m_bids.empty());
333  size_t gap = m_front_element - m_front_block->begin();
334  assert(gap > 0);
335  std::copy(m_front_element, m_front_block->end(), m_front_block->begin());
336  std::copy(m_back_block->begin(), m_back_block->begin() + gap, m_front_block->begin() + (block_type::size - gap));
337  std::copy(m_back_block->begin() + gap, m_back_block->end(), m_back_block->begin());
338  m_front_element -= gap;
339  m_back_element -= gap;
340 
341  ++m_back_element;
342  *m_back_element = val;
343  ++m_size;
344  return;
345  }
346  else
347  {
348  STXXL_VERBOSE1("sequence::push_back Case 2");
349  // write the back block
350  // need to allocate new block
351  bid_type newbid;
352 
353  m_bm->new_block(m_alloc_strategy, newbid, m_alloc_count++);
354 
355  STXXL_VERBOSE_SEQUENCE("sequence[" << this << "]: push_back block " << m_back_block << " @ " << FMT_BID(newbid));
356  m_bids.push_back(newbid);
357  m_pool->write(m_back_block, newbid);
358  if (m_bids.size() <= m_blocks2prefetch) {
359  STXXL_VERBOSE1("sequence::push_back Case Hints");
360  m_pool->hint(newbid);
361  }
362  }
363  m_back_block = m_pool->steal();
364 
365  m_back_element = m_back_block->begin();
366  *m_back_element = val;
367  ++m_size;
368  }
369  else // not at end of a block
370  {
371  ++m_back_element;
372  *m_back_element = val;
373  ++m_size;
374  }
375  }
376 
377  //! Removes element from the front of the sequence
378  void pop_front()
379  {
380  assert(!empty());
381 
382  if (UNLIKELY(m_front_element == m_front_block->begin() + (block_type::size - 1)))
383  {
384  // if there is only one block, it implies ...
385  if (m_back_block == m_front_block)
386  {
387  STXXL_VERBOSE1("sequence::pop_front Case 1");
388  assert(size() == 1);
389  assert(m_back_element == m_front_element);
390  assert(m_bids.empty());
391  // reset everything
392  m_back_element = m_back_block->begin() - 1;
393  m_front_element = m_back_block->begin();
394  m_size = 0;
395  return;
396  }
397 
398  --m_size;
399  if (m_size <= block_type::size)
400  {
401  STXXL_VERBOSE1("sequence::pop_front Case 2");
402  assert(m_bids.empty());
403  // the m_back_block is the next block
404  m_pool->add(m_front_block);
405  m_front_block = m_back_block;
406  m_front_element = m_back_block->begin();
407  return;
408  }
409  STXXL_VERBOSE1("sequence::pop_front Case 3");
410 
411  assert(!m_bids.empty());
412  request_ptr req = m_pool->read(m_front_block, m_bids.front());
413  STXXL_VERBOSE_SEQUENCE("sequence[" << this << "]: pop_front block " << m_front_block << " @ " << FMT_BID(m_bids.front()));
414 
415  // give prefetching hints
416  for (unsigned_type i = 0; i < m_blocks2prefetch && i < m_bids.size() - 1; ++i)
417  {
418  STXXL_VERBOSE1("sequence::pop_front Case Hints");
419  m_pool->hint(m_bids[i + 1]);
420  }
421 
422  m_front_element = m_front_block->begin();
423  req->wait();
424 
425  m_bm->delete_block(m_bids.front());
426  m_bids.pop_front();
427  }
428  else
429  {
430  ++m_front_element;
431  --m_size;
432  }
433  }
434 
435  //! Removes element from the back of the sequence
436  void pop_back()
437  {
438  assert(!empty());
439 
440  if (UNLIKELY(m_back_element == m_back_block->begin()))
441  {
442  // if there is only one block, it implies ...
443  if (m_back_block == m_front_block)
444  {
445  STXXL_VERBOSE1("sequence::pop_back Case 1");
446  assert(size() == 1);
447  assert(m_back_element == m_front_element);
448  assert(m_bids.empty());
449  // reset everything
450  m_back_element = m_back_block->begin() - 1;
451  m_front_element = m_back_block->begin();
452  m_size = 0;
453  return;
454  }
455 
456  --m_size;
457  if (m_size <= block_type::size)
458  {
459  STXXL_VERBOSE1("sequence::pop_back Case 2");
460  assert(m_bids.empty());
461  // the m_front_block is the next block
462  m_pool->add(m_back_block);
463  m_back_block = m_front_block;
464  m_back_element = m_back_block->end() - 1;
465  return;
466  }
467 
468  STXXL_VERBOSE1("sequence::pop_back Case 3");
469 
470  assert(!m_bids.empty());
471  request_ptr req = m_pool->read(m_back_block, m_bids.back());
472  STXXL_VERBOSE_SEQUENCE("sequence[" << this << "]: pop_back block " << m_back_block << " @ " << FMT_BID(m_bids.back()));
473 
474  // give prefetching hints
475  for (unsigned_type i = 1; i < m_blocks2prefetch && i < m_bids.size() - 1; ++i)
476  {
477  STXXL_VERBOSE1("sequence::pop_front Case Hints");
478  m_pool->hint(m_bids[m_bids.size() - 1 - i]);
479  }
480 
481  m_back_element = m_back_block->end() - 1;
482  req->wait();
483 
484  m_bm->delete_block(m_bids.back());
485  m_bids.pop_back();
486  }
487  else
488  {
489  --m_back_element;
490  --m_size;
491  }
492  }
493 
494  //! \}
495 
496  //! \name Capacity
497  //! \{
498 
499  //! Returns the size of the sequence
500  size_type size() const
501  {
502  return m_size;
503  }
504 
505  //! Returns \c true if sequence is empty
506  bool empty() const
507  {
508  return (m_size == 0);
509  }
510 
511  //! \}
512 
513  //! \name Operators
514  //! \{
515 
516  //! Returns a mutable reference at the back of the sequence
518  {
519  assert(!empty());
520  return *m_back_element;
521  }
522 
523  //! Returns a const reference at the back of the sequence
524  const value_type & back() const
525  {
526  assert(!empty());
527  return *m_back_element;
528  }
529 
530  //! Returns a mutable reference at the front of the sequence
532  {
533  assert(!empty());
534  return *m_front_element;
535  }
536 
537  //! Returns a const reference at the front of the sequence
538  const value_type & front() const
539  {
540  assert(!empty());
541  return *m_front_element;
542  }
543 
544  //! \}
545 
546  //! \name Constructors/Destructors
547  //! \{
548 
550  {
551  if (m_front_block != m_back_block)
552  m_pool->add(m_back_block);
553 
554  m_pool->add(m_front_block);
555 
556  if (m_owns_pool)
557  delete m_pool;
558 
559  if (!m_bids.empty())
560  m_bm->delete_blocks(m_bids.begin(), m_bids.end());
561  }
562 
563  //! \}
564 
565  /********************************************************************************/
566 
567  class stream
568  {
569  public:
571 
572  typedef typename bid_deque_type::const_iterator bid_iter_type;
573 
574  protected:
576 
578 
580 
582 
584 
585  public:
587  : m_sequence(sequence),
588  m_size(sequence.size())
589  {
590  m_current_block = sequence.m_front_block;
591  m_current_element = sequence.m_front_element;
592  m_next_bid = sequence.m_bids.begin();
593  }
594 
596  {
597  if (m_current_block != m_sequence.m_front_block &&
598  m_current_block != m_sequence.m_back_block) // give m_current_block back to pool
599  m_sequence.m_pool->add(m_current_block);
600  }
601 
602  //! return number of element left till end-of-stream.
603  size_type size() const
604  {
605  return m_size;
606  }
607 
608  //! standard stream method
609  bool empty() const
610  {
611  return (m_size == 0);
612  }
613 
614  //! standard stream method
615  const value_type& operator * () const
616  {
617  assert(!empty());
618  return *m_current_element;
619  }
620 
621  //! standard stream method
623  {
624  assert(!empty());
625 
626  if (UNLIKELY(m_current_element == m_current_block->begin() + (block_type::size - 1)))
627  {
628  // next item position is beyond end of current block, find next block
629  --m_size;
630 
631  if (m_size == 0)
632  {
633  STXXL_VERBOSE1("sequence::stream::operator++ last block finished clean at block end");
634  assert(m_next_bid == m_sequence.m_bids.end());
635  assert(m_current_block == m_sequence.m_back_block);
636  // nothing to give back to sequence pool
637  m_current_element = NULL;
638  return *this;
639  }
640  else if (m_size <= block_type::size) // still items left in last partial block
641  {
642  STXXL_VERBOSE1("sequence::stream::operator++ reached last block");
643  assert(m_next_bid == m_sequence.m_bids.end());
644  // the m_back_block is the next block
645  if (m_current_block != m_sequence.m_front_block) // give current_block back to pool
646  m_sequence.m_pool->add(m_current_block);
647  m_current_block = m_sequence.m_back_block;
648  m_current_element = m_current_block->begin();
649  return *this;
650  }
651  else if (m_current_block == m_sequence.m_front_block)
652  {
653  STXXL_VERBOSE1("sequence::stream::operator++ first own-block case: steal block from sequence's pool");
654  m_current_block = m_sequence.m_pool->steal();
655  }
656 
657  STXXL_VERBOSE1("sequence::stream::operator++ default case: fetch next block");
658 
659  assert(m_next_bid != m_sequence.m_bids.end());
660  request_ptr req = m_sequence.m_pool->read(m_current_block, *m_next_bid);
661  STXXL_VERBOSE_SEQUENCE("sequence[" << this << "]::stream::operator++ read block " << m_current_block << " @ " << FMT_BID(*m_next_bid));
662 
663  // give prefetching hints
664  bid_iter_type bid = m_next_bid + 1;
665  for (unsigned_type i = 0; i < m_sequence.m_blocks2prefetch && bid != m_sequence.m_bids.end(); ++i, ++bid)
666  {
667  STXXL_VERBOSE1("sequence::stream::operator++ giving prefetch hints");
668  m_sequence.m_pool->hint(*bid);
669  }
670 
671  m_current_element = m_current_block->begin();
672  req->wait();
673 
674  ++m_next_bid;
675  }
676  else
677  {
678  --m_size;
679  ++m_current_element;
680  }
681  return *this;
682  }
683  };
684 
685  //! \name Miscellaneous
686  //! \{
687 
688  //! construct a forward stream from this sequence
690  {
691  return stream(*this);
692  }
693 
694  //! \}
695 
696  /********************************************************************************/
697 
699  {
700  public:
702 
703  typedef typename bid_deque_type::const_reverse_iterator bid_iter_type;
704 
705  protected:
707 
709 
711 
713 
715 
716  public:
718  : m_sequence(sequence),
719  m_size(sequence.size())
720  {
721  m_current_block = sequence.m_back_block;
722  m_current_element = sequence.m_back_element;
723  m_next_bid = sequence.m_bids.rbegin();
724  }
725 
727  {
728  if (m_current_block != m_sequence.m_front_block &&
729  m_current_block != m_sequence.m_back_block) // give m_current_block back to pool
730  m_sequence.m_pool->add(m_current_block);
731  }
732 
733  //! return number of element left till end-of-stream.
734  size_type size() const
735  {
736  return m_size;
737  }
738 
739  //! standard stream method
740  bool empty() const
741  {
742  return (m_size == 0);
743  }
744 
745  //! standard stream method
746  const value_type& operator * () const
747  {
748  assert(!empty());
749  return *m_current_element;
750  }
751 
752  //! standard stream method
754  {
755  assert(!empty());
756 
757  if (UNLIKELY(m_current_element == m_current_block->begin()))
758  {
759  // next item position is beyond begin of current block, find next block
760  --m_size;
761 
762  if (m_size == 0)
763  {
764  STXXL_VERBOSE1("sequence::reverse_stream::operator++ last block finished clean at block begin");
765  assert(m_next_bid == m_sequence.m_bids.rend());
766  assert(m_current_block == m_sequence.m_front_block);
767  // nothing to give back to sequence pool
768  m_current_element = NULL;
769  return *this;
770  }
771  else if (m_size <= block_type::size)
772  {
773  STXXL_VERBOSE1("sequence::reverse_stream::operator++ reached first block");
774  assert(m_next_bid == m_sequence.m_bids.rend());
775  // the m_back_block is the next block
776  if (m_current_block != m_sequence.m_back_block) // give current_block back to pool
777  m_sequence.m_pool->add(m_current_block);
778  m_current_block = m_sequence.m_front_block;
779  m_current_element = m_current_block->begin() + (block_type::size - 1);
780  return *this;
781  }
782  else if (m_current_block == m_sequence.m_back_block)
783  {
784  STXXL_VERBOSE1("sequence::reverse_stream::operator++ first own-block case: steal block from sequence's pool");
785  m_current_block = m_sequence.m_pool->steal();
786  }
787 
788  STXXL_VERBOSE1("sequence::reverse_stream::operator++ default case: fetch previous block");
789 
790  assert(m_next_bid != m_sequence.m_bids.rend());
791  request_ptr req = m_sequence.m_pool->read(m_current_block, *m_next_bid);
792  STXXL_VERBOSE_SEQUENCE("sequence[" << this << "]::reverse_stream::operator++ read block " << m_current_block << " @ " << FMT_BID(*m_next_bid));
793 
794  // give prefetching hints
795  bid_iter_type bid = m_next_bid + 1;
796  for (unsigned_type i = 0; i < m_sequence.m_blocks2prefetch && bid != m_sequence.m_bids.rend(); ++i, ++bid)
797  {
798  STXXL_VERBOSE1("sequence::reverse_stream::operator++ giving prefetch hints");
799  m_sequence.m_pool->hint(*bid);
800  }
801 
802  m_current_element = m_current_block->begin() + (block_type::size - 1);
803  req->wait();
804 
805  ++m_next_bid;
806  }
807  else
808  {
809  --m_size;
810  --m_current_element;
811  }
812  return *this;
813  }
814  };
815 
816  //! \name Miscellaneous
817  //! \{
818 
819  //! construct a reverse stream from this sequence
821  {
822  return reverse_stream(*this);
823  }
824 
825  //! \}
826 };
827 
828 //! \}
829 
831 
832 #endif // !STXXL_CONTAINERS_SEQUENCE_HEADER
833 // vim: et:ts=4:sw=4
void pop_front()
Removes element from the front of the sequence.
Definition: sequence.h:378
#define STXXL_DEFAULT_BLOCK_SIZE(type)
BID< block_size > bid_type
Definition: sequence.h:74
pool_type * m_pool
read_write_pool of blocks
Definition: sequence.h:88
bid_deque_type::const_iterator bid_iter_type
Definition: sequence.h:572
void push_back(const value_type &val)
Adds an element to the end of the sequence.
Definition: sequence.h:317
Block manager class.
Definition: block_manager.h:63
block_type * m_front_block
current front block of sequence
Definition: sequence.h:91
bool empty() const
standard stream method
Definition: sequence.h:609
unsigned long long int uint64
Definition: types.h:41
value_type * m_back_element
pointer to current back element in m_back_block
Definition: sequence.h:100
bid_iter_type m_next_bid
Definition: sequence.h:583
size_type size() const
return number of element left till end-of-stream.
Definition: sequence.h:734
sequence(int_type D=-1)
Constructs empty sequence with own write and prefetch block pool.
Definition: sequence.h:126
stream get_stream()
construct a forward stream from this sequence
Definition: sequence.h:689
void swap(sequence &obj)
Definition: sequence.h:177
void push_front(const value_type &val)
Adds an element to the front of the sequence.
Definition: sequence.h:247
void init(int blocks2prefetch=-1)
Definition: sequence.h:196
#define STXXL_DEFAULT_ALLOC_STRATEGY
Definition: block_alloc.h:259
size_type m_size
current number of items in the sequence
Definition: sequence.h:82
value_type * m_current_element
Definition: sequence.h:579
AllocStr alloc_strategy_type
Definition: sequence.h:67
uint_pair & operator++()
prefix increment operator (directly manipulates the integer parts)
Definition: uint_types.h:166
value_type & front()
Returns a mutable reference at the front of the sequence.
Definition: sequence.h:531
const value_type & front() const
Returns a const reference at the front of the sequence.
Definition: sequence.h:538
unsigned_type m_alloc_count
block allocation counter
Definition: sequence.h:106
void pop_back()
Removes element from the back of the sequence.
Definition: sequence.h:436
Block containing elements of fixed length.
Definition: typed_block.h:238
External sequence or deque container without random access. Introduction to sequence container: se...
Definition: sequence.h:63
size_type size() const
return number of element left till end-of-stream.
Definition: sequence.h:603
Implements dynamically resizable buffered writing and prefetched reading pool.
choose_int_types< my_pointer_size >::int_type int_type
Definition: types.h:66
#define UNLIKELY(c)
Definition: utils.h:226
ValueType value_type
Definition: sequence.h:66
#define STXXL_VERBOSE_SEQUENCE
Definition: sequence.h:32
#define STXXL_BEGIN_NAMESPACE
Definition: namespace.h:16
#define STXXL_VERBOSE1(x)
Definition: verbose.h:99
sequence(unsigned_type w_pool_size, unsigned_type p_pool_size, int blocks2prefetch=-1)
Constructs empty sequence with own write and prefetch block pool.
Definition: sequence.h:144
bool m_owns_pool
whether the m_pool object is own and should be deleted.
Definition: sequence.h:85
void set_prefetch_aggr(int_type blocks2prefetch)
Defines the number of blocks to prefetch (front side). This method should be called whenever the pref...
Definition: sequence.h:227
stream(const sequence &sequence)
Definition: sequence.h:586
block_type * m_current_block
Definition: sequence.h:581
reverse_stream get_reverse_stream()
construct a reverse stream from this sequence
Definition: sequence.h:820
sequence(pool_type &pool, int blocks2prefetch=-1)
Constructs empty sequence.
Definition: sequence.h:161
const sequence & m_sequence
Definition: sequence.h:575
read_write_pool< block_type > pool_type
Definition: sequence.h:79
SizeType size_type
Definition: sequence.h:68
bid_deque_type m_bids
allocated block identifiers
Definition: sequence.h:109
#define STXXL_ERRMSG(x)
Definition: verbose.h:79
alloc_strategy_type m_alloc_strategy
block allocation strategy
Definition: sequence.h:103
unsigned_type m_blocks2prefetch
number of blocks to prefetch
Definition: sequence.h:115
choose_int_types< my_pointer_size >::unsigned_type unsigned_type
Definition: types.h:67
size_type size() const
Returns the size of the sequence.
Definition: sequence.h:500
block_type * m_back_block
current back block of sequence
Definition: sequence.h:94
#define STXXL_MSG(x)
Definition: verbose.h:72
std::deque< bid_type > bid_deque_type
Definition: sequence.h:76
value_type * m_front_element
pointer to current front element in m_front_block
Definition: sequence.h:97
sequence::value_type value_type
Definition: sequence.h:570
const value_type & back() const
Returns a const reference at the back of the sequence.
Definition: sequence.h:524
value_type & back()
Returns a mutable reference at the back of the sequence.
Definition: sequence.h:517
const sequence & m_sequence
Definition: sequence.h:706
bool empty() const
Returns true if sequence is empty.
Definition: sequence.h:506
reverse_stream(const sequence &sequence)
Definition: sequence.h:717
sequence::value_type value_type
Definition: sequence.h:701
bool empty() const
standard stream method
Definition: sequence.h:740
block_manager * m_bm
block manager used
Definition: sequence.h:112
typed_block< block_size, value_type > block_type
Definition: sequence.h:73
#define FMT_BID(_bid_)
Definition: bid.h:30
#define STXXL_END_NAMESPACE
Definition: namespace.h:17
bid_deque_type::const_reverse_iterator bid_iter_type
Definition: sequence.h:703
unsigned_type get_prefetch_aggr() const
Returns the number of blocks prefetched from the front side.
Definition: sequence.h:236