31 #ifndef LEDGER_CORE_FUTURE_HPP 32 #define LEDGER_CORE_FUTURE_HPP 38 #include "Deffered.hpp" 39 #include "api/ExecutionContext.hpp" 40 #include "utils/Exception.hpp" 41 #include "utils/ImmediateExecutionContext.hpp" 42 #include "traits/callback_traits.hpp" 43 #include "api/Error.hpp" 44 #include "traits/shared_ptr_traits.hpp" 51 typedef std::shared_ptr<api::ExecutionContext> Context;
53 Future(
const std::shared_ptr<Deffered<T>> &_defer) : _defer(_defer) {}
54 Future(
const Future<T>& future) {
55 _defer = future._defer;
58 Future(Future<T>&& future) : _defer(future._defer) {}
59 Future<T>& operator=(
const Future<T>& future) {
61 _defer = future._defer;
64 Future<T>& operator=(Future<T>&& future) {
66 _defer = future._defer;
71 Future<R> map(
const Context& context, std::function<R (
const T&)> map) {
72 auto defer = Future<R>::make_deffered();
73 _defer->addCallback([defer, map] (
const Try<T>& result) {
75 if (result.isSuccess()) {
76 r = Try<R>::from([map, result] () -> R {
77 return map(result.getValue());
80 r.fail(result.getFailure());
84 return Future<R>(defer);
88 Future<std::shared_ptr<R>> mapPtr(
const Context& context, std::function<std::shared_ptr<R> (
const T&)> map) {
89 return this->
template map<std::shared_ptr<R>>(context, map);
93 Future<R> flatMap(
const Context& context, std::function<Future<R> (
const T&)> map) {
94 auto deffer = Future<R>::make_deffered();
95 _defer->addCallback([deffer, map, context] (
const Try<T>& result) {
96 if (result.isSuccess()) {
98 r = Try<Future<R>>::from([deffer, map, result] () -> Future<R> {
99 return map(result.getValue());
102 Future<R> future = r.getValue();
103 future.onComplete(context, [deffer] (
const Try<R>& finalResult) {
104 deffer->setResult(finalResult);
108 re.fail(r.getFailure());
109 deffer->setResult(re);
113 r.fail(result.getFailure());
114 deffer->setResult(r);
117 return Future<R>(deffer);
120 template <
typename R>
121 Future<std::shared_ptr<R>> flatMapPtr(
const Context& context, std::function<Future<std::shared_ptr<R>> (
const T&)> map) {
122 return this->flatMap<std::shared_ptr<R>>(context, map);
125 Future<T> recover(
const Context& context, std::function<T (
const Exception&)> f) {
126 auto deffer = Future<T>::make_deffered();
127 _defer->addCallback([deffer, f] (
const Try<T>& result) {
128 if (result.isFailure()) {
129 deffer->setResult(Try<T>::from([f, result] () {
130 return f(result.getFailure());
133 deffer->setResult(result);
136 return Future<T>(deffer);
139 Future<T> recoverWith(
const Context& context, std::function<Future<T> (
const Exception&)> f) {
140 auto deffer = Future<T>::make_deffered();
141 _defer->addCallback([deffer, f, context] (
const Try<T>& result) {
142 if (result.isFailure()) {
143 auto future = Try<Future<T>>::from([f, result] () {
144 return f(result.getFailure());
146 if (future.isFailure()) {
148 r.fail(future.getFailure());
149 deffer->setResult(r);
151 Future<T> fut = future.getValue();
152 fut.onComplete(context, [deffer] (
const Try<T>& finalResult) {
153 deffer->setResult(finalResult);
157 deffer->setResult(result);
160 return Future<T>(deffer);
164 Future<T> fallback(
const T& fallback) {
165 return recover(ImmediateExecutionContext::INSTANCE, [fallback] (
const Exception& ex) {
169 Future<T> fallbackWith(Future<T> fallback) {
170 return recoverWith(ImmediateExecutionContext::INSTANCE, [fallback] (
const Exception& ex) {
175 Future<T> filter(
const Context& context, std::function<
bool (
const T&)> f) {
176 return map<T>(context, [f] (
const T& v) {
180 throw Exception(api::ErrorCode::NO_SUCH_ELEMENT,
"Value didn't pass the filter function.");
185 void foreach(
const Context& context, std::function<
void (T&)> f) {
186 _defer->addCallback([f] (
const Try<T>& result) {
187 if (result.isSuccess()) {
188 T value = result.getValue();
194 Option<Try<T>> getValue()
const {
195 return _defer->getValue();
198 bool isCompleted()
const {
199 return getValue().hasValue();
202 Future<Exception> failed() {
203 auto deffer = Future<Exception>::make_deffered();
204 _defer->addCallback([deffer] (
const Try<T>& result) {
205 if (result.isFailure()) {
206 deffer->setResult(Try<Exception>(result.getFailure()));
209 r.fail(Exception(api::ErrorCode::FUTURE_WAS_SUCCESSFULL,
"Future was successful but rejected cause of the failed projection."));
210 deffer->setResult(r);
212 }, ImmediateExecutionContext::INSTANCE);
213 return Future<Exception>(deffer);
216 void onComplete(
const Context& context, std::function<
void (
const Try<T>&)> f) {
217 _defer->addCallback(f, context);
220 template<
typename Callback>
221 typename std::enable_if<has_on_callback_method<Callback, void (T&)>::value,
void>::type
222 callback(
const Context& context, std::shared_ptr<Callback> cb) {
223 onComplete(context, [cb] (
const Try<T>& result) {
224 cb->onCallback(result.getValue());
228 template<
typename Callback>
230 callback(
const Context& context, std::shared_ptr<Callback> cb) {
231 onComplete(context, [cb] (
const Try<T>& result) {
232 if (result.isSuccess()) {
233 cb->onCallback(result.toOption().toOptional(), Option<api::Error>().toOptional());
235 cb->onCallback(Option<T>().toOptional(), Option<api::Error>(result.getFailure().toApiError()).toOptional());
241 template<
typename Callback>
242 typename std::enable_if<is_shared_ptr<T>::value && has_on_callback_method<Callback, void (const T&, const std::experimental::optional<api::Error>&)>::value,
void>::type
243 callback(
const Context& context, std::shared_ptr<Callback> cb) {
244 onComplete(context, [cb] (
const Try<T>& result) {
245 if (result.isSuccess()) {
246 cb->onCallback(result.getValue(), Option<api::Error>().toOptional());
248 cb->onCallback(
nullptr, Option<api::Error>(result.getFailure().toApiError()).toOptional());
256 static Future<T> successful(T value) {
259 return p.getFuture();
262 static Future<T> failure(Exception&& exception) {
264 p.failure(exception);
265 return p.getFuture();
268 static Future<T> failure(
const Exception& exception) {
270 p.failure(exception);
271 return p.getFuture();
274 static Future<T> async(
const Context& context, std::function<T ()> f) {
276 throw make_exception(api::ErrorCode::ILLEGAL_STATE,
"Context has been released before async operation");
278 auto deffer = make_deffered();
279 context->execute(make_runnable([deffer, f] () {
280 auto result = Try<T>::from([&] () -> T {
283 deffer->setResult(result);
285 return Future<T>(deffer);
288 static Future<T> async(
const Context& context, std::function<Future<T> ()> f) {
290 throw make_exception(api::ErrorCode::ILLEGAL_STATE,
"Context has been released before async operation");
292 auto deffer = make_deffered();
293 context->execute(make_runnable([context, deffer, f] () {
294 auto result = Try<Future<T>>::from([&] () -> Future<T> {
297 if (result.isFailure()) {
298 deffer->setError(result.getFailure());
300 Future<T> f = result.getValue();
301 f.onComplete(context, [deffer] (
const Try<T>& r) {
302 deffer->setResult(r);
306 return Future<T>(deffer);
309 static std::shared_ptr<Deffered<T>> make_deffered() {
310 auto d =
new Deffered<T>();
311 return std::shared_ptr<Deffered<T>>(d);
315 std::shared_ptr<Deffered<T>> _defer;
317 template <
typename T>
318 using FuturePtr = Future<std::shared_ptr<T>>;
323 #endif //LEDGER_CORE_FUTURE_HPP Definition: Account.cpp:8
Definition: optional.hpp:177