/************************************************************************
* EOS - the CERN Disk Storage System *
* Copyright (C) 2019 CERN/Switzerland *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see .*
************************************************************************/
//------------------------------------------------------------------------------
//! @author Georgios Bitzes
//! @brief Helper class to consume a future vector of futures,
//! and make iteration sane
//------------------------------------------------------------------------------
#pragma once
#include "namespace/Namespace.hh"
#include
#include
EOSNSNAMESPACE_BEGIN
template
class FutureVectorIterator {
private:
using FutureT = folly::Future;
using VectorT = std::vector;
using FutureVectorT = folly::Future;
public:
//----------------------------------------------------------------------------
//! Construtor, consumes future vector of futures
//----------------------------------------------------------------------------
FutureVectorIterator(folly::Future>> &&vec)
: mainFuture(std::move(vec)), futureVectorPopulated(false) { }
//----------------------------------------------------------------------------
//! Construtor, consumes concrete vector of futures
//----------------------------------------------------------------------------
FutureVectorIterator(std::vector> &&vec)
: mainFuture(folly::makeFuture(VectorT())),
futureVectorPopulated(true), futureVector(std::move(vec)) {}
//----------------------------------------------------------------------------
//! Null construtor, everything is ready, and we're already at EOF
//----------------------------------------------------------------------------
FutureVectorIterator()
: FutureVectorIterator(std::vector>()) {}
//----------------------------------------------------------------------------
//! Is the top-level future ready?
//----------------------------------------------------------------------------
bool isMainFutureReady() const {
if(futureVectorPopulated) {
return true;
}
return mainFuture.isReady();
}
//----------------------------------------------------------------------------
//! Get vector size. The function will block if isMainFutureReady is false!
//----------------------------------------------------------------------------
size_t size() {
processMainFuture();
return futureVector.size();
}
//----------------------------------------------------------------------------
//! Is the next element ready to fetch?
//! If we've reached the end, the answer will always be "yes".
//----------------------------------------------------------------------------
bool isReady() {
if(!futureVectorPopulated) {
//------------------------------------------------------------------------
//! Still waiting to process the top-level future?
//------------------------------------------------------------------------
if(!mainFuture.isReady()) {
return false;
}
processMainFuture();
}
//--------------------------------------------------------------------------
//! EOF?
//--------------------------------------------------------------------------
if(futureVectorNext >= futureVector.size()) {
return true;
}
return futureVector[futureVectorNext].isReady();
}
//----------------------------------------------------------------------------
//! Fetch next element.
//! - If we've reached EOF, return false. In this case, "out" is NOT updated.
//! - Else, return true. In this case, out IS updated, and you should call
//!
//! fetchNext will block if isReady is false!
//----------------------------------------------------------------------------
bool fetchNext(T& out) {
processMainFuture();
if(futureVectorNext >= futureVector.size()) {
return false;
}
futureVectorNext++;
out = std::move(futureVector[futureVectorNext-1]).get();
return true;
}
private:
//----------------------------------------------------------------------------
//! Process mainFuture - block if necessary
//----------------------------------------------------------------------------
void processMainFuture() {
if(futureVectorPopulated) {
return;
}
futureVector = std::move(mainFuture).get();
futureVectorPopulated = true;
}
folly::Future>> mainFuture;
bool futureVectorPopulated = false;
std::vector> futureVector;
size_t futureVectorNext = 0;
};
EOSNSNAMESPACE_END