Loading src/sled/error/error.h 0 → 100644 +14 −0 Original line number Diff line number Diff line #ifndef SLED_ERROR_ERROR_H #define SLED_ERROR_ERROR_H #pragma once namespace sled { class Error { public: template<typename T> static Error Wrap(); }; }// namespace sled #endif// SLED_ERROR_ERROR_H src/sled/futures/future.h +42 −42 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ #include "sled/futures/internal/promise.h" #include "sled/lang/attributes.h" #include "sled/log/log.h" #include "sled/meta/type_traits.h" #include "sled/synchronization/event.h" #include "sled/synchronization/mutex.h" #include "sled/task_queue/task_queue_base.h" Loading @@ -17,16 +18,16 @@ namespace sled { namespace future_detail { template<typename F, typename... Args> struct is_invocable : std::is_constructible<std::function<void(Args...)>, std::reference_wrapper<typename std::remove_reference<F>::type>> {}; template<typename R, typename F, typename... Args> struct is_invocable_r : std::is_constructible<std::function<R(Args...)>, std::reference_wrapper<typename std::remove_reference<F>::type>> {}; template<bool cond, typename T = void> using enable_if_t = typename std::enable_if<cond, T>::type; // template<typename F, typename... Args> // struct is_invocable : std::is_constructible<std::function<void(Args...)>, // std::reference_wrapper<typename std::remove_reference<F>::type>> {}; // // template<typename R, typename F, typename... Args> // struct is_invocable_r : std::is_constructible<std::function<R(Args...)>, // std::reference_wrapper<typename std::remove_reference<F>::type>> {}; // // template<bool cond, typename T = void> // using enable_if_t = typename std::enable_if<cond, T>::type; enum FutureState { kNotCompletedFuture = 0, Loading Loading @@ -83,27 +84,27 @@ public: Future<T, FailureT> &operator=(Future<T, FailureT> &&) noexcept = default; ~Future() = default; Future(const T &value) noexcept { static_assert(!std::is_same<T, FailureT>::value, "T and FailureT must be different types"); data_ = Future<T, FailureT>::Create().data_; FillSuccess(value); } Future(T &&value) noexcept { static_assert(!std::is_same<T, FailureT>::value, "T and FailureT must be different types"); data_ = Future<T, FailureT>::Create().data_; FillSuccess(std::move(value)); } template<typename = typename std::enable_if<!std::is_same<T, FailureT>::value>> Future(const FailureT &failure) noexcept { static_assert(!std::is_same<T, FailureT>::value, "T and FailureT must be different types"); data_ = Future<T, FailureT>::Create().data_; FillFailure(failure); } // Future(const T &value) noexcept // { // static_assert(!std::is_same<T, FailureT>::value, "T and FailureT must be different types"); // data_ = Future<T, FailureT>::Create().data_; // FillSuccess(value); // } // // Future(T &&value) noexcept // { // static_assert(!std::is_same<T, FailureT>::value, "T and FailureT must be different types"); // data_ = Future<T, FailureT>::Create().data_; // FillSuccess(std::move(value)); // } // // template<typename = EnableIfT<!std::is_same<T, FailureT>::value>> // Future(const FailureT &failure) noexcept // { // static_assert(!std::is_same<T, FailureT>::value, "T and FailureT must be different types"); // data_ = Future<T, FailureT>::Create().data_; // FillFailure(failure); // } bool operator==(const Future<T, FailureT> &other) const noexcept { return data_ == other.data_; } Loading Loading @@ -147,8 +148,7 @@ public: return IsCompleted(); } template<typename Dummy = void, typename = typename std::enable_if<std::is_copy_constructible<T>::value, Dummy>::type> template<typename Dummy = void, typename = EnableIfT<std::is_copy_constructible<T>::value, Dummy>> T Result() const noexcept { SLED_ASSERT(data_ != nullptr, "Future is not valid"); Loading Loading @@ -183,7 +183,7 @@ public: return FailureT(); } template<typename Func, typename = typename std::enable_if<future_detail::is_invocable<Func, T>::value>::type> template<typename Func, typename = EnableIfT<IsInvocable<Func, T>::value>> Future<T, FailureT> OnSuccess(Func &&f) const noexcept { SLED_ASSERT(data_ != nullptr, "Future is not valid"); Loading Loading @@ -211,7 +211,7 @@ public: return Future<T, FailureT>(data_); } template<typename Func, typename = future_detail::enable_if_t<future_detail::is_invocable<Func, FailureT>::value>> template<typename Func, typename = EnableIfT<IsInvocable<Func, FailureT>::value>> Future<T, FailureT> OnFailure(Func &&f) const noexcept { SLED_ASSERT(data_ != nullptr, "Future is not valid"); Loading Loading @@ -239,7 +239,7 @@ public: return Future<T, FailureT>(data_); } template<typename Func, typename = future_detail::enable_if_t<future_detail::is_invocable<Func>::value>> template<typename Func, typename = EnableIfT<IsInvocable<Func>::value>> Future<T, FailureT> OnComplete(Func &&f) const noexcept { SLED_ASSERT(data_ != nullptr, "Future is not valid"); Loading @@ -248,7 +248,7 @@ public: return Future<T, FailureT>(data_); } template<typename Func, typename = future_detail::enable_if_t<future_detail::is_invocable_r<bool, Func, T>::value>> template<typename Func, typename = EnableIfT<IsInvocableR<bool, Func, T>::value>> Future<T, FailureT> Filter(Func &&f, const FailureT &rejected = failure::FailureFromString<FailureT>("Result wasn't good enough")) const noexcept Loading @@ -271,7 +271,7 @@ public: return result; } template<typename Func, typename U = eggs::invoke_result_t<Func, T>> template<typename Func, typename U = InvokeResultT<Func, T>> Future<U, FailureT> Map(Func &&f) const noexcept { Future<U, FailureT> result = Future<U, FailureT>::Create(); Loading @@ -288,7 +288,7 @@ public: return result; } template<typename Func, typename OtherFailureT = eggs::invoke_result_t<Func, FailureT>> template<typename Func, typename OtherFailureT = InvokeResultT<Func, FailureT>> Future<T, OtherFailureT> MapFailure(Func &&f) const noexcept { Future<T, OtherFailureT> result = Future<T, OtherFailureT>::Create(); Loading @@ -305,7 +305,7 @@ public: return result; } template<typename Func, typename U = decltype(std::declval<eggs::invoke_result_t<Func, T>>().Result())> template<typename Func, typename U = decltype(std::declval<InvokeResultT<Func, T>>().Result())> Future<U, FailureT> FlatMap(Func &&f) const noexcept { Future<U, FailureT> result = Future<U, FailureT>::Create(); Loading @@ -324,7 +324,7 @@ public: return result; } template<typename Func, typename U = decltype(std::declval<eggs::invoke_result_t<Func, T>().Result()>)> template<typename Func, typename U = decltype(std::declval<InvokeResultT<Func, T>().Result()>)> Future<U, FailureT> AndThen(Func &&f) const noexcept { return FlatMap([f](const T &) { return f(); }); Loading Loading @@ -353,7 +353,7 @@ public: return result; } template<typename Func, typename = future_detail::enable_if_t<future_detail::is_invocable<Func>::value>> template<typename Func, typename = EnableIfT<IsInvocable<Func>::value>> static Future<T, FailureT> Async(Func &&f) noexcept { Future<T, FailureT> result = Future<T, FailureT>::Create(); Loading src/sled/futures/future_test.cc +6 −7 Original line number Diff line number Diff line #include <sled/futures/future.h> #include <sled/system/thread.h> #include <type_traits> TEST_SUITE("future") { Loading Loading @@ -122,8 +121,8 @@ TEST_SUITE("future") TEST_CASE("Constructor") { sled::Future<int, std::string> f1 = 1; sled::Future<int, std::string> f2 = std::string("1"); auto f1 = sled::Future<int, std::string>::Successful(1); auto f2 = sled::Future<int, std::string>::Failed(std::string("1")); REQUIRE(f1.IsCompleted()); REQUIRE(f2.IsFailed()); REQUIRE_EQ(f1.Result(), 1); Loading @@ -132,14 +131,14 @@ TEST_SUITE("future") TEST_CASE("MapFailure") { sled::Future<int, bool> f = false; auto f = sled::Future<int, bool>::Failed(false); auto f1 = f.MapFailure([](bool) { return std::string("error"); }); CHECK_EQ(f1.FailureReason(), "error"); } TEST_CASE("Chain") { sled::Future<int, bool> f = 1; auto f = sled::Future<int, bool>::Successful(1); auto f1 = f.Map([](int i) { return i + 1; }) .FlatMap([](int i) { sled::Promise<std::string, bool> p; Loading src/sled/futures/internal/failure_handling.h +3 −5 Original line number Diff line number Diff line Loading @@ -3,7 +3,7 @@ #pragma once #include "sled/any.h" #include "sled/nonstd/string_view.h" #include "sled/meta/type_traits.h" #include <string> namespace sled { Loading @@ -25,16 +25,14 @@ private: std::string message_; }; template<typename FailureT, typename = typename std::enable_if<!std::is_constructible<FailureT, std::string>::value>::type> template<typename FailureT, typename = EnableIfT<!std::is_constructible<FailureT, std::string>::value>> inline FailureT FailureFromString(std::string &&str) { return FailureT(); } template<typename FailureT, typename = typename std::enable_if<std::is_constructible<FailureT, const std::string &>::value>::type> template<typename FailureT, typename = EnableIfT<std::is_constructible<FailureT, const std::string &>::value>> inline FailureT FailureFromString(const std::string &str) { Loading src/sled/meta/type_traits.h 0 → 100644 +34 −0 Original line number Diff line number Diff line #ifndef SLED_META_TYPE_TRAITS_H #define SLED_META_TYPE_TRAITS_H #pragma once #include "sled/exec/detail/invoke_result.h" namespace sled { template<typename Callable, typename... Args> using InvokeResultT = typename eggs::invoke_result_t<Callable, Args...>; template<typename Callable, typename... Args> using IsInvocable = eggs::is_invocable<Callable, Args...>; template<typename Convertible, typename Callable, typename... Args> using IsInvocableR = eggs::is_invocable_r<Convertible, Callable, Args...>; template<typename Convertible, typename Callable, typename... Args> using IsNothrowInvocable = eggs::is_nothrow_invocable<Convertible, Callable, Args...>; template<typename Convertible, typename Callable, typename... Args> using IsNothrowInvocableR = eggs::is_nothrow_invocable_r<Convertible, Callable, Args...>; // EnableIfT template<bool B, typename T = void> using EnableIfT = typename std::enable_if<B, T>::type; template<typename T> using DecayT = typename std::decay<T>::type; }// namespace sled #endif// SLED_META_TYPE_TRAITS_H Loading
src/sled/error/error.h 0 → 100644 +14 −0 Original line number Diff line number Diff line #ifndef SLED_ERROR_ERROR_H #define SLED_ERROR_ERROR_H #pragma once namespace sled { class Error { public: template<typename T> static Error Wrap(); }; }// namespace sled #endif// SLED_ERROR_ERROR_H
src/sled/futures/future.h +42 −42 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ #include "sled/futures/internal/promise.h" #include "sled/lang/attributes.h" #include "sled/log/log.h" #include "sled/meta/type_traits.h" #include "sled/synchronization/event.h" #include "sled/synchronization/mutex.h" #include "sled/task_queue/task_queue_base.h" Loading @@ -17,16 +18,16 @@ namespace sled { namespace future_detail { template<typename F, typename... Args> struct is_invocable : std::is_constructible<std::function<void(Args...)>, std::reference_wrapper<typename std::remove_reference<F>::type>> {}; template<typename R, typename F, typename... Args> struct is_invocable_r : std::is_constructible<std::function<R(Args...)>, std::reference_wrapper<typename std::remove_reference<F>::type>> {}; template<bool cond, typename T = void> using enable_if_t = typename std::enable_if<cond, T>::type; // template<typename F, typename... Args> // struct is_invocable : std::is_constructible<std::function<void(Args...)>, // std::reference_wrapper<typename std::remove_reference<F>::type>> {}; // // template<typename R, typename F, typename... Args> // struct is_invocable_r : std::is_constructible<std::function<R(Args...)>, // std::reference_wrapper<typename std::remove_reference<F>::type>> {}; // // template<bool cond, typename T = void> // using enable_if_t = typename std::enable_if<cond, T>::type; enum FutureState { kNotCompletedFuture = 0, Loading Loading @@ -83,27 +84,27 @@ public: Future<T, FailureT> &operator=(Future<T, FailureT> &&) noexcept = default; ~Future() = default; Future(const T &value) noexcept { static_assert(!std::is_same<T, FailureT>::value, "T and FailureT must be different types"); data_ = Future<T, FailureT>::Create().data_; FillSuccess(value); } Future(T &&value) noexcept { static_assert(!std::is_same<T, FailureT>::value, "T and FailureT must be different types"); data_ = Future<T, FailureT>::Create().data_; FillSuccess(std::move(value)); } template<typename = typename std::enable_if<!std::is_same<T, FailureT>::value>> Future(const FailureT &failure) noexcept { static_assert(!std::is_same<T, FailureT>::value, "T and FailureT must be different types"); data_ = Future<T, FailureT>::Create().data_; FillFailure(failure); } // Future(const T &value) noexcept // { // static_assert(!std::is_same<T, FailureT>::value, "T and FailureT must be different types"); // data_ = Future<T, FailureT>::Create().data_; // FillSuccess(value); // } // // Future(T &&value) noexcept // { // static_assert(!std::is_same<T, FailureT>::value, "T and FailureT must be different types"); // data_ = Future<T, FailureT>::Create().data_; // FillSuccess(std::move(value)); // } // // template<typename = EnableIfT<!std::is_same<T, FailureT>::value>> // Future(const FailureT &failure) noexcept // { // static_assert(!std::is_same<T, FailureT>::value, "T and FailureT must be different types"); // data_ = Future<T, FailureT>::Create().data_; // FillFailure(failure); // } bool operator==(const Future<T, FailureT> &other) const noexcept { return data_ == other.data_; } Loading Loading @@ -147,8 +148,7 @@ public: return IsCompleted(); } template<typename Dummy = void, typename = typename std::enable_if<std::is_copy_constructible<T>::value, Dummy>::type> template<typename Dummy = void, typename = EnableIfT<std::is_copy_constructible<T>::value, Dummy>> T Result() const noexcept { SLED_ASSERT(data_ != nullptr, "Future is not valid"); Loading Loading @@ -183,7 +183,7 @@ public: return FailureT(); } template<typename Func, typename = typename std::enable_if<future_detail::is_invocable<Func, T>::value>::type> template<typename Func, typename = EnableIfT<IsInvocable<Func, T>::value>> Future<T, FailureT> OnSuccess(Func &&f) const noexcept { SLED_ASSERT(data_ != nullptr, "Future is not valid"); Loading Loading @@ -211,7 +211,7 @@ public: return Future<T, FailureT>(data_); } template<typename Func, typename = future_detail::enable_if_t<future_detail::is_invocable<Func, FailureT>::value>> template<typename Func, typename = EnableIfT<IsInvocable<Func, FailureT>::value>> Future<T, FailureT> OnFailure(Func &&f) const noexcept { SLED_ASSERT(data_ != nullptr, "Future is not valid"); Loading Loading @@ -239,7 +239,7 @@ public: return Future<T, FailureT>(data_); } template<typename Func, typename = future_detail::enable_if_t<future_detail::is_invocable<Func>::value>> template<typename Func, typename = EnableIfT<IsInvocable<Func>::value>> Future<T, FailureT> OnComplete(Func &&f) const noexcept { SLED_ASSERT(data_ != nullptr, "Future is not valid"); Loading @@ -248,7 +248,7 @@ public: return Future<T, FailureT>(data_); } template<typename Func, typename = future_detail::enable_if_t<future_detail::is_invocable_r<bool, Func, T>::value>> template<typename Func, typename = EnableIfT<IsInvocableR<bool, Func, T>::value>> Future<T, FailureT> Filter(Func &&f, const FailureT &rejected = failure::FailureFromString<FailureT>("Result wasn't good enough")) const noexcept Loading @@ -271,7 +271,7 @@ public: return result; } template<typename Func, typename U = eggs::invoke_result_t<Func, T>> template<typename Func, typename U = InvokeResultT<Func, T>> Future<U, FailureT> Map(Func &&f) const noexcept { Future<U, FailureT> result = Future<U, FailureT>::Create(); Loading @@ -288,7 +288,7 @@ public: return result; } template<typename Func, typename OtherFailureT = eggs::invoke_result_t<Func, FailureT>> template<typename Func, typename OtherFailureT = InvokeResultT<Func, FailureT>> Future<T, OtherFailureT> MapFailure(Func &&f) const noexcept { Future<T, OtherFailureT> result = Future<T, OtherFailureT>::Create(); Loading @@ -305,7 +305,7 @@ public: return result; } template<typename Func, typename U = decltype(std::declval<eggs::invoke_result_t<Func, T>>().Result())> template<typename Func, typename U = decltype(std::declval<InvokeResultT<Func, T>>().Result())> Future<U, FailureT> FlatMap(Func &&f) const noexcept { Future<U, FailureT> result = Future<U, FailureT>::Create(); Loading @@ -324,7 +324,7 @@ public: return result; } template<typename Func, typename U = decltype(std::declval<eggs::invoke_result_t<Func, T>().Result()>)> template<typename Func, typename U = decltype(std::declval<InvokeResultT<Func, T>().Result()>)> Future<U, FailureT> AndThen(Func &&f) const noexcept { return FlatMap([f](const T &) { return f(); }); Loading Loading @@ -353,7 +353,7 @@ public: return result; } template<typename Func, typename = future_detail::enable_if_t<future_detail::is_invocable<Func>::value>> template<typename Func, typename = EnableIfT<IsInvocable<Func>::value>> static Future<T, FailureT> Async(Func &&f) noexcept { Future<T, FailureT> result = Future<T, FailureT>::Create(); Loading
src/sled/futures/future_test.cc +6 −7 Original line number Diff line number Diff line #include <sled/futures/future.h> #include <sled/system/thread.h> #include <type_traits> TEST_SUITE("future") { Loading Loading @@ -122,8 +121,8 @@ TEST_SUITE("future") TEST_CASE("Constructor") { sled::Future<int, std::string> f1 = 1; sled::Future<int, std::string> f2 = std::string("1"); auto f1 = sled::Future<int, std::string>::Successful(1); auto f2 = sled::Future<int, std::string>::Failed(std::string("1")); REQUIRE(f1.IsCompleted()); REQUIRE(f2.IsFailed()); REQUIRE_EQ(f1.Result(), 1); Loading @@ -132,14 +131,14 @@ TEST_SUITE("future") TEST_CASE("MapFailure") { sled::Future<int, bool> f = false; auto f = sled::Future<int, bool>::Failed(false); auto f1 = f.MapFailure([](bool) { return std::string("error"); }); CHECK_EQ(f1.FailureReason(), "error"); } TEST_CASE("Chain") { sled::Future<int, bool> f = 1; auto f = sled::Future<int, bool>::Successful(1); auto f1 = f.Map([](int i) { return i + 1; }) .FlatMap([](int i) { sled::Promise<std::string, bool> p; Loading
src/sled/futures/internal/failure_handling.h +3 −5 Original line number Diff line number Diff line Loading @@ -3,7 +3,7 @@ #pragma once #include "sled/any.h" #include "sled/nonstd/string_view.h" #include "sled/meta/type_traits.h" #include <string> namespace sled { Loading @@ -25,16 +25,14 @@ private: std::string message_; }; template<typename FailureT, typename = typename std::enable_if<!std::is_constructible<FailureT, std::string>::value>::type> template<typename FailureT, typename = EnableIfT<!std::is_constructible<FailureT, std::string>::value>> inline FailureT FailureFromString(std::string &&str) { return FailureT(); } template<typename FailureT, typename = typename std::enable_if<std::is_constructible<FailureT, const std::string &>::value>::type> template<typename FailureT, typename = EnableIfT<std::is_constructible<FailureT, const std::string &>::value>> inline FailureT FailureFromString(const std::string &str) { Loading
src/sled/meta/type_traits.h 0 → 100644 +34 −0 Original line number Diff line number Diff line #ifndef SLED_META_TYPE_TRAITS_H #define SLED_META_TYPE_TRAITS_H #pragma once #include "sled/exec/detail/invoke_result.h" namespace sled { template<typename Callable, typename... Args> using InvokeResultT = typename eggs::invoke_result_t<Callable, Args...>; template<typename Callable, typename... Args> using IsInvocable = eggs::is_invocable<Callable, Args...>; template<typename Convertible, typename Callable, typename... Args> using IsInvocableR = eggs::is_invocable_r<Convertible, Callable, Args...>; template<typename Convertible, typename Callable, typename... Args> using IsNothrowInvocable = eggs::is_nothrow_invocable<Convertible, Callable, Args...>; template<typename Convertible, typename Callable, typename... Args> using IsNothrowInvocableR = eggs::is_nothrow_invocable_r<Convertible, Callable, Args...>; // EnableIfT template<bool B, typename T = void> using EnableIfT = typename std::enable_if<B, T>::type; template<typename T> using DecayT = typename std::decay<T>::type; }// namespace sled #endif// SLED_META_TYPE_TRAITS_H