Files
scylladb/utils/sequential_producer.hh
Avi Kivity 0ae22a09d4 LICENSE: Update to version 1.1
Updated terms of non-commercial use (must be a never-customer).
2026-04-12 19:46:33 +03:00

55 lines
1.4 KiB
C++

/*
* Copyright (C) 2021 ScyllaDB
*/
/*
* SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.1
*/
#pragma once
#include <functional>
#include <seastar/core/shared_future.hh>
#include <stdexcept>
/// Invokes a factory to produce an object, but sequentially: only one fiber at a time may be executing the
/// factory. Any other fiber requesting the object will wait for the existing factory invocation to finish, then
/// copy the result.
///
/// TODO: Move to Seastar.
template<typename T>
class sequential_producer {
public:
using factory_t = std::function<seastar::future<T>()>;
using time_point = seastar::shared_future<T>::time_point;
private:
factory_t _factory;
seastar::shared_future<T> _churning; ///< Resolves when the previous _factory call completes.
public:
sequential_producer(factory_t&& f) : _factory(std::move(f))
{
clear();
}
seastar::future<T> operator()(time_point timeout = time_point::max()) {
if (_churning.available()) {
_churning = _factory();
}
return _churning.get_future(timeout);
}
seastar::future<T> operator()(seastar::abort_source& as) {
if (_churning.available()) {
_churning = _factory();
}
return _churning.get_future(as);
}
void clear() {
_churning = seastar::make_exception_future<T>(
std::logic_error("initial future used in sequential_producer"));
}
};