15 #ifndef STXXL_CONTAINERS_SEQUENCE_HEADER
16 #define STXXL_CONTAINERS_SEQUENCE_HEADER
31 #ifndef STXXL_VERBOSE_SEQUENCE
32 #define STXXL_VERBOSE_SEQUENCE STXXL_VERBOSE2
59 template <
class ValueType,
70 block_size = BlockSize
132 if (D < 1) D = config::get_instance()->disks_number();
151 m_pool =
new pool_type(p_pool_size, w_pool_size);
152 init(blocks2prefetch);
169 init(blocks2prefetch);
179 std::swap(m_size, obj.
m_size);
181 std::swap(m_pool, obj.
m_pool);
188 std::swap(m_bids, obj.
m_bids);
189 std::swap(m_bm, obj.
m_bm);
196 void init(
int blocks2prefetch = -1)
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);
204 if (m_pool->size_write() < 3) {
205 STXXL_MSG(
"sequence: inefficient configuration, no blocks for buffered writing available");
208 if (m_pool->size_prefetch() < 1) {
209 STXXL_MSG(
"sequence: inefficient configuration, no blocks for prefetching available");
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);
229 if (blocks2prefetch < 0)
230 m_blocks2prefetch = m_pool->size_prefetch();
232 m_blocks2prefetch = blocks2prefetch;
238 return m_blocks2prefetch;
249 if (
UNLIKELY(m_front_element == m_front_block->begin()))
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;
261 else if (m_front_block == m_back_block)
267 else if (size() < 2 * block_type::size)
271 assert(m_bids.empty());
272 size_t gap = m_back_block->end() - (m_back_element + 1);
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;
281 *m_front_element = val;
292 m_bm->new_block(m_alloc_strategy, newbid, m_alloc_count++);
295 m_bids.push_front(newbid);
296 m_pool->write(m_front_block, newbid);
297 if (m_bids.size() <= m_blocks2prefetch) {
299 m_pool->hint(newbid);
303 m_front_block = m_pool->steal();
304 m_front_element = m_front_block->end() - 1;
305 *m_front_element = val;
311 *m_front_element = val;
319 if (
UNLIKELY(m_back_element == m_back_block->begin() + (block_type::size - 1)))
322 if (m_front_block == m_back_block)
328 else if (size() < 2 * block_type::size)
332 assert(m_bids.empty());
333 size_t gap = m_front_element - m_front_block->begin();
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;
342 *m_back_element = val;
353 m_bm->new_block(m_alloc_strategy, newbid, m_alloc_count++);
356 m_bids.push_back(newbid);
357 m_pool->write(m_back_block, newbid);
358 if (m_bids.size() <= m_blocks2prefetch) {
360 m_pool->hint(newbid);
363 m_back_block = m_pool->steal();
365 m_back_element = m_back_block->begin();
366 *m_back_element = val;
372 *m_back_element = val;
382 if (
UNLIKELY(m_front_element == m_front_block->begin() + (block_type::size - 1)))
385 if (m_back_block == m_front_block)
389 assert(m_back_element == m_front_element);
390 assert(m_bids.empty());
392 m_back_element = m_back_block->begin() - 1;
393 m_front_element = m_back_block->begin();
399 if (m_size <= block_type::size)
402 assert(m_bids.empty());
404 m_pool->add(m_front_block);
405 m_front_block = m_back_block;
406 m_front_element = m_back_block->begin();
411 assert(!m_bids.empty());
412 request_ptr req = m_pool->read(m_front_block, m_bids.front());
416 for (
unsigned_type i = 0; i < m_blocks2prefetch && i < m_bids.size() - 1; ++i)
419 m_pool->hint(m_bids[i + 1]);
422 m_front_element = m_front_block->begin();
425 m_bm->delete_block(m_bids.front());
440 if (
UNLIKELY(m_back_element == m_back_block->begin()))
443 if (m_back_block == m_front_block)
447 assert(m_back_element == m_front_element);
448 assert(m_bids.empty());
450 m_back_element = m_back_block->begin() - 1;
451 m_front_element = m_back_block->begin();
457 if (m_size <= block_type::size)
460 assert(m_bids.empty());
462 m_pool->add(m_back_block);
463 m_back_block = m_front_block;
464 m_back_element = m_back_block->end() - 1;
470 assert(!m_bids.empty());
471 request_ptr req = m_pool->read(m_back_block, m_bids.back());
475 for (
unsigned_type i = 1; i < m_blocks2prefetch && i < m_bids.size() - 1; ++i)
478 m_pool->hint(m_bids[m_bids.size() - 1 - i]);
481 m_back_element = m_back_block->end() - 1;
484 m_bm->delete_block(m_bids.back());
508 return (m_size == 0);
520 return *m_back_element;
527 return *m_back_element;
534 return *m_front_element;
541 return *m_front_element;
551 if (m_front_block != m_back_block)
552 m_pool->add(m_back_block);
554 m_pool->add(m_front_block);
560 m_bm->delete_blocks(m_bids.begin(), m_bids.end());
587 : m_sequence(sequence),
588 m_size(sequence.size())
592 m_next_bid = sequence.
m_bids.begin();
597 if (m_current_block != m_sequence.m_front_block &&
598 m_current_block != m_sequence.m_back_block)
599 m_sequence.m_pool->add(m_current_block);
611 return (m_size == 0);
618 return *m_current_element;
626 if (
UNLIKELY(m_current_element == m_current_block->begin() + (block_type::size - 1)))
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);
637 m_current_element = NULL;
640 else if (m_size <= block_type::size)
642 STXXL_VERBOSE1(
"sequence::stream::operator++ reached last block");
643 assert(m_next_bid == m_sequence.m_bids.end());
645 if (m_current_block != m_sequence.m_front_block)
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();
651 else if (m_current_block == m_sequence.m_front_block)
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();
657 STXXL_VERBOSE1(
"sequence::stream::operator++ default case: fetch next block");
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);
665 for (
unsigned_type i = 0; i < m_sequence.m_blocks2prefetch && bid != m_sequence.m_bids.end(); ++i, ++bid)
667 STXXL_VERBOSE1(
"sequence::stream::operator++ giving prefetch hints");
668 m_sequence.m_pool->hint(*bid);
671 m_current_element = m_current_block->begin();
718 : m_sequence(sequence),
719 m_size(sequence.size())
723 m_next_bid = sequence.
m_bids.rbegin();
728 if (m_current_block != m_sequence.m_front_block &&
729 m_current_block != m_sequence.m_back_block)
730 m_sequence.m_pool->add(m_current_block);
742 return (m_size == 0);
749 return *m_current_element;
757 if (
UNLIKELY(m_current_element == m_current_block->begin()))
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);
768 m_current_element = NULL;
771 else if (m_size <= block_type::size)
773 STXXL_VERBOSE1(
"sequence::reverse_stream::operator++ reached first block");
774 assert(m_next_bid == m_sequence.m_bids.rend());
776 if (m_current_block != m_sequence.m_back_block)
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);
782 else if (m_current_block == m_sequence.m_back_block)
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();
788 STXXL_VERBOSE1(
"sequence::reverse_stream::operator++ default case: fetch previous block");
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));
796 for (
unsigned_type i = 0; i < m_sequence.m_blocks2prefetch && bid != m_sequence.m_bids.rend(); ++i, ++bid)
798 STXXL_VERBOSE1(
"sequence::reverse_stream::operator++ giving prefetch hints");
799 m_sequence.m_pool->hint(*bid);
802 m_current_element = m_current_block->begin() + (block_type::size - 1);
832 #endif // !STXXL_CONTAINERS_SEQUENCE_HEADER
void pop_front()
Removes element from the front of the sequence.
#define STXXL_DEFAULT_BLOCK_SIZE(type)
BID< block_size > bid_type
pool_type * m_pool
read_write_pool of blocks
bid_deque_type::const_iterator bid_iter_type
void push_back(const value_type &val)
Adds an element to the end of the sequence.
block_type * m_front_block
current front block of sequence
bool empty() const
standard stream method
unsigned long long int uint64
value_type * m_back_element
pointer to current back element in m_back_block
size_type size() const
return number of element left till end-of-stream.
sequence(int_type D=-1)
Constructs empty sequence with own write and prefetch block pool.
stream get_stream()
construct a forward stream from this sequence
void push_front(const value_type &val)
Adds an element to the front of the sequence.
void init(int blocks2prefetch=-1)
#define STXXL_DEFAULT_ALLOC_STRATEGY
size_type m_size
current number of items in the sequence
value_type * m_current_element
AllocStr alloc_strategy_type
uint_pair & operator++()
prefix increment operator (directly manipulates the integer parts)
value_type & front()
Returns a mutable reference at the front of the sequence.
value_type * m_current_element
const value_type & front() const
Returns a const reference at the front of the sequence.
unsigned_type m_alloc_count
block allocation counter
void pop_back()
Removes element from the back of the sequence.
Block containing elements of fixed length.
External sequence or deque container without random access. Introduction to sequence container: se...
size_type size() const
return number of element left till end-of-stream.
Implements dynamically resizable buffered writing and prefetched reading pool.
choose_int_types< my_pointer_size >::int_type int_type
#define STXXL_VERBOSE_SEQUENCE
#define STXXL_BEGIN_NAMESPACE
#define STXXL_VERBOSE1(x)
sequence(unsigned_type w_pool_size, unsigned_type p_pool_size, int blocks2prefetch=-1)
Constructs empty sequence with own write and prefetch block pool.
bool m_owns_pool
whether the m_pool object is own and should be deleted.
void set_prefetch_aggr(int_type blocks2prefetch)
Defines the number of blocks to prefetch (front side). This method should be called whenever the pref...
block_type * m_current_block
stream(const sequence &sequence)
block_type * m_current_block
reverse_stream get_reverse_stream()
construct a reverse stream from this sequence
sequence(pool_type &pool, int blocks2prefetch=-1)
Constructs empty sequence.
const sequence & m_sequence
read_write_pool< block_type > pool_type
bid_deque_type m_bids
allocated block identifiers
alloc_strategy_type m_alloc_strategy
block allocation strategy
unsigned_type m_blocks2prefetch
number of blocks to prefetch
choose_int_types< my_pointer_size >::unsigned_type unsigned_type
size_type size() const
Returns the size of the sequence.
block_type * m_back_block
current back block of sequence
std::deque< bid_type > bid_deque_type
value_type * m_front_element
pointer to current front element in m_front_block
sequence::value_type value_type
const value_type & back() const
Returns a const reference at the back of the sequence.
value_type & back()
Returns a mutable reference at the back of the sequence.
const sequence & m_sequence
bool empty() const
Returns true if sequence is empty.
reverse_stream(const sequence &sequence)
sequence::value_type value_type
bool empty() const
standard stream method
block_manager * m_bm
block manager used
typed_block< block_size, value_type > block_type
#define STXXL_END_NAMESPACE
bid_deque_type::const_reverse_iterator bid_iter_type
unsigned_type get_prefetch_aggr() const
Returns the number of blocks prefetched from the front side.