14 #ifndef STXXL_CONTAINERS_STACK_HEADER
15 #define STXXL_CONTAINERS_STACK_HEADER
39 template <
class ValueType,
40 unsigned BlocksPerPage = 4,
47 enum { blocks_per_page = BlocksPerPage };
49 enum { block_size = BlockSize };
62 template <
class StackConfig>
66 typedef StackConfig
cfg;
73 blocks_per_page = cfg::blocks_per_page,
74 block_size = cfg::block_size
88 std::vector<bid_type>
bids;
99 current_element(NULL),
100 cache(blocks_per_page * 2),
101 front_page(cache.begin() + blocks_per_page),
102 back_page(cache.begin()),
105 bids.reserve(blocks_per_page);
113 std::swap(m_size, obj.
m_size);
116 std::swap(cache, obj.
cache);
119 std::swap(bids, obj.
bids);
131 template <
class stack_type>
135 current_element(NULL),
136 cache(blocks_per_page * 2),
137 front_page(cache.begin() + blocks_per_page),
138 back_page(cache.begin()),
141 bids.reserve(blocks_per_page);
143 stack_type stack_copy = stack_;
147 std::vector<value_type> tmp(sz);
149 for (i = 0; i < sz; ++i)
151 tmp[sz - i - 1] = stack_copy.top();
154 for (i = 0; i < sz; ++i)
161 block_manager::get_instance()->delete_blocks(bids.begin(), bids.end());
191 return (*current_element);
199 return (*current_element);
206 assert(cache_offset <= 2 * blocks_per_page * block_type::size);
209 if (
UNLIKELY(cache_offset == 2 * blocks_per_page * block_type::size))
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());
219 for (
int i = 0; i < blocks_per_page; ++i, ++cur_bid)
221 requests[i] = (back_page + i)->write(*cur_bid);
225 std::swap(back_page, front_page);
227 bids.reserve(bids.size() + blocks_per_page);
229 cache_offset = blocks_per_page * block_type::size + 1;
230 current_element = &((*front_page)[0]);
235 *current_element = val;
240 current_element = element(cache_offset);
241 *current_element = val;
250 assert(cache_offset <= 2 * blocks_per_page * block_type::size);
251 assert(cache_offset > 0);
254 if (
UNLIKELY(cache_offset == 1 && bids.size() >= blocks_per_page))
261 typename std::vector<bid_type>::const_iterator cur_bid = bids.end();
262 for (
int i = blocks_per_page - 1; i >= 0; --i)
264 requests[i] = (front_page + i)->read(*(--cur_bid));
268 std::swap(front_page, back_page);
270 cache_offset = blocks_per_page * block_type::size;
272 current_element = &((*(back_page + (blocks_per_page - 1)))[block_type::size - 1]);
276 block_manager::get_instance()->delete_blocks(bids.end() - blocks_per_page, bids.end());
277 bids.resize(bids.size() - blocks_per_page);
284 current_element = element((--cache_offset) - 1);
292 if (offset < blocks_per_page * block_type::size)
293 return &((*(back_page + offset / block_type::size))[offset % block_type::size]);
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]);
307 template <
class StackConfig>
318 blocks_per_page = cfg::blocks_per_page,
319 block_size = cfg::block_size
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),
352 bids.reserve(blocks_per_page);
362 std::swap(m_size, obj.
m_size);
365 std::swap(cache, obj.
cache);
369 std::swap(bids, obj.
bids);
381 template <
class stack_type>
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),
392 bids.reserve(blocks_per_page);
394 stack_type stack_copy = stack_;
398 std::vector<value_type> tmp(sz);
400 for (i = 0; i < sz; ++i)
402 tmp[sz - i - 1] = stack_copy.top();
405 for (i = 0; i < sz; ++i)
413 if (requests[0].
get())
414 wait_all(requests.begin(), blocks_per_page);
418 block_manager::get_instance()->delete_blocks(bids.begin(), bids.end());
447 return (*current_element);
455 return (*current_element);
462 assert(cache_offset <= blocks_per_page * block_type::size);
465 if (
UNLIKELY(cache_offset == blocks_per_page * block_type::size))
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());
473 for (
int i = 0; i < blocks_per_page; ++i, ++cur_bid)
475 if (requests[i].
get())
478 requests[i] = (cache_buffers + i)->write(*cur_bid);
481 std::swap(cache_buffers, overlap_buffers);
483 bids.reserve(bids.size() + blocks_per_page);
486 current_element = &((*cache_buffers)[0]);
489 *current_element = val;
494 current_element = &((*(cache_buffers + cache_offset / block_type::size))[cache_offset % block_type::size]);
495 *current_element = val;
504 assert(cache_offset <= blocks_per_page * block_type::size);
505 assert(cache_offset > 0);
508 if (
UNLIKELY(cache_offset == 1 && bids.size() >= blocks_per_page))
512 if (requests[0].
get())
513 wait_all(requests.begin(), blocks_per_page);
516 std::swap(cache_buffers, overlap_buffers);
518 if (bids.size() > blocks_per_page)
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));
526 block_manager::get_instance()->delete_blocks(bids.end() - blocks_per_page, bids.end());
527 bids.resize(bids.size() - blocks_per_page);
529 cache_offset = blocks_per_page * block_type::size;
531 current_element = &((*(cache_buffers + (blocks_per_page - 1)))[block_type::size - 1]);
538 current_element = &((*(cache_buffers + cur_offset / block_type::size))[cur_offset % block_type::size]);
546 template <
class StackConfig>
557 blocks_per_page = cfg::blocks_per_page,
558 block_size = cfg::block_size
591 pref_aggr(prefetch_aggressiveness),
615 pref_aggr(prefetch_aggressiveness),
616 owned_pool(new
pool_type(p_pool_, w_pool_)),
629 std::swap(m_size, obj.
m_size);
631 std::swap(cache, obj.
cache);
632 std::swap(bids, obj.
bids);
636 std::swap(pool, obj.
pool);
649 const int_type bids_size = bids.size();
652 for (i = bids_size - 1; i >= last_pref; --i)
655 pool->invalidate(bids[i]);
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)
673 block_manager::get_instance()->delete_blocks(bids.begin(), bids.end());
703 assert(cache_offset <= block_type::size);
705 if (
UNLIKELY(cache_offset == block_type::size))
707 STXXL_VERBOSE2(
"grow_shrink_stack2::push(" << val <<
") growing, size: " << m_size);
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();
716 for (
int_type i = bids_size - 2; i >= last_pref; --i)
719 pool->invalidate(bids[i]);
723 (*cache)[cache_offset] = val;
727 assert(cache_offset > 0);
728 assert(cache_offset <= block_type::size);
736 assert(cache_offset > 0);
737 assert(cache_offset <= block_type::size);
738 return (*cache)[cache_offset - 1];
746 assert(cache_offset > 0);
747 assert(cache_offset <= block_type::size);
748 return (*cache)[cache_offset - 1];
757 assert(cache_offset > 0);
758 assert(cache_offset <= block_type::size);
759 if (
UNLIKELY(cache_offset == 1 && (!bids.empty())))
761 STXXL_VERBOSE2(
"grow_shrink_stack2::pop() shrinking, size = " << m_size);
765 pool->read(cache, last_block)->wait();
766 block_manager::get_instance()->delete_block(last_block);
768 cache_offset = block_type::size + 1;
785 if (pref_aggr > new_p)
787 const int_type bids_size = bids.size();
789 for (
int_type i = bids_size - new_p - 1; i >= last_pref; --i)
792 pool->invalidate(bids[i]);
811 const int_type bids_size = bids.size();
813 for (
int_type i = bids_size - 1; i >= last_pref; --i)
824 template <
unsigned_type CritSize,
class ExternalStack,
class InternalStack>
828 typedef typename ExternalStack::cfg
cfg;
834 blocks_per_page = cfg::blocks_per_page,
835 block_size = cfg::block_size
842 enum { critical_size = CritSize };
849 template <
class stack_type>
884 bool internal()
const
886 assert((int_impl && !ext_impl) || (!int_impl && ext_impl));
887 return (int_impl != NULL);
892 assert((int_impl && !ext_impl) || (!int_impl && ext_impl));
893 return (ext_impl != NULL);
904 assert((int_impl && !ext_impl) || (!int_impl && ext_impl));
905 return (int_impl) ? int_impl->empty() : ext_impl->empty();
910 assert((int_impl && !ext_impl) || (!int_impl && ext_impl));
911 return (int_impl) ?
size_type(int_impl->size()) : ext_impl->size();
923 assert((int_impl && !ext_impl) || (!int_impl && ext_impl));
924 return (int_impl) ? int_impl->top() : ext_impl->top();
931 assert((int_impl && !ext_impl) || (!int_impl && ext_impl));
932 return (int_impl) ? int_impl->top() : ext_impl->top();
939 assert((int_impl && !ext_impl) || (!int_impl && ext_impl));
944 if (
UNLIKELY(int_impl->size() == critical_size))
960 assert((int_impl && !ext_impl) || (!int_impl && ext_impl));
1012 unsigned BlocksPerPage = 4,
1015 class IntStackType = std::stack<ValueType>,
1043 template <
class StackConfig>
1050 template <
class StackConfig>
1057 template <
class StackConfig>
1064 template <stxxl::
unsigned_type CritSize,
class ExternalStack,
class InternalStack>
1073 #endif // !STXXL_CONTAINERS_STACK_HEADER
cfg::size_type size_type
type for sizes (64-bit)
simple_vector< block_type >::iterator front_page
void swap(normal_stack &obj)
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'es and pop's. For semantics of the methods see documentation of the STL std::stack. To gain full bandwidth of disks StackConfig::BlocksPerPage must >= number of disks
#define STXXL_DEFAULT_BLOCK_SIZE(type)
value_type * current_element
std::vector< bid_type > bids
simple_vector< block_type > cache
A stack that migrates from internal memory to external when its size exceeds a certain threshold...
virtual ~migrating_stack()
cfg::size_type size_type
type for sizes (64-bit)
simple_vector< block_type >::iterator cache_buffers
void push(const value_type &val)
Inserts an element at the top of the stack. Postconditions: size() is incremented by 1...
value_type & top()
Return mutable reference to the element at the top of the stack. Precondition: stack is not empty()...
IF< Externality==migrating, migrating_stack< MigrCritSize, ExtStackType, IntStackType >, ExtStackType >::result MigrOrNotStackType
stack_config_generator< ValueType, BlocksPerPage, BlockSize, AllocStr, SizeType > cfg
cfg::alloc_strategy alloc_strategy_type
IF< Behaviour==grow_shrink, grow_shrink_stack< cfg >, grow_shrink_stack2< cfg > >::result GrShrTp
BID< block_size > bid_type
bool external() const
Returns true if current implementation is external, otherwise false.
size_type size() const
Returns the number of elements contained in the stack.
alloc_strategy_type alloc_strategy
value_type * element(unsigned_type offset)
BID< block_size > bid_type
virtual ~grow_shrink_stack2()
void push(const value_type &val)
Inserts an element at the top of the stack. Postconditions: size() is incremented by 1...
value_type & top()
Return mutable reference to the element at the top of the stack. Precondition: stack is not empty()...
grow_shrink_stack(const stack_type &stack_)
Copy-construction from a another stack of any type.
cfg::alloc_strategy alloc_strategy_type
#define STXXL_DEFAULT_ALLOC_STRATEGY
size_type size() const
Returns the number of elements contained in the stack.
size_type size() const
Returns the number of elements contained in the stack.
migrating_stack()
Default constructor: creates empty stack.
#define STXXL_VERBOSE2(x)
cfg::value_type value_type
type of the elements stored in the stack
cfg::alloc_strategy alloc_strategy_type
#define STXXL_DEPRECATED(x)
typed_block< block_size, value_type > block_type
type of block used in disk-memory transfers
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
void set_prefetch_aggr(unsigned_type new_p)
Sets level of prefetch aggressiveness (number of blocks from the prefetch pool used for prefetching)...
ext_stack_type * ext_impl
const value_type & top() const
Return constant reference to the element at the top of the stack. Precondition: stack is not empty()...
void pop()
Removes the element at the top of the stack. Precondition: stack is not empty(). Postcondition: size(...
IF< Externality==internal, IntStackType, MigrOrNotStackType >::result result
typed_block< block_size, value_type > block_type
type of block used in disk-memory transfers
Implements dynamically resizable buffered writing pool.
simple_vector< block_type > cache
simple_vector< block_type >::iterator back_page
const value_type & top() const
Return constant reference to the element at the top of the stack. Precondition: stack is not empty()...
Implements dynamically resizable prefetching pool.
Block containing elements of fixed length.
int_stack_type * int_impl
value_type * current_element
std::vector< bid_type > bids
#define STXXL_VERBOSE3(x)
bool empty() const
Returns true if the stack is empty.
Implements dynamically resizable buffered writing and prefetched reading pool.
const Tp & STXXL_MAX(const Tp &a, const Tp &b)
choose_int_types< my_pointer_size >::int_type int_type
void swap(grow_shrink_stack2 &obj)
iterator begin()
return mutable iterator to first element
void swap(grow_shrink_stack &obj)
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 ...
std::vector< bid_type > bids
virtual ~grow_shrink_stack()
bool empty() const
Returns true if the stack is empty.
#define STXXL_BEGIN_NAMESPACE
void push(const value_type &val)
Inserts an element at the top of the stack. Postconditions: size() is incremented by 1...
read_write_pool< block_type > pool_type
void rehint()
hint the last pref_aggr external blocks.
unsigned_type get_prefetch_aggr() const
Returns number of blocks used for prefetching.
cfg::value_type value_type
type of the elements stored in the stack
void pop()
Removes the element at the top of the stack. Precondition: stack is not empty(). Postcondition: size(...
const value_type & top() const
Return constant reference to the element at the top of the stack. Precondition: stack is not empty()...
bool empty() const
Returns true if the stack is empty.
cfg::size_type size_type
type for sizes (64-bit)
const value_type & top() const
Return constant reference to the element at the top of the stack. Precondition: stack is not empty()...
normal_stack()
Default constructor: creates empty stack.
bool empty() const
Returns true if the stack is empty.
Efficient implementation that uses prefetching and overlapping using (shared) buffers pools...
size_type size() const
Returns the number of elements contained in the stack.
Simpler non-growing vector without initialization.
unsigned_type cache_offset
BID< block_size > bid_type
alloc_strategy_type alloc_strategy
simple_vector< request_ptr > requests
choose_int_types< my_pointer_size >::unsigned_type unsigned_type
value_type & top()
Return mutable reference to the element at the top of the stack. Precondition: stack is not empty()...
value_type & top()
Return mutable reference to the element at the top of the stack. Precondition: stack is not empty()...
unsigned_type cache_offset
InternalStack int_stack_type
Stack type generator Introduction to stack container: see STXXL Stack tutorial. Design and Internals of stack container: see Stack.
void swap(migrating_stack &obj)
IF template metaprogramming statement.
void pop()
Removes the element at the top of the stack. Precondition: stack is not empty(). Postcondition: size(...
Efficient implementation that uses prefetching and overlapping using internal buffers.
cfg::size_type size_type
type for sizes (64-bit)
ExternalStack ext_stack_type
cfg::value_type value_type
type of the elements stored in the stack
cfg::value_type value_type
type of the elements stored in the stack
normal_stack(const stack_type &stack_)
Copy-construction from a another stack of any type.
simple_vector< block_type >::iterator overlap_buffers
void push(const value_type &val)
Inserts an element at the top of the stack. Postconditions: size() is incremented by 1...
typed_block< block_size, value_type > block_type
type of block used in disk-memory transfers
grow_shrink_stack()
Default constructor: creates empty stack.
#define STXXL_PRETTY_FUNCTION_NAME
void pop()
Removes the element at the top of the stack. Precondition: stack is not empty(). Postcondition: size(...
#define STXXL_END_NAMESPACE
unsigned_type cache_offset
IF< Behaviour==normal, normal_stack< cfg >, GrShrTp >::result ExtStackType