Commit 44053667 authored by tqcq's avatar tqcq
Browse files

feat update

parent 569d0813
Loading
Loading
Loading
Loading
+34 −9
Original line number Diff line number Diff line
@@ -10,8 +10,9 @@
#include "sled/synchronization/event.h"
#include "sled/synchronization/mutex.h"
#include "sled/task_queue/task_queue_base.h"
#include "sled/variant.h"
#include "sled/utility/forward_on_copy.h"
#include <atomic>
#include <future>
#include <list>

namespace sled {
@@ -48,7 +49,8 @@ struct FutureData {
    ~FutureData() { DecrementFuturesUsage(); }

    std::atomic_int state{kNotCompletedFuture};
    sled::variant<sled::monostate, T, FailureT> value;
    // sled::variant<sled::monostate, T, FailureT> value;
    sled::any value;
    std::list<std::function<void(const T &)>> success_callbacks;
    std::list<std::function<void(const FailureT &)>> failure_callbacks;
    sled::Mutex mutex_;
@@ -130,7 +132,8 @@ public:
        if (!IsCompleted()) Wait();
        if (IsSucceeded()) {
            try {
                return sled::get<T>(data_->value);
                // return sled::get<T>(data_->value);
                return sled::any_cast<T>(data_->value);
            } catch (...) {}
        }
        return T();
@@ -140,7 +143,8 @@ public:
    {
        SLED_ASSERT(data_ != nullptr, "Future is not valid");
        if (!IsCompleted()) { Wait(); }
        return sled::get<T>(data_->value);
        // return sled::get<T>(data_->value);
        return sled::any_cast<T>(data_->value);
    }

    FailureT FailureReason() const
@@ -149,7 +153,8 @@ public:
        if (!IsCompleted()) { Wait(); }
        if (IsFailed()) {
            try {
                return sled::get<FailureT>(data_->value);
                // return sled::get<FailureT>(data_->value);
                return sled::any_cast<FailureT>(data_->value);
            } catch (...) {}
        }
        return FailureT();
@@ -176,7 +181,8 @@ public:
        }
        if (call_it) {
            try {
                f(sled::get<T>(data_->value));
                // f(sled::get<T>(data_->value));
                f(sled::any_cast<T>(data_->value));
            } catch (...) {}
        }
        return Future<T, FailureT>(data_);
@@ -203,7 +209,8 @@ public:
        }
        if (call_it) {
            try {
                f(sled::get<FailureT>(data_->value));
                // f(sled::get<FailureT>(data_->value));
                f(sled::any_cast<FailureT>(data_->value));
            } catch (...) {}
        }
        return Future<T, FailureT>(data_);
@@ -294,6 +301,20 @@ public:
        return result;
    }

    template<typename Func, typename U = decltype(std::declval<eggs::invoke_result_t<Func, T>().Result()>)>
    Future<U, FailureT> AndThen(Func &&f) const noexcept
    {
        return FlatMap([f](const T &) { return f(); });
    }

    template<typename T2, typename U = typename std::decay<T2>::type>
    Future<U, FailureT> AndThenValue(T2 &&value) const noexcept
    {
        Future<U, FailureT> result = Future<U, FailureT>::Create();
        auto forward_on_copy       = sled::MakeForwardOnCopy(std::forward<T2>(value));
        return Map([forward_on_copy](const T &) noexcept { return forward_on_copy.value(); });
    }

    Future<T, FailureT> Via(TaskQueueBase *task_queue) const noexcept
    {
        SLED_ASSERT(task_queue != nullptr, "TaskQueue is not valid");
@@ -365,6 +386,7 @@ private:
            if (IsCompleted()) { return; }

            try {
                // data_->value.template emplace<T>(std::move(value));
                // data_->value.template emplace<T>(std::move(value));
                data_->value = std::move(value);
            } catch (...) {}
@@ -376,7 +398,8 @@ private:

        for (const auto &f : callbacks) {
            try {
                f(sled::get<T>(data_->value));
                // f(sled::get<T>(data_->value));
                f(sled::any_cast<T>(data_->value));
            } catch (...) {}
        }
    }
@@ -396,6 +419,7 @@ private:
            if (IsCompleted()) { return; }
            try {
                // data_->value.template emplace<FailureT>(std::move(reason));
                // data_->value = std::move(reason);
                data_->value = std::move(reason);
            } catch (...) {}
            data_->state.store(detail::kFailedFuture, std::memory_order_release);
@@ -406,7 +430,8 @@ private:

        for (const auto &f : callbacks) {
            try {
                f(sled::get<FailureT>(data_->value));
                // f(sled::get<FailureT>(data_->value));
                f(sled::any_cast<FailureT>(data_->value));
            } catch (...) {}
        }
    }
+51 −14
Original line number Diff line number Diff line
#include <sled/futures/future.h>
#include <sled/system/thread.h>
#include <type_traits>

TEST_SUITE("future")
{
    TEST_CASE("base success")

    {
        sled::Promise<int, std::string> p;
        auto f = p.GetFuture();
@@ -12,6 +14,7 @@ TEST_SUITE("future")
        CHECK(f.IsValid());
        CHECK_EQ(f.Result(), 42);
    }

    TEST_CASE("base failed")
    {
        sled::Promise<int, std::string> p;
@@ -23,31 +26,65 @@ TEST_SUITE("future")
        CHECK(f.IsValid());
        CHECK_EQ(f.FailureReason(), "error");
    }

    TEST_CASE("throw")
    {
        sled::Promise<int, std::string> p;
        auto f = p.GetFuture().Map([](int x) {
            throw std::runtime_error("test");
            return x;
        });

        p.Success(42);
        REQUIRE(f.IsCompleted());
        REQUIRE(f.IsFailed());
        CHECK_EQ(f.FailureReason(), "test");
    }

    TEST_CASE("base failed")
    {
        sled::Promise<int, std::string> p;
        auto f = p.GetFuture();
        p.Failure("error");
        REQUIRE(p.IsFilled());
        REQUIRE(f.IsCompleted());
        CHECK(f.Wait(-1));
        CHECK(f.IsValid());
        CHECK_EQ(f.FailureReason(), "error");
    }

    TEST_CASE("thread success") {}

    TEST_CASE("map")
    TEST_CASE("Map")
    {
        sled::Promise<int, std::string> p;
        auto f  = p.GetFuture();
        auto f2 = f.Map([](int i) { return i + 1; });
        auto f2 = f.Map([](int i) { return i + 1; })
                      .Map([](int i) { return std::to_string(i) + "00"; })
                      .Map([](const std::string &str) {
                          std::stringstream ss(str);
                          int x;
                          ss >> x;
                          return x;
                      });
        p.Success(42);
        CHECK(f2.Wait(-1));
        CHECK_EQ(f2.Result(), 43);
        CHECK_EQ(f2.Result(), 4300);
    }

    TEST_CASE("FlatMap")
    {
        // sled::Promise<int, std::string> p;
        // auto f = p.GetFuture().FlatMap([](int i) {
        //     auto str = std::to_string(i);
        //     sled::Promise<std::string, std::string> p;
        //     p.Success(str);
        //
        //     return p.GetFuture();
        // });
        // p.Success(42);
        // CHECK(f.Wait(-1));
        // CHECK_EQ(f.Result(), "42");
        sled::Promise<int, std::string> p;
        auto f = p.GetFuture().FlatMap([](int i) {
            auto str = std::to_string(i);
            sled::Promise<std::string, std::string> p;
            p.Success(str);

            return p.GetFuture();
        });
        p.Success(42);
        CHECK(f.IsCompleted());
        CHECK_EQ(f.Result(), "42");
    }

    TEST_CASE("Via")
+76 −0
Original line number Diff line number Diff line
#ifndef SLED_UTILITY_FORWARD_ON_COPY_H
#define SLED_UTILITY_FORWARD_ON_COPY_H

#pragma once
#include "sled/any.h"

namespace sled {
namespace detail {

struct ForwardOnCopyTag {};

};// namespace detail

template<typename T>
struct ForwardOnCopy {
    ForwardOnCopy(ForwardOnCopy &other)
        : is_moved_(other.is_moved_),
          value_(is_moved_ ? other.value_ : std::move(other.value_))
    {}

    // ForwardOnCopy(ForwardOnCopy &&other) noexcept;
    ForwardOnCopy &operator=(ForwardOnCopy &other)
    {
        is_moved_ = other.is_moved_;
        value_    = is_moved_ ? other.value_ : std::move(other.value_);
        return *this;
    }

    // ForwardOnCopy &operator=(ForwardOnCopy &&other) noexcept;
    T value() const
    {
        if (is_moved_) {
            return std::move(sled::any_cast<T>(value_));
        } else {
            return sled::any_cast<T>(value_);
        }
    }

private:
    bool is_moved_;
    sled::any value_;
};

template<typename T>
ForwardOnCopy<T>
MakeForwardOnCopy(T value)
{
    ForwardOnCopy<T> result;
    result.is_moved_ = false;
    result.value_    = value;
    return result;
}

template<typename T>
ForwardOnCopy<T>
MakeForwardOnCopy(T &value)
{
    ForwardOnCopy<T> result;
    result.is_moved_ = false;
    result.value_    = value;
    return result;
}

template<typename T>
ForwardOnCopy<T>
MakeForwardOnCopy(T &&value)
{
    ForwardOnCopy<T> result;
    result.is_moved_ = true;
    result.value_    = std::move(value);
    return result;
}

}// namespace sled

#endif// SLED_UTILITY_FORWARD_ON_COPY_H