Commit f72ff6a5 authored by Matthias Vallentin's avatar Matthias Vallentin

Streamline response promise delivery and return

A common use case involves creating a response promise, doing some work,
and then finalizing it followed by returning from the function:

        auto rp = make_response_promise();
        // do work
        rp.deliver(..);
        return rp;

The last two statements can now be written more idiomatically:

        return rp.deliver(..);
parent 077e7d46
......@@ -46,16 +46,16 @@ public:
/// Satisfies the promise by sending a non-error response message.
template <class T, class... Ts>
typename std::enable_if<
(sizeof...(Ts) > 0) ||
! std::is_convertible<T, error>::value
(sizeof...(Ts) > 0) || ! std::is_convertible<T, error>::value,
response_promise
>::type
deliver(T&&x, Ts&&... xs) {
deliver_impl(make_message(std::forward<T>(x), std::forward<Ts>(xs)...));
return deliver_impl(make_message(std::forward<T>(x), std::forward<Ts>(xs)...));
}
/// Satisfies the promise by sending an error response message.
/// For non-requests, nothing is done.
void deliver(error x);
response_promise deliver(error x);
/// Returns whether this response promise replies to an asynchronous message.
bool async() const;
......@@ -76,7 +76,7 @@ public:
private:
using forwarding_stack = std::vector<strong_actor_ptr>;
void deliver_impl(message response_message);
response_promise deliver_impl(message response_message);
local_actor* self_;
strong_actor_ptr source_;
......
......@@ -53,7 +53,8 @@ public:
/// Satisfies the promise by sending a non-error response message.
template <class U, class... Us>
typename std::enable_if<
(sizeof...(Us) > 0) || ! std::is_convertible<U, error>::value
(sizeof...(Us) > 0) || ! std::is_convertible<U, error>::value,
typed_response_promise
>::type
deliver(U&& x, Us&&... xs) {
static_assert(
......@@ -62,12 +63,14 @@ public:
typename std::decay<Us>::type...>>::value,
"typed_response_promise: message type mismatched");
promise_.deliver(std::forward<U>(x), std::forward<Us>(xs)...);
return *this;
}
/// Satisfies the promise by sending an error response message.
/// For non-requests, nothing is done.
inline void deliver(error x) {
inline typed_response_promise deliver(error x) {
promise_.deliver(std::move(x));
return *this;
}
/// Queries whether this promise is a valid promise that is not satisfied yet.
......
......@@ -41,34 +41,35 @@ response_promise::response_promise(local_actor* self, mailbox_element& src)
}
}
void response_promise::deliver(error x) {
response_promise response_promise::deliver(error x) {
//if (id_.valid())
deliver_impl(make_message(std::move(x)));
return deliver_impl(make_message(std::move(x)));
}
bool response_promise::async() const {
return id_.is_async();
}
void response_promise::deliver_impl(message msg) {
response_promise response_promise::deliver_impl(message msg) {
if (! stages_.empty()) {
auto next = std::move(stages_.back());
stages_.pop_back();
next->enqueue(mailbox_element::make(std::move(source_), id_,
std::move(stages_), std::move(msg)),
self_->context());
return;
return *this;
}
if (source_) {
source_->enqueue(self_->ctrl(), id_.response_id(),
std::move(msg), self_->context());
source_.reset();
return;
return *this;
}
if (self_)
CAF_LOG_ERROR("response promise already satisfied");
else
CAF_LOG_ERROR("invalid response promise");
return *this;
}
} // namespace caf
......@@ -54,8 +54,7 @@ public:
[=](int x) -> foo_promise {
auto resp = response(x * 2);
CAF_CHECK(! resp.pending());
resp.deliver(x * 4); // has no effect
return resp;
return resp.deliver(x * 4); // has no effect
},
[=](get_atom, int x) -> foo_promise {
auto calculator = spawn([](event_based_actor* self) -> behavior {
......@@ -95,8 +94,7 @@ public:
},
[=](get_atom, double) -> foo3_promise {
auto resp = make_response_promise<double>();
resp.deliver(make_error(sec::unexpected_message));
return resp;
return resp.deliver(make_error(sec::unexpected_message));
},
[=](get_atom, double x, double y) {
return response(x * 2, y * 2);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment