15 #ifndef STXXL_CONTAINERS_SEQUENCE_HEADER
16 #define STXXL_CONTAINERS_SEQUENCE_HEADER
30 #ifndef STXXL_VERBOSE_SEQUENCE
31 #define STXXL_VERBOSE_SEQUENCE STXXL_VERBOSE2
58 template <
class ValueType,
69 block_size = BlockSize
131 if (D < 1) D = config::get_instance()->disks_number();
150 m_pool =
new pool_type(p_pool_size, w_pool_size);
151 init(blocks2prefetch);
168 init(blocks2prefetch);
178 std::swap(m_size, obj.
m_size);
180 std::swap(m_pool, obj.
m_pool);
187 std::swap(m_bids, obj.
m_bids);
188 std::swap(m_bm, obj.
m_bm);
195 void init(
int blocks2prefetch = -1)
197 if (m_pool->size_write() < 2) {
198 STXXL_ERRMSG(
"sequence: invalid configuration, not enough blocks (" << m_pool->size_write() <<
199 ") in write pool, at least 2 are needed, resizing to 3");
200 m_pool->resize_write(3);
203 if (m_pool->size_write() < 3) {
204 STXXL_MSG(
"sequence: inefficient configuration, no blocks for buffered writing available");
207 if (m_pool->size_prefetch() < 1) {
208 STXXL_MSG(
"sequence: inefficient configuration, no blocks for prefetching available");
212 m_front_block = m_back_block = m_pool->steal();
213 m_back_element = m_back_block->begin() - 1;
214 m_front_element = m_back_block->begin();
215 set_prefetch_aggr(blocks2prefetch);
228 if (blocks2prefetch < 0)
229 m_blocks2prefetch = m_pool->size_prefetch();
231 m_blocks2prefetch = blocks2prefetch;
237 return m_blocks2prefetch;
248 if (
UNLIKELY(m_front_element == m_front_block->begin()))
253 assert(m_front_block == m_back_block);
254 m_front_element = m_back_element = m_front_block->end() - 1;
255 *m_front_element = val;
260 else if (m_front_block == m_back_block)
266 else if (size() < 2 * block_type::size)
270 assert(m_bids.empty());
271 size_t gap = m_back_block->end() - (m_back_element + 1);
273 std::copy_backward(m_back_block->begin(), m_back_element + 1, m_back_block->end());
274 std::copy_backward(m_front_block->end() - gap, m_front_block->end(), m_back_block->begin() + gap);
275 std::copy_backward(m_front_block->begin(), m_front_block->end() - gap, m_front_block->end());
276 m_front_element += gap;
277 m_back_element += gap;
280 *m_front_element = val;
291 m_bm->new_block(m_alloc_strategy, newbid, m_alloc_count++);
294 m_bids.push_front(newbid);
295 m_pool->write(m_front_block, newbid);
296 if (m_bids.size() <= m_blocks2prefetch) {
298 m_pool->hint(newbid);
302 m_front_block = m_pool->steal();
303 m_front_element = m_front_block->end() - 1;
304 *m_front_element = val;
310 *m_front_element = val;
318 if (
UNLIKELY(m_back_element == m_back_block->begin() + (block_type::size - 1)))
321 if (m_front_block == m_back_block)
327 else if (size() < 2 * block_type::size)
331 assert(m_bids.empty());
332 size_t gap = m_front_element - m_front_block->begin();
334 std::copy(m_front_element, m_front_block->end(), m_front_block->begin());
335 std::copy(m_back_block->begin(), m_back_block->begin() + gap, m_front_block->begin() + (block_type::size - gap));
336 std::copy(m_back_block->begin() + gap, m_back_block->end(), m_back_block->begin());
337 m_front_element -= gap;
338 m_back_element -= gap;
341 *m_back_element = val;
352 m_bm->new_block(m_alloc_strategy, newbid, m_alloc_count++);
355 m_bids.push_back(newbid);
356 m_pool->write(m_back_block, newbid);
357 if (m_bids.size() <= m_blocks2prefetch) {
359 m_pool->hint(newbid);
362 m_back_block = m_pool->steal();
364 m_back_element = m_back_block->begin();
365 *m_back_element = val;
371 *m_back_element = val;
381 if (
UNLIKELY(m_front_element == m_front_block->begin() + (block_type::size - 1)))
384 if (m_back_block == m_front_block)
388 assert(m_back_element == m_front_element);
389 assert(m_bids.empty());
391 m_back_element = m_back_block->begin() - 1;
392 m_front_element = m_back_block->begin();
398 if (m_size <= block_type::size)
401 assert(m_bids.empty());
403 m_pool->add(m_front_block);
404 m_front_block = m_back_block;
405 m_front_element = m_back_block->begin();
410 assert(!m_bids.empty());
411 request_ptr req = m_pool->read(m_front_block, m_bids.front());
415 for (
unsigned_type i = 0; i < m_blocks2prefetch && i < m_bids.size() - 1; ++i)
418 m_pool->hint(m_bids[i + 1]);
421 m_front_element = m_front_block->begin();
424 m_bm->delete_block(m_bids.front());
439 if (
UNLIKELY(m_back_element == m_back_block->begin()))
442 if (m_back_block == m_front_block)
446 assert(m_back_element == m_front_element);
447 assert(m_bids.empty());
449 m_back_element = m_back_block->begin() - 1;
450 m_front_element = m_back_block->begin();
456 if (m_size <= block_type::size)
459 assert(m_bids.empty());
461 m_pool->add(m_back_block);
462 m_back_block = m_front_block;
463 m_back_element = m_back_block->end() - 1;
469 assert(!m_bids.empty());
470 request_ptr req = m_pool->read(m_back_block, m_bids.back());
474 for (
unsigned_type i = 1; i < m_blocks2prefetch && i < m_bids.size() - 1; ++i)
477 m_pool->hint(m_bids[m_bids.size() - 1 - i]);
480 m_back_element = m_back_block->end() - 1;
483 m_bm->delete_block(m_bids.back());
507 return (m_size == 0);
519 return *m_back_element;
526 return *m_back_element;
533 return *m_front_element;
540 return *m_front_element;
550 if (m_front_block != m_back_block)
551 m_pool->add(m_back_block);
553 m_pool->add(m_front_block);
559 m_bm->delete_blocks(m_bids.begin(), m_bids.end());
586 : m_sequence(sequence),
587 m_size(sequence.size())
591 m_next_bid = sequence.
m_bids.begin();
596 if (m_current_block != m_sequence.m_front_block &&
597 m_current_block != m_sequence.m_back_block)
598 m_sequence.m_pool->add(m_current_block);
610 return (m_size == 0);
617 return *m_current_element;
625 if (
UNLIKELY(m_current_element == m_current_block->begin() + (block_type::size - 1)))
632 STXXL_VERBOSE1(
"sequence::stream::operator++ last block finished clean at block end");
633 assert(m_next_bid == m_sequence.m_bids.end());
634 assert(m_current_block == m_sequence.m_back_block);
636 m_current_element = NULL;
639 else if (m_size <= block_type::size)
641 STXXL_VERBOSE1(
"sequence::stream::operator++ reached last block");
642 assert(m_next_bid == m_sequence.m_bids.end());
644 if (m_current_block != m_sequence.m_front_block)
645 m_sequence.m_pool->add(m_current_block);
646 m_current_block = m_sequence.m_back_block;
647 m_current_element = m_current_block->begin();
650 else if (m_current_block == m_sequence.m_front_block)
652 STXXL_VERBOSE1(
"sequence::stream::operator++ first own-block case: steal block from sequence's pool");
653 m_current_block = m_sequence.m_pool->steal();
656 STXXL_VERBOSE1(
"sequence::stream::operator++ default case: fetch next block");
658 assert(m_next_bid != m_sequence.m_bids.end());
659 request_ptr req = m_sequence.m_pool->read(m_current_block, *m_next_bid);
664 for (
unsigned_type i = 0; i < m_sequence.m_blocks2prefetch && bid != m_sequence.m_bids.end(); ++i, ++bid)
666 STXXL_VERBOSE1(
"sequence::stream::operator++ giving prefetch hints");
667 m_sequence.m_pool->hint(*bid);
670 m_current_element = m_current_block->begin();
717 : m_sequence(sequence),
718 m_size(sequence.size())
722 m_next_bid = sequence.
m_bids.rbegin();
727 if (m_current_block != m_sequence.m_front_block &&
728 m_current_block != m_sequence.m_back_block)
729 m_sequence.m_pool->add(m_current_block);
741 return (m_size == 0);
748 return *m_current_element;
756 if (
UNLIKELY(m_current_element == m_current_block->begin()))
763 STXXL_VERBOSE1(
"sequence::reverse_stream::operator++ last block finished clean at block begin");
764 assert(m_next_bid == m_sequence.m_bids.rend());
765 assert(m_current_block == m_sequence.m_front_block);
767 m_current_element = NULL;
770 else if (m_size <= block_type::size)
772 STXXL_VERBOSE1(
"sequence::reverse_stream::operator++ reached first block");
773 assert(m_next_bid == m_sequence.m_bids.rend());
775 if (m_current_block != m_sequence.m_back_block)
776 m_sequence.m_pool->add(m_current_block);
777 m_current_block = m_sequence.m_front_block;
778 m_current_element = m_current_block->begin() + (block_type::size - 1);
781 else if (m_current_block == m_sequence.m_back_block)
783 STXXL_VERBOSE1(
"sequence::reverse_stream::operator++ first own-block case: steal block from sequence's pool");
784 m_current_block = m_sequence.m_pool->steal();
787 STXXL_VERBOSE1(
"sequence::reverse_stream::operator++ default case: fetch previous block");
789 assert(m_next_bid != m_sequence.m_bids.rend());
790 request_ptr req = m_sequence.m_pool->read(m_current_block, *m_next_bid);
791 STXXL_VERBOSE_SEQUENCE(
"sequence[" <<
this <<
"]::reverse_stream::operator++ read block " << m_current_block <<
" @ " <<
FMT_BID(*m_next_bid));
795 for (
unsigned_type i = 0; i < m_sequence.m_blocks2prefetch && bid != m_sequence.m_bids.rend(); ++i, ++bid)
797 STXXL_VERBOSE1(
"sequence::reverse_stream::operator++ giving prefetch hints");
798 m_sequence.m_pool->hint(*bid);
801 m_current_element = m_current_block->begin() + (block_type::size - 1);
831 #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.
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.