Page MenuHomePhorge

No OneTemporary

Size
14 KB
Referenced Files
None
Subscribers
None
diff --git a/src/base/promise-interface.hpp b/src/base/promise-interface.hpp
index 8c6ad8b..7a8febc 100644
--- a/src/base/promise-interface.hpp
+++ b/src/base/promise-interface.hpp
@@ -1,308 +1,349 @@
/*
* Copyright (C) 2021 Tusooa Zhu <tusooa@vista.aero>
*
* This file is part of libkazv.
*
* libkazv is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* libkazv 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with libkazv. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <memory>
#include <type_traits>
#include <functional>
namespace Kazv
{
class TypelessPromise
{
};
template<template<class> class DeriveT, class T>
class AbstractPromise;
namespace detail
{
template<class T, class = void>
struct PromiseParameterT
{
using type = T;
};
template<class PromiseT>
struct PromiseParameterT<PromiseT,
std::void_t<std::enable_if_t<std::is_base_of_v<TypelessPromise, PromiseT>, int>>>
{
using type = typename PromiseT::DataT;
};
template<class T>
using PromiseParameter = typename PromiseParameterT<T>::type;
template<class T, class = void>
struct PromiseResult
{
};
template<class T>
struct PromiseResult<T, std::void_t<std::invoke_result_t<T>>>
{
using Res = std::invoke_result_t<T>;
using type = PromiseParameter<Res>;
};
template<class T>
using PromiseResultT = typename PromiseResult<T>::type;
template<class T, class P>
struct PromiseThenResultT
{
using Res = std::invoke_result_t<T, PromiseParameter<P>>;
using type = PromiseParameter<Res>;
};
}
template<class T, class P>
using PromiseThenResult = typename detail::PromiseThenResultT<T, P>::type;
template<class T>
constexpr auto isPromise = std::is_base_of_v<TypelessPromise, T>;
template<template<class> class DeriveT, class T>
class AbstractPromise : TypelessPromise
{
public:
using DataT = T;
static_assert(!isPromise<DataT>, "Cannot create a promise of promise");
AbstractPromise(DeriveT<T> *obj) : m_derived(obj) {}
template<class FuncT>
auto then(FuncT &&func)
-> DeriveT<PromiseThenResult<FuncT, DataT>> {
return m_derived->then(std::forward<FuncT>(func));
}
private:
DeriveT<T> *m_derived;
};
- class BoolPromise : TypelessPromise
+ namespace PromiseCombination
+ {
+ constexpr bool createDefaultForPromiseThen(bool) { return true; }
+ constexpr bool dataCombine(bool a, bool b) { return a && b; }
+ constexpr bool dataCombineNone(bool) { return true; }
+
+ template<class T, class = void>
+ struct DefaultForPromiseT
+ {
+ constexpr T operator()() const { return T(); }
+ };
+
+ template<class T>
+ struct DefaultForPromiseT<
+ T,
+ std::void_t<decltype(createDefaultForPromiseThen(std::declval<T>()))>>
+ {
+ constexpr T operator()() const { return createDefaultForPromiseThen(T()); }
+ };
+
+ template<class T>
+ constexpr T defaultForPromiseThen(T)
+ {
+ return DefaultForPromiseT<T>{}();
+ }
+ }
+
+
+ template<class T>
+ class SingleTypePromise : TypelessPromise
{
public:
- using DataT = bool;
+ using DataT = T;
template<class DeriveT>
- BoolPromise(DeriveT obj)
+ SingleTypePromise(DeriveT obj)
: m_d(std::unique_ptr<Concept>(new Model<DeriveT>(std::move(obj)))) {}
- BoolPromise(const BoolPromise &that)
+ SingleTypePromise(const SingleTypePromise &that)
: m_d(that.m_d->clone())
{}
- BoolPromise(BoolPromise &&that)
+ SingleTypePromise(SingleTypePromise &&that)
: m_d(std::move(that.m_d))
{}
- BoolPromise &operator=(const BoolPromise &that) {
+ SingleTypePromise &operator=(const SingleTypePromise &that) {
m_d = that.m_d->clone();
return *this;
}
- BoolPromise &operator=(BoolPromise &&that) {
+ SingleTypePromise &operator=(SingleTypePromise &&that) {
m_d = std::move(that.m_d);
return *this;
}
template<class F>
- BoolPromise then(F &&f) {
- if constexpr (std::is_same_v<std::invoke_result_t<F, bool>, void>) {
+ SingleTypePromise then(F &&f) {
+ if constexpr (std::is_same_v<std::invoke_result_t<F, DataT>, void>) {
return m_d->thenVoid(f);
- } else if constexpr (std::is_same_v<std::invoke_result_t<F, bool>, bool>) {
- return m_d->thenBool(f);
- } else {
+ } else if constexpr(isPromise<std::invoke_result_t<F, DataT>>) {
return m_d->thenPromise(f);
+ } else {
+ return m_d->thenData(f);
}
}
bool ready() const { return m_d->ready(); }
bool get() const { return m_d->get(); }
private:
struct Concept
{
virtual ~Concept() = default;
- virtual BoolPromise thenVoid(std::function<void(bool)> f) = 0;
- virtual BoolPromise thenBool(std::function<bool(bool)> f) = 0;
- virtual BoolPromise thenPromise(std::function<BoolPromise(bool)> f) = 0;
+ virtual SingleTypePromise thenVoid(std::function<void(DataT)> f) = 0;
+ virtual SingleTypePromise thenData(std::function<DataT(DataT)> f) = 0;
+ virtual SingleTypePromise thenPromise(std::function<SingleTypePromise(DataT)> f) = 0;
virtual std::unique_ptr<Concept> clone() const = 0;
virtual bool ready() const = 0;
- virtual bool get() const = 0;
+ virtual DataT get() const = 0;
};
template<class DeriveT>
struct Model : public Concept
{
Model(DeriveT obj) : instance(std::move(obj)) {}
~Model() override = default;
- BoolPromise thenVoid(std::function<void(bool)> f) override {
- return instance.then([=](bool v) { f(v); return true; });
+ SingleTypePromise thenVoid(std::function<void(DataT)> f) override {
+ return instance.then([=](DataT v) {
+ f(v);
+ return PromiseCombination::defaultForPromiseThen(DataT());
+ });
}
- BoolPromise thenBool(std::function<bool(bool)> f) override {
- return instance.then([=](bool v) { return f(v); });
+ SingleTypePromise thenData(std::function<DataT(DataT)> f) override {
+ return instance.then([=](DataT v) { return f(v); });
}
- BoolPromise thenPromise(std::function<BoolPromise(bool)> f) override {
- return instance.then([=](bool v) { return f(v); });
+ SingleTypePromise thenPromise(std::function<SingleTypePromise(DataT)> f) override {
+ return instance.then([=](DataT v) { return f(v); });
}
std::unique_ptr<Concept> clone() const override {
return std::unique_ptr<Concept>(new Model<DeriveT>(instance));
}
bool ready() const override {
return instance.ready();
}
- bool get() const override {
+ DataT get() const override {
return instance.get();
}
DeriveT instance;
};
std::unique_ptr<Concept> m_d;
};
+ using BoolPromise = SingleTypePromise<bool>;
+
template<class DeriveT, template<class> class PromiseT>
class PromiseInterface
{
public:
PromiseInterface(DeriveT *obj) : m_derived(obj) {}
template<class T, class FuncT>
auto create(FuncT &&func) -> PromiseT<T>;
template<class T>
auto createResolved(T &&val) -> PromiseT<T>;
private:
DeriveT *m_derived;
};
template<class DeriveT, template<class> class PromiseT>
template<class T, class FuncT>
auto PromiseInterface<DeriveT, PromiseT>::create(FuncT &&func) -> PromiseT<T> {
return m_derived->create(std::forward<FuncT>(func));
}
template<class DeriveT, template<class> class PromiseT>
template<class T>
auto PromiseInterface<DeriveT, PromiseT>::createResolved(T &&val) -> PromiseT<T> {
return m_derived->createResolved(std::forward<T>(val));
}
- class BoolPromiseInterface
+ template<class T>
+ class SingleTypePromiseInterface
{
public:
- using ResolveT = std::function<void(bool)>;
- using ResolveToPromiseT = std::function<void(BoolPromise)>;
+ using DataT = T;
+ using PromiseT = SingleTypePromise<DataT>;
+ using ResolveT = std::function<void(DataT)>;
+ using ResolveToPromiseT = std::function<void(PromiseT)>;
template<class DeriveT>
- BoolPromiseInterface(DeriveT obj)
+ SingleTypePromiseInterface(DeriveT obj)
: m_d(std::unique_ptr<Concept>(new Model<std::decay_t<DeriveT>>(std::move(obj)))) {
if (! m_d) {
throw std::logic_error("promise handler is empty");
}
}
- BoolPromiseInterface(const BoolPromiseInterface &that)
+ SingleTypePromiseInterface(const SingleTypePromiseInterface &that)
: m_d(that.m_d) {
if (! m_d) {
throw std::logic_error("promise handler is empty");
}
}
- BoolPromiseInterface(BoolPromiseInterface &&that)
+ SingleTypePromiseInterface(SingleTypePromiseInterface &&that)
: m_d(std::move(that.m_d)) {
if (! m_d) {
throw std::logic_error("promise handler is empty");
}
}
- BoolPromiseInterface &operator=(const BoolPromiseInterface &that) {
+ SingleTypePromiseInterface &operator=(const SingleTypePromiseInterface &that) {
m_d = that.m_d;
return *this;
}
- BoolPromiseInterface &operator=(BoolPromiseInterface &&that) {
+ SingleTypePromiseInterface &operator=(SingleTypePromiseInterface &&that) {
m_d = std::move(that.m_d);
return *this;
}
- BoolPromise create(std::function<void(ResolveT)> f) const {
+ PromiseT create(std::function<void(ResolveT)> f) const {
return m_d->create(f);
}
- BoolPromise createResolveToPromise(std::function<void(ResolveToPromiseT)> f) const {
+ PromiseT createResolveToPromise(std::function<void(ResolveToPromiseT)> f) const {
return m_d->createResolveToPromise(f);
}
- BoolPromise createResolved(bool v) const {
+ PromiseT createResolved(bool v) const {
return m_d->createResolved(v);
}
template<class RangeT>
- BoolPromise all(RangeT promises) const {
+ PromiseT all(RangeT promises) const {
+ using PromiseCombination::dataCombine;
+ using PromiseCombination::dataCombineNone;
if (promises.empty()) {
- return createResolved(true);
+ return createResolved(dataCombineNone(bool{}));
}
auto p1 = *(promises.begin());
promises.erase(promises.begin());
- return p1.then([*this, promises=std::move(promises)](bool val) mutable {
- if (! val) {
- return createResolved(false);
- }
- return all(std::move(promises));
+ return p1.then([*this, promises=std::move(promises)](DataT val) mutable {
+ return all(std::move(promises))
+ .then([=](DataT val2) {
+ return dataCombine(val, val2);
+ });
});
}
private:
struct Concept
{
virtual ~Concept() = default;
- virtual BoolPromise create(std::function<void(ResolveT)> f) = 0;
- virtual BoolPromise createResolveToPromise(std::function<void(ResolveToPromiseT)> f) = 0;
- virtual BoolPromise createResolved(bool v) = 0;
+ virtual PromiseT create(std::function<void(ResolveT)> f) = 0;
+ virtual PromiseT createResolveToPromise(std::function<void(ResolveToPromiseT)> f) = 0;
+ virtual PromiseT createResolved(DataT v) = 0;
};
template<class DeriveT>
struct Model : public Concept
{
static_assert(std::is_same_v<std::decay_t<DeriveT>, DeriveT>, "DeriveT must not be a reference");
Model(DeriveT obj) : instance(std::move(obj)) {}
~Model() override = default;
- BoolPromise create(std::function<void(ResolveT)> f) override {
- return instance.template create<bool>(f);
+ PromiseT create(std::function<void(ResolveT)> f) override {
+ return instance.template create<DataT>(f);
}
- BoolPromise createResolveToPromise(std::function<void(ResolveToPromiseT)> f) override {
- return instance.template create<bool>(f);
+ PromiseT createResolveToPromise(std::function<void(ResolveToPromiseT)> f) override {
+ return instance.template create<DataT>(f);
}
- BoolPromise createResolved(bool v) override {
+ PromiseT createResolved(DataT v) override {
return instance.createResolved(v);
}
DeriveT instance;
};
std::shared_ptr<Concept> m_d;
};
+
+ using BoolPromiseInterface = SingleTypePromiseInterface<bool>;
}

File Metadata

Mime Type
text/x-diff
Expires
Sun, Jan 19, 12:55 PM (5 h, 34 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
55183
Default Alt Text
(14 KB)

Event Timeline