mirror of
https://github.com/XRPLF/clio.git
synced 2026-07-25 16:10:45 +00:00
ci: Use Nix-based images for all workflows except pre-commit (#3098)
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
#include "util/async/AnyStopToken.hpp"
|
||||
#include "util/async/AnyStrand.hpp"
|
||||
#include "util/async/Concepts.hpp"
|
||||
#include "util/async/impl/Any.hpp"
|
||||
#include "util/async/impl/ErasedOperation.hpp"
|
||||
|
||||
#include <any>
|
||||
@@ -68,10 +69,10 @@ public:
|
||||
execute(SomeHandlerWithoutStopToken auto&& fn)
|
||||
{
|
||||
using RetType = std::decay_t<std::invoke_result_t<decltype(fn)>>;
|
||||
static_assert(not std::is_same_v<RetType, std::any>);
|
||||
static_assert(not std::is_same_v<RetType, impl::Any>);
|
||||
|
||||
return AnyOperation<RetType>(
|
||||
pimpl_->execute([fn = std::forward<decltype(fn)>(fn)] mutable -> std::any {
|
||||
pimpl_->execute([fn = std::forward<decltype(fn)>(fn)] mutable -> impl::Any {
|
||||
if constexpr (std::is_void_v<RetType>) {
|
||||
std::invoke(std::forward<decltype(fn)>(fn));
|
||||
return {};
|
||||
@@ -94,10 +95,10 @@ public:
|
||||
execute(SomeHandlerWith<AnyStopToken> auto&& fn)
|
||||
{
|
||||
using RetType = std::decay_t<std::invoke_result_t<decltype(fn), AnyStopToken>>;
|
||||
static_assert(not std::is_same_v<RetType, std::any>);
|
||||
static_assert(not std::is_same_v<RetType, impl::Any>);
|
||||
|
||||
return AnyOperation<RetType>(pimpl_->execute(
|
||||
[fn = std::forward<decltype(fn)>(fn)](auto stopToken) mutable -> std::any {
|
||||
[fn = std::forward<decltype(fn)>(fn)](auto stopToken) mutable -> impl::Any {
|
||||
if constexpr (std::is_void_v<RetType>) {
|
||||
std::invoke(std::forward<decltype(fn)>(fn), std::move(stopToken));
|
||||
return {};
|
||||
@@ -123,10 +124,10 @@ public:
|
||||
execute(SomeHandlerWith<AnyStopToken> auto&& fn, SomeStdDuration auto timeout)
|
||||
{
|
||||
using RetType = std::decay_t<std::invoke_result_t<decltype(fn), AnyStopToken>>;
|
||||
static_assert(not std::is_same_v<RetType, std::any>);
|
||||
static_assert(not std::is_same_v<RetType, impl::Any>);
|
||||
|
||||
return AnyOperation<RetType>(pimpl_->execute(
|
||||
[fn = std::forward<decltype(fn)>(fn)](auto stopToken) mutable -> std::any {
|
||||
[fn = std::forward<decltype(fn)>(fn)](auto stopToken) mutable -> impl::Any {
|
||||
if constexpr (std::is_void_v<RetType>) {
|
||||
std::invoke(std::forward<decltype(fn)>(fn), std::move(stopToken));
|
||||
return {};
|
||||
@@ -153,11 +154,11 @@ public:
|
||||
scheduleAfter(SomeStdDuration auto delay, SomeHandlerWith<AnyStopToken> auto&& fn)
|
||||
{
|
||||
using RetType = std::decay_t<std::invoke_result_t<decltype(fn), AnyStopToken>>;
|
||||
static_assert(not std::is_same_v<RetType, std::any>);
|
||||
static_assert(not std::is_same_v<RetType, impl::Any>);
|
||||
|
||||
auto const millis = std::chrono::duration_cast<std::chrono::milliseconds>(delay);
|
||||
return AnyOperation<RetType>(pimpl_->scheduleAfter(
|
||||
millis, [fn = std::forward<decltype(fn)>(fn)](auto stopToken) mutable -> std::any {
|
||||
millis, [fn = std::forward<decltype(fn)>(fn)](auto stopToken) mutable -> impl::Any {
|
||||
if constexpr (std::is_void_v<RetType>) {
|
||||
std::invoke(std::forward<decltype(fn)>(fn), std::move(stopToken));
|
||||
return {};
|
||||
@@ -184,13 +185,13 @@ public:
|
||||
scheduleAfter(SomeStdDuration auto delay, SomeHandlerWith<AnyStopToken, bool> auto&& fn)
|
||||
{
|
||||
using RetType = std::decay_t<std::invoke_result_t<decltype(fn), AnyStopToken, bool>>;
|
||||
static_assert(not std::is_same_v<RetType, std::any>);
|
||||
static_assert(not std::is_same_v<RetType, impl::Any>);
|
||||
|
||||
auto const millis = std::chrono::duration_cast<std::chrono::milliseconds>(delay);
|
||||
return AnyOperation<RetType>(pimpl_->scheduleAfter(
|
||||
millis,
|
||||
[fn = std::forward<decltype(fn)>(fn)](auto stopToken, auto cancelled) mutable
|
||||
-> std::any {
|
||||
-> impl::Any {
|
||||
if constexpr (std::is_void_v<RetType>) {
|
||||
std::invoke(std::forward<decltype(fn)>(fn), std::move(stopToken), cancelled);
|
||||
return {};
|
||||
@@ -214,12 +215,12 @@ public:
|
||||
executeRepeatedly(SomeStdDuration auto interval, SomeHandlerWithoutStopToken auto&& fn)
|
||||
{
|
||||
using RetType = std::decay_t<std::invoke_result_t<decltype(fn)>>;
|
||||
static_assert(not std::is_same_v<RetType, std::any>);
|
||||
static_assert(not std::is_same_v<RetType, impl::Any>);
|
||||
|
||||
auto const millis = std::chrono::duration_cast<std::chrono::milliseconds>(interval);
|
||||
return AnyOperation<RetType>( //
|
||||
pimpl_->executeRepeatedly(
|
||||
millis, [fn = std::forward<decltype(fn)>(fn)] mutable -> std::any {
|
||||
millis, [fn = std::forward<decltype(fn)>(fn)] mutable -> impl::Any {
|
||||
std::invoke(std::forward<decltype(fn)>(fn));
|
||||
return {};
|
||||
}
|
||||
@@ -277,18 +278,18 @@ private:
|
||||
|
||||
virtual impl::ErasedOperation
|
||||
execute(
|
||||
std::function<std::any(AnyStopToken)>,
|
||||
std::function<impl::Any(AnyStopToken)>,
|
||||
std::optional<std::chrono::milliseconds> timeout = std::nullopt
|
||||
) = 0;
|
||||
virtual impl::ErasedOperation execute(std::function<std::any()>) = 0;
|
||||
virtual impl::ErasedOperation execute(std::function<impl::Any()>) = 0;
|
||||
virtual impl::ErasedOperation
|
||||
scheduleAfter(std::chrono::milliseconds, std::function<std::any(AnyStopToken)>) = 0;
|
||||
scheduleAfter(std::chrono::milliseconds, std::function<impl::Any(AnyStopToken)>) = 0;
|
||||
virtual impl::ErasedOperation scheduleAfter(
|
||||
std::chrono::milliseconds,
|
||||
std::function<std::any(AnyStopToken, bool)>
|
||||
std::function<impl::Any(AnyStopToken, bool)>
|
||||
) = 0;
|
||||
virtual impl::ErasedOperation
|
||||
executeRepeatedly(std::chrono::milliseconds, std::function<std::any()>) = 0;
|
||||
executeRepeatedly(std::chrono::milliseconds, std::function<impl::Any()>) = 0;
|
||||
virtual void submit(std::function<void()>) = 0;
|
||||
virtual AnyStrand
|
||||
makeStrand() = 0;
|
||||
@@ -309,7 +310,7 @@ private:
|
||||
|
||||
impl::ErasedOperation
|
||||
execute(
|
||||
std::function<std::any(AnyStopToken)> fn,
|
||||
std::function<impl::Any(AnyStopToken)> fn,
|
||||
std::optional<std::chrono::milliseconds> timeout
|
||||
) override
|
||||
{
|
||||
@@ -317,7 +318,7 @@ private:
|
||||
}
|
||||
|
||||
impl::ErasedOperation
|
||||
execute(std::function<std::any()> fn) override
|
||||
execute(std::function<impl::Any()> fn) override
|
||||
{
|
||||
return ctx.execute(std::move(fn));
|
||||
}
|
||||
@@ -325,7 +326,7 @@ private:
|
||||
impl::ErasedOperation
|
||||
scheduleAfter(
|
||||
std::chrono::milliseconds delay,
|
||||
std::function<std::any(AnyStopToken)> fn
|
||||
std::function<impl::Any(AnyStopToken)> fn
|
||||
) override
|
||||
{
|
||||
return ctx.scheduleAfter(delay, std::move(fn));
|
||||
@@ -334,14 +335,17 @@ private:
|
||||
impl::ErasedOperation
|
||||
scheduleAfter(
|
||||
std::chrono::milliseconds delay,
|
||||
std::function<std::any(AnyStopToken, bool)> fn
|
||||
std::function<impl::Any(AnyStopToken, bool)> fn
|
||||
) override
|
||||
{
|
||||
return ctx.scheduleAfter(delay, std::move(fn));
|
||||
}
|
||||
|
||||
impl::ErasedOperation
|
||||
executeRepeatedly(std::chrono::milliseconds interval, std::function<std::any()> fn) override
|
||||
executeRepeatedly(
|
||||
std::chrono::milliseconds interval,
|
||||
std::function<impl::Any()> fn
|
||||
) override
|
||||
{
|
||||
return ctx.executeRepeatedly(interval, std::move(fn));
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "util/async/Error.hpp"
|
||||
#include "util/async/impl/Any.hpp"
|
||||
#include "util/async/impl/ErasedOperation.hpp"
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "util/async/AnyOperation.hpp"
|
||||
#include "util/async/AnyStopToken.hpp"
|
||||
#include "util/async/Concepts.hpp"
|
||||
#include "util/async/impl/Any.hpp"
|
||||
#include "util/async/impl/ErasedOperation.hpp"
|
||||
|
||||
#include <any>
|
||||
@@ -46,10 +47,10 @@ public:
|
||||
execute(SomeHandlerWithoutStopToken auto&& fn)
|
||||
{
|
||||
using RetType = std::decay_t<std::invoke_result_t<decltype(fn)>>;
|
||||
static_assert(not std::is_same_v<RetType, std::any>);
|
||||
static_assert(not std::is_same_v<RetType, impl::Any>);
|
||||
|
||||
return AnyOperation<RetType>( //
|
||||
pimpl_->execute([fn = std::forward<decltype(fn)>(fn)] mutable -> std::any {
|
||||
pimpl_->execute([fn = std::forward<decltype(fn)>(fn)] mutable -> impl::Any {
|
||||
if constexpr (std::is_void_v<RetType>) {
|
||||
std::invoke(std::forward<decltype(fn)>(fn));
|
||||
return {};
|
||||
@@ -70,11 +71,11 @@ public:
|
||||
execute(SomeHandlerWith<AnyStopToken> auto&& fn)
|
||||
{
|
||||
using RetType = std::decay_t<std::invoke_result_t<decltype(fn), AnyStopToken>>;
|
||||
static_assert(not std::is_same_v<RetType, std::any>);
|
||||
static_assert(not std::is_same_v<RetType, impl::Any>);
|
||||
|
||||
return AnyOperation<RetType>( //
|
||||
pimpl_->execute(
|
||||
[fn = std::forward<decltype(fn)>(fn)](auto stopToken) mutable -> std::any {
|
||||
[fn = std::forward<decltype(fn)>(fn)](auto stopToken) mutable -> impl::Any {
|
||||
if constexpr (std::is_void_v<RetType>) {
|
||||
std::invoke(std::forward<decltype(fn)>(fn), std::move(stopToken));
|
||||
return {};
|
||||
@@ -99,11 +100,11 @@ public:
|
||||
execute(SomeHandlerWith<AnyStopToken> auto&& fn, SomeStdDuration auto timeout)
|
||||
{
|
||||
using RetType = std::decay_t<std::invoke_result_t<decltype(fn), AnyStopToken>>;
|
||||
static_assert(not std::is_same_v<RetType, std::any>);
|
||||
static_assert(not std::is_same_v<RetType, impl::Any>);
|
||||
|
||||
return AnyOperation<RetType>( //
|
||||
pimpl_->execute(
|
||||
[fn = std::forward<decltype(fn)>(fn)](auto stopToken) mutable -> std::any {
|
||||
[fn = std::forward<decltype(fn)>(fn)](auto stopToken) mutable -> impl::Any {
|
||||
if constexpr (std::is_void_v<RetType>) {
|
||||
std::invoke(std::forward<decltype(fn)>(fn), std::move(stopToken));
|
||||
return {};
|
||||
@@ -129,12 +130,12 @@ public:
|
||||
executeRepeatedly(SomeStdDuration auto interval, SomeHandlerWithoutStopToken auto&& fn)
|
||||
{
|
||||
using RetType = std::decay_t<std::invoke_result_t<decltype(fn)>>;
|
||||
static_assert(not std::is_same_v<RetType, std::any>);
|
||||
static_assert(not std::is_same_v<RetType, impl::Any>);
|
||||
|
||||
auto const millis = std::chrono::duration_cast<std::chrono::milliseconds>(interval);
|
||||
return AnyOperation<RetType>( //
|
||||
pimpl_->executeRepeatedly(
|
||||
millis, [fn = std::forward<decltype(fn)>(fn)] mutable -> std::any {
|
||||
millis, [fn = std::forward<decltype(fn)>(fn)] mutable -> impl::Any {
|
||||
std::invoke(std::forward<decltype(fn)>(fn));
|
||||
return {};
|
||||
}
|
||||
@@ -160,12 +161,12 @@ private:
|
||||
|
||||
[[nodiscard]] virtual impl::ErasedOperation
|
||||
execute(
|
||||
std::function<std::any(AnyStopToken)>,
|
||||
std::function<impl::Any(AnyStopToken)>,
|
||||
std::optional<std::chrono::milliseconds> timeout = std::nullopt
|
||||
) = 0;
|
||||
[[nodiscard]] virtual impl::ErasedOperation execute(std::function<std::any()>) = 0;
|
||||
[[nodiscard]] virtual impl::ErasedOperation execute(std::function<impl::Any()>) = 0;
|
||||
[[nodiscard]] virtual impl::ErasedOperation
|
||||
executeRepeatedly(std::chrono::milliseconds, std::function<std::any()>) = 0;
|
||||
executeRepeatedly(std::chrono::milliseconds, std::function<impl::Any()>) = 0;
|
||||
virtual void submit(std::function<void()>) = 0;
|
||||
};
|
||||
|
||||
@@ -181,7 +182,7 @@ private:
|
||||
|
||||
[[nodiscard]] impl::ErasedOperation
|
||||
execute(
|
||||
std::function<std::any(AnyStopToken)> fn,
|
||||
std::function<impl::Any(AnyStopToken)> fn,
|
||||
std::optional<std::chrono::milliseconds> timeout
|
||||
) override
|
||||
{
|
||||
@@ -189,13 +190,16 @@ private:
|
||||
}
|
||||
|
||||
[[nodiscard]] impl::ErasedOperation
|
||||
execute(std::function<std::any()> fn) override
|
||||
execute(std::function<impl::Any()> fn) override
|
||||
{
|
||||
return strand.execute(std::move(fn));
|
||||
}
|
||||
|
||||
impl::ErasedOperation
|
||||
executeRepeatedly(std::chrono::milliseconds interval, std::function<std::any()> fn) override
|
||||
executeRepeatedly(
|
||||
std::chrono::milliseconds interval,
|
||||
std::function<impl::Any()> fn
|
||||
) override
|
||||
{
|
||||
return strand.executeRepeatedly(interval, std::move(fn));
|
||||
}
|
||||
|
||||
@@ -6,11 +6,6 @@
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
// for the static_assert at the bottom which fixes clang compilation:
|
||||
// see: https://godbolt.org/z/fzTjMd7G1 vs https://godbolt.org/z/jhKG7deen
|
||||
#include <any>
|
||||
#include <expected>
|
||||
|
||||
namespace util::async {
|
||||
|
||||
/**
|
||||
@@ -49,7 +44,4 @@ struct ExecutionError {
|
||||
std::string message;
|
||||
};
|
||||
|
||||
// these are not the droids you are looking for...
|
||||
static_assert(std::is_copy_constructible_v<std::expected<std::any, ExecutionError>>);
|
||||
|
||||
} // namespace util::async
|
||||
|
||||
41
src/util/async/impl/Any.hpp
Normal file
41
src/util/async/impl/Any.hpp
Normal file
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include <any>
|
||||
#include <type_traits>
|
||||
|
||||
namespace util::async::impl {
|
||||
|
||||
/**
|
||||
* @brief A wrapper for std::any used as the type-erased transport for async operation results.
|
||||
*
|
||||
* It exists to work around a recursive-constraint failure in libstdc++'s `<expected>` when the
|
||||
* value type is a raw `std::any`: `std::any`'s greedy templated constructor makes
|
||||
* `std::expected<std::any, E>` ask whether `std::any` is constructible from
|
||||
* `std::expected<std::any, E>`, which re-enters the same constraint. Newer Clang rejects this as
|
||||
* self-referential.
|
||||
*
|
||||
* `Any` only allows construction from `std::any` (never from an `expected`), which breaks the cycle
|
||||
* while still allowing transparent unwrapping back to `std::any&`.
|
||||
*/
|
||||
class Any {
|
||||
std::any value_;
|
||||
|
||||
public:
|
||||
Any() = default;
|
||||
Any(Any const&) = default;
|
||||
|
||||
Any(Any&&) = default;
|
||||
// note: this needs to be `auto` instead of `std::any` because of a bug in gcc 11.4
|
||||
Any(auto&& v)
|
||||
requires(std::is_same_v<std::decay_t<decltype(v)>, std::any>)
|
||||
: value_{std::forward<decltype(v)>(v)}
|
||||
{
|
||||
}
|
||||
|
||||
operator std::any&() noexcept
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace util::async::impl
|
||||
@@ -3,8 +3,8 @@
|
||||
#include "util/Assert.hpp"
|
||||
#include "util/async/Concepts.hpp"
|
||||
#include "util/async/Error.hpp"
|
||||
#include "util/async/impl/Any.hpp"
|
||||
|
||||
#include <any>
|
||||
#include <expected>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
@@ -37,7 +37,7 @@ public:
|
||||
pimpl_->wait();
|
||||
}
|
||||
|
||||
std::expected<std::any, ExecutionError>
|
||||
std::expected<Any, ExecutionError>
|
||||
get()
|
||||
{
|
||||
return pimpl_->get();
|
||||
@@ -64,7 +64,7 @@ private:
|
||||
|
||||
virtual void
|
||||
wait() noexcept = 0;
|
||||
virtual std::expected<std::any, ExecutionError>
|
||||
virtual std::expected<Any, ExecutionError>
|
||||
get() = 0;
|
||||
virtual void
|
||||
abort() = 0;
|
||||
@@ -93,14 +93,14 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
std::expected<std::any, ExecutionError>
|
||||
std::expected<Any, ExecutionError>
|
||||
get() override
|
||||
{
|
||||
if constexpr (not SomeOperationWithData<OpType>) {
|
||||
ASSERT(false, "Called get() on an operation that does not support it");
|
||||
std::unreachable();
|
||||
} else {
|
||||
// Note: return type of the operation was already wrapped to std::any by
|
||||
// Note: return type of the operation was already wrapped to impl::Any by
|
||||
// AnyExecutionContext
|
||||
return operation.get();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user