14 #include <initializer_list>
24 #ifndef _PASL_DATA_CHUNKEDBAG_H_
25 #define _PASL_DATA_CHUNKEDBAG_H_
46 class Iterator=iterator::random_access
130 template <
class Pred>
134 return src.split(chunk_meas, p, chunk_search, middle_meas, prefix, x, dst);
148 middle->push_back(middle_meas, d);
154 if (back_outer.empty()) {
155 if (! back_inner.empty()) {
156 back_inner.swap(back_outer);
157 }
else if (! middle->empty()) {
163 assert(! back_outer.empty() || (back_inner.empty() && middle->empty()) );
169 size_t bisize = back_inner.size();
170 size_t bosize = back_outer.size();
171 if (bisize + bosize <= chunk_capacity)
172 back_inner.transfer_from_front_to_back(chunk_meas, back_outer, bisize);
174 back_outer.transfer_from_front_to_back(chunk_meas, back_inner, chunk_capacity - bisize);
179 if (! back_inner.empty()) {
182 middle->push_back(middle_meas, d);
189 if (! back_outer.empty())
191 if (! back_inner.empty())
193 if (! middle->empty())
194 return middle->cback();
205 template <
class Pred>
208 if (! middle->empty()) {
210 cur = middle_algebra_type::combine(cur, middle->get_cached());
216 if (! back_inner.empty()) {
218 cur = middle_algebra_type::combine(cur,
middle_meas(&back_inner));
220 pos = found_back_inner;
224 if (! back_outer.empty()) {
226 cur = middle_algebra_type::combine(cur,
middle_meas(&back_outer));
228 pos = found_back_outer;
240 template <
class Pred>
244 prefix =
search(p, prefix, pos);
248 #ifdef DEBUG_MIDDLE_SEQUENCE
251 prefix = middle->search_for_chunk(p, prefix, cur);
255 case found_back_inner: {
259 case found_back_outer: {
263 case found_nowhere: {
273 template <
class Pred>
275 assert(other.
empty());
279 prefix =
search(p, prefix, pos);
284 prefix = middle->split(middle_meas, p, prefix, c, *other.
middle);
291 case found_back_inner: {
295 case found_back_outer: {
299 case found_nowhere: {
310 template <
class Pred>
315 if (size_access::csize(prefix) < sz_orig)
336 : chunk_meas(meas), middle_meas(meas) {
341 : back_inner(other.back_inner),
342 back_outer(other.back_outer),
343 chunk_meas(other.chunk_meas),
344 middle_meas(other.middle_meas) {
351 for (
auto it = l.begin(); it != l.end(); it++)
363 return back_outer.empty();
368 sz += size_access::csize(middle->get_cached());
369 sz += back_inner.size();
370 sz += back_outer.size();
382 return back_outer.back();
401 template <
class Consumer>
406 template <
class Consumer>
414 auto it =
begin() + n;
415 assert(it.size() == n + 1);
427 if (back_outer.full()) {
428 if (back_inner.full())
430 back_outer.swap(back_inner);
431 assert(back_outer.empty());
433 back_outer.push_back(chunk_meas, x);
446 back_outer.pop_back(chunk_meas);
473 stream_popn_front<typeof(c), false>(c, nb);
482 stream_popn_back<typeof(c), false>(c, nb);
497 template <
class Producer>
509 m = std::min(m, cap - c.size());
510 std::pair<const_pointer,const_pointer> rng = prod(i, m);
514 c.pushn_back(chunk_meas, lo, nb);
519 assert(sz_orig + nb ==
size());
522 template <
class Producer>
527 template <
class Producer>
532 template <
class Consumer,
bool should_consume=true>
535 assert(sz_orig >= nb);
539 size_type m = std::min(back_outer.size(), nb - i);
540 back_outer.template popn_back<Consumer,should_consume>(
chunk_meas, cons, m);
544 assert(sz_orig ==
size() + nb);
547 template <
class Consumer,
bool should_consume=true>
552 template <
class Consumer,
bool should_consume=true>
559 if (other.
size() == 0)
570 middle->concat(middle_meas, *other.
middle);
571 assert(other.
empty());
575 template <
class Pred>
579 return p(size_access::cclient(m));
582 bool found = (size_access::csize(prefix) < sz_orig);
587 template <
class Pred>
590 bool found =
split(p, middle_item, other);
592 other.
push(middle_item);
633 middle.swap(other.
middle);
648 return iterator(
this, middle_meas, chunkedseq::iterator::begin);
652 return iterator(
this, middle_meas, chunkedseq::iterator::end);
655 template <
class Body>
660 back_inner.for_each(f);
661 back_outer.for_each(f);
664 template <
class Body>
669 template <
class Body>
672 p->for_each_segment(f);
674 back_inner.for_each_segment(f);
675 back_outer.for_each_segment(f);
678 template <
class Body>
692 measured_type n = size_access::cclient(middle->get_cached());
693 m = algebra_type::combine(m, n);
694 m = algebra_type::combine(m, back_inner.get_cached());
695 m = algebra_type::combine(m, back_outer.get_cached());
705 middle_meas.set_client_measure(meas);
720 template <
class ItemPr
inter>
724 ItemPrinter::print(x);
733 template <
class ItemPr
inter,
class CachePr
inter = DummyCachePr
inter>
736 print_chunk<ItemPrinter>(c); };
754 assert(size_access::csize(middle->get_cached()) == sz);
766 if (! back_inner.empty())
767 assert(back_inner.full());
768 if (back_outer.empty()) {
769 assert(back_inner.empty());
770 assert(middle->empty());
774 size_t scur = c->size();
776 assert(sprev + scur >= chunk_capacity);
794 int Chunk_capacity=512,
804 int ___Chunk_capacity,
805 class ___Cached_measure,
806 class Top_item_deleter,
807 class Top_item_copier,
813 class ___Chunk_struct,
817 class Item_alloc=std::allocator<Item>
831 using item_queue_type = Chunk_struct<value_type, Chunk_capacity, item_allocator_type>;
838 #ifdef DISABLE_RANDOM_ACCESS_ITERATOR
843 #ifndef ENABLE_FINGER_SEARCH
879 : client_meas(client_meas) { }
884 m.value2 = client_meas(v);
890 for (
auto p = lo; p < hi; p++)
897 m.value1 = p->
size();
904 for (
auto p = lo; p < hi; p++)
914 this->client_meas = client_meas;
920 std::swap(x.value1, y.value1);
921 std::swap(x.value2, y.value2);
948 #ifdef DEBUG_MIDDLE_SEQUENCE
950 static constexpr
int middle_capacity = 1<<23;
968 namespace bootstrapped {
972 template <
class Item,
973 int Chunk_capacity = 512,
975 class Item_alloc = std::allocator<Item>>
987 int Chunk_capacity = 512,
989 class Item_alloc = std::allocator<Item>>
measured_type operator()(const value_type *lo, const value_type *hi) const
static void chunk_free(chunk_pointer c)
void push_front(const value_type &x)
middle_measured_type search(const Pred &p, middle_measured_type prefix, position_type &pos) const
void ensure_empty_back_inner()
typename Client_cache::algebra_type client_algebra_type
typename algebra_type::value_type measured_type
typename middle_algebra_type::value_type middle_measured_type
void frontn(value_type *dst, size_type nb) const
void stream_backn(const Consumer &cons, size_type nb) const
static constexpr int middle_chunk_capacity
typename middle_cache_type::algebra_type middle_algebra_type
void set_client_measure(client_measure_type client_meas)
typename config_type::segment_type segment_type
typename Configuration::middle_cache_type middle_cache_type
static value_type identity()
static void swap(measured_type &x, measured_type &y)
void restore_back_inner_full_or_empty()
Item_alloc item_allocator_type
typename chunk_cache_type::algebra_type chunk_algebra_type
Fixed-capacity ring buffer.
base::ringbuffer_ptr< base::heap_allocator< Item, Capacity+1 >> ringbuffer_ptr
void popn_front(size_type nb)
void stream_popn_back(const Consumer &cons, size_type nb)
void stream_pushn_front(const Producer &prod, size_type nb)
static constexpr size_type chunk_capacity
value_type operator[](size_type n) const
const_chunk_pointer get_chunk_containing_last_item() const
bootchunkseq< bootchunkseq_deque_config< Item, cachedmeasure::trivial< Item, size_t >, Capacity >> cdeque
typename middle_cache_type::measured_type middle_measured_type
typename config_type::item_allocator_type allocator_type
typename Configuration::size_access size_access
chunkedbagbase(const self_type &other)
iterator insert(iterator position, const value_type &val)
bool is_buffer(const chunk_type *c) const
static constexpr int chunk_capacity
static client_measured_type cclient(middle_measured_type m)
const chunk_type * const_chunk_pointer
void popn_back(value_type *dst, size_type nb)
Fixed-capacity array along with cached measurement of array contents.
middle_measured_type split_aux(const Pred &p, middle_measured_type prefix, reference x, self_type &other)
static value_type combine(value_type x, value_type y)
void stream_popn_front(const Consumer &cons, size_type nb)
typename chunk_cache_type::measured_type chunk_measured_type
void split_approximate(self_type &other)
typename Configuration::chunk_cache_type chunk_cache_type
void push(const value_type &x)
chunkedbagbase(std::initializer_list< value_type > l)
enum{found_back_outer, found_back_inner, found_middle, found_nowhere} position_type
typename config_type::difference_type difference_type
void push_back(const value_type &x)
Representation of a chunk.
middle_measured_type split_aux(const Pred &p, middle_measured_type prefix, self_type &other)
void copy_measure_to(self_type &other)
void swap(self_type &other)
chunkedbagbase(const measure_type &meas)
typename config_type::value_type value_type
chunk_measured_type client_measured_type
chunk< item_queue_type, chunk_cache_type, annotation_type > chunk_type
algebra::combiner< size_algebra_type, client_algebra_type > middle_algebra_type
Hinze & Patterson's 2-3 finger tree.
measured_type operator()(const client_value_type &v) const
typename Client_cache::size_type size_type
void stream_frontn(const Consumer &cons, size_type nb) const
typename Client_cache::measure_type client_measure_type
void popn_back(size_type nb)
void for_each_segment(const Body &f) const
measured_type operator()(value_type p) const
static chunk_pointer chunk_alloc()
static size_type csize(middle_measured_type m)
void push_buffer_back(chunk_type &c)
chunk_type * chunk_pointer
void print_chunk(const chunk_type &c) const
[int_group_under_addition_and_negation]
chunkedbagbase< config_type > self_type
Definitions of a few cached-measurement policies.
measure::measured_pair< value1_type, value2_type > value_type
typename middle_cache_type::measure_type middle_measure_type
typename queue_type::value_type value_type
typename Client_cache::size_type size_type
Client_cache chunk_cache_type
typename Configuration::chunk_type chunk_type
const value_type & const_reference
chunk_cache_type cache_type
void pushn_back(const_pointer src, size_type nb)
typename chunk_cache_type::measure_type chunk_measure_type
void popn_front(value_type *dst, size_type nb)
void split(const Pred &p, self_type &other)
measured_type operator()(const client_value_type *lo, const client_value_type *hi) const
void stream_popn(const Consumer &cons, size_type nb)
Iterator< self_type, config_type > iterator
void for_each(iterator beg, iterator end, const Body &f) const
typename Configuration::middle_type middle_type
void pushn_front(const_pointer src, size_type nb)
const value_type * const_pointer
void split(size_type i, self_type &other)
middle_measured_type chunk_split(const Pred &p, middle_measured_type prefix, chunk_type &src, value_type &x, chunk_type &dst)
middle_measured_type search_for_chunk(const Pred &p, middle_measured_type prefix, bool &found, const_chunk_pointer &cur) const
void split(iterator position, self_type &other)
Configuration config_type
typename chunk_cache_type::measured_type chunk_measured_type
typename config_type::size_type size_type
measured_type get_cached() const
chunk_measure_type chunk_meas
void restore_back_outer_empty_iff_all_empty()
middle_measure_type middle_meas
typename middle_cache_type::measure_type middle_measure_type
void stream_pushn(const Producer &prod, size_type nb)
client_measure_type get_client_measure() const
measure_type get_measure() const
void concat(self_type &other)
bool split(const Pred &p, reference middle_item, self_type &other)
static client_measured_type & client(middle_measured_type &m)
measured_type get_cached() const
void pushn(const_pointer src, size_type nb)
typename cache_type::measured_type measured_type
void backn(value_type *dst, size_type nb) const
typename cache_type::algebra_type algebra_type
Middle_sequence< chunk_type, middle_chunk_capacity, middle_cache_type, Pointer_deleter, Pointer_deep_copier, fixedcapacity::heap_allocated::ringbuffer_ptr, size_access > middle_type
typename cache_type::measure_type measure_type
STL style iterators for our chunked sequences.
static constexpr bool enable_index_optimization
Representation of a chunk.
typename chunk_type::value_type client_value_type
const int chunk_capacity
[weighted_split_example]
void stream_pushn_back(const Producer &prod, size_type nb)
typename Configuration::chunk_search_type chunk_search_type
void popn(value_type *dst, size_type nb)
Chunk_struct< value_type, Chunk_capacity, item_allocator_type > item_queue_type
void for_each(const Body &f) const
ptrdiff_t difference_type
void set_measure(measure_type meas)
static size_type & size(middle_measured_type &m)
measure_type(const client_measure_type &client_meas)
std::unique_ptr< middle_type > middle
void for_each_segment(iterator begin, iterator end, const Body &f) const