1 #ifndef GENESIS_UTILS_CONTAINERS_LAMBDA_ITERATOR_H_
2 #define GENESIS_UTILS_CONTAINERS_LAMBDA_ITERATOR_H_
149 template<
class T,
class D = EmptyLambdaIteratorData>
220 : generator_( generator )
221 , current_block_( std::make_shared<std::vector<T>>() )
222 , buffer_block_( std::make_shared<std::vector<T>>() )
223 , thread_pool_( std::make_shared<utils::
ThreadPool>( 1 ))
224 , future_( std::make_shared<std::future<size_t>>() )
234 if( ! generator_->get_element_ ) {
235 throw std::invalid_argument(
236 "Cannot use LambdaIterator without a function to get elements."
264 assert( current_block_ );
265 assert( current_pos_ < end_pos_ );
266 assert( current_pos_ < current_block_->size() );
267 return &((*current_block_)[current_pos_]);
272 assert( current_block_ );
273 assert( current_pos_ < end_pos_ );
274 assert( current_pos_ < current_block_->size() );
275 return &((*current_block_)[current_pos_]);
280 assert( current_block_ );
281 assert( current_pos_ < end_pos_ );
282 assert( current_pos_ < current_block_->size() );
283 return (*current_block_)[current_pos_];
288 assert( current_block_ );
289 assert( current_pos_ < end_pos_ );
290 assert( current_pos_ < current_block_->size() );
291 return (*current_block_)[current_pos_];
300 throw std::runtime_error(
301 "Cannot access default constructed or past-the-end LambdaIterator content."
304 assert( generator_ );
305 return generator_->data_;
346 operator bool()
const
350 return generator_ !=
nullptr;
369 if( ! generator_ || ! other.generator_ ) {
372 return generator_ == other.generator_;
374 assert( generator_ && other.generator_ );
375 return current_block_ == other.current_block_ && current_pos_ == other.current_pos_;
380 return !(*
this == other);
392 assert( generator_ );
393 assert( current_block_ );
394 assert( buffer_block_ );
398 if( generator_->block_size_ == 0 ) {
400 current_block_->resize( 1 );
408 current_block_->resize( generator_->block_size_ );
409 buffer_block_->resize( generator_->block_size_ );
410 assert( current_block_->size() == generator_->block_size_ );
411 assert( buffer_block_->size() == generator_->block_size_ );
415 end_pos_ = read_block_( generator_, current_block_, generator_->block_size_ );
416 assert( current_pos_ == 0 );
420 if( end_pos_ < generator_->block_size_ ) {
423 if( end_pos_ == 0 ) {
424 generator_ =
nullptr;
431 assert( end_pos_ == generator_->block_size_ );
432 fill_buffer_block_();
438 assert( generator_ );
439 assert( current_block_ && current_block_->size() > 0 );
443 current_block_->size() == generator_->block_size_ ||
445 generator_->block_size_ == 0 &&
446 current_block_->size() == 1
449 assert( buffer_block_->size() == generator_->block_size_ );
453 if( generator_->block_size_ == 0 ) {
454 assert( current_block_->size() == 1 );
455 if( ! get_next_element_( generator_, (*current_block_)[0] )) {
456 generator_ =
nullptr;
467 assert( current_pos_ <= end_pos_ );
471 if( current_pos_ == end_pos_ ) {
475 if( end_pos_ < generator_->block_size_ ) {
476 generator_ =
nullptr;
483 assert( end_pos_ == generator_->block_size_ );
485 assert( future_->valid() );
492 end_pos_ = future_->get();
493 if( end_pos_ == 0 ) {
494 generator_ =
nullptr;
501 assert( end_pos_ > 0 && end_pos_ <= generator_->block_size_ );
502 std::swap( buffer_block_, current_block_ );
503 fill_buffer_block_();
508 void fill_buffer_block_()
511 assert( generator_ );
512 assert( thread_pool_ );
517 assert( thread_pool_->load() == 0 );
518 assert( ! future_->valid() );
522 current_block_->size() == generator_->block_size_ ||
524 generator_->block_size_ == 0 &&
525 current_block_->size() == 1
528 assert( buffer_block_->size() == generator_->block_size_ );
533 auto generator = generator_;
534 auto buffer_block = buffer_block_;
539 *future_ = thread_pool_->enqueue(
541 return read_block_( generator, buffer_block,
block_size );
549 static size_t read_block_(
551 std::shared_ptr<std::vector<T>> buffer_block,
570 if( ! get_next_element_( generator, (*buffer_block)[i] )) {
584 static bool get_next_element_(
589 bool usable_element =
false;
592 bool const got_element = generator->get_element_( target );
599 usable_element =
true;
600 for(
auto const& tra_fil : generator->transforms_and_filters_ ) {
601 usable_element = tra_fil( target );
602 if( ! usable_element ) {
611 if( usable_element ) {
614 assert( got_element );
622 assert( ! got_element );
623 usable_element =
false;
627 return usable_element;
636 std::shared_ptr<std::vector<T>> current_block_;
637 std::shared_ptr<std::vector<T>> buffer_block_;
638 size_t current_pos_ = 0;
644 std::shared_ptr<utils::ThreadPool> thread_pool_;
645 std::shared_ptr<std::future<size_t>> future_;
670 : get_element_(get_element)
686 : get_element_(get_element)
701 : get_element_(get_element)
702 , data_( std::move(
data ))
734 operator bool()
const
736 return static_cast<bool>( get_element_ );
769 transforms_and_filters_.push_back(
770 [transform]( T& element ){
771 transform( element );
787 transforms_and_filters_.push_back(
788 [filter]( T& element ){
789 return filter( element );
807 transforms_and_filters_.push_back(
808 [filter]( T& element ){
809 return filter( element );
820 transforms_and_filters_.clear();
858 std::vector<std::function<bool(T&)>> transforms_and_filters_;
861 std::function<bool(
value_type& )> get_element_;
872 #endif // include guard