Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 108 additions & 9 deletions misc/experimental/promise/api/celix/Deferred.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#pragma once

#include <exception>
#include <utility>

#include "celix/impl/SharedPromiseState.h"
#include "celix/Promise.h"
Expand Down Expand Up @@ -113,9 +114,6 @@ namespace celix {
void resolve(const T& value);

//NOTE not part of the spec.. update to resolveWith with a return celix::Promise<void> ??
template<typename U>
void resolveWith(celix::Promise<U> with);

/**
* Resolve the Promise associated with this Deferred with the specified Promise.
* <p/>
Expand All @@ -136,12 +134,81 @@ namespace celix {
* the specified Promise. The returned Promise will be resolved with a failure of IllegalStateException if the
* associated Promise was already resolved when the specified Promise was resolved.
*/
//TODO support void promises
//Promise<void> resolveWith(Promise<T> with);
template<typename U>
void resolveWith(celix::Promise<U> with);

private:
std::shared_ptr<celix::impl::SharedPromiseState<T>> state;
};

template<>
class Deferred<void> {
public:
using type = void;

Deferred();

explicit Deferred(std::shared_ptr<celix::impl::SharedPromiseState<void>> state);

//TODO deferred ctor with factory

/**
* Fail the Promise associated with this Deferred.
* <p/>
* After the associated Promise is resolved with the specified failure, all registered callbacks are called and any
* chained Promises are resolved.
* <p/>
* Resolving the associated Promise happens-before any registered callback is called. That is, in a registered
* callback, Promise.isDone() must return true and Promise.getValue() and Promise.getFailure() must not block.
*
* @param failure The failure in the form of an exception pointer.
* @throws PromiseInvocationException If the associated Promise was already resolved.
*/
void fail(std::exception_ptr failure);

/**
* Fail the Promise associated with this Deferred.
* <p/>
* After the associated Promise is resolved with the specified failure, all registered callbacks are called and any
* chained Promises are resolved.
* <p/>
* Resolving the associated Promise happens-before any registered callback is called. That is, in a registered
* callback, Promise.isDone() must return true and Promise.getValue() and Promise.getFailure() must not block.
*
* @param failure The failure in the form of an const std::exception reference.
* @throws PromiseInvocationException If the associated Promise was already resolved.
*/
void fail(const std::exception& failure);

/**
* Returns the Promise associated with this Deferred.
* <p>
* All Promise objects created by the associated Promise will use the
* executors of the associated Promise.
*
* @return The Promise associated with this Deferred.
*/
Promise<void> getPromise();

/**
* Successfully resolve the Promise associated with this Deferred.
* <p/>
* After the associated Promise is resolved with the specified value, all registered callbacks are called and any
* chained Promises are resolved.
* <p/>
* Resolving the associated Promise happens-before any registered callback is called. That is, in a registered
* callback, Promise.isDone() must return true and Promise.getValue() and Promise.getFailure() must not block.
*
* @param value The value of the resolved Promise.
* @throws PromiseInvocationException If the associated Promise was already resolved.
*/
void resolve();

void resolveWith(celix::Promise<void> with);

private:
std::shared_ptr<celix::impl::SharedPromiseState<void>> state;
};
}


Expand All @@ -153,24 +220,40 @@ namespace celix {
template<typename T>
inline celix::Deferred<T>::Deferred() : state{std::make_shared<celix::impl::SharedPromiseState<T>>()} {}

inline celix::Deferred<void>::Deferred() : state{std::make_shared<celix::impl::SharedPromiseState<void>>()} {}

template<typename T>
inline celix::Deferred<T>::Deferred(std::shared_ptr<celix::impl::SharedPromiseState<T>> _state) : state{std::move(_state)} {}

inline celix::Deferred<void>::Deferred(std::shared_ptr<celix::impl::SharedPromiseState<void>> _state) : state{std::move(_state)} {}

template<typename T>
inline void celix::Deferred<T>::fail(std::exception_ptr p) {
state->fail(p);
inline void celix::Deferred<T>::fail(std::exception_ptr failure) {
state->fail(std::move(failure));
}

inline void celix::Deferred<void>::fail(std::exception_ptr failure) {
state->fail(std::move(failure));
}

template<typename T>
inline void celix::Deferred<T>::fail(const std::exception& e) {
state->fail(e);
inline void celix::Deferred<T>::fail(const std::exception& failure) {
state->fail(failure);
}

inline void celix::Deferred<void>::fail(const std::exception& failure) {
state->fail(failure);
}

template<typename T>
inline celix::Promise<T> celix::Deferred<T>::getPromise() {
return celix::Promise<T>{state};
}

inline celix::Promise<void> celix::Deferred<void>::getPromise() {
return celix::Promise<void>{state};
}

template<typename T>
template<typename U>
inline void celix::Deferred<T>::resolveWith(celix::Promise<U> with) {
Expand All @@ -185,6 +268,18 @@ inline void celix::Deferred<T>::resolveWith(celix::Promise<U> with) {
});
}

inline void celix::Deferred<void>::resolveWith(celix::Promise<void> with) {
auto s = state;
with.onResolve([s, with]{
if (with.isSuccessfullyResolved()) {
with.getValue();
s->resolve();
} else {
s->fail(with.getFailure());
}
});
}

template<typename T>
inline void celix::Deferred<T>::resolve(T&& value) {
state->resolve(std::forward<T>(value));
Expand All @@ -194,3 +289,7 @@ template<typename T>
inline void celix::Deferred<T>::resolve(const T& value) {
state->resolve(value);
}

inline void celix::Deferred<void>::resolve() {
state->resolve();
}
Loading