void close(const F& f) {
   clear_cached_elements(f);
   if (fetch_new_data(nullptr)) {
     clear_cached_elements(f);
   }
   cache_.clear(f);
 }
 pointer take_head() {
     if (m_head != nullptr || fetch_new_data()) {
         auto result = m_head;
         m_head = m_head->next;
         return result;
     }
     return nullptr;
 }
 pointer take_head() {
   if (head_ != nullptr || fetch_new_data()) {
     auto result = head_;
     head_ = head_->next;
     return result;
   }
   return nullptr;
 }
 size_t count(size_t max_count = std::numeric_limits<size_t>::max()) {
   size_t res = cache_.count(max_count);
   if (res >= max_count) {
     return res;
   }
   fetch_new_data();
   auto ptr = head_;
   while (ptr && res < max_count) {
     ptr = ptr->next;
     ++res;
   }
   return res;
 }
 void remove_if(UnaryPredicate f) {
     pointer head = m_head;
     pointer last = nullptr;
     pointer p = m_head;
     auto loop = [&]() -> bool {
         while (p) {
             if (f(*p)) {
                 if (last == nullptr) m_head = p->next;
                 else last = p->next;
                 m_delete(p);
                 return true;
             }
             else {
                 last = p;
                 p = p->next;
             }
         }
         return false;
     };
     if (!loop()) {
         // last points to the tail now
         auto old_tail = last;
         m_head = nullptr; // fetch_new_data assumes cached list to be empty
         if (fetch_new_data()) {
             last = nullptr;
             p = m_head; // let p point to the first newly fetched element
             loop();
             // restore cached list
             if (head) {
                 old_tail->next = m_head;
                 m_head = head;
             }
         }
         else m_head = head;
     }
 }
 inline bool fetch_new_data() {
     return fetch_new_data(stack_empty_dummy());
 }
 inline void clear() {
     if (!closed()) {
         clear_cached_elements();
         if (fetch_new_data()) clear_cached_elements();
     }
 }
 // closes this queue deletes all remaining elements
 inline void close() {
     clear_cached_elements();
     if (fetch_new_data(nullptr)) clear_cached_elements();
 }