1#pragma once
2
3#include <mbgl/util/optional.hpp>
4
5#include <future>
6#include <utility>
7
8namespace mbgl {
9
10// A movable type-erasing function wrapper. This allows to store arbitrary invokable
11// things (like std::function<>, or the result of a movable-only std::bind()) in the queue.
12// Source: http://stackoverflow.com/a/29642072/331379
13class Message {
14public:
15 virtual ~Message() = default;
16 virtual void operator()() = 0;
17};
18
19template <class Object, class MemberFn, class ArgsTuple>
20class MessageImpl : public Message {
21public:
22 MessageImpl(Object& object_, MemberFn memberFn_, ArgsTuple argsTuple_)
23 : object(object_),
24 memberFn(memberFn_),
25 argsTuple(std::move(argsTuple_)) {
26 }
27
28 void operator()() override {
29 invoke(std::make_index_sequence<std::tuple_size<ArgsTuple>::value>());
30 }
31
32 template <std::size_t... I>
33 void invoke(std::index_sequence<I...>) {
34 (object.*memberFn)(std::move(std::get<I>(argsTuple))...);
35 }
36
37 Object& object;
38 MemberFn memberFn;
39 ArgsTuple argsTuple;
40};
41
42template <class ResultType, class Object, class MemberFn, class ArgsTuple>
43class AskMessageImpl : public Message {
44public:
45 AskMessageImpl(std::promise<ResultType> promise_, Object& object_, MemberFn memberFn_, ArgsTuple argsTuple_)
46 : object(object_),
47 memberFn(memberFn_),
48 argsTuple(std::move(argsTuple_)),
49 promise(std::move(promise_)) {
50 }
51
52 void operator()() override {
53 promise.set_value(ask(std::make_index_sequence<std::tuple_size<ArgsTuple>::value>()));
54 }
55
56 template <std::size_t... I>
57 ResultType ask(std::index_sequence<I...>) {
58 return (object.*memberFn)(std::move(std::get<I>(argsTuple))...);
59 }
60
61 Object& object;
62 MemberFn memberFn;
63 ArgsTuple argsTuple;
64 std::promise<ResultType> promise;
65};
66
67template <class Object, class MemberFn, class ArgsTuple>
68class AskMessageImpl<void, Object, MemberFn, ArgsTuple> : public Message {
69public:
70 AskMessageImpl(std::promise<void> promise_, Object& object_, MemberFn memberFn_, ArgsTuple argsTuple_)
71 : object(object_),
72 memberFn(memberFn_),
73 argsTuple(std::move(argsTuple_)),
74 promise(std::move(promise_)) {
75 }
76
77 void operator()() override {
78 ask(std::make_index_sequence<std::tuple_size<ArgsTuple>::value>());
79 promise.set_value();
80 }
81
82 template <std::size_t... I>
83 void ask(std::index_sequence<I...>) {
84 (object.*memberFn)(std::move(std::get<I>(argsTuple))...);
85 }
86
87 Object& object;
88 MemberFn memberFn;
89 ArgsTuple argsTuple;
90 std::promise<void> promise;
91};
92
93namespace actor {
94
95template <class Object, class MemberFn, class... Args>
96std::unique_ptr<Message> makeMessage(Object& object, MemberFn memberFn, Args&&... args) {
97 auto tuple = std::make_tuple(std::forward<Args>(args)...);
98 return std::make_unique<MessageImpl<Object, MemberFn, decltype(tuple)>>(object, memberFn, std::move(tuple));
99}
100
101template <class ResultType, class Object, class MemberFn, class... Args>
102std::unique_ptr<Message> makeMessage(std::promise<ResultType>&& promise, Object& object, MemberFn memberFn, Args&&... args) {
103 auto tuple = std::make_tuple(std::forward<Args>(args)...);
104 return std::make_unique<AskMessageImpl<ResultType, Object, MemberFn, decltype(tuple)>>(std::move(promise), object, memberFn, std::move(tuple));
105}
106
107} // namespace actor
108} // namespace mbgl
109

source code of qtlocation/src/3rdparty/mapbox-gl-native/include/mbgl/actor/message.hpp