diff options
author | Ivo van Dongen <info@ivovandongen.nl> | 2017-07-20 19:17:49 +0300 |
---|---|---|
committer | Ivo van Dongen <ivovandongen@users.noreply.github.com> | 2017-07-24 19:30:02 +0300 |
commit | a9ac314a5d28bec2a26cd6889364f81f811d4cd4 (patch) | |
tree | b1622c574ee1bc659cd11ab24f3ab16098326eca /include | |
parent | 3364992be94364a6e8b302124db53aeed5d99c15 (diff) | |
download | qtlocation-mapboxgl-a9ac314a5d28bec2a26cd6889364f81f811d4cd4.tar.gz |
[core] implement ask pattern in actor
Diffstat (limited to 'include')
-rw-r--r-- | include/mbgl/actor/actor.hpp | 12 | ||||
-rw-r--r-- | include/mbgl/actor/message.hpp | 34 |
2 files changed, 46 insertions, 0 deletions
diff --git a/include/mbgl/actor/actor.hpp b/include/mbgl/actor/actor.hpp index 810114c513..00e1bb82f8 100644 --- a/include/mbgl/actor/actor.hpp +++ b/include/mbgl/actor/actor.hpp @@ -6,6 +6,7 @@ #include <mbgl/util/noncopyable.hpp> #include <memory> +#include <future> namespace mbgl { @@ -61,6 +62,17 @@ public: mailbox->push(actor::makeMessage(object, fn, std::forward<Args>(args)...)); } + template <typename Fn, class... Args> + auto ask(Fn fn, Args&&... args) { + // Result type is deduced from the function's return type + using ResultType = typename std::result_of<decltype(fn)(Object, Args...)>::type; + + std::promise<ResultType> promise; + auto future = promise.get_future(); + mailbox->push(actor::makeMessage(std::move(promise), object, fn, std::forward<Args>(args)...)); + return future; + } + ActorRef<std::decay_t<Object>> self() { return ActorRef<std::decay_t<Object>>(object, mailbox); } diff --git a/include/mbgl/actor/message.hpp b/include/mbgl/actor/message.hpp index cf071d4933..406de425d4 100644 --- a/include/mbgl/actor/message.hpp +++ b/include/mbgl/actor/message.hpp @@ -1,5 +1,8 @@ #pragma once +#include <mbgl/util/optional.hpp> + +#include <future> #include <utility> namespace mbgl { @@ -36,6 +39,31 @@ public: ArgsTuple argsTuple; }; +template <class ResultType, class Object, class MemberFn, class ArgsTuple> +class AskMessageImpl : public Message { +public: + AskMessageImpl(std::promise<ResultType> promise_, Object& object_, MemberFn memberFn_, ArgsTuple argsTuple_) + : object(object_), + memberFn(memberFn_), + argsTuple(std::move(argsTuple_)), + promise(std::move(promise_)) { + } + + void operator()() override { + promise.set_value(ask(std::make_index_sequence<std::tuple_size<ArgsTuple>::value>())); + } + + template <std::size_t... I> + ResultType ask(std::index_sequence<I...>) { + return (object.*memberFn)(std::move(std::get<I>(argsTuple))...); + } + + Object& object; + MemberFn memberFn; + ArgsTuple argsTuple; + std::promise<ResultType> promise; +}; + namespace actor { template <class Object, class MemberFn, class... Args> @@ -44,5 +72,11 @@ std::unique_ptr<Message> makeMessage(Object& object, MemberFn memberFn, Args&&.. return std::make_unique<MessageImpl<Object, MemberFn, decltype(tuple)>>(object, memberFn, std::move(tuple)); } +template <class ResultType, class Object, class MemberFn, class... Args> +std::unique_ptr<Message> makeMessage(std::promise<ResultType>&& promise, Object& object, MemberFn memberFn, Args&&... args) { + auto tuple = std::make_tuple(std::forward<Args>(args)...); + return std::make_unique<AskMessageImpl<ResultType, Object, MemberFn, decltype(tuple)>>(std::move(promise), object, memberFn, std::move(tuple)); +} + } // namespace actor } // namespace mbgl |